[
  {
    "path": ".all-contributorsrc",
    "content": "{\n  \"files\": [\n    \"README.md\"\n  ],\n  \"imageSize\": 100,\n  \"commit\": false,\n  \"contributors\": [\n    {\n      \"login\": \"iluwatar\",\n      \"name\": \"Ilkka Seppälä\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/582346?v=4\",\n      \"profile\": \"https://github.com/iluwatar\",\n      \"contributions\": [\n        \"projectManagement\",\n        \"maintenance\",\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"ohbus\",\n      \"name\": \"Subhrodip Mohanta\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/13291222?v=4\",\n      \"profile\": \"http://subho.xyz\",\n      \"contributions\": [\n        \"code\",\n        \"review\",\n        \"maintenance\"\n      ]\n    },\n    {\n      \"login\": \"amit1307\",\n      \"name\": \"amit1307\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/23420222?v=4\",\n      \"profile\": \"https://github.com/amit1307\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"npathai\",\n      \"name\": \"Narendra Pathai\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/1792515?v=4\",\n      \"profile\": \"https://github.com/npathai\",\n      \"contributions\": [\n        \"code\",\n        \"ideas\",\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"fluxw42\",\n      \"name\": \"Jeroen Meulemeester\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/1545460?v=4\",\n      \"profile\": \"https://github.com/fluxw42\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"mikulucky\",\n      \"name\": \"Joseph McCarthy\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/4526195?v=4\",\n      \"profile\": \"http://www.joemccarthy.co.uk\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"thomasoss\",\n      \"name\": \"Thomas\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/22516154?v=4\",\n      \"profile\": \"https://github.com/thomasoss\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"anuragagarwal561994\",\n      \"name\": \"Anurag Agarwal\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/6075379?v=4\",\n      \"profile\": \"https://github.com/anuragagarwal561994\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"markusmo3\",\n      \"name\": \"Markus Moser\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/3317416?v=4\",\n      \"profile\": \"https://markusmo3.github.io\",\n      \"contributions\": [\n        \"design\",\n        \"code\",\n        \"ideas\"\n      ]\n    },\n    {\n      \"login\": \"isabiq\",\n      \"name\": \"Sabiq Ihab\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/19510920?v=4\",\n      \"profile\": \"https://twitter.com/i_sabiq\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"inbravo\",\n      \"name\": \"Amit Dixit\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/5253764?v=4\",\n      \"profile\": \"http://inbravo.github.io\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"piyushchaudhari04\",\n      \"name\": \"Piyush Kailash Chaudhari\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/10268029?v=4\",\n      \"profile\": \"https://github.com/piyushchaudhari04\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"joshzambales\",\n      \"name\": \"joshzambales\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/8704552?v=4\",\n      \"profile\": \"https://github.com/joshzambales\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Crossy147\",\n      \"name\": \"Kamil Pietruszka\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/7272996?v=4\",\n      \"profile\": \"https://github.com/Crossy147\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"zafarella\",\n      \"name\": \"Zafar Khaydarov\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/660742?v=4\",\n      \"profile\": \"http://cs.joensuu.fi/~zkhayda\",\n      \"contributions\": [\n        \"code\",\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"kemitix\",\n      \"name\": \"Paul Campbell\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/1147749?v=4\",\n      \"profile\": \"https://kemitix.github.io/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Argyro-Sioziou\",\n      \"name\": \"Argyro Sioziou\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/22822639?v=4\",\n      \"profile\": \"https://github.com/Argyro-Sioziou\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"TylerMcConville\",\n      \"name\": \"TylerMcConville\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/4946449?v=4\",\n      \"profile\": \"https://github.com/TylerMcConville\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"saksham93\",\n      \"name\": \"saksham93\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/37399540?v=4\",\n      \"profile\": \"https://github.com/saksham93\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"nikhilbarar\",\n      \"name\": \"nikhilbarar\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/37332144?v=4\",\n      \"profile\": \"https://github.com/nikhilbarar\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"colinbut\",\n      \"name\": \"Colin But\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/10725674?v=4\",\n      \"profile\": \"http://colinbut.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ruslanpa\",\n      \"name\": \"Ruslan\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/1503411?v=4\",\n      \"profile\": \"https://github.com/ruslanpa\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"JuhoKang\",\n      \"name\": \"Juho Kang\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/4745294?v=4\",\n      \"profile\": \"https://github.com/JuhoKang\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"dheeraj-mummareddy\",\n      \"name\": \"Dheeraj Mummareddy\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/7002230?v=4\",\n      \"profile\": \"https://github.com/dheeraj-mummareddy\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"bernardosulzbach\",\n      \"name\": \"Bernardo Sulzbach\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/8271090?v=4\",\n      \"profile\": \"https://www.bernardosulzbach.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"4lexis\",\n      \"name\": \"Aleksandar Dudukovic\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/19871727?v=4\",\n      \"profile\": \"https://github.com/4lexis\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"yusufaytas\",\n      \"name\": \"Yusuf Aytaş\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/1049483?v=4\",\n      \"profile\": \"https://www.yusufaytas.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"qpi\",\n      \"name\": \"Mihály Kuprivecz\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/1001491?v=4\",\n      \"profile\": \"http://futurehomes.hu\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"kapinuss\",\n      \"name\": \"Stanislav Kapinus\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/17639945?v=4\",\n      \"profile\": \"https://github.com/kapinuss\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"gvsharma\",\n      \"name\": \"GVSharma\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/6648152?v=4\",\n      \"profile\": \"https://github.com/gvsharma\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"SrdjanPaunovic\",\n      \"name\": \"Srđan Paunović\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/22815104?v=4\",\n      \"profile\": \"https://github.com/SrdjanPaunovic\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"sideris\",\n      \"name\": \"Petros G. Sideris\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/5484694?v=4\",\n      \"profile\": \"https://sideris.xyz/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"IAmPramod\",\n      \"name\": \"Pramod Gupta\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/2184241?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/pramodgupta3/\",\n      \"contributions\": [\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"Amarnath510\",\n      \"name\": \"Amarnath Chandana\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/4599623?v=4\",\n      \"profile\": \"https://amarnath510.github.io/portfolio\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Anurag870\",\n      \"name\": \"Anurag870\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/6295975?v=4\",\n      \"profile\": \"https://github.com/Anurag870\",\n      \"contributions\": [\n        \"code\",\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"Deathnerd\",\n      \"name\": \"Wes Gilleland\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/1685953?v=4\",\n      \"profile\": \"http://theerroris.me\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Harshrajsinh\",\n      \"name\": \"Harshraj Thakor\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/22811531?v=4\",\n      \"profile\": \"https://github.com/Harshrajsinh\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"MaVdbussche\",\n      \"name\": \"Martin Vandenbussche\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/26136934?v=4\",\n      \"profile\": \"https://github.com/MaVdbussche\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"alexsomai\",\n      \"name\": \"Alexandru Somai\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/5720977?v=4\",\n      \"profile\": \"https://alexsomai.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"amogozov\",\n      \"name\": \"Artur Mogozov\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/7372215?v=4\",\n      \"profile\": \"https://github.com/amogozov\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"anthonycampbell\",\n      \"name\": \"anthony\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/10249255?v=4\",\n      \"profile\": \"https://github.com/anthonycampbell\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"christophercolumbusdog\",\n      \"name\": \"Christian Cygnus\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/9342724?v=4\",\n      \"profile\": \"http://ccygnus.com/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"dzmitryh\",\n      \"name\": \"Dima Gubin\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/5390492?v=4\",\n      \"profile\": \"https://about.me/dzmitryh\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"jjjimenez100\",\n      \"name\": \"Joshua Jimenez\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/22243493?v=4\",\n      \"profile\": \"https://github.com/jjjimenez100\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"kaiwinter\",\n      \"name\": \"Kai Winter\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/110982?v=4\",\n      \"profile\": \"http://about.me/kaiwinter\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"lbroman\",\n      \"name\": \"lbroman\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/86007?v=4\",\n      \"profile\": \"https://github.com/lbroman\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"pnowy\",\n      \"name\": \"Przemek\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/3254609?v=4\",\n      \"profile\": \"https://przemeknowak.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"prafful1\",\n      \"name\": \"Prafful Agarwal\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/14350274?v=4\",\n      \"profile\": \"https://github.com/prafful1\",\n      \"contributions\": [\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"sankypanhale\",\n      \"name\": \"Sanket Panhale\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/6478783?v=4\",\n      \"profile\": \"https://github.com/sankypanhale\",\n      \"contributions\": [\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"staillebois\",\n      \"name\": \"staillebois\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/23701200?v=4\",\n      \"profile\": \"https://github.com/staillebois\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"valdar-hu\",\n      \"name\": \"Krisztián Nagy\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/17962817?v=4\",\n      \"profile\": \"https://github.com/valdar-hu\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"vanogrid\",\n      \"name\": \"Alexander Ivanov\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/4307918?v=4\",\n      \"profile\": \"https://www.vanogrid.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"yosfik\",\n      \"name\": \"Yosfik Alqadri\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/4850270?v=4\",\n      \"profile\": \"https://github.com/yosfik\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"7agustibm\",\n      \"name\": \"Agustí Becerra Milà\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/8149332?v=4\",\n      \"profile\": \"https://github.com/7agustibm\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Juaanma\",\n      \"name\": \"Juan Manuel Suárez\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/7390500?v=4\",\n      \"profile\": \"https://github.com/Juaanma\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"LuigiCortese\",\n      \"name\": \"Luigi Cortese\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/9956006?v=4\",\n      \"profile\": \"http://www.devsedge.net/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Rzeposlaw\",\n      \"name\": \"Katarzyna Rzepecka\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/18425745?v=4\",\n      \"profile\": \"https://github.com/Rzeposlaw\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"akrystian\",\n      \"name\": \"adamski.pro\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/6537430?v=4\",\n      \"profile\": \"http://adamski.pro\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"baislsl\",\n      \"name\": \"Shengli Bai\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/17060584?v=4\",\n      \"profile\": \"https://github.com/baislsl\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"besok\",\n      \"name\": \"Boris\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/29834592?v=4\",\n      \"profile\": \"https://github.com/besok\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"dmitraver\",\n      \"name\": \"Dmitry Avershin\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/1798156?v=4\",\n      \"profile\": \"https://github.com/dmitraver\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"fanofxiaofeng\",\n      \"name\": \"靳阳\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/3983683?v=4\",\n      \"profile\": \"https://github.com/fanofxiaofeng\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"hoangnam2261\",\n      \"name\": \"hoangnam2261\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/31692990?v=4\",\n      \"profile\": \"https://github.com/hoangnam2261\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"jarpit96\",\n      \"name\": \"Arpit Jain\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/10098713?v=4\",\n      \"profile\": \"https://github.com/jarpit96\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"joningiwork\",\n      \"name\": \"Jón Ingi Sveinbjörnsson\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/6115148?v=4\",\n      \"profile\": \"http://joningi.net\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"kirill-vlasov\",\n      \"name\": \"Kirill Vlasov\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/16112495?v=4\",\n      \"profile\": \"https://github.com/kirill-vlasov\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"mitchellirvin\",\n      \"name\": \"Mitchell Irvin\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/16233245?v=4\",\n      \"profile\": \"http://mitchell-irvin.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ranjeet-floyd\",\n      \"name\": \"Ranjeet\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/1992972?v=4\",\n      \"profile\": \"https://ranjeet-floyd.github.io\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Alwayswithme\",\n      \"name\": \"PhoenixYip\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/3234786?v=4\",\n      \"profile\": \"https://alwayswithme.github.io\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"MSaifAsif\",\n      \"name\": \"M Saif Asif\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/6280554?v=4\",\n      \"profile\": \"https://github.com/MSaifAsif\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"kanwarpreet25\",\n      \"name\": \"kanwarpreet25\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/39183641?v=4\",\n      \"profile\": \"https://github.com/kanwarpreet25\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"leonmak\",\n      \"name\": \"Leon Mak\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/13071508?v=4\",\n      \"profile\": \"http://leonmak.me\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"perwramdemark\",\n      \"name\": \"Per Wramdemark\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/7052193?v=4\",\n      \"profile\": \"http://www.wramdemark.se\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"waisuan\",\n      \"name\": \"Evan Sia Wai Suan\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/10975700?v=4\",\n      \"profile\": \"https://github.com/waisuan\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"AnaghaSasikumar\",\n      \"name\": \"AnaghaSasikumar\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/42939261?v=4\",\n      \"profile\": \"https://github.com/AnaghaSasikumar\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"christofferh\",\n      \"name\": \"Christoffer Hamberg\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/767643?v=4\",\n      \"profile\": \"https://christofferh.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"dgruntz\",\n      \"name\": \"Dominik Gruntz\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/1516800?v=4\",\n      \"profile\": \"https://github.com/dgruntz\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"hannespernpeintner\",\n      \"name\": \"Hannes\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/1679437?v=4\",\n      \"profile\": \"https://bitbucket.org/hannespernpeintner/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"leogtzr\",\n      \"name\": \"Leo Gutiérrez Ramírez\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/1211969?v=4\",\n      \"profile\": \"https://github.com/leogtzr\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"npczwh\",\n      \"name\": \"Zhang WH\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/14066422?v=4\",\n      \"profile\": \"https://github.com/npczwh\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"oconnelc\",\n      \"name\": \"Christopher O'Connell\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/1112973?v=4\",\n      \"profile\": \"https://github.com/oconnelc\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"giorgosmav21\",\n      \"name\": \"George Mavroeidis\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/22855493?v=4\",\n      \"profile\": \"https://github.com/giorgosmav21\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"hbothra15\",\n      \"name\": \"Hemant Bothra\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/7418012?v=4\",\n      \"profile\": \"https://github.com/hbothra15\",\n      \"contributions\": [\n        \"code\",\n        \"design\"\n      ]\n    },\n    {\n      \"login\": \"igeligel\",\n      \"name\": \"Kevin Peters\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/12736734?v=4\",\n      \"profile\": \"https://www.kevinpeters.net/about/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"llorllale\",\n      \"name\": \"George Aristy\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/2019896?v=4\",\n      \"profile\": \"https://llorllale.github.io/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"mookkiah\",\n      \"name\": \"Mahendran Mookkiah\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/8975264?v=4\",\n      \"profile\": \"https://github.com/mookkiah\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Azureyjt\",\n      \"name\": \"Azureyjt\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/18476317?v=4\",\n      \"profile\": \"https://github.com/Azureyjt\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"vehpsr\",\n      \"name\": \"gans\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/3133265?v=4\",\n      \"profile\": \"https://github.com/vehpsr\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ThatGuyWithTheHat\",\n      \"name\": \"Matt\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/24470582?v=4\",\n      \"profile\": \"https://github.com/ThatGuyWithTheHat\",\n      \"contributions\": [\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"gopinath-langote\",\n      \"name\": \"Gopinath Langote\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/10210778?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/gopinathlangote/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"hoswey\",\n      \"name\": \"Hoswey\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/3689445?v=4\",\n      \"profile\": \"https://github.com/hoswey\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"amit2103\",\n      \"name\": \"Amit Pandey\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/7566692?v=4\",\n      \"profile\": \"https://github.com/amit2103\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"gwildor28\",\n      \"name\": \"gwildor28\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/16000365?v=4\",\n      \"profile\": \"https://github.com/gwildor28\",\n      \"contributions\": [\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"llitfkitfk\",\n      \"name\": \"田浩\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/2404785?v=4\",\n      \"profile\": \"https://t.me/paul_docker\",\n      \"contributions\": [\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"pitsios-s\",\n      \"name\": \"Stamatis Pitsios\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/6773603?v=4\",\n      \"profile\": \"https://twitter.com/StPitsios\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"qza\",\n      \"name\": \"qza\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/233149?v=4\",\n      \"profile\": \"https://github.com/qza\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Tschis\",\n      \"name\": \"Rodolfo Forte\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/20662669?v=4\",\n      \"profile\": \"http://tschis.github.io\",\n      \"contributions\": [\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"ankurkaushal\",\n      \"name\": \"Ankur Kaushal\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/2236616?v=4\",\n      \"profile\": \"https://github.com/ankurkaushal\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"okinskas\",\n      \"name\": \"Ovidijus Okinskas\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/20372387?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/ovidijus-okinskas/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"robertt240\",\n      \"name\": \"Robert Kasperczyk\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/9137432?v=4\",\n      \"profile\": \"https://github.com/robertt240\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"trautonen\",\n      \"name\": \"Tapio Rautonen\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/1641063?v=4\",\n      \"profile\": \"https://github.com/trautonen\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"yorlov\",\n      \"name\": \"Yuri Orlov\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/1595733?v=4\",\n      \"profile\": \"http://vk.com/yuri.orlov\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"varunu28\",\n      \"name\": \"Varun Upadhyay\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/7676016?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/varunu28/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"PalAditya\",\n      \"name\": \"Aditya Pal\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/25523604?v=4\",\n      \"profile\": \"https://github.com/PalAditya\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"grzesiekkedzior\",\n      \"name\": \"grzesiekkedzior\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/23739158?v=4\",\n      \"profile\": \"https://github.com/grzesiekkedzior\",\n      \"contributions\": [\n        \"code\",\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"sivasubramanim\",\n      \"name\": \"Sivasubramani M\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/51107434?v=4\",\n      \"profile\": \"https://github.com/sivasubramanim\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"d4gg4d\",\n      \"name\": \"Sami Airaksinen\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/99457?v=4\",\n      \"profile\": \"https://github.com/d4gg4d\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"vertti\",\n      \"name\": \"Janne Sinivirta\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/557751?v=4\",\n      \"profile\": \"https://github.com/vertti\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Bobo1239\",\n      \"name\": \"Boris-Chengbiao Zhou\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/2302947?v=4\",\n      \"profile\": \"https://github.com/Bobo1239\",\n      \"contributions\": [\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"Jahhein\",\n      \"name\": \"Jacob Hein\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/10779515?v=4\",\n      \"profile\": \"https://jahhein.github.io\",\n      \"contributions\": [\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"iamrichardjones\",\n      \"name\": \"Richard Jones\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/14842151?v=4\",\n      \"profile\": \"https://github.com/iamrichardjones\",\n      \"contributions\": [\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"rachelcarmena\",\n      \"name\": \"Rachel M. Carmena\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/22792183?v=4\",\n      \"profile\": \"https://rachelcarmena.github.io\",\n      \"contributions\": [\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"zd-zero\",\n      \"name\": \"Zaerald Denze Lungos\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/21978370?v=4\",\n      \"profile\": \"https://zd-zero.github.io\",\n      \"contributions\": [\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"webpro\",\n      \"name\": \"Lars Kappert\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/456426?v=4\",\n      \"profile\": \"https://webpro.nl\",\n      \"contributions\": [\n        \"content\"\n      ]\n    },\n    {\n      \"login\": \"xiaod-dev\",\n      \"name\": \"Mike Liu\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/21277644?v=4\",\n      \"profile\": \"https://xiaod.info\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"charlesfinley\",\n      \"name\": \"Matt Dolan\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/6307904?v=4\",\n      \"profile\": \"https://github.com/charlesfinley\",\n      \"contributions\": [\n        \"code\",\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"MananS77\",\n      \"name\": \"Manan\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/21033516?v=4\",\n      \"profile\": \"https://github.com/MananS77\",\n      \"contributions\": [\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"nishant\",\n      \"name\": \"Nishant Arora\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/15331971?v=4\",\n      \"profile\": \"https://github.com/nishant\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"raja-peeyush-kumar-singh\",\n      \"name\": \"Peeyush\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/5496024?v=4\",\n      \"profile\": \"https://github.com/raja-peeyush-kumar-singh\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ravening\",\n      \"name\": \"Rakesh\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/10645273?v=4\",\n      \"profile\": \"https://github.com/ravening\",\n      \"contributions\": [\n        \"code\",\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"vINCENT8888801\",\n      \"name\": \"Wei Seng\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/8037883?v=4\",\n      \"profile\": \"https://github.com/vINCENT8888801\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ashishtrivedi16\",\n      \"name\": \"Ashish Trivedi\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/23194128?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/ashish-trivedi-218379135/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"RayYH\",\n      \"name\": \"洪月阳\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/41055099?v=4\",\n      \"profile\": \"https://rayyounghong.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"xdvrx1\",\n      \"name\": \"xdvrx1\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/47092464?v=4\",\n      \"profile\": \"https://xdvrx1.github.io/\",\n      \"contributions\": [\n        \"review\",\n        \"ideas\"\n      ]\n    },\n    {\n      \"login\": \"nahteb\",\n      \"name\": \"Bethan Palmer\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/13121570?v=4\",\n      \"profile\": \"https://github.com/nahteb\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ToxicDreamz\",\n      \"name\": \"Toxic Dreamz\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/45225562?v=4\",\n      \"profile\": \"https://github.com/ToxicDreamz\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"edycutjong\",\n      \"name\": \"Edy Cu Tjong\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/1098102?v=4\",\n      \"profile\": \"http://www.edycutjong.com\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"mkrzywanski\",\n      \"name\": \"Michał Krzywański\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/15279585?v=4\",\n      \"profile\": \"https://github.com/mkrzywanski\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"stefanbirkner\",\n      \"name\": \"Stefan Birkner\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/711349?v=4\",\n      \"profile\": \"https://www.stefan-birkner.de\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"fedorskvorcov\",\n      \"name\": \"Fedor Skvorcov\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/43882212?v=4\",\n      \"profile\": \"https://github.com/fedorskvorcov\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"samilAyoub\",\n      \"name\": \"samilAyoub\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/61546990?v=4\",\n      \"profile\": \"https://github.com/samilAyoub\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"vdlald\",\n      \"name\": \"Vladislav Golubinov\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/29997701?v=4\",\n      \"profile\": \"https://github.com/vdlald\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"swarajsaaj\",\n      \"name\": \"Swaraj\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/6285049?v=4\",\n      \"profile\": \"https://github.com/swarajsaaj\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ChFlick\",\n      \"name\": \"Christoph Flick\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/4465376?v=4\",\n      \"profile\": \"http://christophflick.de\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"Ascenio\",\n      \"name\": \"Ascênio\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/7662016?v=4\",\n      \"profile\": \"https://github.com/Ascenio\",\n      \"contributions\": [\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"dsibilio\",\n      \"name\": \"Domenico Sibilio\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/24280982?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/domenico-sibilio/\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"akashchandwani\",\n      \"name\": \"Akash Chandwani\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/3483277?v=4\",\n      \"profile\": \"https://github.com/akashchandwani\",\n      \"contributions\": [\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"manannikov\",\n      \"name\": \"Pavlo Manannikov\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/7019769?v=4\",\n      \"profile\": \"http://www.linkedin.com/in/manannikov\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"eimanip\",\n      \"name\": \"Eiman\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/20307301?v=4\",\n      \"profile\": \"https://github.com/eimanip\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"OrangePants-R\",\n      \"name\": \"Rocky\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/42976136?v=4\",\n      \"profile\": \"https://github.com/OrangePants-R\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"ibrahimAlii\",\n      \"name\": \"Ibrahim ali abdelghany\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/21141301?v=4\",\n      \"profile\": \"https://ibrahimalii.github.io/\",\n      \"contributions\": [\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"gkulkarni2020\",\n      \"name\": \"Girish Kulkarni\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/5161548?v=4\",\n      \"profile\": \"https://github.com/gkulkarni2020\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"omk13\",\n      \"name\": \"Omar Karazoun\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/59054172?v=4\",\n      \"profile\": \"https://github.com/omk13\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"jeff303\",\n      \"name\": \"Jeff Evans\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/3521562?v=4\",\n      \"profile\": \"https://github.com/jeff303\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"viveksb007\",\n      \"name\": \"Vivek Singh\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/12713808?v=4\",\n      \"profile\": \"https://viveksb007.github.io\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"siavashsoleymani\",\n      \"name\": \"siavash\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/18074419?v=4\",\n      \"profile\": \"https://github.com/siavashsoleymani\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ruchpeanuts\",\n      \"name\": \"ruchpeanuts\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/29301900?v=4\",\n      \"profile\": \"https://github.com/ruchpeanuts\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"warp125\",\n      \"name\": \"warp125\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/48073115?v=4\",\n      \"profile\": \"https://github.com/warp125\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"tkhadir\",\n      \"name\": \"KHADIR Tayeb\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/45130488?v=4\",\n      \"profile\": \"http://libkhadir.fr\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"ignite1771\",\n      \"name\": \"ignite1771\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/59446563?v=4\",\n      \"profile\": \"https://github.com/ignite1771\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"demirhalil\",\n      \"name\": \"Halil Demir\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/22895118?v=4\",\n      \"profile\": \"https://github.com/demirhalil\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"rohit10000\",\n      \"name\": \"Rohit Singh\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/20845565?v=4\",\n      \"profile\": \"https://github.com/rohit10000\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"byoungju94\",\n      \"name\": \"byoungju94\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/42516378?v=4\",\n      \"profile\": \"https://github.com/byoungju94\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"moustafafarhat\",\n      \"name\": \"Moustafa Farhat\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/38836727?v=4\",\n      \"profile\": \"https://github.com/moustafafarhat\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"richardmr36\",\n      \"name\": \"Martel Richard\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/19147333?v=4\",\n      \"profile\": \"https://github.com/richardmr36\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"va1m\",\n      \"name\": \"va1m\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/17025445?v=4\",\n      \"profile\": \"https://github.com/va1m\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"noamgrinch\",\n      \"name\": \"Noam Greenshtain\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/31648669?v=4\",\n      \"profile\": \"https://github.com/noamgrinch\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"qfxl\",\n      \"name\": \"yonghong Xu\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/14086462?v=4\",\n      \"profile\": \"https://xuyonghong.cn/\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"jinishavora\",\n      \"name\": \"jinishavora\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/40777762?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/jinisha-vora\",\n      \"contributions\": [\n        \"review\",\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"eas5\",\n      \"name\": \"Elvys Soares\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/50836521?v=4\",\n      \"profile\": \"https://github.com/eas5\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"zWeBrain\",\n      \"name\": \"zWeBrain\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/46642512?v=4\",\n      \"profile\": \"https://github.com/zWeBrain\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Al-assad\",\n      \"name\": \"余林颖\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/22493821?v=4\",\n      \"profile\": \"https://al-assad.github.io/notion/\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"STudio26\",\n      \"name\": \"Alain\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/6988911?v=4\",\n      \"profile\": \"https://github.com/STudio26\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"DEV-VRUPER\",\n      \"name\": \"VR\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/30525467?v=4\",\n      \"profile\": \"https://github.com/DEV-VRUPER\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"JackieNim\",\n      \"name\": \"JackieNim\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/4138836?v=4\",\n      \"profile\": \"https://github.com/JackieNim\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"EdisonE3\",\n      \"name\": \"EdisonE3\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/52118917?v=4\",\n      \"profile\": \"https://github.com/EdisonE3\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"tao-sun2\",\n      \"name\": \"Tao\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/66189688?v=4\",\n      \"profile\": \"https://github.com/tao-sun2\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"JuanManuelAbate\",\n      \"name\": \"Juan Manuel Abate\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/16357060?v=4\",\n      \"profile\": \"https://github.com/JuanManuelAbate\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Xenilo137\",\n      \"name\": \"Xenilo137\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/24865069?v=4\",\n      \"profile\": \"https://github.com/Xenilo137\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"samuelpsouza\",\n      \"name\": \"Samuel Souza\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/17254162?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/souzasamuel/\",\n      \"contributions\": [\n        \"code\",\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"marlo2222\",\n      \"name\": \"Marlo Henrique\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/40809563?v=4\",\n      \"profile\": \"https://github.com/marlo2222\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"AndriyPyzh\",\n      \"name\": \"AndriyPyzh\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/57706635?v=4\",\n      \"profile\": \"https://github.com/AndriyPyzh\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"karthikbhat13\",\n      \"name\": \"karthikbhat13\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/22431014?v=4\",\n      \"profile\": \"https://github.com/karthikbhat13\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"mortezaadi\",\n      \"name\": \"Morteza Adigozalpour\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1329687?v=4\",\n      \"profile\": \"https://github.com/mortezaadi\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"tan31989\",\n      \"name\": \"Nagaraj Tantri\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/3784194?v=4\",\n      \"profile\": \"https://stackoverflow.com/users/308565/nagaraj-tantri\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"frascu\",\n      \"name\": \"Francesco Scuccimarri\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/7107651?v=4\",\n      \"profile\": \"https://github.com/frascu\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Conhan93\",\n      \"name\": \"Conny Hansson\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/71334757?v=4\",\n      \"profile\": \"https://github.com/Conhan93\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"muklasr\",\n      \"name\": \"Muklas Rahmanto\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/43443753?v=4\",\n      \"profile\": \"http://muklasr.medium.com\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"VxDxK\",\n      \"name\": \"Vadim\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/38704817?v=4\",\n      \"profile\": \"https://github.com/VxDxK\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"sims-keshri\",\n      \"name\": \"Simran Keshri\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/62168475?v=4\",\n      \"profile\": \"https://github.com/sims-keshri\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"JCarlosR\",\n      \"name\": \"JCarlos\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/3101238?v=4\",\n      \"profile\": \"https://programacionymas.com\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Dev-AliGhasemi\",\n      \"name\": \"Ali Ghasemi\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/60359433?v=4\",\n      \"profile\": \"https://www.mrmoshkel.ir\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"carldea\",\n      \"name\": \"Carl Dea\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1594624?v=4\",\n      \"profile\": \"http://carlfx.wordpress.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Mozartuss\",\n      \"name\": \"Mozartus\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/32893711?v=4\",\n      \"profile\": \"https://github.com/Mozartuss\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"ManviGoel26\",\n      \"name\": \"Manvi Goel\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/55682355?v=4\",\n      \"profile\": \"https://github.com/ManviGoel26\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"blueberry404\",\n      \"name\": \"Anum Amin\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/39243539?v=4\",\n      \"profile\": \"https://github.com/blueberry404\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"uh-zz\",\n      \"name\": \"Reo Uehara\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/47747828?v=4\",\n      \"profile\": \"https://uh-zz.github.io/blog/\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Fiordy\",\n      \"name\": \"Fiordy\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/53420573?v=4\",\n      \"profile\": \"https://github.com/Fiordy\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"harshalkh\",\n      \"name\": \"Harshal\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/37841724?v=4\",\n      \"profile\": \"https://github.com/harshalkh\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"vashisthabhinav\",\n      \"name\": \"Abhinav Vashisth\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/89785800?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/abhinav-vashisth-06613b208/\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"Kevinyl3\",\n      \"name\": \"Kevin\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/47126749?v=4\",\n      \"profile\": \"http://no website\",\n      \"contributions\": [\n        \"review\",\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Shrirang97\",\n      \"name\": \"Shrirang\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/28738668?v=4\",\n      \"profile\": \"https://github.com/Shrirang97\",\n      \"contributions\": [\n        \"review\",\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"interactwithankush\",\n      \"name\": \"interactwithankush\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/18613127?v=4\",\n      \"profile\": \"https://github.com/interactwithankush\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"yuhangbin\",\n      \"name\": \"CharlieYu\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/17566866?v=4\",\n      \"profile\": \"https://github.com/yuhangbin\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Leisterbecker\",\n      \"name\": \"Leisterbecker\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/20650323?v=4\",\n      \"profile\": \"https://github.com/Leisterbecker\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"castleKing1997\",\n      \"name\": \"DragonDreamer\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/35420129?v=4\",\n      \"profile\": \"http://rosaecrucis.cn\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ShivanshCharak\",\n      \"name\": \"ShivanshCharak\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/96943825?v=4\",\n      \"profile\": \"https://github.com/ShivanshCharak\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"HattoriHenzo\",\n      \"name\": \"HattoriHenzo\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/5141285?v=4\",\n      \"profile\": \"https://github.com/HattoriHenzo\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"arnabsen1729\",\n      \"name\": \"Arnab Sen\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/51032928?v=4\",\n      \"profile\": \"http://arnabsen.bio.link\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"mohanaraosv\",\n      \"name\": \"MohanaRao SV\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1470114?v=4\",\n      \"profile\": \"https://javaforlife.wordpress.com/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"yonatankarp\",\n      \"name\": \"Yonatan Karp-Rudin\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/14914865?v=4\",\n      \"profile\": \"https://github.com/yonatankarp\",\n      \"contributions\": [\n        \"code\",\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"GustavoOliani\",\n      \"name\": \"Oliani\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/25756378?v=4\",\n      \"profile\": \"https://github.com/GustavoOliani\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Liu-rj\",\n      \"name\": \"Renjie LIU\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/64826925?v=4\",\n      \"profile\": \"https://github.com/Liu-rj\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"TreeFireMen\",\n      \"name\": \"perfect guy\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/54127694?v=4\",\n      \"profile\": \"https://github.com/TreeFireMen\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"xyllq999\",\n      \"name\": \"xyllq999\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/72729433?v=4\",\n      \"profile\": \"https://github.com/xyllq999\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"dmdbilal\",\n      \"name\": \"Mohamed Bilal\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/91405690?v=4\",\n      \"profile\": \"https://github.com/dmdbilal\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"karshil2309\",\n      \"name\": \"Karshil sheth\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/37497287?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/karshilsheth/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"kongleong86\",\n      \"name\": \"kongleong86\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/3745455?v=4\",\n      \"profile\": \"https://github.com/kongleong86\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"aitorfi\",\n      \"name\": \"Aitor Fidalgo Sánchez\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/64830228?v=4\",\n      \"profile\": \"https://github.com/aitorfi\",\n      \"contributions\": [\n        \"translation\",\n        \"doc\",\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"HeVictor\",\n      \"name\": \"Victor He\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/20733994?v=4\",\n      \"profile\": \"https://github.com/HeVictor\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"m-inh\",\n      \"name\": \"Minh Nguyen\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/10632233?v=4\",\n      \"profile\": \"http://m-inh.github.io/\",\n      \"contributions\": [\n        \"translation\",\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"HeVictor\",\n      \"name\": \"Victor He\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/20733994?v=4\",\n      \"profile\": \"https://github.com/HeVictor\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"YichuanSun\",\n      \"name\": \"yiichan\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/30886176?v=4\",\n      \"profile\": \"https://github.com/YichuanSun\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"PanSem\",\n      \"name\": \"Pan Sem\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/43316964?v=4\",\n      \"profile\": \"https://github.com/PanSem\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"zhoumengyks\",\n      \"name\": \"zhoumengyks\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/111965739?v=4\",\n      \"profile\": \"https://github.com/zhoumengyks\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"you\",\n      \"name\": \"you\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/57100752?v=4\",\n      \"profile\": \"https://github.com/you\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Thanks\",\n      \"name\": \"Thanks\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1121545?v=4\",\n      \"profile\": \"https://github.com/thanks\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"lazy-pr0grammer\",\n      \"name\": \"LazyProgrammer\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/87204946?v=4\",\n      \"profile\": \"https://github.com/lazy-pr0grammer\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"mdfaizanahmed786\",\n      \"name\": \"Mohammed Faizan Ahmed\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/85175130?v=4\",\n      \"profile\": \"https://github.com/mdfaizanahmed786\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"burno1\",\n      \"name\": \"Bruno Fernandes\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/39165280?v=4\",\n      \"profile\": \"https://github.com/burno1\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"SammanPali\",\n      \"name\": \"SammanPali\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/110753804?v=4\",\n      \"profile\": \"https://github.com/SammanPali\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"LeseChe\",\n      \"name\": \"Qixiang Chen\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/79553089?v=4\",\n      \"profile\": \"https://github.com/LeseChe\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"shouryamanekar\",\n      \"name\": \"Shourya Manekar\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/72398499?v=4\",\n      \"profile\": \"https://github.com/shouryamanekar\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"seongkyu-lim\",\n      \"name\": \"Alan\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/55138532?v=4\",\n      \"profile\": \"https://seongkyu-lim.github.io/Blog/\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"JanFidor\",\n      \"name\": \"JanFidor\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/66260538?v=4\",\n      \"profile\": \"https://github.com/JanFidor\",\n      \"contributions\": [\n        \"code\",\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"drakulavich\",\n      \"name\": \"Anton Yakutovich\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/129260?v=4\",\n      \"profile\": \"https://github.com/drakulavich\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"steph88ss\",\n      \"name\": \"steph88ss\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/111041594?v=4\",\n      \"profile\": \"https://github.com/steph88ss\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"0xYujan\",\n      \"name\": \"Yujan Ranjitkar\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/63731234?v=4\",\n      \"profile\": \"http://yujanranjitkar.com.np\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"yusha-g\",\n      \"name\": \"yusha-g\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/110189579?v=4\",\n      \"profile\": \"https://github.com/yusha-g\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"robertvolkmann\",\n      \"name\": \"Robert Volkmann\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/20912167?v=4\",\n      \"profile\": \"https://github.com/robertvolkmann\",\n      \"contributions\": [\n        \"code\",\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"bipin-k\",\n      \"name\": \"Bipin Kumar Chaurasia\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/21119358?v=4\",\n      \"profile\": \"https://github.com/bipin-k\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"KyleSong30\",\n      \"name\": \"KyleSong30\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/100892032?v=4\",\n      \"profile\": \"https://github.com/KyleSong30\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"u7281975\",\n      \"name\": \"u7281975\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/111095623?v=4\",\n      \"profile\": \"https://github.com/u7281975\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"harshalkhachane\",\n      \"name\": \"harshalkhachane\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/92866584?v=4\",\n      \"profile\": \"https://github.com/harshalkhachane\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ec-026\",\n      \"name\": \"Tejas Singh\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/95495584?v=4\",\n      \"profile\": \"https://github.com/ec-026\",\n      \"contributions\": [\n        \"doc\",\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"artfuldev\",\n      \"name\": \"Sudarsan Balaji\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/3091087?v=4\",\n      \"profile\": \"https://journal.artfuldev.com\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"vaibhav-if\",\n      \"name\": \"Vaibhav Agrawal\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/78676331?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/vaibhav-agr/\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"u7275858\",\n      \"name\": \"u7275858\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/110969489?v=4\",\n      \"profile\": \"https://github.com/u7275858\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"prasad-333\",\n      \"name\": \"prasad-333\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/37048768?v=4\",\n      \"profile\": \"https://gist.github.com/prasad-333\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"JurenXu\",\n      \"name\": \"JurenXu\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/101047547?v=4\",\n      \"profile\": \"https://github.com/JurenXu\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"murphShaw\",\n      \"name\": \"murphShaw\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/111167533?v=4\",\n      \"profile\": \"https://github.com/murphShaw\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"XianWu99\",\n      \"name\": \"XianWu99\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/111103319?v=4\",\n      \"profile\": \"https://github.com/XianWu99\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"JoshuaSinglaANU\",\n      \"name\": \"JoshuaSinglaANU\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/109902734?v=4\",\n      \"profile\": \"https://github.com/JoshuaSinglaANU\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ricardo-ramos-moura\",\n      \"name\": \"Ricardo Ramos\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/36955909?v=4\",\n      \"profile\": \"http://www.linkedin.com/in/ricardo-ramos-moura\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"zhrfrd\",\n      \"name\": \"Farid Zouheir\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/72947724?v=4\",\n      \"profile\": \"https://zhrfrd.github.io/faridzouheir/\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Viniberaldo\",\n      \"name\": \"Vinícius A. B.\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/91766068?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/vinicius-beraldo/\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"StefanelStan\",\n      \"name\": \"Stefanel Stan\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/25990078?v=4\",\n      \"profile\": \"http://www.linkedin.com/in/stefanel-stan/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"bhati00\",\n      \"name\": \"Prince bhati\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/79313705?v=4\",\n      \"profile\": \"https://github.com/bhati00\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"wulangcode\",\n      \"name\": \"WuLang\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/48200100?v=4\",\n      \"profile\": \"https://github.com/wulangcode\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"hkattt\",\n      \"name\": \"Hugo Kat\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/54300585?v=4\",\n      \"profile\": \"https://github.com/hkattt\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"shivu2002a\",\n      \"name\": \"Shivanagouda Agasimani\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/88313126?v=4\",\n      \"profile\": \"https://github.com/shivu2002a\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Ap284\",\n      \"name\": \"Aparna\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/13827254?v=4\",\n      \"profile\": \"https://github.com/Ap284\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"girolamo-giordano\",\n      \"name\": \"Girolamo Giordano\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/56109364?v=4\",\n      \"profile\": \"https://github.com/girolamo-giordano\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Chak-C\",\n      \"name\": \"Chak-C\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/114961815?v=4\",\n      \"profile\": \"https://github.com/Chak-C\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"nakul251197\",\n      \"name\": \"Nakul Nambiar\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/39953357?v=4\",\n      \"profile\": \"https://github.com/nakul251197\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"KarmaTashiCat\",\n      \"name\": \"KarmaTashiCat\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/76797146?v=4\",\n      \"profile\": \"https://github.com/KarmaTashiCat\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Marikattt\",\n      \"name\": \"marikattt\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/49302558?v=4\",\n      \"profile\": \"https://github.com/Marikattt\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Harsh4902\",\n      \"name\": \"Hashvardhan Parmar\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/84663071?v=4\",\n      \"profile\": \"https://github.com/Harsh4902\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"yongyongkr\",\n      \"name\": \"YongHwan\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/67625677?v=4\",\n      \"profile\": \"https://hwan33.tistory.com/\",\n      \"contributions\": [\n        \"doc\",\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"shogohida\",\n      \"name\": \"Shogo Hida\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/10365357?v=4\",\n      \"profile\": \"https://github.com/shogohida\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Regyl\",\n      \"name\": \"Eugene\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/48804404?v=4\",\n      \"profile\": \"https://github.com/Regyl\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"piyush280599\",\n      \"name\": \"Piyush\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/118425491?v=4\",\n      \"profile\": \"https://github.com/piyush280599\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"rahul-raj\",\n      \"name\": \"Rahul Raj\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/517415?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/rahulraj90/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"bharathkalyans\",\n      \"name\": \"Bharath Kalyan S\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/49526472?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/bharathkalyans/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"saiteja55\",\n      \"name\": \"Saiteja Reddy\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/13088886?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/thisissaiteja/\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"TheClerici\",\n      \"name\": \"Enrique Clerici\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/115318468?v=4\",\n      \"profile\": \"http://twitch.tv/clerici\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"ramilS\",\n      \"name\": \"Ramil Sayetov\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/13589365?v=4\",\n      \"profile\": \"https://github.com/ramilS\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"pikapiu\",\n      \"name\": \"东方未白\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/50656114?v=4\",\n      \"profile\": \"https://pkq.xyz\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"swashb0ckler\",\n      \"name\": \"Fredrik Sejr\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/62488841?v=4\",\n      \"profile\": \"https://github.com/swashb0ckler\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"akshatarora0013\",\n      \"name\": \"akshatarora0013\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/102645021?v=4\",\n      \"profile\": \"https://github.com/akshatarora0013\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"MugheesQasim\",\n      \"name\": \"Mughees Qasim\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/45170085?v=4\",\n      \"profile\": \"https://mugheesqasimmq.wixsite.com/portfolio-website\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"behappyleee\",\n      \"name\": \"behappyleee\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/72903623?v=4\",\n      \"profile\": \"https://github.com/behappyleee\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Ayush-Thakur-geek\",\n      \"name\": \"Ayush Thakur\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/116510022?v=4\",\n      \"profile\": \"https://github.com/Ayush-Thakur-geek\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"boscha1\",\n      \"name\": \"Anthony Bosch\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/55814237?v=4\",\n      \"profile\": \"https://github.com/boscha1\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"AnsonTran\",\n      \"name\": \"trananso\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/37683428?v=4\",\n      \"profile\": \"https://github.com/AnsonTran\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"beef-e\",\n      \"name\": \"Giammaria Biffi\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/102854627?v=4\",\n      \"profile\": \"https://github.com/beef-e\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"saif7159\",\n      \"name\": \"Saiful Haque\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/36008396?v=4\",\n      \"profile\": \"https://github.com/saif7159\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"JabezBrew\",\n      \"name\": \"JabezBrew\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/74483609?v=4\",\n      \"profile\": \"https://github.com/JabezBrew\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"konstantin-goldman\",\n      \"name\": \"konstantin-goldman\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/47669472?v=4\",\n      \"profile\": \"https://github.com/konstantin-goldman\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"tiennm99\",\n      \"name\": \"Tien Nguyen Minh\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/39063457?v=4\",\n      \"profile\": \"https://github.com/tiennm99\",\n      \"contributions\": [\n        \"code\",\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"VladimirCreator\",\n      \"name\": \"Vladimir\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/49140851?v=4\",\n      \"profile\": \"https://github.com/VladimirCreator\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"surjendu104\",\n      \"name\": \"Surjendu\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/101238933?v=4\",\n      \"profile\": \"https://surjendu-pal.netlify.app/\",\n      \"contributions\": [\n        \"translation\",\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"bakazhou\",\n      \"name\": \"bakazhou\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/81795984?v=4\",\n      \"profile\": \"https://github.com/bakazhou\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Owen-CH-Leung\",\n      \"name\": \"Owen Leung\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/43698890?v=4\",\n      \"profile\": \"https://github.com/Owen-CH-Leung\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"thestbar\",\n      \"name\": \"Stavros Barousis\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/20283468?v=4\",\n      \"profile\": \"https://github.com/thestbar\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"ibrahim89\",\n      \"name\": \"Syyed Ibrahim Abdullah\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/20753671?v=4\",\n      \"profile\": \"https://github.com/ibrahim89\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"JanisZhang\",\n      \"name\": \"JiaDi Zhang\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/95570096?v=4\",\n      \"profile\": \"https://github.com/JanisZhang\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"sanchitbansal10\",\n      \"name\": \"Sanchit Bansal\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/16536741?v=4\",\n      \"profile\": \"https://github.com/sanchitbansal10\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"mm-saiful6854\",\n      \"name\": \"Md Saiful Islam\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/48361160?v=4\",\n      \"profile\": \"https://github.com/mm-saiful6854\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"AddeusExMachina\",\n      \"name\": \"Antonio Addeo\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/39912670?v=4\",\n      \"profile\": \"https://github.com/AddeusExMachina\",\n      \"contributions\": [\n        \"doc\",\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Upendra-Allagadda\",\n      \"name\": \"Allagadda Sai Upendranath\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/25962010?v=4\",\n      \"profile\": \"https://github.com/Upendra-Allagadda\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"mathbraga\",\n      \"name\": \"Matheus Braga\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/31048764?v=4\",\n      \"profile\": \"https://www.linkedin.com/in/mobraga/\",\n      \"contributions\": [\n        \"translation\",\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"satyabarghav\",\n      \"name\": \"Appari Satya Barghav\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/36763910?v=4\",\n      \"profile\": \"https://github.com/satyabarghav\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"mribeirodantas\",\n      \"name\": \"Marcel Ribeiro-Dantas\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1023197?v=4\",\n      \"profile\": \"http://mribeirodantas.me\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"hamexhanif\",\n      \"name\": \"Muhammad Hanif Amrullah\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/74542852?v=4\",\n      \"profile\": \"https://github.com/hamexhanif\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"JackH408\",\n      \"name\": \"JackH408\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/141727294?v=4\",\n      \"profile\": \"https://github.com/JackH408\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"versus2004\",\n      \"name\": \"Shubham\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/132815243?v=4\",\n      \"profile\": \"https://github.com/versus2004\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"inishantjain\",\n      \"name\": \"Nishant Jain\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/121454072?v=4\",\n      \"profile\": \"https://github.com/inishantjain\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"hallowshaw\",\n      \"name\": \"Rhitam Chaudhury\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/90751158?v=4\",\n      \"profile\": \"https://github.com/hallowshaw\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"JerryZhao275\",\n      \"name\": \"JerryZhao275\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/132061401?v=4\",\n      \"profile\": \"https://github.com/JerryZhao275\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"leonardol\",\n      \"name\": \"Leonardo Lisanti\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/1445890?v=4\",\n      \"profile\": \"https://twitter.com/llisant\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Yenniferh\",\n      \"name\": \"Yennifer Herrera\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/19285706?v=4\",\n      \"profile\": \"http://www.linkedin.com/in/yenniferh\",\n      \"contributions\": [\n        \"translation\",\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"jnniu-n\",\n      \"name\": \"jnniu-n\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/141746282?v=4\",\n      \"profile\": \"https://github.com/jnniu-n\",\n      \"contributions\": [\n        \"translation\",\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"miguel-is-coding\",\n      \"name\": \"Miguel Angel Perez Garcia\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/48435117?v=4\",\n      \"profile\": \"https://github.com/miguel-is-coding\",\n      \"contributions\": [\n        \"review\",\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"SuwanSankaja\",\n      \"name\": \"Suwan Sankaja\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/86839778?v=4\",\n      \"profile\": \"https://github.com/SuwanSankaja\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Iamalok007\",\n      \"name\": \"alok\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/97467835?v=4\",\n      \"profile\": \"https://github.com/Iamalok007\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"dlvideira\",\n      \"name\": \"Daniel Lisboa\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/53951425?v=4\",\n      \"profile\": \"https://github.com/dlvideira\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"ComplexOW\",\n      \"name\": \"Sam Powell\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/105279107?v=4\",\n      \"profile\": \"https://github.com/ComplexOW\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"jppf22\",\n      \"name\": \"João Fernandes\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/104360594?v=4\",\n      \"profile\": \"https://github.com/jppf22\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"HongGeonUi\",\n      \"name\": \"Hong Geon-ui\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/89684956?v=4\",\n      \"profile\": \"https://github.com/HongGeonUi\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"ylcn91\",\n      \"name\": \"Doksanbir\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/7249450?v=4\",\n      \"profile\": \"https://github.com/ylcn91\",\n      \"contributions\": [\n        \"code\",\n        \"doc\",\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"Chant3ll3\",\n      \"name\": \"Chant3ll3\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/141697333?v=4\",\n      \"profile\": \"https://github.com/Chant3ll3\",\n      \"contributions\": [\n        \"doc\",\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"hwan33\",\n      \"name\": \"YongHwan Kwon\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/67625677?v=4\",\n      \"profile\": \"https://hwan33.tistory.com/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"takikuba\",\n      \"name\": \"Jakub Klimek\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/58841343?v=4\",\n      \"profile\": \"https://github.com/takikuba\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"bachbil\",\n      \"name\": \"believe\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/28935461?v=4\",\n      \"profile\": \"https://github.com/bachbil\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"egg0102030405\",\n      \"name\": \"egg0102030405\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/59650695?v=4\",\n      \"profile\": \"https://github.com/egg0102030405\",\n      \"contributions\": [\n        \"translation\",\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"ved-asole\",\n      \"name\": \"Ved Asole\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/77259804?v=4\",\n      \"profile\": \"http://vedasole.cloud\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Holiday-C\",\n      \"name\": \"NewMorning\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/95869761?v=4\",\n      \"profile\": \"https://github.com/Holiday-C\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Kiro-Young\",\n      \"name\": \"资深老萌新\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/98251397?v=4\",\n      \"profile\": \"https://github.com/Kiro-Young\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Nickolodeon98\",\n      \"name\": \"Seunghwan Jeon\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/113348293?v=4\",\n      \"profile\": \"https://itistori.tistory.com/\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"sugan0tech\",\n      \"name\": \"sugavanesh\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/71312159?v=4\",\n      \"profile\": \"https://github.com/sugan0tech\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"FinnS-F\",\n      \"name\": \"FinnS-F\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/126026830?v=4\",\n      \"profile\": \"https://github.com/FinnS-F\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"jerryyummy\",\n      \"name\": \"jerryyummy\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/62087610?v=4\",\n      \"profile\": \"https://github.com/jerryyummy\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Manojkumarchow\",\n      \"name\": \"Manoj Chowdary\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/28005510?v=4\",\n      \"profile\": \"https://manojkumarchow.github.io/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"MaverickWingman\",\n      \"name\": \"Aditya\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/76624290?v=4\",\n      \"profile\": \"https://github.com/MaverickWingman\",\n      \"contributions\": [\n        \"doc\",\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"nooynayr\",\n      \"name\": \"nooynayr\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/141696269?v=4\",\n      \"profile\": \"https://github.com/nooynayr\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"pushpander1010\",\n      \"name\": \"CYBERCRUX2\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/41006191?v=4\",\n      \"profile\": \"https://github.com/pushpander1010\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"luismateoh\",\n      \"name\": \"Luis Mateo Hincapié Martinez\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/44934142?v=4\",\n      \"profile\": \"https://github.com/luismateoh\",\n      \"contributions\": [\n        \"translation\",\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"guqing\",\n      \"name\": \"guqing\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/38999863?v=4\",\n      \"profile\": \"https://guqing.io\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"sashirestela\",\n      \"name\": \"Sashir Estela\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/14045506?v=4\",\n      \"profile\": \"https://github.com/sashirestela\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"omahs\",\n      \"name\": \"omahs\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/73983677?v=4\",\n      \"profile\": \"https://github.com/omahs\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"leiferksn\",\n      \"name\": \"leif e.\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/4026636?v=4\",\n      \"profile\": \"https://github.com/leiferksn\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"junhkang\",\n      \"name\": \"Jun Kang\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/20232155?v=4\",\n      \"profile\": \"https://junhkang.tistory.com/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"KishalayP\",\n      \"name\": \"Kishalay Pandey\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/71012321?v=4\",\n      \"profile\": \"https://github.com/KishalayP\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"drishtii7\",\n      \"name\": \"drishtii7\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/82076566?v=4\",\n      \"profile\": \"https://github.com/drishtii7\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"DavidMedinaO\",\n      \"name\": \"David Medina Orozco\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/53974843?v=4\",\n      \"profile\": \"https://github.com/DavidMedinaO\",\n      \"contributions\": [\n        \"translation\",\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"Romo4ka-bot\",\n      \"name\": \"Roman Leontev\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/61774094?v=4\",\n      \"profile\": \"https://github.com/Romo4ka-bot\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Ehspresso\",\n      \"name\": \"Riley\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/144370752?v=4\",\n      \"profile\": \"https://github.com/Ehspresso\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"k1w1dev\",\n      \"name\": \"k1w1dev\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/121696782?v=4\",\n      \"profile\": \"https://github.com/k1w1dev\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"dev-yugantar\",\n      \"name\": \"dev-yugantar\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/153066190?v=4\",\n      \"profile\": \"https://github.com/dev-yugantar\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Adelechka\",\n      \"name\": \"Adelya\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/65678470?v=4\",\n      \"profile\": \"https://github.com/Adelechka\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"gatlanagaprasanna\",\n      \"name\": \"gatlanagaprasanna\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/154739216?v=4\",\n      \"profile\": \"https://github.com/gatlanagaprasanna\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"Avinash2110\",\n      \"name\": \"Avinash Shukla\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/37360069?v=4\",\n      \"profile\": \"https://github.com/Avinash2110\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Mayankchoudhary294\",\n      \"name\": \"Mayank Choudhary\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/97609699?v=4\",\n      \"profile\": \"https://github.com/Mayankchoudhary294\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"romannimets\",\n      \"name\": \"romannimets\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/137268574?v=4\",\n      \"profile\": \"https://github.com/romannimets\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Joel-Dandin\",\n      \"name\": \"Joel\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/60149879?v=4\",\n      \"profile\": \"https://github.com/Joel-Dandin\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"244Walyson\",\n      \"name\": \"Walyson Moises\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/125759796?v=4\",\n      \"profile\": \"https://github.com/244Walyson\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Xcyq\",\n      \"name\": \"Xcyq\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/39086666?v=4\",\n      \"profile\": \"https://github.com/Xcyq\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Ritabrata1080\",\n      \"name\": \"Ritabrata\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/60834250?v=4\",\n      \"profile\": \"https://github.com/Ritabrata1080\",\n      \"contributions\": [\n        \"review\"\n      ]\n    },\n    {\n      \"login\": \"trivikr\",\n      \"name\": \"Trivikram Kamat\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/16024985?v=4\",\n      \"profile\": \"https://github.com/trivikr\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"vvanghelle\",\n      \"name\": \"Vincent Vanghelle\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/3204600?v=4\",\n      \"profile\": \"https://github.com/vvanghelle\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"antoheri\",\n      \"name\": \"Antoine Héritier\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/79988396?v=4\",\n      \"profile\": \"https://github.com/antoheri\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"fishandsheep\",\n      \"name\": \"QinShower\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/43347407?v=4\",\n      \"profile\": \"https://github.com/fishandsheep\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"LakshyaPunyani-01\",\n      \"name\": \"LakshyaPunyani-01\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/103628913?v=4\",\n      \"profile\": \"https://github.com/LakshyaPunyani-01\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"jasonjyu\",\n      \"name\": \"jasonjyu\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/10333076?v=4\",\n      \"profile\": \"https://github.com/jasonjyu\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"jeffmorrison\",\n      \"name\": \"jeffmorrison\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/26047158?v=4\",\n      \"profile\": \"https://github.com/jeffmorrison\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"dmgodoy\",\n      \"name\": \"David M.\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/10840681?v=4\",\n      \"profile\": \"https://github.com/dmgodoy\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"apophizzz\",\n      \"name\": \"Patrick Kleindienst\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/12052783?v=4\",\n      \"profile\": \"https://github.com/apophizzz\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"proceane\",\n      \"name\": \"Juyeon\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/62143949?v=4\",\n      \"profile\": \"https://github.com/proceane\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"mammadyahyayev\",\n      \"name\": \"Mammad Yahyayev\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/66476643?v=4\",\n      \"profile\": \"https://mammadyahya.vercel.app\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"SalmaAzeem\",\n      \"name\": \"Salma\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/121863224?v=4\",\n      \"profile\": \"https://github.com/SalmaAzeem\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"CodeMaverick-143\",\n      \"name\": \"Arpit Sarang\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/182847716?v=4\",\n      \"profile\": \"https://codemaverick-143.github.io/My-Portfolio/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"mayatarek\",\n      \"name\": \"Maya\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/111644421?v=4\",\n      \"profile\": \"https://github.com/mayatarek\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"HabibaMekay\",\n      \"name\": \"HabibaMekay\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/133516736?v=4\",\n      \"profile\": \"https://github.com/HabibaMekay\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Ahmed-Taha-981\",\n      \"name\": \"Ahmed-Taha-981\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/122402269?v=4\",\n      \"profile\": \"https://github.com/Ahmed-Taha-981\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"malak-elbanna\",\n      \"name\": \"Malak Elbanna\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/67643605?v=4\",\n      \"profile\": \"https://malakelbanna.netlify.app/\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"depthlending\",\n      \"name\": \"BiKangNing\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/164312726?v=4\",\n      \"profile\": \"https://github.com/depthlending\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"TarunVishwakarma1\",\n      \"name\": \"Tarun Vishwakarma\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/138651451?v=4\",\n      \"profile\": \"https://github.com/TarunVishwakarma1\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"shahdhoss\",\n      \"name\": \"Shahd Hossam\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/132148556?v=4\",\n      \"profile\": \"https://github.com/shahdhoss\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"mehdirahimi\",\n      \"name\": \"Mehdi Rahimi\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/24210842?v=4\",\n      \"profile\": \"https://mehdirahimi.github.io\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"clintaire\",\n      \"name\": \"Clint Airé\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/111376518?v=4\",\n      \"profile\": \"https://github.com/clintaire\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"darkhyper24\",\n      \"name\": \"darkhyper24\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/132711528?v=4\",\n      \"profile\": \"https://github.com/darkhyper24\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"MohanedAtef238\",\n      \"name\": \"Mohaned Atef\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/105852138?v=4\",\n      \"profile\": \"https://github.com/MohanedAtef238\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"maximevtush\",\n      \"name\": \"Maxim Evtush\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/154841002?v=4\",\n      \"profile\": \"https://github.com/maximevtush\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"hvgh88\",\n      \"name\": \"Harshita Vidapanakal\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/65297242?v=4\",\n      \"profile\": \"https://github.com/hvgh88\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"smile-ab\",\n      \"name\": \"smile-ab\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/202159894?v=4\",\n      \"profile\": \"https://github.com/smile-ab\",\n      \"contributions\": [\n        \"translation\",\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Francisco-G-P\",\n      \"name\": \"Francisco-G-P\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/186766789?v=4\",\n      \"profile\": \"https://github.com/Francisco-G-P\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"Duartegdm\",\n      \"name\": \"Gabriel Duarte\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/137895372?v=4\",\n      \"profile\": \"https://github.com/Duartegdm\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"DenizAltunkapan\",\n      \"name\": \"Deniz Altunkapan\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/93663085?v=4\",\n      \"profile\": \"https://github.com/DenizAltunkapan\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"johnklint81\",\n      \"name\": \"John Klint\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/70539458?v=4\",\n      \"profile\": \"https://github.com/johnklint81\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"sanurah\",\n      \"name\": \"Sanura Hettiarachchi\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/16178588?v=4\",\n      \"profile\": \"https://github.com/sanurah\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"2897robo\",\n      \"name\": \"Kim Gi Uk\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/31699375?v=4\",\n      \"profile\": \"https://github.com/2897robo\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Suchismita-Deb\",\n      \"name\": \"Suchismita Deb\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/68535074?v=4\",\n      \"profile\": \"https://github.com/Suchismita-Deb\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ssrijan-007-sys\",\n      \"name\": \"ssrijan-007-sys\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/137605821?v=4\",\n      \"profile\": \"https://github.com/ssrijan-007-sys\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"e5LA\",\n      \"name\": \"e5LA\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/208197507?v=4\",\n      \"profile\": \"https://github.com/e5LA\",\n      \"contributions\": [\n        \"code\",\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"maziyar-gerami\",\n      \"name\": \"Maziyar Gerami\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/122622721?v=4\",\n      \"profile\": \"http://maziyar-gerami.github.io/portfolio/\",\n      \"contributions\": [\n        \"translation\"\n      ]\n    },\n    {\n      \"login\": \"yybmion\",\n      \"name\": \"yoobin_mion\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/113106136?v=4\",\n      \"profile\": \"https://github.com/yybmion\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"ronodhirSoumik\",\n      \"name\": \"Soumik Sarker\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/46843689?v=4\",\n      \"profile\": \"https://ronodhirsoumik.github.io\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    },\n    {\n      \"login\": \"naman-sriv\",\n      \"name\": \"Naman Srivastava\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/82610773?v=4\",\n      \"profile\": \"https://github.com/naman-sriv\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"letdtcode\",\n      \"name\": \"Thanh Nguyen Duc\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/92111552?v=4\",\n      \"profile\": \"https://github.com/letdtcode\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"skamble2\",\n      \"name\": \"Soham Kamble\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/121136639?v=4\",\n      \"profile\": \"https://github.com/skamble2\",\n      \"contributions\": [\n        \"code\"\n      ]\n    },\n    {\n      \"login\": \"Olexandr88\",\n      \"name\": \"Olexandr88\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/93856062?v=4\",\n      \"profile\": \"https://github.com/Olexandr88\",\n      \"contributions\": [\n        \"doc\"\n      ]\n    }\n  ],\n  \"contributorsPerLine\": 6,\n  \"projectName\": \"java-design-patterns\",\n  \"projectOwner\": \"iluwatar\",\n  \"repoType\": \"github\",\n  \"repoHost\": \"https://github.com\",\n  \"skipCi\": true,\n  \"commitConvention\": \"angular\",\n  \"commitType\": \"docs\"\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "#\n# This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n#\n# The MIT License\n# Copyright © 2014-2022 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nroot = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_size = 4\nindent_style = space\ninsert_final_newline = false\nmax_line_length = off\ntab_width = 4\nij_continuation_indent_size = 8\nij_formatter_off_tag = @formatter:off\nij_formatter_on_tag = @formatter:on\nij_formatter_tags_enabled = true\nij_smart_tabs = false\nij_visual_guides = \nij_wrap_on_typing = false\n\n[*.java]\nindent_size = 2\nmax_line_length = 100\nij_continuation_indent_size = 4\nij_java_align_consecutive_assignments = false\nij_java_align_consecutive_variable_declarations = false\nij_java_align_group_field_declarations = false\nij_java_align_multiline_annotation_parameters = false\nij_java_align_multiline_array_initializer_expression = false\nij_java_align_multiline_assignment = false\nij_java_align_multiline_binary_operation = false\nij_java_align_multiline_chained_methods = false\nij_java_align_multiline_deconstruction_list_components = true\nij_java_align_multiline_extends_list = false\nij_java_align_multiline_for = true\nij_java_align_multiline_method_parentheses = false\nij_java_align_multiline_parameters = true\nij_java_align_multiline_parameters_in_calls = false\nij_java_align_multiline_parenthesized_expression = false\nij_java_align_multiline_records = true\nij_java_align_multiline_resources = true\nij_java_align_multiline_ternary_operation = false\nij_java_align_multiline_text_blocks = false\nij_java_align_multiline_throws_list = false\nij_java_align_subsequent_simple_methods = false\nij_java_align_throws_keyword = false\nij_java_align_types_in_multi_catch = true\nij_java_annotation_parameter_wrap = off\nij_java_array_initializer_new_line_after_left_brace = false\nij_java_array_initializer_right_brace_on_new_line = false\nij_java_array_initializer_wrap = normal\nij_java_assert_statement_colon_on_next_line = false\nij_java_assert_statement_wrap = normal\nij_java_assignment_wrap = normal\nij_java_binary_operation_sign_on_next_line = false\nij_java_binary_operation_wrap = normal\nij_java_blank_lines_after_anonymous_class_header = 0\nij_java_blank_lines_after_class_header = 0\nij_java_blank_lines_after_imports = 1\nij_java_blank_lines_after_package = 1\nij_java_blank_lines_around_class = 1\nij_java_blank_lines_around_field = 0\nij_java_blank_lines_around_field_in_interface = 0\nij_java_blank_lines_around_initializer = 1\nij_java_blank_lines_around_method = 1\nij_java_blank_lines_around_method_in_interface = 1\nij_java_blank_lines_before_class_end = 0\nij_java_blank_lines_before_imports = 1\nij_java_blank_lines_before_method_body = 0\nij_java_blank_lines_before_package = 1\nij_java_block_brace_style = end_of_line\nij_java_block_comment_add_space = false\nij_java_block_comment_at_first_column = true\nij_java_builder_methods = \nij_java_call_parameters_new_line_after_left_paren = false\nij_java_call_parameters_right_paren_on_new_line = false\nij_java_call_parameters_wrap = normal\nij_java_case_statement_on_separate_line = true\nij_java_catch_on_new_line = false\nij_java_class_annotation_wrap = split_into_lines\nij_java_class_brace_style = end_of_line\nij_java_class_count_to_use_import_on_demand = 999\nij_java_class_names_in_javadoc = 1\nij_java_deconstruction_list_wrap = normal\nij_java_do_not_indent_top_level_class_members = false\nij_java_do_not_wrap_after_single_annotation = false\nij_java_do_not_wrap_after_single_annotation_in_parameter = false\nij_java_do_while_brace_force = always\nij_java_doc_add_blank_line_after_description = true\nij_java_doc_add_blank_line_after_param_comments = false\nij_java_doc_add_blank_line_after_return = false\nij_java_doc_add_p_tag_on_empty_lines = true\nij_java_doc_align_exception_comments = true\nij_java_doc_align_param_comments = true\nij_java_doc_do_not_wrap_if_one_line = false\nij_java_doc_enable_formatting = true\nij_java_doc_enable_leading_asterisks = true\nij_java_doc_indent_on_continuation = false\nij_java_doc_keep_empty_lines = true\nij_java_doc_keep_empty_parameter_tag = true\nij_java_doc_keep_empty_return_tag = true\nij_java_doc_keep_empty_throws_tag = true\nij_java_doc_keep_invalid_tags = true\nij_java_doc_param_description_on_new_line = false\nij_java_doc_preserve_line_breaks = false\nij_java_doc_use_throws_not_exception_tag = true\nij_java_else_on_new_line = false\nij_java_entity_dd_prefix = \nij_java_entity_dd_suffix = EJB\nij_java_entity_eb_prefix = \nij_java_entity_eb_suffix = Bean\nij_java_entity_hi_prefix = \nij_java_entity_hi_suffix = Home\nij_java_entity_lhi_prefix = Local\nij_java_entity_lhi_suffix = Home\nij_java_entity_li_prefix = Local\nij_java_entity_li_suffix = \nij_java_entity_pk_class = java.lang.String\nij_java_entity_ri_prefix = \nij_java_entity_ri_suffix = \nij_java_entity_vo_prefix = \nij_java_entity_vo_suffix = VO\nij_java_enum_constants_wrap = normal\nij_java_extends_keyword_wrap = normal\nij_java_extends_list_wrap = normal\nij_java_field_annotation_wrap = split_into_lines\nij_java_field_name_prefix = \nij_java_field_name_suffix = \nij_java_filter_class_prefix = \nij_java_filter_class_suffix = \nij_java_filter_dd_prefix = \nij_java_filter_dd_suffix = \nij_java_finally_on_new_line = false\nij_java_for_brace_force = always\nij_java_for_statement_new_line_after_left_paren = false\nij_java_for_statement_right_paren_on_new_line = false\nij_java_for_statement_wrap = normal\nij_java_generate_final_locals = false\nij_java_generate_final_parameters = false\nij_java_if_brace_force = always\nij_java_imports_layout = $*,|,*\nij_java_indent_case_from_switch = true\nij_java_insert_inner_class_imports = false\nij_java_insert_override_annotation = true\nij_java_keep_blank_lines_before_right_brace = 2\nij_java_keep_blank_lines_between_package_declaration_and_header = 2\nij_java_keep_blank_lines_in_code = 2\nij_java_keep_blank_lines_in_declarations = 2\nij_java_keep_builder_methods_indents = false\nij_java_keep_control_statement_in_one_line = true\nij_java_keep_first_column_comment = true\nij_java_keep_indents_on_empty_lines = false\nij_java_keep_line_breaks = true\nij_java_keep_multiple_expressions_in_one_line = false\nij_java_keep_simple_blocks_in_one_line = false\nij_java_keep_simple_classes_in_one_line = false\nij_java_keep_simple_lambdas_in_one_line = false\nij_java_keep_simple_methods_in_one_line = false\nij_java_label_indent_absolute = false\nij_java_label_indent_size = 0\nij_java_lambda_brace_style = end_of_line\nij_java_layout_static_imports_separately = true\nij_java_line_comment_add_space = false\nij_java_line_comment_add_space_on_reformat = false\nij_java_line_comment_at_first_column = true\nij_java_listener_class_prefix = \nij_java_listener_class_suffix = \nij_java_local_variable_name_prefix = \nij_java_local_variable_name_suffix = \nij_java_message_dd_prefix = \nij_java_message_dd_suffix = EJB\nij_java_message_eb_prefix = \nij_java_message_eb_suffix = Bean\nij_java_method_annotation_wrap = split_into_lines\nij_java_method_brace_style = end_of_line\nij_java_method_call_chain_wrap = normal\nij_java_method_parameters_new_line_after_left_paren = false\nij_java_method_parameters_right_paren_on_new_line = false\nij_java_method_parameters_wrap = normal\nij_java_modifier_list_wrap = false\nij_java_multi_catch_types_wrap = normal\nij_java_names_count_to_use_import_on_demand = 999\nij_java_new_line_after_lparen_in_annotation = false\nij_java_new_line_after_lparen_in_deconstruction_pattern = true\nij_java_new_line_after_lparen_in_record_header = false\nij_java_packages_to_use_import_on_demand = \nij_java_parameter_annotation_wrap = normal\nij_java_parameter_name_prefix = \nij_java_parameter_name_suffix = \nij_java_parentheses_expression_new_line_after_left_paren = false\nij_java_parentheses_expression_right_paren_on_new_line = false\nij_java_place_assignment_sign_on_next_line = false\nij_java_prefer_longer_names = true\nij_java_prefer_parameters_wrap = false\nij_java_record_components_wrap = normal\nij_java_repeat_annotations = \nij_java_repeat_synchronized = true\nij_java_replace_instanceof_and_cast = false\nij_java_replace_null_check = true\nij_java_replace_sum_lambda_with_method_ref = true\nij_java_resource_list_new_line_after_left_paren = false\nij_java_resource_list_right_paren_on_new_line = false\nij_java_resource_list_wrap = normal\nij_java_rparen_on_new_line_in_annotation = false\nij_java_rparen_on_new_line_in_deconstruction_pattern = true\nij_java_rparen_on_new_line_in_record_header = false\nij_java_servlet_class_prefix = \nij_java_servlet_class_suffix = \nij_java_servlet_dd_prefix = \nij_java_servlet_dd_suffix = \nij_java_session_dd_prefix = \nij_java_session_dd_suffix = EJB\nij_java_session_eb_prefix = \nij_java_session_eb_suffix = Bean\nij_java_session_hi_prefix = \nij_java_session_hi_suffix = Home\nij_java_session_lhi_prefix = Local\nij_java_session_lhi_suffix = Home\nij_java_session_li_prefix = Local\nij_java_session_li_suffix = \nij_java_session_ri_prefix = \nij_java_session_ri_suffix = \nij_java_session_si_prefix = \nij_java_session_si_suffix = Service\nij_java_space_after_closing_angle_bracket_in_type_argument = false\nij_java_space_after_colon = true\nij_java_space_after_comma = true\nij_java_space_after_comma_in_type_arguments = true\nij_java_space_after_for_semicolon = true\nij_java_space_after_quest = true\nij_java_space_after_type_cast = true\nij_java_space_before_annotation_array_initializer_left_brace = false\nij_java_space_before_annotation_parameter_list = false\nij_java_space_before_array_initializer_left_brace = true\nij_java_space_before_catch_keyword = true\nij_java_space_before_catch_left_brace = true\nij_java_space_before_catch_parentheses = true\nij_java_space_before_class_left_brace = true\nij_java_space_before_colon = true\nij_java_space_before_colon_in_foreach = true\nij_java_space_before_comma = false\nij_java_space_before_deconstruction_list = false\nij_java_space_before_do_left_brace = true\nij_java_space_before_else_keyword = true\nij_java_space_before_else_left_brace = true\nij_java_space_before_finally_keyword = true\nij_java_space_before_finally_left_brace = true\nij_java_space_before_for_left_brace = true\nij_java_space_before_for_parentheses = true\nij_java_space_before_for_semicolon = false\nij_java_space_before_if_left_brace = true\nij_java_space_before_if_parentheses = true\nij_java_space_before_method_call_parentheses = false\nij_java_space_before_method_left_brace = true\nij_java_space_before_method_parentheses = false\nij_java_space_before_opening_angle_bracket_in_type_parameter = false\nij_java_space_before_quest = true\nij_java_space_before_switch_left_brace = true\nij_java_space_before_switch_parentheses = true\nij_java_space_before_synchronized_left_brace = true\nij_java_space_before_synchronized_parentheses = true\nij_java_space_before_try_left_brace = true\nij_java_space_before_try_parentheses = true\nij_java_space_before_type_parameter_list = false\nij_java_space_before_while_keyword = true\nij_java_space_before_while_left_brace = true\nij_java_space_before_while_parentheses = true\nij_java_space_inside_one_line_enum_braces = false\nij_java_space_within_empty_array_initializer_braces = false\nij_java_space_within_empty_method_call_parentheses = false\nij_java_space_within_empty_method_parentheses = false\nij_java_spaces_around_additive_operators = true\nij_java_spaces_around_annotation_eq = true\nij_java_spaces_around_assignment_operators = true\nij_java_spaces_around_bitwise_operators = true\nij_java_spaces_around_equality_operators = true\nij_java_spaces_around_lambda_arrow = true\nij_java_spaces_around_logical_operators = true\nij_java_spaces_around_method_ref_dbl_colon = false\nij_java_spaces_around_multiplicative_operators = true\nij_java_spaces_around_relational_operators = true\nij_java_spaces_around_shift_operators = true\nij_java_spaces_around_type_bounds_in_type_parameters = true\nij_java_spaces_around_unary_operator = false\nij_java_spaces_within_angle_brackets = false\nij_java_spaces_within_annotation_parentheses = false\nij_java_spaces_within_array_initializer_braces = false\nij_java_spaces_within_braces = false\nij_java_spaces_within_brackets = false\nij_java_spaces_within_cast_parentheses = false\nij_java_spaces_within_catch_parentheses = false\nij_java_spaces_within_deconstruction_list = false\nij_java_spaces_within_for_parentheses = false\nij_java_spaces_within_if_parentheses = false\nij_java_spaces_within_method_call_parentheses = false\nij_java_spaces_within_method_parentheses = false\nij_java_spaces_within_parentheses = false\nij_java_spaces_within_record_header = false\nij_java_spaces_within_switch_parentheses = false\nij_java_spaces_within_synchronized_parentheses = false\nij_java_spaces_within_try_parentheses = false\nij_java_spaces_within_while_parentheses = false\nij_java_special_else_if_treatment = true\nij_java_static_field_name_prefix = \nij_java_static_field_name_suffix = \nij_java_subclass_name_prefix = \nij_java_subclass_name_suffix = Impl\nij_java_ternary_operation_signs_on_next_line = false\nij_java_ternary_operation_wrap = normal\nij_java_test_name_prefix = \nij_java_test_name_suffix = Test\nij_java_throws_keyword_wrap = normal\nij_java_throws_list_wrap = normal\nij_java_use_external_annotations = false\nij_java_use_fq_class_names = false\nij_java_use_relative_indents = false\nij_java_use_single_class_imports = true\nij_java_variable_annotation_wrap = normal\nij_java_visibility = public\nij_java_while_brace_force = always\nij_java_while_on_new_line = false\nij_java_wrap_comments = false\nij_java_wrap_first_method_in_call_chain = false\nij_java_wrap_long_lines = false\n\n[{*.markdown,*.md}]\nij_markdown_force_one_space_after_blockquote_symbol = true\nij_markdown_force_one_space_after_header_symbol = true\nij_markdown_force_one_space_after_list_bullet = true\nij_markdown_force_one_space_between_words = true\nij_markdown_format_tables = true\nij_markdown_insert_quote_arrows_on_wrap = true\nij_markdown_keep_indents_on_empty_lines = false\nij_markdown_keep_line_breaks_inside_text_blocks = true\nij_markdown_max_line_length = off\nij_markdown_max_lines_around_block_elements = 1\nij_markdown_max_lines_around_header = 1\nij_markdown_max_lines_between_paragraphs = 1\nij_markdown_min_lines_around_block_elements = 1\nij_markdown_min_lines_around_header = 1\nij_markdown_min_lines_between_paragraphs = 1\nij_markdown_wrap_text_if_long = true\nij_markdown_wrap_text_inside_blockquotes = true\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [iluwatar]\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where the package manifests are located.\n# Please see the documentation for all configuration options:\n# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates\n\nversion: 2\nupdates:\n  - package-ecosystem: \"maven\" # See documentation for possible values\n    directory: \"/\" # Location of package manifests\n    schedule:\n      interval: \"weekly\""
  },
  {
    "path": ".github/workflows/maven-ci.yml",
    "content": "name: Java CI\n\non:\n  push:\n    branches: [ master ]\n\njobs:\n\n  build-and-analyze:\n\n    name: Build and Run Sonar analysis on JDK 21\n    runs-on: ubuntu-22.04\n    steps:\n\n      - name: Checkout Code\n        uses: actions/checkout@v4\n        with:\n          # Disabling shallow clone for improving relevancy of SonarQube reporting\n          fetch-depth: 0\n\n      - name: Set up JDK 21\n        uses: actions/setup-java@v4\n        with:\n          java-version: '21'\n          distribution: 'temurin'\n          cache: 'maven'\n\n      - name: Cache local Maven repository\n        uses: actions/cache@v4\n        with:\n          path: ~/.m2/repository\n          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}\n          restore-keys: |\n            ${{ runner.os }}-maven-\n\n      # Cache Sonar packages which are used to run analysis and collect metrics\n      - name: Cache SonarCloud packages\n        uses: actions/cache@v4\n        with:\n          path: ~/.sonar/cache\n          key: ${{ runner.os }}-sonar\n          restore-keys: ${{ runner.os }}-sonar\n\n      # Some tests need screen access\n      - name: Install xvfb\n        run: sudo apt-get install -y xvfb\n\n      - name: Build with Maven and run SonarQube analysis\n        run: xvfb-run ./mvnw clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar\n        env:\n          # These two env variables are needed for sonar analysis\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}"
  },
  {
    "path": ".github/workflows/maven-pr-builder.yml",
    "content": "name: Java PR Builder\n\non:\n  pull_request_target:\n    branches: [ master ]\n    types: [ opened, reopened, synchronize ]\n\npermissions:\n  contents: read\n\njobs:\n  build-and-analyze:\n\n    name: Build on JDK 21\n    runs-on: ubuntu-22.04\n    steps:\n\n      - name: Checkout Code\n        uses: actions/checkout@v4\n        with:\n          ref: ${{ github.event.pull_request.head.sha }}\n\n      - name: Set up JDK 21\n        uses: actions/setup-java@v4\n        with:\n          java-version: '21'\n          distribution: 'temurin'\n          cache: 'maven'\n\n      - name: Cache local Maven repository\n        uses: actions/cache@v4\n        with:\n          path: ~/.m2/repository\n          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}\n          restore-keys: |\n            ${{ runner.os }}-maven-      \n\n      # Cache Sonar packages which are used to run analysis and collect metrics\n      - name: Cache SonarCloud packages\n        uses: actions/cache@v4\n        with:\n          path: ~/.sonar/cache\n          key: ${{ runner.os }}-sonar\n          restore-keys: ${{ runner.os }}-sonar\n\n      # Some tests need screen access\n      - name: Install xvfb\n        run: sudo apt-get install -y xvfb\n\n      - name: Build with Maven and run SonarQube analysis\n        env:\n          # Intermediate variable\n          HEAD_REF: ${{ github.head_ref }}\n          # These two env variables are needed for sonar analysis\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}\n        run: xvfb-run ./mvnw clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=iluwatar -Dsonar.projectKey=iluwatar_java-design-patterns -Dsonar.pullrequest.branch=$HEAD_REF -Dsonar.pullrequest.base=${{ github.base_ref }} -Dsonar.pullrequest.key=${{ github.event.pull_request.number }}"
  },
  {
    "path": ".github/workflows/presubmit.yml",
    "content": "name: Presubmit.ai\n\npermissions:\n    contents: read\n    pull-requests: write\n    issues: write\n\non:\n    pull_request_target:\n        types: [opened, synchronize]\n    pull_request_review_comment:\n        types: [created]\n\njobs:\n    review:\n        runs-on: ubuntu-latest\n        steps:\n            - name: Check required secrets\n              run: |\n                  if [ -z \"${{ secrets.LLM_API_KEY }}\" ]; then\n                    echo \"Error: LLM_API_KEY secret is not configured\"\n                    exit 1\n                  fi\n            - uses: presubmit/ai-reviewer@latest\n              env:\n                  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n                  LLM_API_KEY: ${{ secrets.LLM_API_KEY }}\n                  LLM_MODEL: \"gpt-5-nano\""
  },
  {
    "path": ".github/workflows/stale.yml",
    "content": "name: 'Comment on stale issues and PRs'\non:\n  schedule:\n    - cron: '30 1 * * *'\n\njobs:\n  stale:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/stale@v9\n        with:\n          stale-issue-message: 'This issue is stale because it has been open 60 days with no activity.'\n          stale-pr-message: 'This PR is stale because it has been open 60 days with no activity.'\n          close-issue-message: 'This issue was closed because it has been stalled for too long with no activity.'\n          close-pr-message: 'This PR was closed because it has been stalled for too long with no activity.'\n          days-before-issue-stale: 60\n          days-before-pr-stale: 60\n          days-before-issue-close: -1\n          days-before-pr-close: -1\n          exempt-issue-labels: 'info: help wanted'\n"
  },
  {
    "path": ".gitignore",
    "content": "################## Eclipse ######################\ntarget\n.metadata\n.settings\n.classpath\n.project\n*.class\ntmp/\n*.tmp\n*.bak\n*~.nib\nlocal.properties\n.loadpath\n.recommenders\n.DS_Store\n\n#######  Java annotation processor (APT) ########\n.factorypath\n\n################ Package Files ##################\n*.jar\n*.war\n*.ear\n*.swp\ndatanucleus.log\n/bin/\n*.log\nevent-sourcing/Journal.json\n\n################## Checkstyle ###################\n.checkstyle\n\n##################### STS #######################\n.apt_generated\n.springBeans\n.sts4-cache\n\n################# IntelliJ IDEA #################\n.idea\n*.iws\n*.iml\n*.ipr\n\n################### NetBeans ####################\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\nbuild/\n!**/src/main/**/build/\n!**/src/test/**/build/\n\n#################### VS Code ####################\n.vscode/\n\n#################### Java Design Patterns #######\netc/Java Design Patterns.urm.puml\nserialized-entity/output.txt\nfish1.out\nfish2.out\n"
  },
  {
    "path": ".mvn/wrapper/maven-wrapper.properties",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\ndistributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip\nwrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar\n"
  },
  {
    "path": "CONTRIBUTING.MD",
    "content": "The project guidelines can be found in [Java Design Patterns developer wiki](https://github.com/iluwatar/java-design-patterns/wiki). \n\nA good place to start is: https://github.com/iluwatar/java-design-patterns/wiki/01.-How-to-contribute\n"
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright � 2014-2024 Ilkka Seppälä\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\nModule Model-view-viewmodel is using ZK framework\nZK framework is licensed under LGPL and the license can be found at lgpl-3.0.txt\n"
  },
  {
    "path": "PULL_REQUEST_TEMPLATE.md",
    "content": "# Pull Request Template\n\n## What does this PR do?\n\n<!-- Provide a short description of what this pull request does. -->\n\n<!-- Fixes #<issue-number> (if applicable) -->\n"
  },
  {
    "path": "README.md",
    "content": "# Design Patterns Implemented in Java\n\n[![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)](https://github.com/iluwatar/java-design-patterns/actions/workflows/maven-ci.yml)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-392-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n<br/>\n\nRead in different language : [**zh**](localization/zh/README.md), [**ko**](localization/ko/README.md), [**fr**](localization/fr/README.md), [**tr**](localization/tr/README.md), [**ar**](localization/ar/README.md), [**es**](localization/es/README.md), [**pt**](localization/pt/README.md), [**id**](localization/id/README.md), [**ru**](localization/ru/README.md), [**de**](localization/de/README.md), [**ja**](localization/ja/README.md), [**vi**](localization/vi/README.md), [**bn**](localization/bn/README.md), [**np**](localization/ne/README.md), [**it**](localization/it/README.md), [**da**](localization/da/README.md)\n<br/>\n\n# Introduction\n\nDesign patterns are the best, formalized practices a programmer can use to solve common problems when designing an application or system.\n\nDesign patterns can speed up the development process by providing tested, proven development paradigms.\n\nReusing design patterns helps prevent subtle issues that cause major problems, and it also improves code readability for coders and architects who are familiar with the patterns.\n\n# Getting Started\n\nThis site showcases Java Design Patterns. The solutions have been developed by experienced programmers and architects from the open-source community. The patterns can be browsed by their high-level descriptions or by looking at their\nsource code. The source code examples are well commented and can be thought of as programming tutorials on how to implement a specific pattern. We use the most popular battle-proven open-source Java technologies.\n\nBefore you dive into the material, you should be familiar with various [Software Design Principles](https://java-design-patterns.com/principles/).\n\nAll designs should be as simple as possible. You should start with KISS, YAGNI, and Do The Simplest Thing That Could Possibly Work principles. Complexity and patterns should only be introduced when they are needed for practical extensibility.\n\nOnce you are familiar with these concepts you can start drilling down into the [available design patterns](https://java-design-patterns.com/patterns/) by any of the following approaches:\n\n - Search for a specific pattern by name. Can't find one? Please report a new pattern [here](https://github.com/iluwatar/java-design-patterns/issues).\n - Using tags such as `Performance`, `Gang of Four` or `Data access`.\n - Using pattern categories, `Creational`, `Behavioral`, and others.\n\nHopefully, you find the object-oriented solutions presented on this site useful in your architectures and have as much fun learning them as we had while developing them.\n\n# How to Contribute\n\nIf you are willing to contribute to the project you will find the relevant information in our [developer wiki](https://github.com/iluwatar/java-design-patterns/wiki). We will help you and answer your questions in the [Gitter chatroom](https://gitter.im/iluwatar/java-design-patterns).\n\n# The Book\n\nThe design patterns are now available as an e-book. Find out more about \"Open Source Java Design Patterns\" here: https://payhip.com/b/bNQFX\n\nThe project contributors can get the book for free. Contact the maintainer via [Gitter chatroom](https://gitter.im/iluwatar/java-design-patterns) or email (iluwatar (at) gmail (dot) com ). Send a message that contains your email address, Github username, and a link to an accepted pull request.\n\n# License\n\nThis project is licensed under the terms of the MIT license.\n\n# Contributors\n\n<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->\n<!-- prettier-ignore-start -->\n<!-- markdownlint-disable -->\n<table>\n  <tbody>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/iluwatar\"><img src=\"https://avatars1.githubusercontent.com/u/582346?v=4?s=100\" width=\"100px;\" alt=\"Ilkka Seppälä\"/><br /><sub><b>Ilkka Seppälä</b></sub></a><br /><a href=\"#projectManagement-iluwatar\" title=\"Project Management\">📆</a> <a href=\"#maintenance-iluwatar\" title=\"Maintenance\">🚧</a> <a href=\"#content-iluwatar\" title=\"Content\">🖋</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://subho.xyz\"><img src=\"https://avatars0.githubusercontent.com/u/13291222?v=4?s=100\" width=\"100px;\" alt=\"Subhrodip Mohanta\"/><br /><sub><b>Subhrodip Mohanta</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ohbus\" title=\"Code\">💻</a> <a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Aohbus\" title=\"Reviewed Pull Requests\">👀</a> <a href=\"#maintenance-ohbus\" title=\"Maintenance\">🚧</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/amit1307\"><img src=\"https://avatars0.githubusercontent.com/u/23420222?v=4?s=100\" width=\"100px;\" alt=\"amit1307\"/><br /><sub><b>amit1307</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=amit1307\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/npathai\"><img src=\"https://avatars2.githubusercontent.com/u/1792515?v=4?s=100\" width=\"100px;\" alt=\"Narendra Pathai\"/><br /><sub><b>Narendra Pathai</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=npathai\" title=\"Code\">💻</a> <a href=\"#ideas-npathai\" title=\"Ideas, Planning, & Feedback\">🤔</a> <a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Anpathai\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/fluxw42\"><img src=\"https://avatars1.githubusercontent.com/u/1545460?v=4?s=100\" width=\"100px;\" alt=\"Jeroen Meulemeester\"/><br /><sub><b>Jeroen Meulemeester</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=fluxw42\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://www.joemccarthy.co.uk\"><img src=\"https://avatars0.githubusercontent.com/u/4526195?v=4?s=100\" width=\"100px;\" alt=\"Joseph McCarthy\"/><br /><sub><b>Joseph McCarthy</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=mikulucky\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/thomasoss\"><img src=\"https://avatars1.githubusercontent.com/u/22516154?v=4?s=100\" width=\"100px;\" alt=\"Thomas\"/><br /><sub><b>Thomas</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=thomasoss\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/anuragagarwal561994\"><img src=\"https://avatars1.githubusercontent.com/u/6075379?v=4?s=100\" width=\"100px;\" alt=\"Anurag Agarwal\"/><br /><sub><b>Anurag Agarwal</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=anuragagarwal561994\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://markusmo3.github.io\"><img src=\"https://avatars1.githubusercontent.com/u/3317416?v=4?s=100\" width=\"100px;\" alt=\"Markus Moser\"/><br /><sub><b>Markus Moser</b></sub></a><br /><a href=\"#design-markusmo3\" title=\"Design\">🎨</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=markusmo3\" title=\"Code\">💻</a> <a href=\"#ideas-markusmo3\" title=\"Ideas, Planning, & Feedback\">🤔</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://twitter.com/i_sabiq\"><img src=\"https://avatars1.githubusercontent.com/u/19510920?v=4?s=100\" width=\"100px;\" alt=\"Sabiq Ihab\"/><br /><sub><b>Sabiq Ihab</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=isabiq\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://inbravo.github.io\"><img src=\"https://avatars3.githubusercontent.com/u/5253764?v=4?s=100\" width=\"100px;\" alt=\"Amit Dixit\"/><br /><sub><b>Amit Dixit</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=inbravo\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/piyushchaudhari04\"><img src=\"https://avatars3.githubusercontent.com/u/10268029?v=4?s=100\" width=\"100px;\" alt=\"Piyush Kailash Chaudhari\"/><br /><sub><b>Piyush Kailash Chaudhari</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=piyushchaudhari04\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/joshzambales\"><img src=\"https://avatars1.githubusercontent.com/u/8704552?v=4?s=100\" width=\"100px;\" alt=\"joshzambales\"/><br /><sub><b>joshzambales</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=joshzambales\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Crossy147\"><img src=\"https://avatars2.githubusercontent.com/u/7272996?v=4?s=100\" width=\"100px;\" alt=\"Kamil Pietruszka\"/><br /><sub><b>Kamil Pietruszka</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Crossy147\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://cs.joensuu.fi/~zkhayda\"><img src=\"https://avatars2.githubusercontent.com/u/660742?v=4?s=100\" width=\"100px;\" alt=\"Zafar Khaydarov\"/><br /><sub><b>Zafar Khaydarov</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=zafarella\" title=\"Code\">💻</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=zafarella\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://kemitix.github.io/\"><img src=\"https://avatars1.githubusercontent.com/u/1147749?v=4?s=100\" width=\"100px;\" alt=\"Paul Campbell\"/><br /><sub><b>Paul Campbell</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=kemitix\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Argyro-Sioziou\"><img src=\"https://avatars0.githubusercontent.com/u/22822639?v=4?s=100\" width=\"100px;\" alt=\"Argyro Sioziou\"/><br /><sub><b>Argyro Sioziou</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Argyro-Sioziou\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/TylerMcConville\"><img src=\"https://avatars0.githubusercontent.com/u/4946449?v=4?s=100\" width=\"100px;\" alt=\"TylerMcConville\"/><br /><sub><b>TylerMcConville</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=TylerMcConville\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/saksham93\"><img src=\"https://avatars1.githubusercontent.com/u/37399540?v=4?s=100\" width=\"100px;\" alt=\"saksham93\"/><br /><sub><b>saksham93</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=saksham93\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/nikhilbarar\"><img src=\"https://avatars2.githubusercontent.com/u/37332144?v=4?s=100\" width=\"100px;\" alt=\"nikhilbarar\"/><br /><sub><b>nikhilbarar</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=nikhilbarar\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://colinbut.com\"><img src=\"https://avatars2.githubusercontent.com/u/10725674?v=4?s=100\" width=\"100px;\" alt=\"Colin But\"/><br /><sub><b>Colin But</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=colinbut\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ruslanpa\"><img src=\"https://avatars2.githubusercontent.com/u/1503411?v=4?s=100\" width=\"100px;\" alt=\"Ruslan\"/><br /><sub><b>Ruslan</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ruslanpa\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/JuhoKang\"><img src=\"https://avatars1.githubusercontent.com/u/4745294?v=4?s=100\" width=\"100px;\" alt=\"Juho Kang\"/><br /><sub><b>Juho Kang</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=JuhoKang\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/dheeraj-mummareddy\"><img src=\"https://avatars2.githubusercontent.com/u/7002230?v=4?s=100\" width=\"100px;\" alt=\"Dheeraj Mummareddy\"/><br /><sub><b>Dheeraj Mummareddy</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=dheeraj-mummareddy\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.bernardosulzbach.com\"><img src=\"https://avatars0.githubusercontent.com/u/8271090?v=4?s=100\" width=\"100px;\" alt=\"Bernardo Sulzbach\"/><br /><sub><b>Bernardo Sulzbach</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=bernardosulzbach\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/4lexis\"><img src=\"https://avatars0.githubusercontent.com/u/19871727?v=4?s=100\" width=\"100px;\" alt=\"Aleksandar Dudukovic\"/><br /><sub><b>Aleksandar Dudukovic</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=4lexis\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.yusufaytas.com\"><img src=\"https://avatars2.githubusercontent.com/u/1049483?v=4?s=100\" width=\"100px;\" alt=\"Yusuf Aytaş\"/><br /><sub><b>Yusuf Aytaş</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=yusufaytas\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://futurehomes.hu\"><img src=\"https://avatars2.githubusercontent.com/u/1001491?v=4?s=100\" width=\"100px;\" alt=\"Mihály Kuprivecz\"/><br /><sub><b>Mihály Kuprivecz</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=qpi\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/kapinuss\"><img src=\"https://avatars0.githubusercontent.com/u/17639945?v=4?s=100\" width=\"100px;\" alt=\"Stanislav Kapinus\"/><br /><sub><b>Stanislav Kapinus</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=kapinuss\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/gvsharma\"><img src=\"https://avatars1.githubusercontent.com/u/6648152?v=4?s=100\" width=\"100px;\" alt=\"GVSharma\"/><br /><sub><b>GVSharma</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=gvsharma\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/SrdjanPaunovic\"><img src=\"https://avatars1.githubusercontent.com/u/22815104?v=4?s=100\" width=\"100px;\" alt=\"Srđan Paunović\"/><br /><sub><b>Srđan Paunović</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=SrdjanPaunovic\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://sideris.xyz/\"><img src=\"https://avatars3.githubusercontent.com/u/5484694?v=4?s=100\" width=\"100px;\" alt=\"Petros G. Sideris\"/><br /><sub><b>Petros G. Sideris</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=sideris\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/pramodgupta3/\"><img src=\"https://avatars1.githubusercontent.com/u/2184241?v=4?s=100\" width=\"100px;\" alt=\"Pramod Gupta\"/><br /><sub><b>Pramod Gupta</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AIAmPramod\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://amarnath510.github.io/portfolio\"><img src=\"https://avatars0.githubusercontent.com/u/4599623?v=4?s=100\" width=\"100px;\" alt=\"Amarnath Chandana\"/><br /><sub><b>Amarnath Chandana</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Amarnath510\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Anurag870\"><img src=\"https://avatars1.githubusercontent.com/u/6295975?v=4?s=100\" width=\"100px;\" alt=\"Anurag870\"/><br /><sub><b>Anurag870</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Anurag870\" title=\"Code\">💻</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Anurag870\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://theerroris.me\"><img src=\"https://avatars0.githubusercontent.com/u/1685953?v=4?s=100\" width=\"100px;\" alt=\"Wes Gilleland\"/><br /><sub><b>Wes Gilleland</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Deathnerd\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Harshrajsinh\"><img src=\"https://avatars2.githubusercontent.com/u/22811531?v=4?s=100\" width=\"100px;\" alt=\"Harshraj Thakor\"/><br /><sub><b>Harshraj Thakor</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Harshrajsinh\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/MaVdbussche\"><img src=\"https://avatars1.githubusercontent.com/u/26136934?v=4?s=100\" width=\"100px;\" alt=\"Martin Vandenbussche\"/><br /><sub><b>Martin Vandenbussche</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=MaVdbussche\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://alexsomai.com\"><img src=\"https://avatars1.githubusercontent.com/u/5720977?v=4?s=100\" width=\"100px;\" alt=\"Alexandru Somai\"/><br /><sub><b>Alexandru Somai</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=alexsomai\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/amogozov\"><img src=\"https://avatars3.githubusercontent.com/u/7372215?v=4?s=100\" width=\"100px;\" alt=\"Artur Mogozov\"/><br /><sub><b>Artur Mogozov</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=amogozov\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/anthonycampbell\"><img src=\"https://avatars3.githubusercontent.com/u/10249255?v=4?s=100\" width=\"100px;\" alt=\"anthony\"/><br /><sub><b>anthony</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=anthonycampbell\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://ccygnus.com/\"><img src=\"https://avatars1.githubusercontent.com/u/9342724?v=4?s=100\" width=\"100px;\" alt=\"Christian Cygnus\"/><br /><sub><b>Christian Cygnus</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=christophercolumbusdog\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://about.me/dzmitryh\"><img src=\"https://avatars2.githubusercontent.com/u/5390492?v=4?s=100\" width=\"100px;\" alt=\"Dima Gubin\"/><br /><sub><b>Dima Gubin</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=dzmitryh\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/jjjimenez100\"><img src=\"https://avatars3.githubusercontent.com/u/22243493?v=4?s=100\" width=\"100px;\" alt=\"Joshua Jimenez\"/><br /><sub><b>Joshua Jimenez</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=jjjimenez100\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://about.me/kaiwinter\"><img src=\"https://avatars0.githubusercontent.com/u/110982?v=4?s=100\" width=\"100px;\" alt=\"Kai Winter\"/><br /><sub><b>Kai Winter</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=kaiwinter\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/lbroman\"><img src=\"https://avatars1.githubusercontent.com/u/86007?v=4?s=100\" width=\"100px;\" alt=\"lbroman\"/><br /><sub><b>lbroman</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=lbroman\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://przemeknowak.com\"><img src=\"https://avatars1.githubusercontent.com/u/3254609?v=4?s=100\" width=\"100px;\" alt=\"Przemek\"/><br /><sub><b>Przemek</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=pnowy\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/prafful1\"><img src=\"https://avatars0.githubusercontent.com/u/14350274?v=4?s=100\" width=\"100px;\" alt=\"Prafful Agarwal\"/><br /><sub><b>Prafful Agarwal</b></sub></a><br /><a href=\"#content-prafful1\" title=\"Content\">🖋</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/sankypanhale\"><img src=\"https://avatars1.githubusercontent.com/u/6478783?v=4?s=100\" width=\"100px;\" alt=\"Sanket Panhale\"/><br /><sub><b>Sanket Panhale</b></sub></a><br /><a href=\"#content-sankypanhale\" title=\"Content\">🖋</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/staillebois\"><img src=\"https://avatars0.githubusercontent.com/u/23701200?v=4?s=100\" width=\"100px;\" alt=\"staillebois\"/><br /><sub><b>staillebois</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=staillebois\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/valdar-hu\"><img src=\"https://avatars3.githubusercontent.com/u/17962817?v=4?s=100\" width=\"100px;\" alt=\"Krisztián Nagy\"/><br /><sub><b>Krisztián Nagy</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=valdar-hu\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.vanogrid.com\"><img src=\"https://avatars0.githubusercontent.com/u/4307918?v=4?s=100\" width=\"100px;\" alt=\"Alexander Ivanov\"/><br /><sub><b>Alexander Ivanov</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=vanogrid\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/yosfik\"><img src=\"https://avatars3.githubusercontent.com/u/4850270?v=4?s=100\" width=\"100px;\" alt=\"Yosfik Alqadri\"/><br /><sub><b>Yosfik Alqadri</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=yosfik\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/7agustibm\"><img src=\"https://avatars0.githubusercontent.com/u/8149332?v=4?s=100\" width=\"100px;\" alt=\"Agustí Becerra Milà\"/><br /><sub><b>Agustí Becerra Milà</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=7agustibm\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Juaanma\"><img src=\"https://avatars3.githubusercontent.com/u/7390500?v=4?s=100\" width=\"100px;\" alt=\"Juan Manuel Suárez\"/><br /><sub><b>Juan Manuel Suárez</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Juaanma\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://www.devsedge.net/\"><img src=\"https://avatars0.githubusercontent.com/u/9956006?v=4?s=100\" width=\"100px;\" alt=\"Luigi Cortese\"/><br /><sub><b>Luigi Cortese</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=LuigiCortese\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Rzeposlaw\"><img src=\"https://avatars2.githubusercontent.com/u/18425745?v=4?s=100\" width=\"100px;\" alt=\"Katarzyna Rzepecka\"/><br /><sub><b>Katarzyna Rzepecka</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Rzeposlaw\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://adamski.pro\"><img src=\"https://avatars1.githubusercontent.com/u/6537430?v=4?s=100\" width=\"100px;\" alt=\"adamski.pro\"/><br /><sub><b>adamski.pro</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=akrystian\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/baislsl\"><img src=\"https://avatars0.githubusercontent.com/u/17060584?v=4?s=100\" width=\"100px;\" alt=\"Shengli Bai\"/><br /><sub><b>Shengli Bai</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=baislsl\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/besok\"><img src=\"https://avatars2.githubusercontent.com/u/29834592?v=4?s=100\" width=\"100px;\" alt=\"Boris\"/><br /><sub><b>Boris</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=besok\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/dmitraver\"><img src=\"https://avatars3.githubusercontent.com/u/1798156?v=4?s=100\" width=\"100px;\" alt=\"Dmitry Avershin\"/><br /><sub><b>Dmitry Avershin</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=dmitraver\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/fanofxiaofeng\"><img src=\"https://avatars0.githubusercontent.com/u/3983683?v=4?s=100\" width=\"100px;\" alt=\"靳阳\"/><br /><sub><b>靳阳</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=fanofxiaofeng\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/hoangnam2261\"><img src=\"https://avatars2.githubusercontent.com/u/31692990?v=4?s=100\" width=\"100px;\" alt=\"hoangnam2261\"/><br /><sub><b>hoangnam2261</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=hoangnam2261\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/jarpit96\"><img src=\"https://avatars2.githubusercontent.com/u/10098713?v=4?s=100\" width=\"100px;\" alt=\"Arpit Jain\"/><br /><sub><b>Arpit Jain</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=jarpit96\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://joningi.net\"><img src=\"https://avatars2.githubusercontent.com/u/6115148?v=4?s=100\" width=\"100px;\" alt=\"Jón Ingi Sveinbjörnsson\"/><br /><sub><b>Jón Ingi Sveinbjörnsson</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=joningiwork\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/kirill-vlasov\"><img src=\"https://avatars3.githubusercontent.com/u/16112495?v=4?s=100\" width=\"100px;\" alt=\"Kirill Vlasov\"/><br /><sub><b>Kirill Vlasov</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=kirill-vlasov\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://mitchell-irvin.com\"><img src=\"https://avatars0.githubusercontent.com/u/16233245?v=4?s=100\" width=\"100px;\" alt=\"Mitchell Irvin\"/><br /><sub><b>Mitchell Irvin</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=mitchellirvin\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://ranjeet-floyd.github.io\"><img src=\"https://avatars0.githubusercontent.com/u/1992972?v=4?s=100\" width=\"100px;\" alt=\"Ranjeet\"/><br /><sub><b>Ranjeet</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ranjeet-floyd\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://alwayswithme.github.io\"><img src=\"https://avatars3.githubusercontent.com/u/3234786?v=4?s=100\" width=\"100px;\" alt=\"PhoenixYip\"/><br /><sub><b>PhoenixYip</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Alwayswithme\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/MSaifAsif\"><img src=\"https://avatars1.githubusercontent.com/u/6280554?v=4?s=100\" width=\"100px;\" alt=\"M Saif Asif\"/><br /><sub><b>M Saif Asif</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=MSaifAsif\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/kanwarpreet25\"><img src=\"https://avatars0.githubusercontent.com/u/39183641?v=4?s=100\" width=\"100px;\" alt=\"kanwarpreet25\"/><br /><sub><b>kanwarpreet25</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=kanwarpreet25\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://leonmak.me\"><img src=\"https://avatars3.githubusercontent.com/u/13071508?v=4?s=100\" width=\"100px;\" alt=\"Leon Mak\"/><br /><sub><b>Leon Mak</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=leonmak\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://www.wramdemark.se\"><img src=\"https://avatars2.githubusercontent.com/u/7052193?v=4?s=100\" width=\"100px;\" alt=\"Per Wramdemark\"/><br /><sub><b>Per Wramdemark</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=perwramdemark\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/waisuan\"><img src=\"https://avatars2.githubusercontent.com/u/10975700?v=4?s=100\" width=\"100px;\" alt=\"Evan Sia Wai Suan\"/><br /><sub><b>Evan Sia Wai Suan</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=waisuan\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/AnaghaSasikumar\"><img src=\"https://avatars2.githubusercontent.com/u/42939261?v=4?s=100\" width=\"100px;\" alt=\"AnaghaSasikumar\"/><br /><sub><b>AnaghaSasikumar</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=AnaghaSasikumar\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://christofferh.com\"><img src=\"https://avatars1.githubusercontent.com/u/767643?v=4?s=100\" width=\"100px;\" alt=\"Christoffer Hamberg\"/><br /><sub><b>Christoffer Hamberg</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=christofferh\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/dgruntz\"><img src=\"https://avatars0.githubusercontent.com/u/1516800?v=4?s=100\" width=\"100px;\" alt=\"Dominik Gruntz\"/><br /><sub><b>Dominik Gruntz</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=dgruntz\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://bitbucket.org/hannespernpeintner/\"><img src=\"https://avatars3.githubusercontent.com/u/1679437?v=4?s=100\" width=\"100px;\" alt=\"Hannes\"/><br /><sub><b>Hannes</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=hannespernpeintner\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/leogtzr\"><img src=\"https://avatars0.githubusercontent.com/u/1211969?v=4?s=100\" width=\"100px;\" alt=\"Leo Gutiérrez Ramírez\"/><br /><sub><b>Leo Gutiérrez Ramírez</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=leogtzr\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/npczwh\"><img src=\"https://avatars0.githubusercontent.com/u/14066422?v=4?s=100\" width=\"100px;\" alt=\"Zhang WH\"/><br /><sub><b>Zhang WH</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=npczwh\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/oconnelc\"><img src=\"https://avatars0.githubusercontent.com/u/1112973?v=4?s=100\" width=\"100px;\" alt=\"Christopher O'Connell\"/><br /><sub><b>Christopher O'Connell</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=oconnelc\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/giorgosmav21\"><img src=\"https://avatars2.githubusercontent.com/u/22855493?v=4?s=100\" width=\"100px;\" alt=\"George Mavroeidis\"/><br /><sub><b>George Mavroeidis</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=giorgosmav21\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/hbothra15\"><img src=\"https://avatars1.githubusercontent.com/u/7418012?v=4?s=100\" width=\"100px;\" alt=\"Hemant Bothra\"/><br /><sub><b>Hemant Bothra</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=hbothra15\" title=\"Code\">💻</a> <a href=\"#design-hbothra15\" title=\"Design\">🎨</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.kevinpeters.net/about/\"><img src=\"https://avatars1.githubusercontent.com/u/12736734?v=4?s=100\" width=\"100px;\" alt=\"Kevin Peters\"/><br /><sub><b>Kevin Peters</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=igeligel\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://llorllale.github.io/\"><img src=\"https://avatars1.githubusercontent.com/u/2019896?v=4?s=100\" width=\"100px;\" alt=\"George Aristy\"/><br /><sub><b>George Aristy</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=llorllale\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/mookkiah\"><img src=\"https://avatars1.githubusercontent.com/u/8975264?v=4?s=100\" width=\"100px;\" alt=\"Mahendran Mookkiah\"/><br /><sub><b>Mahendran Mookkiah</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=mookkiah\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Azureyjt\"><img src=\"https://avatars2.githubusercontent.com/u/18476317?v=4?s=100\" width=\"100px;\" alt=\"Azureyjt\"/><br /><sub><b>Azureyjt</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Azureyjt\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/vehpsr\"><img src=\"https://avatars2.githubusercontent.com/u/3133265?v=4?s=100\" width=\"100px;\" alt=\"gans\"/><br /><sub><b>gans</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=vehpsr\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ThatGuyWithTheHat\"><img src=\"https://avatars0.githubusercontent.com/u/24470582?v=4?s=100\" width=\"100px;\" alt=\"Matt\"/><br /><sub><b>Matt</b></sub></a><br /><a href=\"#content-ThatGuyWithTheHat\" title=\"Content\">🖋</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/gopinathlangote/\"><img src=\"https://avatars2.githubusercontent.com/u/10210778?v=4?s=100\" width=\"100px;\" alt=\"Gopinath Langote\"/><br /><sub><b>Gopinath Langote</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=gopinath-langote\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/hoswey\"><img src=\"https://avatars3.githubusercontent.com/u/3689445?v=4?s=100\" width=\"100px;\" alt=\"Hoswey\"/><br /><sub><b>Hoswey</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=hoswey\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/amit2103\"><img src=\"https://avatars3.githubusercontent.com/u/7566692?v=4?s=100\" width=\"100px;\" alt=\"Amit Pandey\"/><br /><sub><b>Amit Pandey</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=amit2103\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/gwildor28\"><img src=\"https://avatars0.githubusercontent.com/u/16000365?v=4?s=100\" width=\"100px;\" alt=\"gwildor28\"/><br /><sub><b>gwildor28</b></sub></a><br /><a href=\"#content-gwildor28\" title=\"Content\">🖋</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://t.me/paul_docker\"><img src=\"https://avatars1.githubusercontent.com/u/2404785?v=4?s=100\" width=\"100px;\" alt=\"田浩\"/><br /><sub><b>田浩</b></sub></a><br /><a href=\"#content-llitfkitfk\" title=\"Content\">🖋</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://twitter.com/StPitsios\"><img src=\"https://avatars1.githubusercontent.com/u/6773603?v=4?s=100\" width=\"100px;\" alt=\"Stamatis Pitsios\"/><br /><sub><b>Stamatis Pitsios</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=pitsios-s\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/qza\"><img src=\"https://avatars3.githubusercontent.com/u/233149?v=4?s=100\" width=\"100px;\" alt=\"qza\"/><br /><sub><b>qza</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=qza\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://tschis.github.io\"><img src=\"https://avatars1.githubusercontent.com/u/20662669?v=4?s=100\" width=\"100px;\" alt=\"Rodolfo Forte\"/><br /><sub><b>Rodolfo Forte</b></sub></a><br /><a href=\"#content-Tschis\" title=\"Content\">🖋</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ankurkaushal\"><img src=\"https://avatars2.githubusercontent.com/u/2236616?v=4?s=100\" width=\"100px;\" alt=\"Ankur Kaushal\"/><br /><sub><b>Ankur Kaushal</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ankurkaushal\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/ovidijus-okinskas/\"><img src=\"https://avatars0.githubusercontent.com/u/20372387?v=4?s=100\" width=\"100px;\" alt=\"Ovidijus Okinskas\"/><br /><sub><b>Ovidijus Okinskas</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=okinskas\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/robertt240\"><img src=\"https://avatars1.githubusercontent.com/u/9137432?v=4?s=100\" width=\"100px;\" alt=\"Robert Kasperczyk\"/><br /><sub><b>Robert Kasperczyk</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=robertt240\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/trautonen\"><img src=\"https://avatars3.githubusercontent.com/u/1641063?v=4?s=100\" width=\"100px;\" alt=\"Tapio Rautonen\"/><br /><sub><b>Tapio Rautonen</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=trautonen\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://vk.com/yuri.orlov\"><img src=\"https://avatars0.githubusercontent.com/u/1595733?v=4?s=100\" width=\"100px;\" alt=\"Yuri Orlov\"/><br /><sub><b>Yuri Orlov</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=yorlov\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/varunu28/\"><img src=\"https://avatars0.githubusercontent.com/u/7676016?v=4?s=100\" width=\"100px;\" alt=\"Varun Upadhyay\"/><br /><sub><b>Varun Upadhyay</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=varunu28\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/PalAditya\"><img src=\"https://avatars2.githubusercontent.com/u/25523604?v=4?s=100\" width=\"100px;\" alt=\"Aditya Pal\"/><br /><sub><b>Aditya Pal</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=PalAditya\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/grzesiekkedzior\"><img src=\"https://avatars3.githubusercontent.com/u/23739158?v=4?s=100\" width=\"100px;\" alt=\"grzesiekkedzior\"/><br /><sub><b>grzesiekkedzior</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=grzesiekkedzior\" title=\"Code\">💻</a> <a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Agrzesiekkedzior\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/sivasubramanim\"><img src=\"https://avatars2.githubusercontent.com/u/51107434?v=4?s=100\" width=\"100px;\" alt=\"Sivasubramani M\"/><br /><sub><b>Sivasubramani M</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=sivasubramanim\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/d4gg4d\"><img src=\"https://avatars2.githubusercontent.com/u/99457?v=4?s=100\" width=\"100px;\" alt=\"Sami Airaksinen\"/><br /><sub><b>Sami Airaksinen</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=d4gg4d\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/vertti\"><img src=\"https://avatars0.githubusercontent.com/u/557751?v=4?s=100\" width=\"100px;\" alt=\"Janne Sinivirta\"/><br /><sub><b>Janne Sinivirta</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=vertti\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Bobo1239\"><img src=\"https://avatars1.githubusercontent.com/u/2302947?v=4?s=100\" width=\"100px;\" alt=\"Boris-Chengbiao Zhou\"/><br /><sub><b>Boris-Chengbiao Zhou</b></sub></a><br /><a href=\"#content-Bobo1239\" title=\"Content\">🖋</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://jahhein.github.io\"><img src=\"https://avatars2.githubusercontent.com/u/10779515?v=4?s=100\" width=\"100px;\" alt=\"Jacob Hein\"/><br /><sub><b>Jacob Hein</b></sub></a><br /><a href=\"#content-Jahhein\" title=\"Content\">🖋</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/iamrichardjones\"><img src=\"https://avatars3.githubusercontent.com/u/14842151?v=4?s=100\" width=\"100px;\" alt=\"Richard Jones\"/><br /><sub><b>Richard Jones</b></sub></a><br /><a href=\"#content-iamrichardjones\" title=\"Content\">🖋</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://rachelcarmena.github.io\"><img src=\"https://avatars0.githubusercontent.com/u/22792183?v=4?s=100\" width=\"100px;\" alt=\"Rachel M. Carmena\"/><br /><sub><b>Rachel M. Carmena</b></sub></a><br /><a href=\"#content-rachelcarmena\" title=\"Content\">🖋</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://zd-zero.github.io\"><img src=\"https://avatars0.githubusercontent.com/u/21978370?v=4?s=100\" width=\"100px;\" alt=\"Zaerald Denze Lungos\"/><br /><sub><b>Zaerald Denze Lungos</b></sub></a><br /><a href=\"#content-zd-zero\" title=\"Content\">🖋</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://webpro.nl\"><img src=\"https://avatars1.githubusercontent.com/u/456426?v=4?s=100\" width=\"100px;\" alt=\"Lars Kappert\"/><br /><sub><b>Lars Kappert</b></sub></a><br /><a href=\"#content-webpro\" title=\"Content\">🖋</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://xiaod.info\"><img src=\"https://avatars2.githubusercontent.com/u/21277644?v=4?s=100\" width=\"100px;\" alt=\"Mike Liu\"/><br /><sub><b>Mike Liu</b></sub></a><br /><a href=\"#translation-xiaod-dev\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/charlesfinley\"><img src=\"https://avatars1.githubusercontent.com/u/6307904?v=4?s=100\" width=\"100px;\" alt=\"Matt Dolan\"/><br /><sub><b>Matt Dolan</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=charlesfinley\" title=\"Code\">💻</a> <a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Acharlesfinley\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/MananS77\"><img src=\"https://avatars3.githubusercontent.com/u/21033516?v=4?s=100\" width=\"100px;\" alt=\"Manan\"/><br /><sub><b>Manan</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AMananS77\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/nishant\"><img src=\"https://avatars2.githubusercontent.com/u/15331971?v=4?s=100\" width=\"100px;\" alt=\"Nishant Arora\"/><br /><sub><b>Nishant Arora</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=nishant\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/raja-peeyush-kumar-singh\"><img src=\"https://avatars0.githubusercontent.com/u/5496024?v=4?s=100\" width=\"100px;\" alt=\"Peeyush\"/><br /><sub><b>Peeyush</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=raja-peeyush-kumar-singh\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ravening\"><img src=\"https://avatars1.githubusercontent.com/u/10645273?v=4?s=100\" width=\"100px;\" alt=\"Rakesh\"/><br /><sub><b>Rakesh</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ravening\" title=\"Code\">💻</a> <a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Aravening\" title=\"Reviewed Pull Requests\">👀</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/vINCENT8888801\"><img src=\"https://avatars0.githubusercontent.com/u/8037883?v=4?s=100\" width=\"100px;\" alt=\"Wei Seng\"/><br /><sub><b>Wei Seng</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=vINCENT8888801\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/ashish-trivedi-218379135/\"><img src=\"https://avatars3.githubusercontent.com/u/23194128?v=4?s=100\" width=\"100px;\" alt=\"Ashish Trivedi\"/><br /><sub><b>Ashish Trivedi</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ashishtrivedi16\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://rayyounghong.com\"><img src=\"https://avatars1.githubusercontent.com/u/41055099?v=4?s=100\" width=\"100px;\" alt=\"洪月阳\"/><br /><sub><b>洪月阳</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=RayYH\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://xdvrx1.github.io/\"><img src=\"https://avatars0.githubusercontent.com/u/47092464?v=4?s=100\" width=\"100px;\" alt=\"xdvrx1\"/><br /><sub><b>xdvrx1</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Axdvrx1\" title=\"Reviewed Pull Requests\">👀</a> <a href=\"#ideas-xdvrx1\" title=\"Ideas, Planning, & Feedback\">🤔</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/nahteb\"><img src=\"https://avatars3.githubusercontent.com/u/13121570?v=4?s=100\" width=\"100px;\" alt=\"Bethan Palmer\"/><br /><sub><b>Bethan Palmer</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=nahteb\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ToxicDreamz\"><img src=\"https://avatars0.githubusercontent.com/u/45225562?v=4?s=100\" width=\"100px;\" alt=\"Toxic Dreamz\"/><br /><sub><b>Toxic Dreamz</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ToxicDreamz\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://www.edycutjong.com\"><img src=\"https://avatars1.githubusercontent.com/u/1098102?v=4?s=100\" width=\"100px;\" alt=\"Edy Cu Tjong\"/><br /><sub><b>Edy Cu Tjong</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=edycutjong\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/mkrzywanski\"><img src=\"https://avatars0.githubusercontent.com/u/15279585?v=4?s=100\" width=\"100px;\" alt=\"Michał Krzywański\"/><br /><sub><b>Michał Krzywański</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=mkrzywanski\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.stefan-birkner.de\"><img src=\"https://avatars1.githubusercontent.com/u/711349?v=4?s=100\" width=\"100px;\" alt=\"Stefan Birkner\"/><br /><sub><b>Stefan Birkner</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=stefanbirkner\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/fedorskvorcov\"><img src=\"https://avatars3.githubusercontent.com/u/43882212?v=4?s=100\" width=\"100px;\" alt=\"Fedor Skvorcov\"/><br /><sub><b>Fedor Skvorcov</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=fedorskvorcov\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/samilAyoub\"><img src=\"https://avatars0.githubusercontent.com/u/61546990?v=4?s=100\" width=\"100px;\" alt=\"samilAyoub\"/><br /><sub><b>samilAyoub</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=samilAyoub\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/vdlald\"><img src=\"https://avatars0.githubusercontent.com/u/29997701?v=4?s=100\" width=\"100px;\" alt=\"Vladislav Golubinov\"/><br /><sub><b>Vladislav Golubinov</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=vdlald\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/swarajsaaj\"><img src=\"https://avatars2.githubusercontent.com/u/6285049?v=4?s=100\" width=\"100px;\" alt=\"Swaraj\"/><br /><sub><b>Swaraj</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=swarajsaaj\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://christophflick.de\"><img src=\"https://avatars0.githubusercontent.com/u/4465376?v=4?s=100\" width=\"100px;\" alt=\"Christoph Flick\"/><br /><sub><b>Christoph Flick</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ChFlick\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Ascenio\"><img src=\"https://avatars1.githubusercontent.com/u/7662016?v=4?s=100\" width=\"100px;\" alt=\"Ascênio\"/><br /><sub><b>Ascênio</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AAscenio\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/domenico-sibilio/\"><img src=\"https://avatars2.githubusercontent.com/u/24280982?v=4?s=100\" width=\"100px;\" alt=\"Domenico Sibilio\"/><br /><sub><b>Domenico Sibilio</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=dsibilio\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/akashchandwani\"><img src=\"https://avatars2.githubusercontent.com/u/3483277?v=4?s=100\" width=\"100px;\" alt=\"Akash Chandwani\"/><br /><sub><b>Akash Chandwani</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Aakashchandwani\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://www.linkedin.com/in/manannikov\"><img src=\"https://avatars2.githubusercontent.com/u/7019769?v=4?s=100\" width=\"100px;\" alt=\"Pavlo Manannikov\"/><br /><sub><b>Pavlo Manannikov</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=manannikov\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/eimanip\"><img src=\"https://avatars0.githubusercontent.com/u/20307301?v=4?s=100\" width=\"100px;\" alt=\"Eiman\"/><br /><sub><b>Eiman</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=eimanip\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/OrangePants-R\"><img src=\"https://avatars0.githubusercontent.com/u/42976136?v=4?s=100\" width=\"100px;\" alt=\"Rocky\"/><br /><sub><b>Rocky</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=OrangePants-R\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://ibrahimalii.github.io/\"><img src=\"https://avatars2.githubusercontent.com/u/21141301?v=4?s=100\" width=\"100px;\" alt=\"Ibrahim ali abdelghany\"/><br /><sub><b>Ibrahim ali abdelghany</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AibrahimAlii\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/gkulkarni2020\"><img src=\"https://avatars3.githubusercontent.com/u/5161548?v=4?s=100\" width=\"100px;\" alt=\"Girish Kulkarni\"/><br /><sub><b>Girish Kulkarni</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=gkulkarni2020\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/omk13\"><img src=\"https://avatars0.githubusercontent.com/u/59054172?v=4?s=100\" width=\"100px;\" alt=\"Omar Karazoun\"/><br /><sub><b>Omar Karazoun</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=omk13\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/jeff303\"><img src=\"https://avatars0.githubusercontent.com/u/3521562?v=4?s=100\" width=\"100px;\" alt=\"Jeff Evans\"/><br /><sub><b>Jeff Evans</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=jeff303\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://viveksb007.github.io\"><img src=\"https://avatars1.githubusercontent.com/u/12713808?v=4?s=100\" width=\"100px;\" alt=\"Vivek Singh\"/><br /><sub><b>Vivek Singh</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=viveksb007\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/siavashsoleymani\"><img src=\"https://avatars2.githubusercontent.com/u/18074419?v=4?s=100\" width=\"100px;\" alt=\"siavash\"/><br /><sub><b>siavash</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=siavashsoleymani\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ruchpeanuts\"><img src=\"https://avatars0.githubusercontent.com/u/29301900?v=4?s=100\" width=\"100px;\" alt=\"ruchpeanuts\"/><br /><sub><b>ruchpeanuts</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ruchpeanuts\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/warp125\"><img src=\"https://avatars1.githubusercontent.com/u/48073115?v=4?s=100\" width=\"100px;\" alt=\"warp125\"/><br /><sub><b>warp125</b></sub></a><br /><a href=\"#translation-warp125\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://libkhadir.fr\"><img src=\"https://avatars1.githubusercontent.com/u/45130488?v=4?s=100\" width=\"100px;\" alt=\"KHADIR Tayeb\"/><br /><sub><b>KHADIR Tayeb</b></sub></a><br /><a href=\"#translation-tkhadir\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ignite1771\"><img src=\"https://avatars2.githubusercontent.com/u/59446563?v=4?s=100\" width=\"100px;\" alt=\"ignite1771\"/><br /><sub><b>ignite1771</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ignite1771\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/demirhalil\"><img src=\"https://avatars1.githubusercontent.com/u/22895118?v=4?s=100\" width=\"100px;\" alt=\"Halil Demir\"/><br /><sub><b>Halil Demir</b></sub></a><br /><a href=\"#translation-demirhalil\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/rohit10000\"><img src=\"https://avatars.githubusercontent.com/u/20845565?v=4?s=100\" width=\"100px;\" alt=\"Rohit Singh\"/><br /><sub><b>Rohit Singh</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=rohit10000\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/byoungju94\"><img src=\"https://avatars.githubusercontent.com/u/42516378?v=4?s=100\" width=\"100px;\" alt=\"byoungju94\"/><br /><sub><b>byoungju94</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=byoungju94\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/moustafafarhat\"><img src=\"https://avatars.githubusercontent.com/u/38836727?v=4?s=100\" width=\"100px;\" alt=\"Moustafa Farhat\"/><br /><sub><b>Moustafa Farhat</b></sub></a><br /><a href=\"#translation-moustafafarhat\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/richardmr36\"><img src=\"https://avatars.githubusercontent.com/u/19147333?v=4?s=100\" width=\"100px;\" alt=\"Martel Richard\"/><br /><sub><b>Martel Richard</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=richardmr36\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/va1m\"><img src=\"https://avatars.githubusercontent.com/u/17025445?v=4?s=100\" width=\"100px;\" alt=\"va1m\"/><br /><sub><b>va1m</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=va1m\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/noamgrinch\"><img src=\"https://avatars.githubusercontent.com/u/31648669?v=4?s=100\" width=\"100px;\" alt=\"Noam Greenshtain\"/><br /><sub><b>Noam Greenshtain</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=noamgrinch\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://xuyonghong.cn/\"><img src=\"https://avatars.githubusercontent.com/u/14086462?v=4?s=100\" width=\"100px;\" alt=\"yonghong Xu\"/><br /><sub><b>yonghong Xu</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=qfxl\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/jinisha-vora\"><img src=\"https://avatars.githubusercontent.com/u/40777762?v=4?s=100\" width=\"100px;\" alt=\"jinishavora\"/><br /><sub><b>jinishavora</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Ajinishavora\" title=\"Reviewed Pull Requests\">👀</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=jinishavora\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/eas5\"><img src=\"https://avatars.githubusercontent.com/u/50836521?v=4?s=100\" width=\"100px;\" alt=\"Elvys Soares\"/><br /><sub><b>Elvys Soares</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=eas5\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/zWeBrain\"><img src=\"https://avatars.githubusercontent.com/u/46642512?v=4?s=100\" width=\"100px;\" alt=\"zWeBrain\"/><br /><sub><b>zWeBrain</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=zWeBrain\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://al-assad.github.io/notion/\"><img src=\"https://avatars.githubusercontent.com/u/22493821?v=4?s=100\" width=\"100px;\" alt=\"余林颖\"/><br /><sub><b>余林颖</b></sub></a><br /><a href=\"#translation-Al-assad\" title=\"Translation\">🌍</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/STudio26\"><img src=\"https://avatars.githubusercontent.com/u/6988911?v=4?s=100\" width=\"100px;\" alt=\"Alain\"/><br /><sub><b>Alain</b></sub></a><br /><a href=\"#translation-STudio26\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/DEV-VRUPER\"><img src=\"https://avatars.githubusercontent.com/u/30525467?v=4?s=100\" width=\"100px;\" alt=\"VR\"/><br /><sub><b>VR</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=DEV-VRUPER\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/JackieNim\"><img src=\"https://avatars.githubusercontent.com/u/4138836?v=4?s=100\" width=\"100px;\" alt=\"JackieNim\"/><br /><sub><b>JackieNim</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=JackieNim\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/EdisonE3\"><img src=\"https://avatars.githubusercontent.com/u/52118917?v=4?s=100\" width=\"100px;\" alt=\"EdisonE3\"/><br /><sub><b>EdisonE3</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=EdisonE3\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/tao-sun2\"><img src=\"https://avatars.githubusercontent.com/u/66189688?v=4?s=100\" width=\"100px;\" alt=\"Tao\"/><br /><sub><b>Tao</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=tao-sun2\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/JuanManuelAbate\"><img src=\"https://avatars.githubusercontent.com/u/16357060?v=4?s=100\" width=\"100px;\" alt=\"Juan Manuel Abate\"/><br /><sub><b>Juan Manuel Abate</b></sub></a><br /><a href=\"#translation-JuanManuelAbate\" title=\"Translation\">🌍</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Xenilo137\"><img src=\"https://avatars.githubusercontent.com/u/24865069?v=4?s=100\" width=\"100px;\" alt=\"Xenilo137\"/><br /><sub><b>Xenilo137</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Xenilo137\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/souzasamuel/\"><img src=\"https://avatars.githubusercontent.com/u/17254162?v=4?s=100\" width=\"100px;\" alt=\"Samuel Souza\"/><br /><sub><b>Samuel Souza</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=samuelpsouza\" title=\"Code\">💻</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=samuelpsouza\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/marlo2222\"><img src=\"https://avatars.githubusercontent.com/u/40809563?v=4?s=100\" width=\"100px;\" alt=\"Marlo Henrique\"/><br /><sub><b>Marlo Henrique</b></sub></a><br /><a href=\"#translation-marlo2222\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/AndriyPyzh\"><img src=\"https://avatars.githubusercontent.com/u/57706635?v=4?s=100\" width=\"100px;\" alt=\"AndriyPyzh\"/><br /><sub><b>AndriyPyzh</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=AndriyPyzh\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/karthikbhat13\"><img src=\"https://avatars.githubusercontent.com/u/22431014?v=4?s=100\" width=\"100px;\" alt=\"karthikbhat13\"/><br /><sub><b>karthikbhat13</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=karthikbhat13\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/mortezaadi\"><img src=\"https://avatars.githubusercontent.com/u/1329687?v=4?s=100\" width=\"100px;\" alt=\"Morteza Adigozalpour\"/><br /><sub><b>Morteza Adigozalpour</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=mortezaadi\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://stackoverflow.com/users/308565/nagaraj-tantri\"><img src=\"https://avatars.githubusercontent.com/u/3784194?v=4?s=100\" width=\"100px;\" alt=\"Nagaraj Tantri\"/><br /><sub><b>Nagaraj Tantri</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=tan31989\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/frascu\"><img src=\"https://avatars.githubusercontent.com/u/7107651?v=4?s=100\" width=\"100px;\" alt=\"Francesco Scuccimarri\"/><br /><sub><b>Francesco Scuccimarri</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=frascu\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Conhan93\"><img src=\"https://avatars.githubusercontent.com/u/71334757?v=4?s=100\" width=\"100px;\" alt=\"Conny Hansson\"/><br /><sub><b>Conny Hansson</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Conhan93\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://muklasr.medium.com\"><img src=\"https://avatars.githubusercontent.com/u/43443753?v=4?s=100\" width=\"100px;\" alt=\"Muklas Rahmanto\"/><br /><sub><b>Muklas Rahmanto</b></sub></a><br /><a href=\"#translation-muklasr\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/VxDxK\"><img src=\"https://avatars.githubusercontent.com/u/38704817?v=4?s=100\" width=\"100px;\" alt=\"Vadim\"/><br /><sub><b>Vadim</b></sub></a><br /><a href=\"#translation-VxDxK\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/sims-keshri\"><img src=\"https://avatars.githubusercontent.com/u/62168475?v=4?s=100\" width=\"100px;\" alt=\"Simran Keshri\"/><br /><sub><b>Simran Keshri</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=sims-keshri\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://programacionymas.com\"><img src=\"https://avatars.githubusercontent.com/u/3101238?v=4?s=100\" width=\"100px;\" alt=\"JCarlos\"/><br /><sub><b>JCarlos</b></sub></a><br /><a href=\"#translation-JCarlosR\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.mrmoshkel.ir\"><img src=\"https://avatars.githubusercontent.com/u/60359433?v=4?s=100\" width=\"100px;\" alt=\"Ali Ghasemi\"/><br /><sub><b>Ali Ghasemi</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Dev-AliGhasemi\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://carlfx.wordpress.com\"><img src=\"https://avatars.githubusercontent.com/u/1594624?v=4?s=100\" width=\"100px;\" alt=\"Carl Dea\"/><br /><sub><b>Carl Dea</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=carldea\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Mozartuss\"><img src=\"https://avatars.githubusercontent.com/u/32893711?v=4?s=100\" width=\"100px;\" alt=\"Mozartus\"/><br /><sub><b>Mozartus</b></sub></a><br /><a href=\"#translation-Mozartuss\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ManviGoel26\"><img src=\"https://avatars.githubusercontent.com/u/55682355?v=4?s=100\" width=\"100px;\" alt=\"Manvi Goel\"/><br /><sub><b>Manvi Goel</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ManviGoel26\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/blueberry404\"><img src=\"https://avatars.githubusercontent.com/u/39243539?v=4?s=100\" width=\"100px;\" alt=\"Anum Amin\"/><br /><sub><b>Anum Amin</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=blueberry404\" title=\"Documentation\">📖</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://uh-zz.github.io/blog/\"><img src=\"https://avatars.githubusercontent.com/u/47747828?v=4?s=100\" width=\"100px;\" alt=\"Reo Uehara\"/><br /><sub><b>Reo Uehara</b></sub></a><br /><a href=\"#translation-uh-zz\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Fiordy\"><img src=\"https://avatars.githubusercontent.com/u/53420573?v=4?s=100\" width=\"100px;\" alt=\"Fiordy\"/><br /><sub><b>Fiordy</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Fiordy\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/harshalkh\"><img src=\"https://avatars.githubusercontent.com/u/37841724?v=4?s=100\" width=\"100px;\" alt=\"Harshal\"/><br /><sub><b>Harshal</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=harshalkh\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/abhinav-vashisth-06613b208/\"><img src=\"https://avatars.githubusercontent.com/u/89785800?v=4?s=100\" width=\"100px;\" alt=\"Abhinav Vashisth\"/><br /><sub><b>Abhinav Vashisth</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=vashisthabhinav\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://no website\"><img src=\"https://avatars.githubusercontent.com/u/47126749?v=4?s=100\" width=\"100px;\" alt=\"Kevin\"/><br /><sub><b>Kevin</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AKevinyl3\" title=\"Reviewed Pull Requests\">👀</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Kevinyl3\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Shrirang97\"><img src=\"https://avatars.githubusercontent.com/u/28738668?v=4?s=100\" width=\"100px;\" alt=\"Shrirang\"/><br /><sub><b>Shrirang</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AShrirang97\" title=\"Reviewed Pull Requests\">👀</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Shrirang97\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/interactwithankush\"><img src=\"https://avatars.githubusercontent.com/u/18613127?v=4?s=100\" width=\"100px;\" alt=\"interactwithankush\"/><br /><sub><b>interactwithankush</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=interactwithankush\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/yuhangbin\"><img src=\"https://avatars.githubusercontent.com/u/17566866?v=4?s=100\" width=\"100px;\" alt=\"CharlieYu\"/><br /><sub><b>CharlieYu</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=yuhangbin\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Leisterbecker\"><img src=\"https://avatars.githubusercontent.com/u/20650323?v=4?s=100\" width=\"100px;\" alt=\"Leisterbecker\"/><br /><sub><b>Leisterbecker</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Leisterbecker\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://rosaecrucis.cn\"><img src=\"https://avatars.githubusercontent.com/u/35420129?v=4?s=100\" width=\"100px;\" alt=\"DragonDreamer\"/><br /><sub><b>DragonDreamer</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=castleKing1997\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ShivanshCharak\"><img src=\"https://avatars.githubusercontent.com/u/96943825?v=4?s=100\" width=\"100px;\" alt=\"ShivanshCharak\"/><br /><sub><b>ShivanshCharak</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ShivanshCharak\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/HattoriHenzo\"><img src=\"https://avatars.githubusercontent.com/u/5141285?v=4?s=100\" width=\"100px;\" alt=\"HattoriHenzo\"/><br /><sub><b>HattoriHenzo</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=HattoriHenzo\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://arnabsen.bio.link\"><img src=\"https://avatars.githubusercontent.com/u/51032928?v=4?s=100\" width=\"100px;\" alt=\"Arnab Sen\"/><br /><sub><b>Arnab Sen</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=arnabsen1729\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://javaforlife.wordpress.com/\"><img src=\"https://avatars.githubusercontent.com/u/1470114?v=4?s=100\" width=\"100px;\" alt=\"MohanaRao SV\"/><br /><sub><b>MohanaRao SV</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=mohanaraosv\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/yonatankarp\"><img src=\"https://avatars.githubusercontent.com/u/14914865?v=4?s=100\" width=\"100px;\" alt=\"Yonatan Karp-Rudin\"/><br /><sub><b>Yonatan Karp-Rudin</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=yonatankarp\" title=\"Code\">💻</a> <a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Ayonatankarp\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/GustavoOliani\"><img src=\"https://avatars.githubusercontent.com/u/25756378?v=4?s=100\" width=\"100px;\" alt=\"Oliani\"/><br /><sub><b>Oliani</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=GustavoOliani\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Liu-rj\"><img src=\"https://avatars.githubusercontent.com/u/64826925?v=4?s=100\" width=\"100px;\" alt=\"Renjie LIU\"/><br /><sub><b>Renjie LIU</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Liu-rj\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/TreeFireMen\"><img src=\"https://avatars.githubusercontent.com/u/54127694?v=4?s=100\" width=\"100px;\" alt=\"perfect guy\"/><br /><sub><b>perfect guy</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=TreeFireMen\" title=\"Documentation\">📖</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/xyllq999\"><img src=\"https://avatars.githubusercontent.com/u/72729433?v=4?s=100\" width=\"100px;\" alt=\"xyllq999\"/><br /><sub><b>xyllq999</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=xyllq999\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/dmdbilal\"><img src=\"https://avatars.githubusercontent.com/u/91405690?v=4?s=100\" width=\"100px;\" alt=\"Mohamed Bilal\"/><br /><sub><b>Mohamed Bilal</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=dmdbilal\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/karshilsheth/\"><img src=\"https://avatars.githubusercontent.com/u/37497287?v=4?s=100\" width=\"100px;\" alt=\"Karshil sheth\"/><br /><sub><b>Karshil sheth</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=karshil2309\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/kongleong86\"><img src=\"https://avatars.githubusercontent.com/u/3745455?v=4?s=100\" width=\"100px;\" alt=\"kongleong86\"/><br /><sub><b>kongleong86</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=kongleong86\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/aitorfi\"><img src=\"https://avatars.githubusercontent.com/u/64830228?v=4?s=100\" width=\"100px;\" alt=\"Aitor Fidalgo Sánchez\"/><br /><sub><b>Aitor Fidalgo Sánchez</b></sub></a><br /><a href=\"#translation-aitorfi\" title=\"Translation\">🌍</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=aitorfi\" title=\"Documentation\">📖</a> <a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Aaitorfi\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/HeVictor\"><img src=\"https://avatars.githubusercontent.com/u/20733994?v=4?s=100\" width=\"100px;\" alt=\"Victor He\"/><br /><sub><b>Victor He</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=HeVictor\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://m-inh.github.io/\"><img src=\"https://avatars.githubusercontent.com/u/10632233?v=4?s=100\" width=\"100px;\" alt=\"Minh Nguyen\"/><br /><sub><b>Minh Nguyen</b></sub></a><br /><a href=\"#translation-m-inh\" title=\"Translation\">🌍</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=m-inh\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/HeVictor\"><img src=\"https://avatars.githubusercontent.com/u/20733994?v=4?s=100\" width=\"100px;\" alt=\"Victor He\"/><br /><sub><b>Victor He</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=HeVictor\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/YichuanSun\"><img src=\"https://avatars.githubusercontent.com/u/30886176?v=4?s=100\" width=\"100px;\" alt=\"yiichan\"/><br /><sub><b>yiichan</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=YichuanSun\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/PanSem\"><img src=\"https://avatars.githubusercontent.com/u/43316964?v=4?s=100\" width=\"100px;\" alt=\"Pan Sem\"/><br /><sub><b>Pan Sem</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=PanSem\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/zhoumengyks\"><img src=\"https://avatars.githubusercontent.com/u/111965739?v=4?s=100\" width=\"100px;\" alt=\"zhoumengyks\"/><br /><sub><b>zhoumengyks</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=zhoumengyks\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/you\"><img src=\"https://avatars.githubusercontent.com/u/57100752?v=4?s=100\" width=\"100px;\" alt=\"you\"/><br /><sub><b>you</b></sub></a><br /><a href=\"#translation-you\" title=\"Translation\">🌍</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/thanks\"><img src=\"https://avatars.githubusercontent.com/u/1121545?v=4?s=100\" width=\"100px;\" alt=\"Thanks\"/><br /><sub><b>Thanks</b></sub></a><br /><a href=\"#translation-Thanks\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/lazy-pr0grammer\"><img src=\"https://avatars.githubusercontent.com/u/87204946?v=4?s=100\" width=\"100px;\" alt=\"LazyProgrammer\"/><br /><sub><b>LazyProgrammer</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=lazy-pr0grammer\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/mdfaizanahmed786\"><img src=\"https://avatars.githubusercontent.com/u/85175130?v=4?s=100\" width=\"100px;\" alt=\"Mohammed Faizan Ahmed\"/><br /><sub><b>Mohammed Faizan Ahmed</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=mdfaizanahmed786\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/burno1\"><img src=\"https://avatars.githubusercontent.com/u/39165280?v=4?s=100\" width=\"100px;\" alt=\"Bruno Fernandes\"/><br /><sub><b>Bruno Fernandes</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=burno1\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/SammanPali\"><img src=\"https://avatars.githubusercontent.com/u/110753804?v=4?s=100\" width=\"100px;\" alt=\"SammanPali\"/><br /><sub><b>SammanPali</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=SammanPali\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/LeseChe\"><img src=\"https://avatars.githubusercontent.com/u/79553089?v=4?s=100\" width=\"100px;\" alt=\"Qixiang Chen\"/><br /><sub><b>Qixiang Chen</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=LeseChe\" title=\"Documentation\">📖</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/shouryamanekar\"><img src=\"https://avatars.githubusercontent.com/u/72398499?v=4?s=100\" width=\"100px;\" alt=\"Shourya Manekar\"/><br /><sub><b>Shourya Manekar</b></sub></a><br /><a href=\"#translation-shouryamanekar\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://seongkyu-lim.github.io/Blog/\"><img src=\"https://avatars.githubusercontent.com/u/55138532?v=4?s=100\" width=\"100px;\" alt=\"Alan\"/><br /><sub><b>Alan</b></sub></a><br /><a href=\"#translation-seongkyu-lim\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/JanFidor\"><img src=\"https://avatars.githubusercontent.com/u/66260538?v=4?s=100\" width=\"100px;\" alt=\"JanFidor\"/><br /><sub><b>JanFidor</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=JanFidor\" title=\"Code\">💻</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=JanFidor\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/drakulavich\"><img src=\"https://avatars.githubusercontent.com/u/129260?v=4?s=100\" width=\"100px;\" alt=\"Anton Yakutovich\"/><br /><sub><b>Anton Yakutovich</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=drakulavich\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/steph88ss\"><img src=\"https://avatars.githubusercontent.com/u/111041594?v=4?s=100\" width=\"100px;\" alt=\"steph88ss\"/><br /><sub><b>steph88ss</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=steph88ss\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://yujanranjitkar.com.np\"><img src=\"https://avatars.githubusercontent.com/u/63731234?v=4?s=100\" width=\"100px;\" alt=\"Yujan Ranjitkar\"/><br /><sub><b>Yujan Ranjitkar</b></sub></a><br /><a href=\"#translation-0xYujan\" title=\"Translation\">🌍</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/yusha-g\"><img src=\"https://avatars.githubusercontent.com/u/110189579?v=4?s=100\" width=\"100px;\" alt=\"yusha-g\"/><br /><sub><b>yusha-g</b></sub></a><br /><a href=\"#translation-yusha-g\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/robertvolkmann\"><img src=\"https://avatars.githubusercontent.com/u/20912167?v=4?s=100\" width=\"100px;\" alt=\"Robert Volkmann\"/><br /><sub><b>Robert Volkmann</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=robertvolkmann\" title=\"Code\">💻</a> <a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Arobertvolkmann\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/bipin-k\"><img src=\"https://avatars.githubusercontent.com/u/21119358?v=4?s=100\" width=\"100px;\" alt=\"Bipin Kumar Chaurasia\"/><br /><sub><b>Bipin Kumar Chaurasia</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=bipin-k\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/KyleSong30\"><img src=\"https://avatars.githubusercontent.com/u/100892032?v=4?s=100\" width=\"100px;\" alt=\"KyleSong30\"/><br /><sub><b>KyleSong30</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=KyleSong30\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/u7281975\"><img src=\"https://avatars.githubusercontent.com/u/111095623?v=4?s=100\" width=\"100px;\" alt=\"u7281975\"/><br /><sub><b>u7281975</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=u7281975\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/harshalkhachane\"><img src=\"https://avatars.githubusercontent.com/u/92866584?v=4?s=100\" width=\"100px;\" alt=\"harshalkhachane\"/><br /><sub><b>harshalkhachane</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=harshalkhachane\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ec-026\"><img src=\"https://avatars.githubusercontent.com/u/95495584?v=4?s=100\" width=\"100px;\" alt=\"Tejas Singh\"/><br /><sub><b>Tejas Singh</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ec-026\" title=\"Documentation\">📖</a> <a href=\"#translation-ec-026\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://journal.artfuldev.com\"><img src=\"https://avatars.githubusercontent.com/u/3091087?v=4?s=100\" width=\"100px;\" alt=\"Sudarsan Balaji\"/><br /><sub><b>Sudarsan Balaji</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=artfuldev\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/vaibhav-agr/\"><img src=\"https://avatars.githubusercontent.com/u/78676331?v=4?s=100\" width=\"100px;\" alt=\"Vaibhav Agrawal\"/><br /><sub><b>Vaibhav Agrawal</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=vaibhav-if\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/u7275858\"><img src=\"https://avatars.githubusercontent.com/u/110969489?v=4?s=100\" width=\"100px;\" alt=\"u7275858\"/><br /><sub><b>u7275858</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=u7275858\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://gist.github.com/prasad-333\"><img src=\"https://avatars.githubusercontent.com/u/37048768?v=4?s=100\" width=\"100px;\" alt=\"prasad-333\"/><br /><sub><b>prasad-333</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=prasad-333\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/JurenXu\"><img src=\"https://avatars.githubusercontent.com/u/101047547?v=4?s=100\" width=\"100px;\" alt=\"JurenXu\"/><br /><sub><b>JurenXu</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=JurenXu\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/murphShaw\"><img src=\"https://avatars.githubusercontent.com/u/111167533?v=4?s=100\" width=\"100px;\" alt=\"murphShaw\"/><br /><sub><b>murphShaw</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=murphShaw\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/XianWu99\"><img src=\"https://avatars.githubusercontent.com/u/111103319?v=4?s=100\" width=\"100px;\" alt=\"XianWu99\"/><br /><sub><b>XianWu99</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=XianWu99\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/JoshuaSinglaANU\"><img src=\"https://avatars.githubusercontent.com/u/109902734?v=4?s=100\" width=\"100px;\" alt=\"JoshuaSinglaANU\"/><br /><sub><b>JoshuaSinglaANU</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=JoshuaSinglaANU\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://www.linkedin.com/in/ricardo-ramos-moura\"><img src=\"https://avatars.githubusercontent.com/u/36955909?v=4?s=100\" width=\"100px;\" alt=\"Ricardo Ramos\"/><br /><sub><b>Ricardo Ramos</b></sub></a><br /><a href=\"#translation-ricardo-ramos-moura\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://zhrfrd.github.io/faridzouheir/\"><img src=\"https://avatars.githubusercontent.com/u/72947724?v=4?s=100\" width=\"100px;\" alt=\"Farid Zouheir\"/><br /><sub><b>Farid Zouheir</b></sub></a><br /><a href=\"#translation-zhrfrd\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/vinicius-beraldo/\"><img src=\"https://avatars.githubusercontent.com/u/91766068?v=4?s=100\" width=\"100px;\" alt=\"Vinícius A. B.\"/><br /><sub><b>Vinícius A. B.</b></sub></a><br /><a href=\"#translation-Viniberaldo\" title=\"Translation\">🌍</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://www.linkedin.com/in/stefanel-stan/\"><img src=\"https://avatars.githubusercontent.com/u/25990078?v=4?s=100\" width=\"100px;\" alt=\"Stefanel Stan\"/><br /><sub><b>Stefanel Stan</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=StefanelStan\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/bhati00\"><img src=\"https://avatars.githubusercontent.com/u/79313705?v=4?s=100\" width=\"100px;\" alt=\"Prince bhati\"/><br /><sub><b>Prince bhati</b></sub></a><br /><a href=\"#translation-bhati00\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/wulangcode\"><img src=\"https://avatars.githubusercontent.com/u/48200100?v=4?s=100\" width=\"100px;\" alt=\"WuLang\"/><br /><sub><b>WuLang</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=wulangcode\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/hkattt\"><img src=\"https://avatars.githubusercontent.com/u/54300585?v=4?s=100\" width=\"100px;\" alt=\"Hugo Kat\"/><br /><sub><b>Hugo Kat</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=hkattt\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/shivu2002a\"><img src=\"https://avatars.githubusercontent.com/u/88313126?v=4?s=100\" width=\"100px;\" alt=\"Shivanagouda Agasimani\"/><br /><sub><b>Shivanagouda Agasimani</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=shivu2002a\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Ap284\"><img src=\"https://avatars.githubusercontent.com/u/13827254?v=4?s=100\" width=\"100px;\" alt=\"Aparna\"/><br /><sub><b>Aparna</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Ap284\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/girolamo-giordano\"><img src=\"https://avatars.githubusercontent.com/u/56109364?v=4?s=100\" width=\"100px;\" alt=\"Girolamo Giordano\"/><br /><sub><b>Girolamo Giordano</b></sub></a><br /><a href=\"#translation-girolamo-giordano\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Chak-C\"><img src=\"https://avatars.githubusercontent.com/u/114961815?v=4?s=100\" width=\"100px;\" alt=\"Chak-C\"/><br /><sub><b>Chak-C</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Chak-C\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/nakul251197\"><img src=\"https://avatars.githubusercontent.com/u/39953357?v=4?s=100\" width=\"100px;\" alt=\"Nakul Nambiar\"/><br /><sub><b>Nakul Nambiar</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=nakul251197\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/KarmaTashiCat\"><img src=\"https://avatars.githubusercontent.com/u/76797146?v=4?s=100\" width=\"100px;\" alt=\"KarmaTashiCat\"/><br /><sub><b>KarmaTashiCat</b></sub></a><br /><a href=\"#translation-KarmaTashiCat\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Marikattt\"><img src=\"https://avatars.githubusercontent.com/u/49302558?v=4?s=100\" width=\"100px;\" alt=\"marikattt\"/><br /><sub><b>marikattt</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Marikattt\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Harsh4902\"><img src=\"https://avatars.githubusercontent.com/u/84663071?v=4?s=100\" width=\"100px;\" alt=\"Hashvardhan Parmar\"/><br /><sub><b>Hashvardhan Parmar</b></sub></a><br /><a href=\"#translation-Harsh4902\" title=\"Translation\">🌍</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://hwan33.tistory.com/\"><img src=\"https://avatars.githubusercontent.com/u/67625677?v=4?s=100\" width=\"100px;\" alt=\"YongHwan\"/><br /><sub><b>YongHwan</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=yongyongkr\" title=\"Documentation\">📖</a> <a href=\"#translation-yongyongkr\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/shogohida\"><img src=\"https://avatars.githubusercontent.com/u/10365357?v=4?s=100\" width=\"100px;\" alt=\"Shogo Hida\"/><br /><sub><b>Shogo Hida</b></sub></a><br /><a href=\"#translation-shogohida\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Regyl\"><img src=\"https://avatars.githubusercontent.com/u/48804404?v=4?s=100\" width=\"100px;\" alt=\"Eugene\"/><br /><sub><b>Eugene</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Regyl\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/piyush280599\"><img src=\"https://avatars.githubusercontent.com/u/118425491?v=4?s=100\" width=\"100px;\" alt=\"Piyush\"/><br /><sub><b>Piyush</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=piyush280599\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/rahulraj90/\"><img src=\"https://avatars.githubusercontent.com/u/517415?v=4?s=100\" width=\"100px;\" alt=\"Rahul Raj\"/><br /><sub><b>Rahul Raj</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=rahul-raj\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/bharathkalyans/\"><img src=\"https://avatars.githubusercontent.com/u/49526472?v=4?s=100\" width=\"100px;\" alt=\"Bharath Kalyan S\"/><br /><sub><b>Bharath Kalyan S</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=bharathkalyans\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/thisissaiteja/\"><img src=\"https://avatars.githubusercontent.com/u/13088886?v=4?s=100\" width=\"100px;\" alt=\"Saiteja Reddy\"/><br /><sub><b>Saiteja Reddy</b></sub></a><br /><a href=\"#translation-saiteja55\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://twitch.tv/clerici\"><img src=\"https://avatars.githubusercontent.com/u/115318468?v=4?s=100\" width=\"100px;\" alt=\"Enrique Clerici\"/><br /><sub><b>Enrique Clerici</b></sub></a><br /><a href=\"#translation-TheClerici\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ramilS\"><img src=\"https://avatars.githubusercontent.com/u/13589365?v=4?s=100\" width=\"100px;\" alt=\"Ramil Sayetov\"/><br /><sub><b>Ramil Sayetov</b></sub></a><br /><a href=\"#translation-ramilS\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://pkq.xyz\"><img src=\"https://avatars.githubusercontent.com/u/50656114?v=4?s=100\" width=\"100px;\" alt=\"东方未白\"/><br /><sub><b>东方未白</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=pikapiu\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/swashb0ckler\"><img src=\"https://avatars.githubusercontent.com/u/62488841?v=4?s=100\" width=\"100px;\" alt=\"Fredrik Sejr\"/><br /><sub><b>Fredrik Sejr</b></sub></a><br /><a href=\"#translation-swashb0ckler\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/akshatarora0013\"><img src=\"https://avatars.githubusercontent.com/u/102645021?v=4?s=100\" width=\"100px;\" alt=\"akshatarora0013\"/><br /><sub><b>akshatarora0013</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=akshatarora0013\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://mugheesqasimmq.wixsite.com/portfolio-website\"><img src=\"https://avatars.githubusercontent.com/u/45170085?v=4?s=100\" width=\"100px;\" alt=\"Mughees Qasim\"/><br /><sub><b>Mughees Qasim</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=MugheesQasim\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/behappyleee\"><img src=\"https://avatars.githubusercontent.com/u/72903623?v=4?s=100\" width=\"100px;\" alt=\"behappyleee\"/><br /><sub><b>behappyleee</b></sub></a><br /><a href=\"#translation-behappyleee\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Ayush-Thakur-geek\"><img src=\"https://avatars.githubusercontent.com/u/116510022?v=4?s=100\" width=\"100px;\" alt=\"Ayush Thakur\"/><br /><sub><b>Ayush Thakur</b></sub></a><br /><a href=\"#translation-Ayush-Thakur-geek\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/boscha1\"><img src=\"https://avatars.githubusercontent.com/u/55814237?v=4?s=100\" width=\"100px;\" alt=\"Anthony Bosch\"/><br /><sub><b>Anthony Bosch</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=boscha1\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/AnsonTran\"><img src=\"https://avatars.githubusercontent.com/u/37683428?v=4?s=100\" width=\"100px;\" alt=\"trananso\"/><br /><sub><b>trananso</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=AnsonTran\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/beef-e\"><img src=\"https://avatars.githubusercontent.com/u/102854627?v=4?s=100\" width=\"100px;\" alt=\"Giammaria Biffi\"/><br /><sub><b>Giammaria Biffi</b></sub></a><br /><a href=\"#translation-beef-e\" title=\"Translation\">🌍</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/saif7159\"><img src=\"https://avatars.githubusercontent.com/u/36008396?v=4?s=100\" width=\"100px;\" alt=\"Saiful Haque\"/><br /><sub><b>Saiful Haque</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=saif7159\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/JabezBrew\"><img src=\"https://avatars.githubusercontent.com/u/74483609?v=4?s=100\" width=\"100px;\" alt=\"JabezBrew\"/><br /><sub><b>JabezBrew</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=JabezBrew\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/konstantin-goldman\"><img src=\"https://avatars.githubusercontent.com/u/47669472?v=4?s=100\" width=\"100px;\" alt=\"konstantin-goldman\"/><br /><sub><b>konstantin-goldman</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=konstantin-goldman\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/tiennm99\"><img src=\"https://avatars.githubusercontent.com/u/39063457?v=4?s=100\" width=\"100px;\" alt=\"Tien Nguyen Minh\"/><br /><sub><b>Tien Nguyen Minh</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=tiennm99\" title=\"Code\">💻</a> <a href=\"#translation-tiennm99\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/VladimirCreator\"><img src=\"https://avatars.githubusercontent.com/u/49140851?v=4?s=100\" width=\"100px;\" alt=\"Vladimir\"/><br /><sub><b>Vladimir</b></sub></a><br /><a href=\"#translation-VladimirCreator\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://surjendu-pal.netlify.app/\"><img src=\"https://avatars.githubusercontent.com/u/101238933?v=4?s=100\" width=\"100px;\" alt=\"Surjendu\"/><br /><sub><b>Surjendu</b></sub></a><br /><a href=\"#translation-surjendu104\" title=\"Translation\">🌍</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=surjendu104\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/bakazhou\"><img src=\"https://avatars.githubusercontent.com/u/81795984?v=4?s=100\" width=\"100px;\" alt=\"bakazhou\"/><br /><sub><b>bakazhou</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=bakazhou\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Owen-CH-Leung\"><img src=\"https://avatars.githubusercontent.com/u/43698890?v=4?s=100\" width=\"100px;\" alt=\"Owen Leung\"/><br /><sub><b>Owen Leung</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Owen-CH-Leung\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/thestbar\"><img src=\"https://avatars.githubusercontent.com/u/20283468?v=4?s=100\" width=\"100px;\" alt=\"Stavros Barousis\"/><br /><sub><b>Stavros Barousis</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=thestbar\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ibrahim89\"><img src=\"https://avatars.githubusercontent.com/u/20753671?v=4?s=100\" width=\"100px;\" alt=\"Syyed Ibrahim Abdullah\"/><br /><sub><b>Syyed Ibrahim Abdullah</b></sub></a><br /><a href=\"#translation-ibrahim89\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/JanisZhang\"><img src=\"https://avatars.githubusercontent.com/u/95570096?v=4?s=100\" width=\"100px;\" alt=\"JiaDi Zhang\"/><br /><sub><b>JiaDi Zhang</b></sub></a><br /><a href=\"#translation-JanisZhang\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/sanchitbansal10\"><img src=\"https://avatars.githubusercontent.com/u/16536741?v=4?s=100\" width=\"100px;\" alt=\"Sanchit Bansal\"/><br /><sub><b>Sanchit Bansal</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=sanchitbansal10\" title=\"Documentation\">📖</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/mm-saiful6854\"><img src=\"https://avatars.githubusercontent.com/u/48361160?v=4?s=100\" width=\"100px;\" alt=\"Md Saiful Islam\"/><br /><sub><b>Md Saiful Islam</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=mm-saiful6854\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/AddeusExMachina\"><img src=\"https://avatars.githubusercontent.com/u/39912670?v=4?s=100\" width=\"100px;\" alt=\"Antonio Addeo\"/><br /><sub><b>Antonio Addeo</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=AddeusExMachina\" title=\"Documentation\">📖</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=AddeusExMachina\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Upendra-Allagadda\"><img src=\"https://avatars.githubusercontent.com/u/25962010?v=4?s=100\" width=\"100px;\" alt=\"Allagadda Sai Upendranath\"/><br /><sub><b>Allagadda Sai Upendranath</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Upendra-Allagadda\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://www.linkedin.com/in/mobraga/\"><img src=\"https://avatars.githubusercontent.com/u/31048764?v=4?s=100\" width=\"100px;\" alt=\"Matheus Braga\"/><br /><sub><b>Matheus Braga</b></sub></a><br /><a href=\"#translation-mathbraga\" title=\"Translation\">🌍</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=mathbraga\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/satyabarghav\"><img src=\"https://avatars.githubusercontent.com/u/36763910?v=4?s=100\" width=\"100px;\" alt=\"Appari Satya Barghav\"/><br /><sub><b>Appari Satya Barghav</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=satyabarghav\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://mribeirodantas.me\"><img src=\"https://avatars.githubusercontent.com/u/1023197?v=4?s=100\" width=\"100px;\" alt=\"Marcel Ribeiro-Dantas\"/><br /><sub><b>Marcel Ribeiro-Dantas</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=mribeirodantas\" title=\"Documentation\">📖</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/hamexhanif\"><img src=\"https://avatars.githubusercontent.com/u/74542852?v=4?s=100\" width=\"100px;\" alt=\"Muhammad Hanif Amrullah\"/><br /><sub><b>Muhammad Hanif Amrullah</b></sub></a><br /><a href=\"#translation-hamexhanif\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/JackH408\"><img src=\"https://avatars.githubusercontent.com/u/141727294?v=4?s=100\" width=\"100px;\" alt=\"JackH408\"/><br /><sub><b>JackH408</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=JackH408\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/versus2004\"><img src=\"https://avatars.githubusercontent.com/u/132815243?v=4?s=100\" width=\"100px;\" alt=\"Shubham\"/><br /><sub><b>Shubham</b></sub></a><br /><a href=\"#translation-versus2004\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/inishantjain\"><img src=\"https://avatars.githubusercontent.com/u/121454072?v=4?s=100\" width=\"100px;\" alt=\"Nishant Jain\"/><br /><sub><b>Nishant Jain</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=inishantjain\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/hallowshaw\"><img src=\"https://avatars.githubusercontent.com/u/90751158?v=4?s=100\" width=\"100px;\" alt=\"Rhitam Chaudhury\"/><br /><sub><b>Rhitam Chaudhury</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=hallowshaw\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/JerryZhao275\"><img src=\"https://avatars.githubusercontent.com/u/132061401?v=4?s=100\" width=\"100px;\" alt=\"JerryZhao275\"/><br /><sub><b>JerryZhao275</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=JerryZhao275\" title=\"Documentation\">📖</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://twitter.com/llisant\"><img src=\"https://avatars.githubusercontent.com/u/1445890?v=4?s=100\" width=\"100px;\" alt=\"Leonardo Lisanti\"/><br /><sub><b>Leonardo Lisanti</b></sub></a><br /><a href=\"#translation-leonardol\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://www.linkedin.com/in/yenniferh\"><img src=\"https://avatars.githubusercontent.com/u/19285706?v=4?s=100\" width=\"100px;\" alt=\"Yennifer Herrera\"/><br /><sub><b>Yennifer Herrera</b></sub></a><br /><a href=\"#translation-Yenniferh\" title=\"Translation\">🌍</a> <a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AYenniferh\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/jnniu-n\"><img src=\"https://avatars.githubusercontent.com/u/141746282?v=4?s=100\" width=\"100px;\" alt=\"jnniu-n\"/><br /><sub><b>jnniu-n</b></sub></a><br /><a href=\"#translation-jnniu-n\" title=\"Translation\">🌍</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=jnniu-n\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/miguel-is-coding\"><img src=\"https://avatars.githubusercontent.com/u/48435117?v=4?s=100\" width=\"100px;\" alt=\"Miguel Angel Perez Garcia\"/><br /><sub><b>Miguel Angel Perez Garcia</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Amiguel-is-coding\" title=\"Reviewed Pull Requests\">👀</a> <a href=\"#translation-miguel-is-coding\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/SuwanSankaja\"><img src=\"https://avatars.githubusercontent.com/u/86839778?v=4?s=100\" width=\"100px;\" alt=\"Suwan Sankaja\"/><br /><sub><b>Suwan Sankaja</b></sub></a><br /><a href=\"#translation-SuwanSankaja\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Iamalok007\"><img src=\"https://avatars.githubusercontent.com/u/97467835?v=4?s=100\" width=\"100px;\" alt=\"alok\"/><br /><sub><b>alok</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Iamalok007\" title=\"Documentation\">📖</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/dlvideira\"><img src=\"https://avatars.githubusercontent.com/u/53951425?v=4?s=100\" width=\"100px;\" alt=\"Daniel Lisboa\"/><br /><sub><b>Daniel Lisboa</b></sub></a><br /><a href=\"#translation-dlvideira\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ComplexOW\"><img src=\"https://avatars.githubusercontent.com/u/105279107?v=4?s=100\" width=\"100px;\" alt=\"Sam Powell\"/><br /><sub><b>Sam Powell</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ComplexOW\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/jppf22\"><img src=\"https://avatars.githubusercontent.com/u/104360594?v=4?s=100\" width=\"100px;\" alt=\"João Fernandes\"/><br /><sub><b>João Fernandes</b></sub></a><br /><a href=\"#translation-jppf22\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/HongGeonUi\"><img src=\"https://avatars.githubusercontent.com/u/89684956?v=4?s=100\" width=\"100px;\" alt=\"Hong Geon-ui\"/><br /><sub><b>Hong Geon-ui</b></sub></a><br /><a href=\"#translation-HongGeonUi\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ylcn91\"><img src=\"https://avatars.githubusercontent.com/u/7249450?v=4?s=100\" width=\"100px;\" alt=\"Doksanbir\"/><br /><sub><b>Doksanbir</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ylcn91\" title=\"Code\">💻</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ylcn91\" title=\"Documentation\">📖</a> <a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Aylcn91\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Chant3ll3\"><img src=\"https://avatars.githubusercontent.com/u/141697333?v=4?s=100\" width=\"100px;\" alt=\"Chant3ll3\"/><br /><sub><b>Chant3ll3</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Chant3ll3\" title=\"Documentation\">📖</a> <a href=\"#translation-Chant3ll3\" title=\"Translation\">🌍</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://hwan33.tistory.com/\"><img src=\"https://avatars.githubusercontent.com/u/67625677?v=4?s=100\" width=\"100px;\" alt=\"YongHwan Kwon\"/><br /><sub><b>YongHwan Kwon</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=hwan33\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/takikuba\"><img src=\"https://avatars.githubusercontent.com/u/58841343?v=4?s=100\" width=\"100px;\" alt=\"Jakub Klimek\"/><br /><sub><b>Jakub Klimek</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=takikuba\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/bachbil\"><img src=\"https://avatars.githubusercontent.com/u/28935461?v=4?s=100\" width=\"100px;\" alt=\"believe\"/><br /><sub><b>believe</b></sub></a><br /><a href=\"#translation-bachbil\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/egg0102030405\"><img src=\"https://avatars.githubusercontent.com/u/59650695?v=4?s=100\" width=\"100px;\" alt=\"egg0102030405\"/><br /><sub><b>egg0102030405</b></sub></a><br /><a href=\"#translation-egg0102030405\" title=\"Translation\">🌍</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=egg0102030405\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://vedasole.cloud\"><img src=\"https://avatars.githubusercontent.com/u/77259804?v=4?s=100\" width=\"100px;\" alt=\"Ved Asole\"/><br /><sub><b>Ved Asole</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ved-asole\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Holiday-C\"><img src=\"https://avatars.githubusercontent.com/u/95869761?v=4?s=100\" width=\"100px;\" alt=\"NewMorning\"/><br /><sub><b>NewMorning</b></sub></a><br /><a href=\"#translation-Holiday-C\" title=\"Translation\">🌍</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Kiro-Young\"><img src=\"https://avatars.githubusercontent.com/u/98251397?v=4?s=100\" width=\"100px;\" alt=\"资深老萌新\"/><br /><sub><b>资深老萌新</b></sub></a><br /><a href=\"#translation-Kiro-Young\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://itistori.tistory.com/\"><img src=\"https://avatars.githubusercontent.com/u/113348293?v=4?s=100\" width=\"100px;\" alt=\"Seunghwan Jeon\"/><br /><sub><b>Seunghwan Jeon</b></sub></a><br /><a href=\"#translation-Nickolodeon98\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/sugan0tech\"><img src=\"https://avatars.githubusercontent.com/u/71312159?v=4?s=100\" width=\"100px;\" alt=\"sugavanesh\"/><br /><sub><b>sugavanesh</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=sugan0tech\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/FinnS-F\"><img src=\"https://avatars.githubusercontent.com/u/126026830?v=4?s=100\" width=\"100px;\" alt=\"FinnS-F\"/><br /><sub><b>FinnS-F</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=FinnS-F\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/jerryyummy\"><img src=\"https://avatars.githubusercontent.com/u/62087610?v=4?s=100\" width=\"100px;\" alt=\"jerryyummy\"/><br /><sub><b>jerryyummy</b></sub></a><br /><a href=\"#translation-jerryyummy\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://manojkumarchow.github.io/\"><img src=\"https://avatars.githubusercontent.com/u/28005510?v=4?s=100\" width=\"100px;\" alt=\"Manoj Chowdary\"/><br /><sub><b>Manoj Chowdary</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Manojkumarchow\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/MaverickWingman\"><img src=\"https://avatars.githubusercontent.com/u/76624290?v=4?s=100\" width=\"100px;\" alt=\"Aditya\"/><br /><sub><b>Aditya</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=MaverickWingman\" title=\"Documentation\">📖</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=MaverickWingman\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/nooynayr\"><img src=\"https://avatars.githubusercontent.com/u/141696269?v=4?s=100\" width=\"100px;\" alt=\"nooynayr\"/><br /><sub><b>nooynayr</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=nooynayr\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/pushpander1010\"><img src=\"https://avatars.githubusercontent.com/u/41006191?v=4?s=100\" width=\"100px;\" alt=\"CYBERCRUX2\"/><br /><sub><b>CYBERCRUX2</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=pushpander1010\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/luismateoh\"><img src=\"https://avatars.githubusercontent.com/u/44934142?v=4?s=100\" width=\"100px;\" alt=\"Luis Mateo Hincapié Martinez\"/><br /><sub><b>Luis Mateo Hincapié Martinez</b></sub></a><br /><a href=\"#translation-luismateoh\" title=\"Translation\">🌍</a> <a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Aluismateoh\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://guqing.io\"><img src=\"https://avatars.githubusercontent.com/u/38999863?v=4?s=100\" width=\"100px;\" alt=\"guqing\"/><br /><sub><b>guqing</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=guqing\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/sashirestela\"><img src=\"https://avatars.githubusercontent.com/u/14045506?v=4?s=100\" width=\"100px;\" alt=\"Sashir Estela\"/><br /><sub><b>Sashir Estela</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=sashirestela\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/omahs\"><img src=\"https://avatars.githubusercontent.com/u/73983677?v=4?s=100\" width=\"100px;\" alt=\"omahs\"/><br /><sub><b>omahs</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=omahs\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/leiferksn\"><img src=\"https://avatars.githubusercontent.com/u/4026636?v=4?s=100\" width=\"100px;\" alt=\"leif e.\"/><br /><sub><b>leif e.</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=leiferksn\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://junhkang.tistory.com/\"><img src=\"https://avatars.githubusercontent.com/u/20232155?v=4?s=100\" width=\"100px;\" alt=\"Jun Kang\"/><br /><sub><b>Jun Kang</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=junhkang\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/KishalayP\"><img src=\"https://avatars.githubusercontent.com/u/71012321?v=4?s=100\" width=\"100px;\" alt=\"Kishalay Pandey\"/><br /><sub><b>Kishalay Pandey</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=KishalayP\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/drishtii7\"><img src=\"https://avatars.githubusercontent.com/u/82076566?v=4?s=100\" width=\"100px;\" alt=\"drishtii7\"/><br /><sub><b>drishtii7</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=drishtii7\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/DavidMedinaO\"><img src=\"https://avatars.githubusercontent.com/u/53974843?v=4?s=100\" width=\"100px;\" alt=\"David Medina Orozco\"/><br /><sub><b>David Medina Orozco</b></sub></a><br /><a href=\"#translation-DavidMedinaO\" title=\"Translation\">🌍</a> <a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3ADavidMedinaO\" title=\"Reviewed Pull Requests\">👀</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Romo4ka-bot\"><img src=\"https://avatars.githubusercontent.com/u/61774094?v=4?s=100\" width=\"100px;\" alt=\"Roman Leontev\"/><br /><sub><b>Roman Leontev</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Romo4ka-bot\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Ehspresso\"><img src=\"https://avatars.githubusercontent.com/u/144370752?v=4?s=100\" width=\"100px;\" alt=\"Riley\"/><br /><sub><b>Riley</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Ehspresso\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/k1w1dev\"><img src=\"https://avatars.githubusercontent.com/u/121696782?v=4?s=100\" width=\"100px;\" alt=\"k1w1dev\"/><br /><sub><b>k1w1dev</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=k1w1dev\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/dev-yugantar\"><img src=\"https://avatars.githubusercontent.com/u/153066190?v=4?s=100\" width=\"100px;\" alt=\"dev-yugantar\"/><br /><sub><b>dev-yugantar</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=dev-yugantar\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Adelechka\"><img src=\"https://avatars.githubusercontent.com/u/65678470?v=4?s=100\" width=\"100px;\" alt=\"Adelya\"/><br /><sub><b>Adelya</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Adelechka\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/gatlanagaprasanna\"><img src=\"https://avatars.githubusercontent.com/u/154739216?v=4?s=100\" width=\"100px;\" alt=\"gatlanagaprasanna\"/><br /><sub><b>gatlanagaprasanna</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=gatlanagaprasanna\" title=\"Documentation\">📖</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Avinash2110\"><img src=\"https://avatars.githubusercontent.com/u/37360069?v=4?s=100\" width=\"100px;\" alt=\"Avinash Shukla\"/><br /><sub><b>Avinash Shukla</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Avinash2110\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Mayankchoudhary294\"><img src=\"https://avatars.githubusercontent.com/u/97609699?v=4?s=100\" width=\"100px;\" alt=\"Mayank Choudhary\"/><br /><sub><b>Mayank Choudhary</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Mayankchoudhary294\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/romannimets\"><img src=\"https://avatars.githubusercontent.com/u/137268574?v=4?s=100\" width=\"100px;\" alt=\"romannimets\"/><br /><sub><b>romannimets</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=romannimets\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Joel-Dandin\"><img src=\"https://avatars.githubusercontent.com/u/60149879?v=4?s=100\" width=\"100px;\" alt=\"Joel\"/><br /><sub><b>Joel</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Joel-Dandin\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/244Walyson\"><img src=\"https://avatars.githubusercontent.com/u/125759796?v=4?s=100\" width=\"100px;\" alt=\"Walyson Moises\"/><br /><sub><b>Walyson Moises</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=244Walyson\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Xcyq\"><img src=\"https://avatars.githubusercontent.com/u/39086666?v=4?s=100\" width=\"100px;\" alt=\"Xcyq\"/><br /><sub><b>Xcyq</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Xcyq\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Ritabrata1080\"><img src=\"https://avatars.githubusercontent.com/u/60834250?v=4?s=100\" width=\"100px;\" alt=\"Ritabrata\"/><br /><sub><b>Ritabrata</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3ARitabrata1080\" title=\"Reviewed Pull Requests\">👀</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/trivikr\"><img src=\"https://avatars.githubusercontent.com/u/16024985?v=4?s=100\" width=\"100px;\" alt=\"Trivikram Kamat\"/><br /><sub><b>Trivikram Kamat</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=trivikr\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/vvanghelle\"><img src=\"https://avatars.githubusercontent.com/u/3204600?v=4?s=100\" width=\"100px;\" alt=\"Vincent Vanghelle\"/><br /><sub><b>Vincent Vanghelle</b></sub></a><br /><a href=\"#translation-vvanghelle\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/antoheri\"><img src=\"https://avatars.githubusercontent.com/u/79988396?v=4?s=100\" width=\"100px;\" alt=\"Antoine Héritier\"/><br /><sub><b>Antoine Héritier</b></sub></a><br /><a href=\"#translation-antoheri\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/fishandsheep\"><img src=\"https://avatars.githubusercontent.com/u/43347407?v=4?s=100\" width=\"100px;\" alt=\"QinShower\"/><br /><sub><b>QinShower</b></sub></a><br /><a href=\"#translation-fishandsheep\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/LakshyaPunyani-01\"><img src=\"https://avatars.githubusercontent.com/u/103628913?v=4?s=100\" width=\"100px;\" alt=\"LakshyaPunyani-01\"/><br /><sub><b>LakshyaPunyani-01</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=LakshyaPunyani-01\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/jasonjyu\"><img src=\"https://avatars.githubusercontent.com/u/10333076?v=4?s=100\" width=\"100px;\" alt=\"jasonjyu\"/><br /><sub><b>jasonjyu</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=jasonjyu\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/jeffmorrison\"><img src=\"https://avatars.githubusercontent.com/u/26047158?v=4?s=100\" width=\"100px;\" alt=\"jeffmorrison\"/><br /><sub><b>jeffmorrison</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=jeffmorrison\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/dmgodoy\"><img src=\"https://avatars.githubusercontent.com/u/10840681?v=4?s=100\" width=\"100px;\" alt=\"David M.\"/><br /><sub><b>David M.</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=dmgodoy\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/apophizzz\"><img src=\"https://avatars.githubusercontent.com/u/12052783?v=4?s=100\" width=\"100px;\" alt=\"Patrick Kleindienst\"/><br /><sub><b>Patrick Kleindienst</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=apophizzz\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/proceane\"><img src=\"https://avatars.githubusercontent.com/u/62143949?v=4?s=100\" width=\"100px;\" alt=\"Juyeon\"/><br /><sub><b>Juyeon</b></sub></a><br /><a href=\"#translation-proceane\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://mammadyahya.vercel.app\"><img src=\"https://avatars.githubusercontent.com/u/66476643?v=4?s=100\" width=\"100px;\" alt=\"Mammad Yahyayev\"/><br /><sub><b>Mammad Yahyayev</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=mammadyahyayev\" title=\"Documentation\">📖</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/SalmaAzeem\"><img src=\"https://avatars.githubusercontent.com/u/121863224?v=4?s=100\" width=\"100px;\" alt=\"Salma\"/><br /><sub><b>Salma</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=SalmaAzeem\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://codemaverick-143.github.io/My-Portfolio/\"><img src=\"https://avatars.githubusercontent.com/u/182847716?v=4?s=100\" width=\"100px;\" alt=\"Arpit Sarang\"/><br /><sub><b>Arpit Sarang</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=CodeMaverick-143\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/mayatarek\"><img src=\"https://avatars.githubusercontent.com/u/111644421?v=4?s=100\" width=\"100px;\" alt=\"Maya\"/><br /><sub><b>Maya</b></sub></a><br /><a href=\"#translation-mayatarek\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/HabibaMekay\"><img src=\"https://avatars.githubusercontent.com/u/133516736?v=4?s=100\" width=\"100px;\" alt=\"HabibaMekay\"/><br /><sub><b>HabibaMekay</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=HabibaMekay\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Ahmed-Taha-981\"><img src=\"https://avatars.githubusercontent.com/u/122402269?v=4?s=100\" width=\"100px;\" alt=\"Ahmed-Taha-981\"/><br /><sub><b>Ahmed-Taha-981</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Ahmed-Taha-981\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://malakelbanna.netlify.app/\"><img src=\"https://avatars.githubusercontent.com/u/67643605?v=4?s=100\" width=\"100px;\" alt=\"Malak Elbanna\"/><br /><sub><b>Malak Elbanna</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=malak-elbanna\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/depthlending\"><img src=\"https://avatars.githubusercontent.com/u/164312726?v=4?s=100\" width=\"100px;\" alt=\"BiKangNing\"/><br /><sub><b>BiKangNing</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=depthlending\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/TarunVishwakarma1\"><img src=\"https://avatars.githubusercontent.com/u/138651451?v=4?s=100\" width=\"100px;\" alt=\"Tarun Vishwakarma\"/><br /><sub><b>Tarun Vishwakarma</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=TarunVishwakarma1\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/shahdhoss\"><img src=\"https://avatars.githubusercontent.com/u/132148556?v=4?s=100\" width=\"100px;\" alt=\"Shahd Hossam\"/><br /><sub><b>Shahd Hossam</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=shahdhoss\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://mehdirahimi.github.io\"><img src=\"https://avatars.githubusercontent.com/u/24210842?v=4?s=100\" width=\"100px;\" alt=\"Mehdi Rahimi\"/><br /><sub><b>Mehdi Rahimi</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=mehdirahimi\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/clintaire\"><img src=\"https://avatars.githubusercontent.com/u/111376518?v=4?s=100\" width=\"100px;\" alt=\"Clint Airé\"/><br /><sub><b>Clint Airé</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=clintaire\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/darkhyper24\"><img src=\"https://avatars.githubusercontent.com/u/132711528?v=4?s=100\" width=\"100px;\" alt=\"darkhyper24\"/><br /><sub><b>darkhyper24</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=darkhyper24\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/MohanedAtef238\"><img src=\"https://avatars.githubusercontent.com/u/105852138?v=4?s=100\" width=\"100px;\" alt=\"Mohaned Atef\"/><br /><sub><b>Mohaned Atef</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=MohanedAtef238\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/maximevtush\"><img src=\"https://avatars.githubusercontent.com/u/154841002?v=4?s=100\" width=\"100px;\" alt=\"Maxim Evtush\"/><br /><sub><b>Maxim Evtush</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=maximevtush\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/hvgh88\"><img src=\"https://avatars.githubusercontent.com/u/65297242?v=4?s=100\" width=\"100px;\" alt=\"Harshita Vidapanakal\"/><br /><sub><b>Harshita Vidapanakal</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=hvgh88\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/smile-ab\"><img src=\"https://avatars.githubusercontent.com/u/202159894?v=4?s=100\" width=\"100px;\" alt=\"smile-ab\"/><br /><sub><b>smile-ab</b></sub></a><br /><a href=\"#translation-smile-ab\" title=\"Translation\">🌍</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=smile-ab\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Francisco-G-P\"><img src=\"https://avatars.githubusercontent.com/u/186766789?v=4?s=100\" width=\"100px;\" alt=\"Francisco-G-P\"/><br /><sub><b>Francisco-G-P</b></sub></a><br /><a href=\"#translation-Francisco-G-P\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Duartegdm\"><img src=\"https://avatars.githubusercontent.com/u/137895372?v=4?s=100\" width=\"100px;\" alt=\"Gabriel Duarte\"/><br /><sub><b>Gabriel Duarte</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Duartegdm\" title=\"Documentation\">📖</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/DenizAltunkapan\"><img src=\"https://avatars.githubusercontent.com/u/93663085?v=4?s=100\" width=\"100px;\" alt=\"Deniz Altunkapan\"/><br /><sub><b>Deniz Altunkapan</b></sub></a><br /><a href=\"#translation-DenizAltunkapan\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/johnklint81\"><img src=\"https://avatars.githubusercontent.com/u/70539458?v=4?s=100\" width=\"100px;\" alt=\"John Klint\"/><br /><sub><b>John Klint</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=johnklint81\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/sanurah\"><img src=\"https://avatars.githubusercontent.com/u/16178588?v=4?s=100\" width=\"100px;\" alt=\"Sanura Hettiarachchi\"/><br /><sub><b>Sanura Hettiarachchi</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=sanurah\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/2897robo\"><img src=\"https://avatars.githubusercontent.com/u/31699375?v=4?s=100\" width=\"100px;\" alt=\"Kim Gi Uk\"/><br /><sub><b>Kim Gi Uk</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=2897robo\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Suchismita-Deb\"><img src=\"https://avatars.githubusercontent.com/u/68535074?v=4?s=100\" width=\"100px;\" alt=\"Suchismita Deb\"/><br /><sub><b>Suchismita Deb</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Suchismita-Deb\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/ssrijan-007-sys\"><img src=\"https://avatars.githubusercontent.com/u/137605821?v=4?s=100\" width=\"100px;\" alt=\"ssrijan-007-sys\"/><br /><sub><b>ssrijan-007-sys</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ssrijan-007-sys\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/e5LA\"><img src=\"https://avatars.githubusercontent.com/u/208197507?v=4?s=100\" width=\"100px;\" alt=\"e5LA\"/><br /><sub><b>e5LA</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=e5LA\" title=\"Code\">💻</a> <a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=e5LA\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"http://maziyar-gerami.github.io/portfolio/\"><img src=\"https://avatars.githubusercontent.com/u/122622721?v=4?s=100\" width=\"100px;\" alt=\"Maziyar Gerami\"/><br /><sub><b>Maziyar Gerami</b></sub></a><br /><a href=\"#translation-maziyar-gerami\" title=\"Translation\">🌍</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/yybmion\"><img src=\"https://avatars.githubusercontent.com/u/113106136?v=4?s=100\" width=\"100px;\" alt=\"yoobin_mion\"/><br /><sub><b>yoobin_mion</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=yybmion\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://ronodhirsoumik.github.io\"><img src=\"https://avatars.githubusercontent.com/u/46843689?v=4?s=100\" width=\"100px;\" alt=\"Soumik Sarker\"/><br /><sub><b>Soumik Sarker</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=ronodhirSoumik\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/naman-sriv\"><img src=\"https://avatars.githubusercontent.com/u/82610773?v=4?s=100\" width=\"100px;\" alt=\"Naman Srivastava\"/><br /><sub><b>Naman Srivastava</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=naman-sriv\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/letdtcode\"><img src=\"https://avatars.githubusercontent.com/u/92111552?v=4?s=100\" width=\"100px;\" alt=\"Thanh Nguyen Duc\"/><br /><sub><b>Thanh Nguyen Duc</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=letdtcode\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/skamble2\"><img src=\"https://avatars.githubusercontent.com/u/121136639?v=4?s=100\" width=\"100px;\" alt=\"Soham Kamble\"/><br /><sub><b>Soham Kamble</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=skamble2\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"16.66%\"><a href=\"https://github.com/Olexandr88\"><img src=\"https://avatars.githubusercontent.com/u/93856062?v=4?s=100\" width=\"100px;\" alt=\"Olexandr88\"/><br /><sub><b>Olexandr88</b></sub></a><br /><a href=\"https://github.com/iluwatar/java-design-patterns/commits?author=Olexandr88\" title=\"Documentation\">📖</a></td>\n    </tr>\n  </tbody>\n</table>\n\n<!-- markdownlint-restore -->\n<!-- prettier-ignore-end -->\n\n<!-- ALL-CONTRIBUTORS-LIST:END -->\n"
  },
  {
    "path": "abstract-document/README.md",
    "content": "---\ntitle: \"Abstract Document Pattern in Java: Simplifying Data Handling with Flexibility\"\nshortTitle: Abstract Document\ndescription: \"Explore the Abstract Document design pattern in Java. Learn its intent, explanation, applicability, benefits, and see real-world examples to implement flexible and dynamic data structures.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Abstraction\n  - Decoupling\n  - Dynamic typing\n  - Encapsulation\n  - Extensibility\n  - Polymorphism\n---\n\n## Intent of Abstract Document Design Pattern\n\nThe Abstract Document design pattern in Java is a crucial structural design pattern that provides a consistent way to handle hierarchical and tree-like data structures by defining a common interface for various document types. It separates the core document structure from specific data formats, enabling dynamic updates and simplified maintenance.\n\n## Detailed Explanation of Abstract Document Pattern with Real-World Examples\n\nThe Abstract Document design pattern in Java allows dynamic handling of non-static properties. This pattern uses concept of traits to enable type safety and separate properties of different classes into set of interfaces.\n\nReal-world example\n\n> Consider a library system implementing the Abstract Document design pattern in Java, where books can have diverse formats and attributes: physical books, eBooks, and audiobooks. Each format has unique properties, such as page count for physical books, file size for eBooks, and duration for audiobooks. The Abstract Document design pattern allows the library system to manage these diverse formats flexibly. By using this pattern, the system can store and retrieve properties dynamically, without needing a rigid structure for each book type, making it easier to add new formats or attributes in the future without significant changes to the codebase.\n\nIn plain words\n\n> Abstract Document pattern allows attaching properties to objects without them knowing about it.\n\nWikipedia says\n\n> An object-oriented structural design pattern for organizing objects in loosely typed key-value stores and exposing the data using typed views. The purpose of the pattern is to achieve a high degree of flexibility between components in a strongly typed language where new properties can be added to the object-tree on the fly, without losing the support of type-safety. The pattern makes use of traits to separate different properties of a class into different interfaces.\n\nClass diagram\n\n![Abstract Document class diagram](./etc/abstract-document.png \"Abstract Document class diagram\")\n\n\n## Programmatic Example of Abstract Document Pattern in Java\n\nConsider a car that consists of multiple parts. However, we don't know if the specific car really has all the parts, or just some of them. Our cars are dynamic and extremely flexible.\n\nLet's first define the base classes `Document` and `AbstractDocument`. They basically make the object hold a property map and any amount of child objects.\n\n```java\npublic interface Document {\n\n    Void put(String key, Object value);\n\n    Object get(String key);\n\n    <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);\n}\n\npublic abstract class AbstractDocument implements Document {\n\n    private final Map<String, Object> properties;\n\n    protected AbstractDocument(Map<String, Object> properties) {\n        Objects.requireNonNull(properties, \"properties map is required\");\n        this.properties = properties;\n    }\n\n    @Override\n    public Void put(String key, Object value) {\n        properties.put(key, value);\n        return null;\n    }\n\n    @Override\n    public Object get(String key) {\n        return properties.get(key);\n    }\n\n    @Override\n    public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {\n        return Stream.ofNullable(get(key))\n                .filter(Objects::nonNull)\n                .map(el -> (List<Map<String, Object>>) el)\n                .findAny()\n                .stream()\n                .flatMap(Collection::stream)\n                .map(constructor);\n    }\n    \n    // Other properties and methods...\n}\n```\n\nNext we define an enum `Property` and a set of interfaces for type, price, model and parts. This allows us to create static looking interface to our `Car` class.\n\n```java\npublic enum Property {\n\n    PARTS, TYPE, PRICE, MODEL\n}\n\npublic interface HasType extends Document {\n\n    default Optional<String> getType() {\n        return Optional.ofNullable((String) get(Property.TYPE.toString()));\n    }\n}\n\npublic interface HasPrice extends Document {\n\n    default Optional<Number> getPrice() {\n        return Optional.ofNullable((Number) get(Property.PRICE.toString()));\n    }\n}\n\npublic interface HasModel extends Document {\n\n    default Optional<String> getModel() {\n        return Optional.ofNullable((String) get(Property.MODEL.toString()));\n    }\n}\n\npublic interface HasParts extends Document {\n\n    default Stream<Part> getParts() {\n        return children(Property.PARTS.toString(), Part::new);\n    }\n}\n\npublic class Part extends AbstractDocument implements HasType, HasModel, HasPrice {\n\n    public Part(Map<String, Object> properties) {\n        super(properties);\n    }\n}\n```\n\nNow we are ready to introduce the `Car`.\n\n```java\npublic class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {\n\n    public Car(Map<String, Object> properties) {\n        super(properties);\n    }\n}\n```\n\nAnd finally here's how we construct and use the `Car` in a full example.\n\n```java\n  public static void main(String[] args) {\n    LOGGER.info(\"Constructing parts and car\");\n\n    var wheelProperties = Map.of(\n            Property.TYPE.toString(), \"wheel\",\n            Property.MODEL.toString(), \"15C\",\n            Property.PRICE.toString(), 100L);\n\n    var doorProperties = Map.of(\n            Property.TYPE.toString(), \"door\",\n            Property.MODEL.toString(), \"Lambo\",\n            Property.PRICE.toString(), 300L);\n\n    var carProperties = Map.of(\n            Property.MODEL.toString(), \"300SL\",\n            Property.PRICE.toString(), 10000L,\n            Property.PARTS.toString(), List.of(wheelProperties, doorProperties));\n\n    var car = new Car(carProperties);\n\n    LOGGER.info(\"Here is our car:\");\n    LOGGER.info(\"-> model: {}\", car.getModel().orElseThrow());\n    LOGGER.info(\"-> price: {}\", car.getPrice().orElseThrow());\n    LOGGER.info(\"-> parts: \");\n    car.getParts().forEach(p -> LOGGER.info(\"\\t{}/{}/{}\",\n            p.getType().orElse(null),\n            p.getModel().orElse(null),\n            p.getPrice().orElse(null))\n    );\n}\n```\n\nThe program output:\n\n```\n07:21:57.391 [main] INFO com.iluwatar.abstractdocument.App -- Constructing parts and car\n07:21:57.393 [main] INFO com.iluwatar.abstractdocument.App -- Here is our car:\n07:21:57.393 [main] INFO com.iluwatar.abstractdocument.App -- -> model: 300SL\n07:21:57.394 [main] INFO com.iluwatar.abstractdocument.App -- -> price: 10000\n07:21:57.394 [main] INFO com.iluwatar.abstractdocument.App -- -> parts: \n07:21:57.395 [main] INFO com.iluwatar.abstractdocument.App -- \twheel/15C/100\n07:21:57.395 [main] INFO com.iluwatar.abstractdocument.App -- \tdoor/Lambo/300\n```\n\n## When to Use the Abstract Document Pattern in Java\n\nThe Abstract Document design pattern is especially beneficial in scenarios requiring management of different document types in Java that share some common attributes or behaviors, but also have unique attributes or behaviors specific to their individual types. Here are some scenarios where the Abstract Document design pattern can be applicable:\n\n* Content Management Systems (CMS): In a CMS, you might have various types of content such as articles, images, videos, etc. Each type of content could have shared attributes like creation date, author, and tags, while also having specific attributes like image dimensions for images or video duration for videos.\n\n* File Systems: If you're designing a file system where different types of files need to be managed, such as documents, images, audio files, and directories, the Abstract Document pattern can help provide a consistent way to access attributes like file size, creation date, etc., while allowing for specific attributes like image resolution or audio duration.\n\n* E-commerce Systems: An e-commerce platform might have different product types such as physical products, digital downloads, and subscriptions. Each type could share common attributes like name, price, and description, while having unique attributes like shipping weight for physical products or download link for digital products.\n\n* Medical Records Systems: In healthcare, patient records might include various types of data such as demographics, medical history, test results, and prescriptions. The Abstract Document pattern can help manage shared attributes like patient ID and date of birth, while accommodating specialized attributes like test results or prescribed medications.\n\n* Configuration Management: When dealing with configuration settings for software applications, there can be different types of configuration elements, each with its own set of attributes. The Abstract Document pattern can be used to manage these configuration elements while ensuring a consistent way to access and manipulate their attributes.\n\n* Educational Platforms: Educational systems might have various types of learning materials such as text-based content, videos, quizzes, and assignments. Common attributes like title, author, and publication date can be shared, while unique attributes like video duration or assignment due dates can be specific to each type.\n\n* Project Management Tools: In project management applications, you could have different types of tasks like to-do items, milestones, and issues. The Abstract Document pattern could be used to handle general attributes like task name and assignee, while allowing for specific attributes like milestone date or issue priority.\n\n* Documents have diverse and evolving attribute structures.\n\n* Dynamically adding new properties is a common requirement.\n\n* Decoupling data access from specific formats is crucial.\n\n* Maintainability and flexibility are critical for the codebase.\n\nThe key idea behind the Abstract Document design pattern is to provide a flexible and extensible way to manage different types of documents or entities with shared and distinct attributes. By defining a common interface and implementing it across various document types, you can achieve a more organized and consistent approach to handling complex data structures.\n\n## Benefits and Trade-offs of Abstract Document Pattern\n\nBenefits:\n\n* Flexibility: Accommodates varied document structures and properties.\n\n* Extensibility: Dynamically add new attributes without breaking existing code.\n\n* Maintainability: Promotes clean and adaptable code due to separation of concerns.\n\n* Reusability: Typed views enable code reuse for accessing specific attribute types.\n\nTrade-offs:\n\n* Complexity: Requires defining interfaces and views, adding implementation overhead.\n\n* Performance: Might introduce slight performance overhead compared to direct data access.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n* [Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4)](https://amzn.to/49zRP4R)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Abstract Document Pattern (Wikipedia)](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)\n* [Dealing with Properties (Martin Fowler)](http://martinfowler.com/apsupp/properties.pdf)\n"
  },
  {
    "path": "abstract-document/etc/abstract-document.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.2.2\" icons=\"true\" always-add-relationships=\"false\" generalizations=\"true\" realizations=\"true\" \n  associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.abstractdocument.AbstractDocument\" project=\"abstract-document\" \n    file=\"/abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"659\" y=\"286\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"2\" language=\"java\" name=\"com.iluwatar.abstractdocument.Document\" project=\"abstract-document\" \n    file=\"/abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"562\" y=\"27\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.abstractdocument.domain.Car\" project=\"abstract-document\" \n    file=\"/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"348\" y=\"737\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.abstractdocument.domain.Part\" project=\"abstract-document\" \n    file=\"/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"760\" y=\"746\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"5\" language=\"java\" name=\"com.iluwatar.abstractdocument.domain.HasModel\" project=\"abstract-document\" \n    file=\"/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"355\" y=\"297\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"6\" language=\"java\" name=\"com.iluwatar.abstractdocument.domain.HasParts\" project=\"abstract-document\" \n    file=\"/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"109\" y=\"297\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"7\" language=\"java\" name=\"com.iluwatar.abstractdocument.domain.HasPrice\" project=\"abstract-document\" \n    file=\"/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1008\" y=\"283\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"8\" language=\"java\" name=\"com.iluwatar.abstractdocument.domain.HasType\" project=\"abstract-document\" \n    file=\"/abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasType.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1257\" y=\"277\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <realization id=\"9\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </realization>  \n  <realization id=\"10\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </realization>  \n  <generalization id=\"11\">    \n    <end type=\"SOURCE\" refId=\"6\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </generalization>  \n  <realization id=\"12\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </realization>  \n  <realization id=\"13\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </realization>  \n  <generalization id=\"14\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <realization id=\"15\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </realization>  \n  <generalization id=\"16\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </generalization>  \n  <generalization id=\"17\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </generalization>  \n  <realization id=\"18\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </realization>  \n  <generalization id=\"19\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <generalization id=\"20\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </generalization>  \n  <realization id=\"21\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "abstract-document/etc/abstract-document.urm.puml",
    "content": "@startuml\npackage com.iluwatar.abstractdocument.domain.enums {\n  enum Property {\n    + MODEL {static}\n    + PARTS {static}\n    + PRICE {static}\n    + TYPE {static}\n    + valueOf(name : String) : Property {static}\n    + values() : Property[] {static}\n  }\n}\npackage com.iluwatar.abstractdocument.domain {\n  class Car {\n    + Car(properties : Map<String, Object>)\n  }\n  interface HasModel {\n    + getModel() : Optional<String>\n  }\n  interface HasParts {\n    + getParts() : Stream<Part>\n  }\n  interface HasPrice {\n    + getPrice() : Optional<Number>\n  }\n  interface HasType {\n    + getType() : Optional<String>\n  }\n  class Part {\n    + Part(properties : Map<String, Object>)\n  }\n}\npackage com.iluwatar.abstractdocument {\n  abstract class AbstractDocument {\n    - properties : Map<String, Object>\n    # AbstractDocument(properties : Map<String, Object>)\n    + children(key : String, constructor : Function<Map<String, Object>, T>) : Stream<T>\n    + get(key : String) : Object\n    + put(key : String, value : Object)\n    + toString() : String\n  }\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  interface Document {\n    + children(String, Function<Map<String, Object>, T>) : Stream<T> {abstract}\n    + get(String) : Object {abstract}\n    + put(String, Object) {abstract}\n  }\n}\nAbstractDocument ..|> Document \nCar ..|> HasModel \nCar ..|> HasPrice \nCar ..|> HasParts \nCar --|> AbstractDocument \nHasModel --|> Document \nHasParts --|> Document \nHasPrice --|> Document \nHasType --|> Document \nPart ..|> HasType \nPart ..|> HasModel \nPart ..|> HasPrice \nPart --|> AbstractDocument \n@enduml"
  },
  {
    "path": "abstract-document/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>abstract-document</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <!-- Maven assembly plugin is invoked with default setting which we have \n\t\t\t\tin parent pom and specifying the class having main method -->\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.abstractdocument.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.function.Function;\nimport java.util.stream.Stream;\n\n/** Abstract implementation of Document interface. */\npublic abstract class AbstractDocument implements Document {\n\n  private final Map<String, Object> documentProperties;\n\n  protected AbstractDocument(Map<String, Object> properties) {\n    Objects.requireNonNull(properties, \"properties map is required\");\n    this.documentProperties = properties;\n  }\n\n  @Override\n  public Void put(String key, Object value) {\n    documentProperties.put(key, value);\n    return null;\n  }\n\n  @Override\n  public Object get(String key) {\n    return documentProperties.get(key);\n  }\n\n  @Override\n  public <T> Stream<T> children(String key, Function<Map<String, Object>, T> childConstructor) {\n    return Stream.ofNullable(get(key))\n        .filter(Objects::nonNull)\n        .map(el -> (List<Map<String, Object>>) el)\n        .findAny()\n        .stream()\n        .flatMap(Collection::stream)\n        .map(childConstructor);\n  }\n\n  @Override\n  public String toString() {\n    return buildStringRepresentation();\n  }\n\n  private String buildStringRepresentation() {\n    var builder = new StringBuilder();\n    builder.append(getClass().getName()).append(\"[\");\n\n    // Explaining variable for document properties map\n    Map<String, Object> documentProperties = this.documentProperties;\n\n    // Explaining variable for the size of document properties map\n    int numProperties = documentProperties.size();\n\n    // Explaining variable for tracking the current property index\n    int currentPropertyIndex = 0;\n\n    // Iterate over document properties map\n    for (Map.Entry<String, Object> entry : documentProperties.entrySet()) {\n      String key = entry.getKey();\n      Object value = entry.getValue();\n\n      // Append key-value pair\n      builder.append(\"[\").append(key).append(\" : \").append(value).append(\"]\");\n\n      // Add comma if not last property\n      if (++currentPropertyIndex < numProperties) {\n        builder.append(\", \");\n      }\n    }\n\n    builder.append(\"]\");\n    return builder.toString();\n  }\n}\n"
  },
  {
    "path": "abstract-document/src/main/java/com/iluwatar/abstractdocument/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument;\n\nimport com.iluwatar.abstractdocument.domain.Car;\nimport com.iluwatar.abstractdocument.domain.enums.Property;\nimport java.util.List;\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Abstract Document pattern enables handling additional, non-static properties. This pattern\n * uses concept of traits to enable type safety and separate properties of different classes into\n * set of interfaces.\n *\n * <p>In Abstract Document pattern,({@link AbstractDocument}) fully implements {@link Document})\n * interface. Traits are then defined to enable access to properties in usual, static way.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    LOGGER.info(\"Constructing parts and car\");\n\n    var wheelProperties =\n        Map.of(\n            Property.TYPE.toString(), \"wheel\",\n            Property.MODEL.toString(), \"15C\",\n            Property.PRICE.toString(), 100L);\n\n    var doorProperties =\n        Map.of(\n            Property.TYPE.toString(), \"door\",\n            Property.MODEL.toString(), \"Lambo\",\n            Property.PRICE.toString(), 300L);\n\n    var carProperties =\n        Map.of(\n            Property.MODEL.toString(),\n            \"300SL\",\n            Property.PRICE.toString(),\n            10000L,\n            Property.PARTS.toString(),\n            List.of(wheelProperties, doorProperties));\n\n    var car = new Car(carProperties);\n\n    LOGGER.info(\"Here is our car:\");\n    LOGGER.info(\"-> model: {}\", car.getModel().orElseThrow());\n    LOGGER.info(\"-> price: {}\", car.getPrice().orElseThrow());\n    LOGGER.info(\"-> parts: \");\n    car.getParts()\n        .forEach(\n            p ->\n                LOGGER.info(\n                    \"\\t{}/{}/{}\",\n                    p.getType().orElse(null),\n                    p.getModel().orElse(null),\n                    p.getPrice().orElse(null)));\n  }\n}\n"
  },
  {
    "path": "abstract-document/src/main/java/com/iluwatar/abstractdocument/Document.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument;\n\nimport java.util.Map;\nimport java.util.function.Function;\nimport java.util.stream.Stream;\n\n/** Document interface. */\npublic interface Document {\n\n  /**\n   * Puts the value related to the key.\n   *\n   * @param key element key\n   * @param value element value\n   * @return Void\n   */\n  Void put(String key, Object value);\n\n  /**\n   * Gets the value for the key.\n   *\n   * @param key element key\n   * @return value or null\n   */\n  Object get(String key);\n\n  /**\n   * Gets the stream of child documents.\n   *\n   * @param key element key\n   * @param constructor constructor of child class\n   * @return child documents\n   */\n  <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);\n}\n"
  },
  {
    "path": "abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument.domain;\n\nimport com.iluwatar.abstractdocument.AbstractDocument;\nimport java.util.Map;\n\n/** Car entity. */\npublic class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {\n\n  public Car(Map<String, Object> properties) {\n    super(properties);\n  }\n}\n"
  },
  {
    "path": "abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasModel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument.domain;\n\nimport com.iluwatar.abstractdocument.Document;\nimport com.iluwatar.abstractdocument.domain.enums.Property;\nimport java.util.Optional;\n\n/** HasModel trait for static access to 'model' property. */\npublic interface HasModel extends Document {\n\n  default Optional<String> getModel() {\n    return Optional.ofNullable((String) get(Property.MODEL.toString()));\n  }\n}\n"
  },
  {
    "path": "abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasParts.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument.domain;\n\nimport com.iluwatar.abstractdocument.Document;\nimport com.iluwatar.abstractdocument.domain.enums.Property;\nimport java.util.stream.Stream;\n\n/** HasParts trait for static access to 'parts' property. */\npublic interface HasParts extends Document {\n\n  default Stream<Part> getParts() {\n    return children(Property.PARTS.toString(), Part::new);\n  }\n}\n"
  },
  {
    "path": "abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument.domain;\n\nimport com.iluwatar.abstractdocument.Document;\nimport com.iluwatar.abstractdocument.domain.enums.Property;\nimport java.util.Optional;\n\n/** HasPrice trait for static access to 'price' property. */\npublic interface HasPrice extends Document {\n\n  default Optional<Number> getPrice() {\n    return Optional.ofNullable((Number) get(Property.PRICE.toString()));\n  }\n}\n"
  },
  {
    "path": "abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument.domain;\n\nimport com.iluwatar.abstractdocument.Document;\nimport com.iluwatar.abstractdocument.domain.enums.Property;\nimport java.util.Optional;\n\n/** HasType trait for static access to 'type' property. */\npublic interface HasType extends Document {\n\n  default Optional<String> getType() {\n    return Optional.ofNullable((String) get(Property.TYPE.toString()));\n  }\n}\n"
  },
  {
    "path": "abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Part.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument.domain;\n\nimport com.iluwatar.abstractdocument.AbstractDocument;\nimport java.util.Map;\n\n/** Part entity. */\npublic class Part extends AbstractDocument implements HasType, HasModel, HasPrice {\n\n  public Part(Map<String, Object> properties) {\n    super(properties);\n  }\n}\n"
  },
  {
    "path": "abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/enums/Property.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument.domain.enums;\n\n/** Enum To Describe Property type. */\npublic enum Property {\n  PARTS,\n  TYPE,\n  PRICE,\n  MODEL\n}\n"
  },
  {
    "path": "abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport org.junit.jupiter.api.Test;\n\n/** AbstractDocument test class */\nclass AbstractDocumentTest {\n\n  private static final String KEY = \"key\";\n  private static final String VALUE = \"value\";\n\n  private static class DocumentImplementation extends AbstractDocument {\n\n    DocumentImplementation(Map<String, Object> properties) {\n      super(properties);\n    }\n  }\n\n  private final DocumentImplementation document = new DocumentImplementation(new HashMap<>());\n\n  @Test\n  void shouldPutAndGetValue() {\n    document.put(KEY, VALUE);\n    assertEquals(VALUE, document.get(KEY));\n  }\n\n  @Test\n  void shouldRetrieveChildren() {\n    var children = List.of(Map.of(), Map.of());\n\n    document.put(KEY, children);\n\n    var childrenStream = document.children(KEY, DocumentImplementation::new);\n    assertNotNull(children);\n    assertEquals(2, childrenStream.count());\n  }\n\n  @Test\n  void shouldRetrieveEmptyStreamForNonExistingChildren() {\n    var children = document.children(KEY, DocumentImplementation::new);\n    assertNotNull(children);\n    assertEquals(0, children.count());\n  }\n\n  @Test\n  void shouldIncludePropsInToString() {\n    var props = Map.of(KEY, (Object) VALUE);\n    var document = new DocumentImplementation(props);\n    assertTrue(document.toString().contains(KEY));\n    assertTrue(document.toString().contains(VALUE));\n  }\n\n  @Test\n  void shouldHandleExceptionDuringConstruction() {\n    Map<String, Object> invalidProperties =\n        null; // Invalid properties, causing NullPointerException\n\n    // Throw null pointer exception\n    assertThrows(\n        NullPointerException.class,\n        () -> {\n          // Attempt to construct a document with invalid properties\n          new DocumentImplementation(invalidProperties);\n        });\n  }\n\n  @Test\n  void shouldPutAndGetNestedDocument() {\n    // Creating a nested document\n    DocumentImplementation nestedDocument = new DocumentImplementation(new HashMap<>());\n    nestedDocument.put(\"nestedKey\", \"nestedValue\");\n\n    document.put(\"nested\", nestedDocument);\n\n    // Retrieving the nested document\n    DocumentImplementation retrievedNestedDocument =\n        (DocumentImplementation) document.get(\"nested\");\n\n    assertNotNull(retrievedNestedDocument);\n    assertEquals(\"nestedValue\", retrievedNestedDocument.get(\"nestedKey\"));\n  }\n\n  @Test\n  void shouldUpdateExistingValue() {\n    // Arrange\n    final String key = \"key\";\n    final String originalValue = \"originalValue\";\n    final String updatedValue = \"updatedValue\";\n\n    // Initializing the value\n    document.put(key, originalValue);\n\n    // Verifying that the initial value is retrieved correctly\n    assertEquals(originalValue, document.get(key));\n\n    // Updating the value\n    document.put(key, updatedValue);\n\n    // Verifying that the updated value is retrieved correctly\n    assertEquals(updatedValue, document.get(key));\n  }\n}\n"
  },
  {
    "path": "abstract-document/src/test/java/com/iluwatar/abstractdocument/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Simple App test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteAppWithoutException() {\n    assertDoesNotThrow(() -> App.main(null));\n  }\n}\n"
  },
  {
    "path": "abstract-document/src/test/java/com/iluwatar/abstractdocument/DomainTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractdocument;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.abstractdocument.domain.Car;\nimport com.iluwatar.abstractdocument.domain.Part;\nimport com.iluwatar.abstractdocument.domain.enums.Property;\nimport java.util.List;\nimport java.util.Map;\nimport org.junit.jupiter.api.Test;\n\n/** Test for Part and Car */\nclass DomainTest {\n\n  private static final String TEST_PART_TYPE = \"test-part-type\";\n  private static final String TEST_PART_MODEL = \"test-part-model\";\n  private static final long TEST_PART_PRICE = 0L;\n\n  private static final String TEST_CAR_MODEL = \"test-car-model\";\n  private static final long TEST_CAR_PRICE = 1L;\n\n  @Test\n  void shouldConstructPart() {\n    var partProperties =\n        Map.of(\n            Property.TYPE.toString(), TEST_PART_TYPE,\n            Property.MODEL.toString(), TEST_PART_MODEL,\n            Property.PRICE.toString(), (Object) TEST_PART_PRICE);\n    var part = new Part(partProperties);\n    assertEquals(TEST_PART_TYPE, part.getType().orElseThrow());\n    assertEquals(TEST_PART_MODEL, part.getModel().orElseThrow());\n    assertEquals(TEST_PART_PRICE, part.getPrice().orElseThrow());\n  }\n\n  @Test\n  void shouldConstructCar() {\n    var carProperties =\n        Map.of(\n            Property.MODEL.toString(), TEST_CAR_MODEL,\n            Property.PRICE.toString(), TEST_CAR_PRICE,\n            Property.PARTS.toString(), List.of(Map.of(), Map.of()));\n    var car = new Car(carProperties);\n    assertEquals(TEST_CAR_MODEL, car.getModel().orElseThrow());\n    assertEquals(TEST_CAR_PRICE, car.getPrice().orElseThrow());\n    assertEquals(2, car.getParts().count());\n  }\n}\n"
  },
  {
    "path": "abstract-factory/.gitignore",
    "content": "/target/\n"
  },
  {
    "path": "abstract-factory/README.md",
    "content": "---\ntitle: \"Abstract Factory Pattern in Java: Mastering Object Creation Elegantly\"\nshortTitle: Abstract Factory\ndescription: \"Learn the Abstract Factory pattern in Java with real-world examples, class diagrams, and tutorials. Understand its intent, applicability, benefits, and known uses to enhance your design pattern knowledge.\"\ncategory: Creational\nlanguage: en\ntag:\n  - Abstraction\n  - Decoupling\n  - Gang of Four\n  - Instantiation\n  - Polymorphism\n---\n\n## Also known as\n\n* Kit\n\n## Intent of Abstract Factory Design Pattern\n\nThe Abstract Factory pattern in Java provides an interface for creating families of related or dependent objects without specifying their concrete classes, enhancing modularity and flexibility in software design.\n\n## Detailed Explanation of Abstract Factory Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a furniture company that uses the Abstract Factory pattern in Java to produce various styles of furniture: modern, Victorian, and rustic. Each style includes products like chairs, tables, and sofas. To ensure consistency within each style, the company uses an Abstract Factory pattern.\n>\n> In this scenario, the Abstract Factory is an interface for creating families of related furniture objects (chairs, tables, sofas). Each concrete factory (ModernFurnitureFactory, VictorianFurnitureFactory, RusticFurnitureFactory) implements the Abstract Factory interface and creates a set of products that match the specific style. This way, clients can create a whole set of modern or Victorian furniture without worrying about the details of their instantiation. This maintains a consistent style and allows easy swapping of one style of furniture for another.\n\nIn plain words\n\n> A factory of factories; a factory that groups the individual but related/dependent factories together without specifying their concrete classes.\n\nWikipedia says\n\n> The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes\n\nClass diagram\n\n![Abstract Factory class diagram](./etc/abstract-factory.urm.png \"Abstract Factory class diagram\")\n\n## Programmatic Example of Abstract Factory in Java\n\nTo create a kingdom using the Abstract Factory pattern in Java, we need objects with a common theme. The elven kingdom needs an elven king, elven castle, and elven army whereas the orcish kingdom needs an orcish king, orcish castle, and orcish army. There is a dependency between the objects in the kingdom.\n\nTranslating the kingdom example above. First of all, we have some interfaces and implementation for the objects in the kingdom.\n\n```java\npublic interface Castle {\n    String getDescription();\n}\n\npublic interface King {\n    String getDescription();\n}\n\npublic interface Army {\n    String getDescription();\n}\n\n// Elven implementations ->\npublic class ElfCastle implements Castle {\n    static final String DESCRIPTION = \"This is the elven castle!\";\n\n    @Override\n    public String getDescription() {\n        return DESCRIPTION;\n    }\n}\n\npublic class ElfKing implements King {\n    static final String DESCRIPTION = \"This is the elven king!\";\n\n    @Override\n    public String getDescription() {\n        return DESCRIPTION;\n    }\n}\n\npublic class ElfArmy implements Army {\n    static final String DESCRIPTION = \"This is the elven Army!\";\n\n    @Override\n    public String getDescription() {\n        return DESCRIPTION;\n    }\n}\n\n// Orcish implementations similarly -> ...\n```\n\nThen we have the abstraction and implementations for the kingdom factory.\n\n```java\npublic interface KingdomFactory {\n    Castle createCastle();\n\n    King createKing();\n\n    Army createArmy();\n}\n\npublic class ElfKingdomFactory implements KingdomFactory {\n\n    @Override\n    public Castle createCastle() {\n        return new ElfCastle();\n    }\n\n    @Override\n    public King createKing() {\n        return new ElfKing();\n    }\n\n    @Override\n    public Army createArmy() {\n        return new ElfArmy();\n    }\n}\n\n// Orcish implementations similarly -> ...\n```\n\nNow, we can design a factory for our different kingdom factories. In this example, we created `FactoryMaker`, responsible for returning an instance of either `ElfKingdomFactory` or `OrcKingdomFactory`. The client can use `FactoryMaker` to create the desired concrete factory which, in turn, will produce different concrete objects (derived from `Army`, `King`, `Castle`). In this example, we also used an enum to parameterize which type of kingdom factory the client will ask for.\n\n```java\npublic static class FactoryMaker {\n\n    public enum KingdomType {\n        ELF, ORC\n    }\n\n    public static KingdomFactory makeFactory(KingdomType type) {\n        return switch (type) {\n            case ELF -> new ElfKingdomFactory();\n            case ORC -> new OrcKingdomFactory();\n        };\n    }\n}\n```\n\nHere is the main function of our example application:\n\n```java\nLOGGER.info(\"elf kingdom\");\ncreateKingdom(Kingdom.FactoryMaker.KingdomType.ELF);\nLOGGER.info(kingdom.getArmy().getDescription());\nLOGGER.info(kingdom.getCastle().getDescription());\nLOGGER.info(kingdom.getKing().getDescription());\n\nLOGGER.info(\"orc kingdom\");\ncreateKingdom(Kingdom.FactoryMaker.KingdomType.ORC);\nLOGGER.info(kingdom.getArmy().getDescription());\nLOGGER.info(kingdom.getCastle().getDescription());\nLOGGER.info(kingdom.getKing().getDescription());\n```\n\nThe program output:\n\n```\n07:35:46.340 [main] INFO com.iluwatar.abstractfactory.App -- elf kingdom\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven army!\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven castle!\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven king!\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- orc kingdom\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc army!\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc castle!\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc king!\n```\n\n## When to Use the Abstract Factory Pattern in Java\n\nUse the Abstract Factory pattern in Java when:\n\n* The system should be independent of how its products are created, composed, and represented.\n* You need to configure the system with one of multiple families of products.\n* A family of related product objects must be used together, enforcing consistency.\n* You want to provide a class library of products, exposing only their interfaces, not their implementations.\n* The lifetime of dependencies is shorter than the consumer's lifetime.\n* Dependencies need to be constructed using runtime values or parameters.\n* You need to choose which product to use from a family at runtime.\n* Adding new products or families should not require changes to existing code.\n\n## Abstract Factory Pattern Java Tutorials\n\n* [Abstract Factory Design Pattern in Java (DigitalOcean)](https://www.digitalocean.com/community/tutorials/abstract-factory-design-pattern-in-java)\n* [Abstract Factory(Refactoring Guru)](https://refactoring.guru/design-patterns/abstract-factory)\n\n## Benefits and Trade-offs of Abstract Factory Pattern\n\nBenefits:\n\n* Flexibility: Easily switch between product families without code modifications.\n\n* Decoupling: Client code only interacts with abstract interfaces, promoting portability and maintainability.\n\n* Reusability: Abstract factories and products facilitate component reuse across projects.\n\n* Maintainability: Changes to individual product families are localized, simplifying updates.\n\nTrade-offs:\n\n* Complexity: Defining abstract interfaces and concrete factories adds initial overhead.\n\n* Indirectness: Client code interacts with products indirectly through factories, potentially reducing transparency.\n\n## Real-World Applications of Abstract Factory Pattern in Java\n\n* Java Swing's `LookAndFeel` classes for providing different look-and-feel options.\n* Various implementations in the Java Abstract Window Toolkit (AWT) for creating different GUI components.\n* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)\n* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)\n* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)\n\n## Related Java Design Patterns\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Abstract Factory uses Factory Methods to create products.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Abstract Factory classes are often implemented as Singletons.\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/): Similar to Abstract Factory but focuses on configuring and managing a set of related objects in a flexible way.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Design Patterns in Java](https://amzn.to/3Syw0vC)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3HWNf4U)\n"
  },
  {
    "path": "abstract-factory/etc/abstract-factory.urm.puml",
    "content": "@startuml\npackage com.iluwatar.abstractfactory {\n  class App {\n    - LOGGER : Logger {static}\n    - army : Army\n    - castle : Castle\n    - king : King\n    + App()\n    + createKingdom(factory : KingdomFactory)\n    + getArmy() : Army\n    ~ getArmy(factory : KingdomFactory) : Army\n    + getCastle() : Castle\n    ~ getCastle(factory : KingdomFactory) : Castle\n    + getKing() : King\n    ~ getKing(factory : KingdomFactory) : King\n    + main(args : String[]) {static}\n    - setArmy(army : Army)\n    - setCastle(castle : Castle)\n    - setKing(king : King)\n  }\n  class FactoryMaker {\n    + FactoryMaker()\n    + makeFactory(type : KingdomType) : KingdomFactory {static}\n  }\n  enum KingdomType {\n    + ELF {static}\n    + ORC {static}\n    + valueOf(name : String) : KingdomType {static}\n    + values() : KingdomType[] {static}\n  }\n  interface Army {\n    + getDescription() : String {abstract}\n  }\n  interface Castle {\n    + getDescription() : String {abstract}\n  }\n  class ElfArmy {\n    ~ DESCRIPTION : String {static}\n    + ElfArmy()\n    + getDescription() : String\n  }\n  class ElfCastle {\n    ~ DESCRIPTION : String {static}\n    + ElfCastle()\n    + getDescription() : String\n  }\n  class ElfKing {\n    ~ DESCRIPTION : String {static}\n    + ElfKing()\n    + getDescription() : String\n  }\n  class ElfKingdomFactory {\n    + ElfKingdomFactory()\n    + createArmy() : Army\n    + createCastle() : Castle\n    + createKing() : King\n  }\n  interface King {\n    + getDescription() : String {abstract}\n  }\n  interface KingdomFactory {\n    + createArmy() : Army {abstract}\n    + createCastle() : Castle {abstract}\n    + createKing() : King {abstract}\n  }\n  class OrcArmy {\n    ~ DESCRIPTION : String {static}\n    + OrcArmy()\n    + getDescription() : String\n  }\n  class OrcCastle {\n    ~ DESCRIPTION : String {static}\n    + OrcCastle()\n    + getDescription() : String\n  }\n  class OrcKing {\n    ~ DESCRIPTION : String {static}\n    + OrcKing()\n    + getDescription() : String\n  }\n  class OrcKingdomFactory {\n    + OrcKingdomFactory()\n    + createArmy() : Army\n    + createCastle() : Castle\n    + createKing() : King\n  }\n}\nKingdomType ..+ FactoryMaker\nApp -->  \"-castle\" Castle\nFactoryMaker ..+ App\nApp -->  \"-king\" King\nApp -->  \"-army\" Army\nElfArmy ..|> Army \nElfCastle ..|> Castle \nElfKing ..|> King \nElfKingdomFactory ..|> KingdomFactory \nOrcArmy ..|> Army \nOrcCastle ..|> Castle \nOrcKing ..|> King \nOrcKingdomFactory ..|> KingdomFactory \n@enduml"
  },
  {
    "path": "abstract-factory/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>abstract-factory</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <!-- Maven assembly plugin is invoked with default setting which we have \n\t\t\t\tin parent pom and specifying the class having main method -->\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.abstractfactory.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Abstract Factory pattern provides a way to encapsulate a group of individual factories that\n * have a common theme without specifying their concrete classes. In normal usage, the client\n * software creates a concrete implementation of the abstract factory and then uses the generic\n * interface of the factory to create the concrete objects that are part of the theme. The client\n * does not know (or care) which concrete objects it gets from each of these internal factories,\n * since it uses only the generic interfaces of their products. This pattern separates the details\n * of implementation of a set of objects from their general usage and relies on object composition,\n * as object creation is implemented in methods exposed in the factory interface.\n *\n * <p>The essence of the Abstract Factory pattern is a factory interface ({@link KingdomFactory})\n * and its implementations ( {@link ElfKingdomFactory}, {@link OrcKingdomFactory}). The example uses\n * both concrete implementations to create a king, a castle, and an army.\n */\n@Slf4j\n@Getter\npublic class App implements Runnable {\n\n  private final Kingdom kingdom = new Kingdom();\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var app = new App();\n    app.run();\n  }\n\n  @Override\n  public void run() {\n    LOGGER.info(\"elf kingdom\");\n    createKingdom(Kingdom.FactoryMaker.KingdomType.ELF);\n    LOGGER.info(kingdom.getArmy().getDescription());\n    LOGGER.info(kingdom.getCastle().getDescription());\n    LOGGER.info(kingdom.getKing().getDescription());\n\n    LOGGER.info(\"orc kingdom\");\n    createKingdom(Kingdom.FactoryMaker.KingdomType.ORC);\n    LOGGER.info(kingdom.getArmy().getDescription());\n    LOGGER.info(kingdom.getCastle().getDescription());\n    LOGGER.info(kingdom.getKing().getDescription());\n  }\n\n  /**\n   * Creates kingdom.\n   *\n   * @param kingdomType type of Kingdom\n   */\n  public void createKingdom(final Kingdom.FactoryMaker.KingdomType kingdomType) {\n    final KingdomFactory kingdomFactory = Kingdom.FactoryMaker.makeFactory(kingdomType);\n    kingdom.setKing(kingdomFactory.createKing());\n    kingdom.setCastle(kingdomFactory.createCastle());\n    kingdom.setArmy(kingdomFactory.createArmy());\n  }\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/Army.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\n/** Army interface. */\npublic interface Army {\n\n  String getDescription();\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/Castle.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\n/** Castle interface. */\npublic interface Castle {\n\n  String getDescription();\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfArmy.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\n/** ElfArmy. */\npublic class ElfArmy implements Army {\n\n  static final String DESCRIPTION = \"This is the elven army!\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfCastle.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\n/** ElfCastle. */\npublic class ElfCastle implements Castle {\n\n  static final String DESCRIPTION = \"This is the elven castle!\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKing.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\n/** ElfKing. */\npublic class ElfKing implements King {\n\n  static final String DESCRIPTION = \"This is the elven king!\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKingdomFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\n/** ElfKingdomFactory concrete factory. */\npublic class ElfKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new ElfCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new ElfKing();\n  }\n\n  @Override\n  public Army createArmy() {\n    return new ElfArmy();\n  }\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/King.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\n/** King interface. */\npublic interface King {\n\n  String getDescription();\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/Kingdom.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Helper class to manufacture {@link KingdomFactory} beans. */\n@Getter\n@Setter\npublic class Kingdom {\n\n  private King king;\n  private Castle castle;\n  private Army army;\n\n  /** The factory of kingdom factories. */\n  public static class FactoryMaker {\n\n    /** Enumeration for the different types of Kingdoms. */\n    public enum KingdomType {\n      ELF,\n      ORC\n    }\n\n    /** The factory method to create KingdomFactory concrete objects. */\n    public static KingdomFactory makeFactory(KingdomType type) {\n      return switch (type) {\n        case ELF -> new ElfKingdomFactory();\n        case ORC -> new OrcKingdomFactory();\n      };\n    }\n  }\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/KingdomFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\n/** KingdomFactory factory interface. */\npublic interface KingdomFactory {\n\n  Castle createCastle();\n\n  King createKing();\n\n  Army createArmy();\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcArmy.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\n/** OrcArmy. */\npublic class OrcArmy implements Army {\n\n  static final String DESCRIPTION = \"This is the orc army!\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcCastle.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\n/** OrcCastle. */\npublic class OrcCastle implements Castle {\n\n  static final String DESCRIPTION = \"This is the orc castle!\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKing.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\n/** OrcKing. */\npublic class OrcKing implements King {\n\n  static final String DESCRIPTION = \"This is the orc king!\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n"
  },
  {
    "path": "abstract-factory/src/main/java/com/iluwatar/abstractfactory/OrcKingdomFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\n/** OrcKingdomFactory concrete factory. */\npublic class OrcKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new OrcCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new OrcKing();\n  }\n\n  @Override\n  public Army createArmy() {\n    return new OrcArmy();\n  }\n}\n"
  },
  {
    "path": "abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests for abstract factory. */\nclass AbstractFactoryTest {\n\n  private final App app = new App();\n\n  @Test\n  void verifyKingCreation() {\n    app.createKingdom(Kingdom.FactoryMaker.KingdomType.ELF);\n    final var kingdom = app.getKingdom();\n\n    final var elfKing = kingdom.getKing();\n    assertTrue(elfKing instanceof ElfKing);\n    assertEquals(ElfKing.DESCRIPTION, elfKing.getDescription());\n\n    app.createKingdom(Kingdom.FactoryMaker.KingdomType.ORC);\n    final var orcKing = kingdom.getKing();\n    assertTrue(orcKing instanceof OrcKing);\n    assertEquals(OrcKing.DESCRIPTION, orcKing.getDescription());\n  }\n\n  @Test\n  void verifyCastleCreation() {\n    app.createKingdom(Kingdom.FactoryMaker.KingdomType.ELF);\n    final var kingdom = app.getKingdom();\n\n    final var elfCastle = kingdom.getCastle();\n    assertTrue(elfCastle instanceof ElfCastle);\n    assertEquals(ElfCastle.DESCRIPTION, elfCastle.getDescription());\n\n    app.createKingdom(Kingdom.FactoryMaker.KingdomType.ORC);\n    final var orcCastle = kingdom.getCastle();\n    assertTrue(orcCastle instanceof OrcCastle);\n    assertEquals(OrcCastle.DESCRIPTION, orcCastle.getDescription());\n  }\n\n  @Test\n  void verifyArmyCreation() {\n    app.createKingdom(Kingdom.FactoryMaker.KingdomType.ELF);\n    final var kingdom = app.getKingdom();\n\n    final var elfArmy = kingdom.getArmy();\n    assertTrue(elfArmy instanceof ElfArmy);\n    assertEquals(ElfArmy.DESCRIPTION, elfArmy.getDescription());\n\n    app.createKingdom(Kingdom.FactoryMaker.KingdomType.ORC);\n    final var orcArmy = kingdom.getArmy();\n    assertTrue(orcArmy instanceof OrcArmy);\n    assertEquals(OrcArmy.DESCRIPTION, orcArmy.getDescription());\n  }\n\n  @Test\n  void verifyElfKingdomCreation() {\n    app.createKingdom(Kingdom.FactoryMaker.KingdomType.ELF);\n    final var kingdom = app.getKingdom();\n\n    final var king = kingdom.getKing();\n    final var castle = kingdom.getCastle();\n    final var army = kingdom.getArmy();\n    assertTrue(king instanceof ElfKing);\n    assertEquals(ElfKing.DESCRIPTION, king.getDescription());\n    assertTrue(castle instanceof ElfCastle);\n    assertEquals(ElfCastle.DESCRIPTION, castle.getDescription());\n    assertTrue(army instanceof ElfArmy);\n    assertEquals(ElfArmy.DESCRIPTION, army.getDescription());\n  }\n\n  @Test\n  void verifyOrcKingdomCreation() {\n    app.createKingdom(Kingdom.FactoryMaker.KingdomType.ORC);\n    final var kingdom = app.getKingdom();\n\n    final var king = kingdom.getKing();\n    final var castle = kingdom.getCastle();\n    final var army = kingdom.getArmy();\n    assertTrue(king instanceof OrcKing);\n    assertEquals(OrcKing.DESCRIPTION, king.getDescription());\n    assertTrue(castle instanceof OrcCastle);\n    assertEquals(OrcCastle.DESCRIPTION, castle.getDescription());\n    assertTrue(army instanceof OrcArmy);\n    assertEquals(OrcArmy.DESCRIPTION, army.getDescription());\n  }\n}\n"
  },
  {
    "path": "abstract-factory/src/test/java/com/iluwatar/abstractfactory/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.abstractfactory;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Check whether the execution of the main method in {@link App} throws an exception. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "active-object/README.md",
    "content": "---\ntitle: \"Active Object Pattern in Java: Achieving Efficient Asynchronous Processing\"\nshortTitle: Active Object\ndescription: \"Learn about the Active Object design pattern in Java. This guide covers asynchronous behavior, concurrency, and practical examples to enhance your Java applications' performance.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Asynchronous\n  - Decoupling\n  - Messaging\n  - Synchronization\n  - Thread management\n---\n\n## Intent of Active Object Design Pattern\n\nThe Active Object pattern provides a reliable method for asynchronous processing in Java, ensuring responsive applications and efficient thread management. It achieves this by encapsulating tasks within objects that have their own thread and message queue. This separation keeps the main thread responsive and avoids issues like direct thread manipulation or shared state access.\n\n## Detailed Explanation of Active Object Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a busy restaurant where customers place orders with waiters. Instead of the waiters going to the kitchen to prepare the food themselves, they write the orders on slips and hand them to a dispatcher. The dispatcher manages a pool of chefs who prepare the meals asynchronously. Once a chef is free, they pick up the next order from the queue, prepare the dish, and notify the waiter when it's ready for serving.\n>\n> In this analogy, the waiters represent the client threads, the dispatcher represents the scheduler, and the chefs represent the method execution in separate threads. This setup allows the waiters to continue taking orders without being blocked by the food preparation process, much like the Active Object pattern decouples method invocation from execution to enhance concurrency.\n\nIn plain words\n\n> The Active Object pattern decouples method execution from method invocation to improve concurrency and responsiveness in multithreaded applications.\n\nWikipedia says\n\n> The active object design pattern decouples method execution from method invocation for objects that each reside in their own thread of control.[1] The goal is to introduce concurrency, by using asynchronous method invocation and a scheduler for handling requests.\n>\n> The pattern consists of six elements:\n>\n> * A proxy, which provides an interface towards clients with publicly accessible methods.\n> * An interface which defines the method request on an active object.\n> * A list of pending requests from clients.\n> * A scheduler, which decides which request to execute next.\n> * The implementation of the active object method.\n> * A callback or variable for the client to receive the result.\n\nSequence diagram\n\n![Active Object sequence diagram](./etc/active-object-sequence-diagram.png)\n\n\n## Programmatic Example of Active Object in Java\n\nThis section explains how the Active Object design pattern works in Java, highlighting its use in asynchronous task management and concurrency control.\n\nThe Orcs are known for their wildness and untameable soul. It seems like they have their own thread of control based on previous behavior. To implement a creature that has its own thread of control mechanism and expose its API only and not the execution itself, we can use the Active Object pattern.\n\n```java\npublic abstract class ActiveCreature {\n    private final Logger logger = LoggerFactory.getLogger(ActiveCreature.class.getName());\n\n    private BlockingQueue<Runnable> requests;\n\n    private String name;\n\n    private Thread thread;\n\n    public ActiveCreature(String name) {\n        this.name = name;\n        this.requests = new LinkedBlockingQueue<Runnable>();\n        thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                while (true) {\n                    try {\n                        requests.take().run();\n                    } catch (InterruptedException e) {\n                        logger.error(e.getMessage());\n                    }\n                }\n            }\n        }\n        );\n        thread.start();\n    }\n\n    public void eat() throws InterruptedException {\n        requests.put(new Runnable() {\n                         @Override\n                         public void run() {\n                             logger.info(\"{} is eating!\", name());\n                             logger.info(\"{} has finished eating!\", name());\n                         }\n                     }\n        );\n    }\n\n    public void roam() throws InterruptedException {\n        requests.put(new Runnable() {\n                         @Override\n                         public void run() {\n                             logger.info(\"{} has started to roam the wastelands.\", name());\n                         }\n                     }\n        );\n    }\n\n    public String name() {\n        return this.name;\n    }\n}\n```\n\nWe can see that any class that will extend the `ActiveCreature` class will have its own thread of control to invoke and execute methods.\n\nFor example, the `Orc` class:\n\n```java\npublic class Orc extends ActiveCreature {\n\n    public Orc(String name) {\n        super(name);\n    }\n}\n```\n\nNow, we can create multiple creatures such as orcs, tell them to eat and roam, and they will execute it on their own thread of control:\n\n```java\npublic class App implements Runnable {\n\n    private static final Logger logger = LoggerFactory.getLogger(App.class.getName());\n\n    private static final int NUM_CREATURES = 3;\n\n    public static void main(String[] args) {\n        var app = new App();\n        app.run();\n    }\n\n    @Override\n    public void run() {\n        List<ActiveCreature> creatures = new ArrayList<>();\n        try {\n            for (int i = 0; i < NUM_CREATURES; i++) {\n                creatures.add(new Orc(Orc.class.getSimpleName() + i));\n                creatures.get(i).eat();\n                creatures.get(i).roam();\n            }\n            Thread.sleep(1000);\n        } catch (InterruptedException e) {\n            logger.error(e.getMessage());\n            Thread.currentThread().interrupt();\n        } finally {\n            for (int i = 0; i < NUM_CREATURES; i++) {\n                creatures.get(i).kill(0);\n            }\n        }\n    }\n}\n```\n\nProgram output:\n\n```\n09:00:02.501 [Thread-0] INFO com.iluwatar.activeobject.ActiveCreature -- Orc0 is eating!\n09:00:02.501 [Thread-2] INFO com.iluwatar.activeobject.ActiveCreature -- Orc2 is eating!\n09:00:02.501 [Thread-1] INFO com.iluwatar.activeobject.ActiveCreature -- Orc1 is eating!\n09:00:02.504 [Thread-0] INFO com.iluwatar.activeobject.ActiveCreature -- Orc0 has finished eating!\n09:00:02.504 [Thread-1] INFO com.iluwatar.activeobject.ActiveCreature -- Orc1 has finished eating!\n09:00:02.504 [Thread-0] INFO com.iluwatar.activeobject.ActiveCreature -- Orc0 has started to roam in the wastelands.\n09:00:02.504 [Thread-2] INFO com.iluwatar.activeobject.ActiveCreature -- Orc2 has finished eating!\n09:00:02.504 [Thread-1] INFO com.iluwatar.activeobject.ActiveCreature -- Orc1 has started to roam in the wastelands.\n09:00:02.504 [Thread-2] INFO com.iluwatar.activeobject.ActiveCreature -- Orc2 has started to roam in the wastelands.\n```\n\n## When to Use the Active Object Pattern in Java\n\nUse the Active Object pattern in Java when:\n\n* when you need to handle asynchronous tasks without blocking the main thread, ensuring better performance and responsiveness.\n* When you need to interact with external resources asynchronously.\n* When you want to improve the responsiveness of your application.\n* When you need to manage concurrent tasks in a modular and maintainable way.\n\n## Active Object Pattern Java Tutorials\n\n* [Android and Java Concurrency: The Active Object Pattern(Douglas Schmidt)](https://www.youtube.com/watch?v=Cd8t2u5Qmvc)\n\n## Real-World Applications of Active Object Pattern in Java\n\n* Real-time trading systems where transaction requests are handled asynchronously.\n* GUIs where long-running tasks are executed in the background without freezing the user interface.\n* Game programming to handle concurrent updates to game state or AI computations.\n\n## Benefits and Trade-offs of Active Object Pattern\n\nDiscover the benefits and trade-offs of using the Active Object pattern in Java, including improved thread safety and potential overhead concerns.\n\nBenefits:\n\n* Improves responsiveness of the main thread.\n* Encapsulates concurrency concerns within objects.\n* Promotes better code organization and maintainability.\n* Provides thread safety and avoids shared state access problems.\n\nTrade-offs:\n\n* Introduces additional overhead due to message passing and thread management.\n* May not be suitable for all types of concurrency problems.\n\n## Related Java Design Patterns\n\n* [Command](https://java-design-patterns.com/patterns/command/): Encapsulates a request as an object, similarly to how the Active Object pattern encapsulates method calls.\n* [Promise](https://java-design-patterns.com/patterns/promise/): Provides a means to retrieve the result of an asynchronous method call, often used in conjunction with Active Object.\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): The Active Object pattern can use a proxy to handle method invocations asynchronously.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object Software](https://amzn.to/3HYqrBE)\n* [Concurrent Programming in Java: Design Principles and Patterns](https://amzn.to/498SRVq)\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n* [Learning Concurrent Programming in Scala](https://amzn.to/3UE07nV)\n* [Pattern Languages of Program Design 3](https://amzn.to/3OI1j61)\n* [Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects](https://amzn.to/3UgC24V)\n"
  },
  {
    "path": "active-object/etc/active-object.urm.puml",
    "content": "@startuml\npackage com.iluwatar.activeobject {\n  abstract class ActiveCreature {\n    - logger : Logger\n    - name : String\n    - requests : BlockingQueue<Runnable>\n    - thread : Thread\n    + ActiveCreature(name : String)\n    + eat()\n    + name() : String\n    + roam()\n  }\n  class App {\n    - creatures : Integer\n    - logger : Logger\n    + App()\n    + main(args : String[]) {static}\n    + run()\n  }\n  class Orc {\n    + Orc(name : String)\n  }\n}\nOrc --|> ActiveCreature \n@enduml"
  },
  {
    "path": "active-object/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>active-object</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <!-- Maven assembly plugin is invoked with default setting which we have \n\t\t\t\tin parent pom and specifying the class having main method -->\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.activeobject.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "active-object/src/main/java/com/iluwatar/activeobject/ActiveCreature.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.activeobject;\n\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** ActiveCreature class is the base of the active object example. */\npublic abstract class ActiveCreature {\n\n  private static final Logger logger = LoggerFactory.getLogger(ActiveCreature.class.getName());\n\n  private BlockingQueue<Runnable> requests;\n\n  private String name;\n\n  private Thread thread; // Thread of execution.\n\n  private int status; // status of the thread of execution.\n\n  /** Constructor and initialization. */\n  protected ActiveCreature(String name) {\n    this.name = name;\n    this.status = 0;\n    this.requests = new LinkedBlockingQueue<>();\n    thread =\n        new Thread(\n            () -> {\n              boolean infinite = true;\n              while (infinite) {\n                try {\n                  requests.take().run();\n                } catch (InterruptedException e) {\n                  if (this.status != 0) {\n                    logger.error(\"Thread was interrupted. --> {}\", e.getMessage());\n                  }\n                  infinite = false;\n                  Thread.currentThread().interrupt();\n                }\n              }\n            });\n    thread.start();\n  }\n\n  /**\n   * Eats the porridge.\n   *\n   * @throws InterruptedException due to firing a new Runnable.\n   */\n  public void eat() throws InterruptedException {\n    requests.put(\n        () -> {\n          logger.info(\"{} is eating!\", name());\n          logger.info(\"{} has finished eating!\", name());\n        });\n  }\n\n  /**\n   * Roam the wastelands.\n   *\n   * @throws InterruptedException due to firing a new Runnable.\n   */\n  public void roam() throws InterruptedException {\n    requests.put(() -> logger.info(\"{} has started to roam in the wastelands.\", name()));\n  }\n\n  /**\n   * Returns the name of the creature.\n   *\n   * @return the name of the creature.\n   */\n  public String name() {\n    return this.name;\n  }\n\n  /**\n   * Kills the thread of execution.\n   *\n   * @param status of the thread of execution. 0 == OK, the rest is logging an error.\n   */\n  public void kill(int status) {\n    this.status = status;\n    this.thread.interrupt();\n  }\n\n  /**\n   * Returns the status of the thread of execution.\n   *\n   * @return the status of the thread of execution.\n   */\n  public int getStatus() {\n    return this.status;\n  }\n}\n"
  },
  {
    "path": "active-object/src/main/java/com/iluwatar/activeobject/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.activeobject;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * The Active Object pattern helps to solve synchronization difficulties without using\n * 'synchronized' methods. The active object will contain a thread-safe data structure (such as\n * BlockingQueue) and use to synchronize method calls by moving the logic of the method into an\n * invocator(usually a Runnable) and store it in the DSA.\n *\n * <p>In this example, we fire 20 threads to modify a value in the target class.\n */\npublic class App implements Runnable {\n\n  private static final Logger logger = LoggerFactory.getLogger(App.class.getName());\n\n  private static final int NUM_CREATURES = 3;\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line arguments.\n   */\n  public static void main(String[] args) {\n    var app = new App();\n    app.run();\n  }\n\n  @Override\n  public void run() {\n    List<ActiveCreature> creatures = new ArrayList<>();\n    try {\n      for (int i = 0; i < NUM_CREATURES; i++) {\n        creatures.add(new Orc(Orc.class.getSimpleName() + i));\n        creatures.get(i).eat();\n        creatures.get(i).roam();\n      }\n      Thread.sleep(1000);\n    } catch (InterruptedException e) {\n      logger.error(e.getMessage());\n      Thread.currentThread().interrupt();\n    } finally {\n      for (int i = 0; i < NUM_CREATURES; i++) {\n        creatures.get(i).kill(0);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "active-object/src/main/java/com/iluwatar/activeobject/Orc.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.activeobject;\n\n/** An implementation of the ActiveCreature class. */\npublic class Orc extends ActiveCreature {\n\n  public Orc(String name) {\n    super(name);\n  }\n}\n"
  },
  {
    "path": "active-object/src/test/java/com/iluwatar/activeobject/ActiveCreatureTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.activeobject;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\nclass ActiveCreatureTest {\n\n  @Test\n  void executionTest() throws InterruptedException {\n    ActiveCreature orc = new Orc(\"orc1\");\n    assertEquals(\"orc1\", orc.name());\n    assertEquals(0, orc.getStatus());\n    orc.eat();\n    orc.roam();\n    orc.kill(0);\n  }\n}\n"
  },
  {
    "path": "active-object/src/test/java/com/iluwatar/activeobject/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.activeobject;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "actor-model/README.md",
    "content": "---\ntitle: \"Actor Model Pattern in Java: Building Concurrent Systems with Elegance\"\nshortTitle: Actor Model\ndescription: \"Explore the Actor Model pattern in Java with real-world examples and practical implementation. Learn how to build scalable, message-driven systems using actors, messages, and asynchronous communication.\"\ncategory: Concurrency\nlanguage: en\ntag:\n    - Concurrency\n    - Messaging\n    - Isolation\n    - Asynchronous\n    - Distributed Systems\n    - Actor Model\n---\n\n## Also Known As\n\n- Message-passing concurrency\n- Actor-based concurrency\n\n---\n\n## Intent of Actor Model Pattern\n\nThe Actor Model pattern enables the construction of highly concurrent, distributed, and fault-tolerant systems by using isolated components (actors) that interact exclusively through asynchronous message passing.\n\n---\n\n## Detailed Explanation of Actor Model Pattern with Real-World Examples\n\n### 📦 Real-world Example\n\nImagine a customer service system:\n- Each **customer support agent** is an **actor**.\n- Customers **send questions (messages)** to agents.\n- Each agent handles one request at a time and can **respond asynchronously** without interfering with other agents.\n\n---\n\n### 🧠 In Plain Words\n\n> \"Actors are like independent workers that never share memory and only communicate through messages.\"\n\n---\n\n### 📖 Wikipedia Says\n\n> [Actor model](https://en.wikipedia.org/wiki/Actor_model) is a mathematical model of concurrent computation that treats \"actors\" as the universal primitives of concurrent computation.\n\n---\n\n### 🧹 Architecture Diagram\n\n![UML Class Diagram](./etc/Actor_Model_UML_Class_Diagram.png)\n\n---\n\n## Programmatic Example of Actor Model Pattern in Java\n\n### Actor.java\n\n```java\npublic abstract class Actor implements Runnable {\n\n    @Setter @Getter private String actorId;\n    private final BlockingQueue<Message> mailbox = new LinkedBlockingQueue<>();\n    private volatile boolean active = true; \n\n\n    public void send(Message message) {\n        mailbox.add(message); \n    }\n\n    public void stop() {\n        active = false; \n    }\n\n    @Override\n    public void run() {\n        \n    }\n\n    protected abstract void onReceive(Message message);\n}\n\n```\n\n### Message.java\n\n```java\n\n@AllArgsConstructor\n@Getter\n@Setter\npublic class Message {\n    private final String content;\n    private final String senderId;\n}\n```\n\n### ActorSystem.java\n\n```java\npublic class ActorSystem {\n    public void startActor(Actor actor) {\n        String actorId = \"actor-\" + idCounter.incrementAndGet(); // Generate a new and unique ID\n        actor.setActorId(actorId); // assign the actor it's ID\n        actorRegister.put(actorId, actor); // Register and save the actor with it's ID\n        executor.submit(actor); // Run the actor in a thread\n    }\n    public Actor getActorById(String actorId) {\n        return actorRegister.get(actorId); //  Find by Id\n    }\n\n    public void shutdown() {\n        executor.shutdownNow(); // Stop all threads\n    }\n}\n```\n\n### App.java\n\n```java\npublic class App {\n  public static void main(String[] args) {\n    ActorSystem system = new ActorSystem();\n      Actor srijan = new ExampleActor(system);\n      Actor ansh = new ExampleActor2(system);\n\n      system.startActor(srijan);\n      system.startActor(ansh);\n      ansh.send(new Message(\"Hello ansh\", srijan.getActorId()));\n      srijan.send(new Message(\"Hello srijan!\", ansh.getActorId()));\n\n      Thread.sleep(1000); // Give time for messages to process\n\n      srijan.stop(); // Stop the actor gracefully\n      ansh.stop();\n      system.shutdown(); // Stop the actor system\n  }\n}\n```\n\n---\n\n## When to Use the Actor Model Pattern in Java\n\n- When building **concurrent or distributed systems**\n- When you want **no shared mutable state**\n- When you need **asynchronous, message-driven communication**\n- When components should be **isolated and loosely coupled**\n\n---\n\n## Actor Model Pattern Java Tutorials\n\n- [Baeldung – Akka with Java](https://www.baeldung.com/java-akka)\n- [Vaughn Vernon – Reactive Messaging Patterns](https://vaughnvernon.co/?p=1143)\n\n---\n\n## Real-World Applications of Actor Model Pattern in Java\n\n- [Akka Framework](https://akka.io/)\n- [Erlang and Elixir concurrency](https://www.erlang.org/)\n- [Microsoft Orleans](https://learn.microsoft.com/en-us/dotnet/orleans/)\n- JVM-based game engines and simulators\n\n---\n\n## Benefits and Trade-offs of Actor Model Pattern\n\n### ✅ Benefits\n- High concurrency support\n- Easy scaling across threads or machines\n- Fault isolation and recovery\n- Message ordering within actors\n\n### ⚠️ Trade-offs\n- Harder to debug due to asynchronous behavior\n- Slight performance overhead due to message queues\n- More complex to design than simple method calls\n\n---\n\n## Related Java Design Patterns\n\n- [Command Pattern](../command)\n- [Mediator Pattern](../mediator)\n- [Event-Driven Architecture](../event-driven-architecture)\n- [Observer Pattern](../observer)\n\n---\n\n## References and Credits\n\n- *Programming Erlang*, Joe Armstrong\n- *Reactive Design Patterns*, Roland Kuhn\n- *The Actor Model in 10 Minutes*, [InfoQ Article](https://www.infoq.com/articles/actor-model/)\n- [Akka Documentation](https://doc.akka.io/docs/akka/current/index.html)\n\n"
  },
  {
    "path": "actor-model/etc/actor-model.urm.puml",
    "content": "@startuml actor-model\n\ntitle Actor Model - UML Class Diagram\n\nclass ActorSystem {\n  +actorOf(actor: Actor): Actor\n  +shutdown(): void\n}\n\nclass Actor {\n  -mailbox: BlockingQueue<Message>\n  -active: boolean\n  +send(message: Message): void\n  +stop(): void\n  +run(): void\n  #onReceive(message: Message): void\n}\n\nclass ExampleActor {\n  +onReceive(message: Message): void\n}\n\nclass Message {\n  -content: String\n  -sender: Actor\n  +getContent(): String\n  +getSender(): Actor\n}\n\nActorSystem --> Actor : creates\nActor <|-- ExampleActor : extends\nActor --> Message : processes\nExampleActor --> Message : uses\n\n@enduml\n"
  },
  {
    "path": "actor-model/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0\n                             http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>actor-model</artifactId>\n    <name>Actor Model</name>\n\n    <!-- Force unified JUnit version to avoid classpath mismatches -->\n    <dependencyManagement>\n        <dependencies>\n            <dependency>\n                <groupId>org.junit</groupId>\n                <artifactId>junit-bom</artifactId>\n                <version>5.11.0</version>\n                <type>pom</type>\n                <scope>import</scope>\n            </dependency>\n        </dependencies>\n    </dependencyManagement>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-api</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.platform</groupId>\n            <artifactId>junit-platform-launcher</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <!-- Assembly plugin for creating fat JARs -->\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <version>3.3.0</version>\n                <configuration>\n                    <descriptorRefs>\n                        <descriptorRef>jar-with-dependencies</descriptorRef>\n                    </descriptorRefs>\n                    <archive>\n                        <manifest>\n                            <mainClass>com.iluwatar.actormodel.App</mainClass>\n                        </manifest>\n                    </archive>\n                </configuration>\n                <executions>\n                    <execution>\n                        <id>make-assembly</id>\n                        <phase>package</phase>\n                        <goals>\n                            <goal>single</goal>\n                        </goals>\n                    </execution>\n                </executions>\n\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "actor-model/src/main/java/com/iluwatar/actormodel/Actor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.actormodel;\n\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport lombok.Getter;\nimport lombok.Setter;\n\npublic abstract class Actor implements Runnable {\n\n  @Setter @Getter private String actorId;\n  private final BlockingQueue<Message> mailbox = new LinkedBlockingQueue<>();\n  private volatile boolean active =\n      true; // always read from main memory and written back to main memory,\n\n  // rather than being cached in a thread's local memory. To make it consistent to all Actors\n\n  public void send(Message message) {\n    mailbox.add(message); // Add message to queue\n  }\n\n  public void stop() {\n    active = false; // Stop the actor loop\n  }\n\n  @Override\n  public void run() {\n    while (active) {\n      try {\n        Message message = mailbox.take(); // Wait for a message\n        onReceive(message); // Process it\n      } catch (InterruptedException e) {\n        Thread.currentThread().interrupt();\n      }\n    }\n  }\n\n  // Child classes must define what to do with a message\n  protected abstract void onReceive(Message message);\n}\n"
  },
  {
    "path": "actor-model/src/main/java/com/iluwatar/actormodel/ActorSystem.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.actormodel;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.atomic.AtomicInteger;\n\npublic class ActorSystem {\n  private final ExecutorService executor = Executors.newCachedThreadPool();\n  private final ConcurrentHashMap<String, Actor> actorRegister = new ConcurrentHashMap<>();\n  private final AtomicInteger idCounter = new AtomicInteger(0);\n\n  public void startActor(Actor actor) {\n    String actorId = \"actor-\" + idCounter.incrementAndGet(); // Generate a new and unique ID\n    actor.setActorId(actorId); // assign the actor it's ID\n    actorRegister.put(actorId, actor); // Register and save the actor with it's ID\n    executor.submit(actor); // Run the actor in a thread\n  }\n\n  public Actor getActorById(String actorId) {\n    return actorRegister.get(actorId); //  Find by Id\n  }\n\n  public void shutdown() {\n    executor.shutdownNow(); // Stop all threads\n  }\n}\n"
  },
  {
    "path": "actor-model/src/main/java/com/iluwatar/actormodel/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n/**\n * The Actor Model is a design pattern used to handle concurrency in a safe, scalable, and\n * message-driven way.\n *\n * <p>In the Actor Model: - An **Actor** is an independent unit that has its own state and behavior.\n * - Actors **communicate only through messages** — they do not share memory. - An **ActorSystem**\n * is responsible for creating, starting, and managing the lifecycle of actors. - Messages are\n * delivered asynchronously, and each actor processes them one at a time.\n *\n * <p>💡 Key benefits: - No shared memory = no need for complex thread-safety - Easy to scale with\n * many actors - Suitable for highly concurrent or distributed systems\n *\n * <p>🔍 This example demonstrates the Actor Model: - `ActorSystem` starts two actors: `srijan` and\n * `ansh`. - `ExampleActor` and `ExampleActor2` extend the `Actor` class and override the\n * `onReceive()` method to handle messages. - Actors communicate using `send()` to pass `Message`\n * objects that include the message content and sender's ID. - The actors process messages\n * **asynchronously in separate threads**, and we allow a short delay (`Thread.sleep`) to let them\n * run. - The system is shut down gracefully at the end.\n */\npackage com.iluwatar.actormodel;\n\npublic class App {\n  public static void main(String[] args) throws InterruptedException {\n    ActorSystem system = new ActorSystem();\n    Actor srijan = new ExampleActor(system);\n    Actor ansh = new ExampleActor2(system);\n\n    system.startActor(srijan);\n    system.startActor(ansh);\n    ansh.send(new Message(\"Hello ansh\", srijan.getActorId()));\n    srijan.send(new Message(\"Hello srijan!\", ansh.getActorId()));\n\n    Thread.sleep(1000); // Give time for messages to process\n\n    srijan.stop(); // Stop the actor gracefully\n    ansh.stop();\n    system.shutdown(); // Stop the actor system\n  }\n}\n"
  },
  {
    "path": "actor-model/src/main/java/com/iluwatar/actormodel/ExampleActor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.actormodel;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n@Slf4j\npublic class ExampleActor extends Actor {\n  private final ActorSystem actorSystem;\n  @Getter private final List<String> receivedMessages = new ArrayList<>();\n\n  public ExampleActor(ActorSystem actorSystem) {\n    this.actorSystem = actorSystem;\n  }\n\n  // Logger log = Logger.getLogger(getClass().getName());\n\n  @Override\n  protected void onReceive(Message message) {\n    LOGGER.info(\n        \"[{}]Received : {} from : [{}]\", getActorId(), message.getContent(), message.getSenderId());\n    Actor sender = actorSystem.getActorById(message.getSenderId()); // sender actor id\n    // Reply of the message\n    if (sender != null && !message.getSenderId().equals(getActorId())) {\n      sender.send(new Message(\"I got your message \", getActorId()));\n    }\n  }\n}\n"
  },
  {
    "path": "actor-model/src/main/java/com/iluwatar/actormodel/ExampleActor2.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.actormodel;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n@Slf4j\npublic class ExampleActor2 extends Actor {\n  private final ActorSystem actorSystem;\n  @Getter private final List<String> receivedMessages = new ArrayList<>();\n\n  public ExampleActor2(ActorSystem actorSystem) {\n    this.actorSystem = actorSystem;\n  }\n\n  @Override\n  protected void onReceive(Message message) {\n    receivedMessages.add(message.getContent());\n    LOGGER.info(\"[{}]Received : {}\", getActorId(), message.getContent());\n  }\n}\n"
  },
  {
    "path": "actor-model/src/main/java/com/iluwatar/actormodel/Message.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.actormodel;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\n@AllArgsConstructor\n@Getter\npublic class Message {\n  private final String content;\n  private final String senderId;\n}\n"
  },
  {
    "path": "actor-model/src/test/java/com/iluwatar/actor/ActorModelTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.actor;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport com.iluwatar.actormodel.ActorSystem;\nimport com.iluwatar.actormodel.App;\nimport com.iluwatar.actormodel.ExampleActor;\nimport com.iluwatar.actormodel.ExampleActor2;\nimport com.iluwatar.actormodel.Message;\nimport org.junit.jupiter.api.Test;\n\npublic class ActorModelTest {\n  @Test\n  void testMainMethod() throws InterruptedException {\n    App.main(new String[] {});\n  }\n\n  @Test\n  public void testMessagePassing() throws InterruptedException {\n    ActorSystem system = new ActorSystem();\n\n    ExampleActor srijan = new ExampleActor(system);\n    ExampleActor2 ansh = new ExampleActor2(system);\n\n    system.startActor(srijan);\n    system.startActor(ansh);\n\n    // Ansh recieves a message from Srijan\n    ansh.send(new Message(\"Hello ansh\", srijan.getActorId()));\n\n    // Wait briefly to allow async processing\n    Thread.sleep(200);\n\n    // Check that Srijan received the message\n    assertTrue(\n        ansh.getReceivedMessages().contains(\"Hello ansh\"),\n        \"ansh should receive the message from Srijan\");\n  }\n}\n"
  },
  {
    "path": "acyclic-visitor/README.md",
    "content": "---\ntitle: \"Acyclic Visitor Pattern in Java: Streamlining Object Interactions\"\nshortTitle: Acyclic Visitor\ndescription: \"Learn about the Acyclic Visitor pattern in Java. This guide explains how it decouples operations from object hierarchies, providing examples and real-world applications.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Decoupling\n  - Extensibility\n  - Interface\n  - Object composition\n---\n\n## Intent of Acyclic Visitor Design Pattern\n\nThe Acyclic Visitor pattern in Java decouples operations from an object hierarchy, providing a flexible design for various applications.\n\n## Detailed Explanation of Acyclic Visitor Pattern with Real-World Examples\n\nReal-world example\n\n> An analogous real-world example of the Acyclic Visitor pattern in Java is a museum guide system, demonstrating the practical application of this design pattern. Imagine a museum with various exhibits like paintings, sculptures, and historical artifacts. The museum has different types of guides (audio guide, human guide, virtual reality guide) that provide information about each exhibit. Instead of modifying the exhibits every time a new guide type is introduced, each guide implements an interface to visit different exhibit types. This way, the museum can add new types of guides without altering the existing exhibits, ensuring that the system remains extensible and maintainable without forming any dependency cycles.\n\nIn plain words\n\n> Acyclic Visitor allows functions to be added to existing class hierarchies without modifying the hierarchies.\n\n[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) says\n\n> The Acyclic Visitor pattern allows new functions to be added to existing class hierarchies without affecting those hierarchies, and without creating the dependency cycles that are inherent to the GangOfFour VisitorPattern.\n\nSequence diagram\n\n![Acyclic Visitor sequence diagram](./etc/acyclic-visitor-sequence-diagram.png \"Acyclic Visitor sequence diagram\")\n\n\n## Programmatic Example of Acyclic Visitor in Java\n\nIn this Java example, we have a hierarchy of modem classes illustrating the Acyclic Visitor pattern. The modems in this hierarchy need to be visited by an external algorithm based on filtering criteria (is it Unix or DOS compatible modem).\n\nHere's the `Modem` hierarchy.\n\n```java\npublic abstract class Modem {\n    public abstract void accept(ModemVisitor modemVisitor);\n}\n\npublic class Zoom extends Modem {\n\n    // Other properties and methods...\n\n    @Override\n    public void accept(ModemVisitor modemVisitor) {\n        if (modemVisitor instanceof ZoomVisitor) {\n            ((ZoomVisitor) modemVisitor).visit(this);\n        } else {\n            LOGGER.info(\"Only ZoomVisitor is allowed to visit Zoom modem\");\n        }\n    }\n}\n\npublic class Hayes extends Modem {\n\n    // Other properties and methods...\n\n    @Override\n    public void accept(ModemVisitor modemVisitor) {\n        if (modemVisitor instanceof HayesVisitor) {\n            ((HayesVisitor) modemVisitor).visit(this);\n        } else {\n            LOGGER.info(\"Only HayesVisitor is allowed to visit Hayes modem\");\n        }\n    }\n}\n```\n\nNext, we introduce the `ModemVisitor` hierarchy.\n\n```java\npublic interface ModemVisitor {\n}\n\npublic interface HayesVisitor extends ModemVisitor {\n    void visit(Hayes hayes);\n}\n\npublic interface ZoomVisitor extends ModemVisitor {\n    void visit(Zoom zoom);\n}\n\npublic interface AllModemVisitor extends ZoomVisitor, HayesVisitor {\n}\n\npublic class ConfigureForDosVisitor implements AllModemVisitor {\n\n    // Other properties and methods...\n\n    @Override\n    public void visit(Hayes hayes) {\n        LOGGER.info(hayes + \" used with Dos configurator.\");\n    }\n\n    @Override\n    public void visit(Zoom zoom) {\n        LOGGER.info(zoom + \" used with Dos configurator.\");\n    }\n}\n\npublic class ConfigureForUnixVisitor implements ZoomVisitor {\n\n    // Other properties and methods...\n\n    @Override\n    public void visit(Zoom zoom) {\n        LOGGER.info(zoom + \" used with Unix configurator.\");\n    }\n}\n```\n\nFinally, here are the visitors in action.\n\n```java\npublic static void main(String[] args) {\n    var conUnix = new ConfigureForUnixVisitor();\n    var conDos = new ConfigureForDosVisitor();\n\n    var zoom = new Zoom();\n    var hayes = new Hayes();\n\n    hayes.accept(conDos); // Hayes modem with Dos configurator\n    zoom.accept(conDos); // Zoom modem with Dos configurator\n    hayes.accept(conUnix); // Hayes modem with Unix configurator\n    zoom.accept(conUnix); // Zoom modem with Unix configurator   \n}\n```\n\nProgram output:\n\n```\n09:15:11.125 [main] INFO com.iluwatar.acyclicvisitor.ConfigureForDosVisitor -- Hayes modem used with Dos configurator.\n09:15:11.127 [main] INFO com.iluwatar.acyclicvisitor.ConfigureForDosVisitor -- Zoom modem used with Dos configurator.\n09:15:11.127 [main] INFO com.iluwatar.acyclicvisitor.Hayes -- Only HayesVisitor is allowed to visit Hayes modem\n09:15:11.127 [main] INFO com.iluwatar.acyclicvisitor.ConfigureForUnixVisitor -- Zoom modem used with Unix configurator.\n```\n\n## When to Use the Acyclic Visitor Pattern in Java\n\nThis pattern can be used:\n\n* When you need to add a new function to an existing hierarchy without the need to alter or affect that hierarchy.\n* When there are functions that operate upon a hierarchy, but which do not belong in the hierarchy itself. e.g. the ConfigureForDOS / ConfigureForUnix / ConfigureForX issue.\n* When you need to perform very different operations on an object depending upon its type.\n* When the visited class hierarchy will be frequently extended with new derivatives of the Element class.\n* When the recompilation, relinking, retesting or redistribution of the derivatives of Element is very expensive.\n\n## Acyclic Visitor Pattern Java Tutorials\n\n* [The Acyclic Visitor Pattern (Code Crafter)](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html)\n\n## Benefits and Trade-offs of Acyclic Visitor Pattern\n\nBenefits:\n\n* Extensible: New operations can be added easily without changing the object structure.\n* Decoupled: Reduces coupling between the objects and the operations on them.\n* No dependency cycles: Ensures acyclic dependencies, improving maintainability and reducing complexity.\n\nTrade-offs:\n\n* Increased complexity: Can introduce additional complexity with the need for multiple visitor interfaces.\n* Maintenance overhead: Modifying the object hierarchy requires updating all visitors.\n\n## Related Java Design Patterns\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): Often used in conjunction with Acyclic Visitor to allow treating individual objects and compositions uniformly.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Can be used alongside to add responsibilities to objects dynamically.\n* [Visitor](https://java-design-patterns.com/patterns/visitor/): The Acyclic Visitor pattern is a variation of the Visitor pattern that avoids cyclic dependencies.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n* [Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML](https://amzn.to/4bOtzwF)\n* [Acyclic Visitor (Robert C. Martin)](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf)\n* [Acyclic Visitor (WikiWikiWeb)](https://wiki.c2.com/?AcyclicVisitor)\n"
  },
  {
    "path": "acyclic-visitor/etc/acyclic-visitor.urm.puml",
    "content": "@startuml\npackage com.iluwatar.acyclicvisitor {\n  interface AllModemVisitor {\n  }\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class ConfigureForDosVisitor {\n    - LOGGER : Logger {static}\n    + ConfigureForDosVisitor()\n    + visit(hayes : Hayes)\n    + visit(zoom : Zoom)\n  }\n  class ConfigureForUnixVisitor {\n    - LOGGER : Logger {static}\n    + ConfigureForUnixVisitor()\n    + visit(zoom : Zoom)\n  }\n  class Hayes {\n    - LOGGER : Logger {static}\n    + Hayes()\n    + accept(modemVisitor : ModemVisitor)\n    + toString() : String\n  }\n  interface HayesVisitor {\n    + visit(Hayes) {abstract}\n  }\n  abstract class Modem {\n    + Modem()\n    + accept(ModemVisitor) {abstract}\n  }\n  interface ModemVisitor {\n  }\n  class Zoom {\n    - LOGGER : Logger {static}\n    + Zoom()\n    + accept(modemVisitor : ModemVisitor)\n    + toString() : String\n  }\n  interface ZoomVisitor {\n    + visit(Zoom) {abstract}\n  }\n}\nAllModemVisitor --|> ZoomVisitor \nAllModemVisitor --|> HayesVisitor \nConfigureForDosVisitor ..|> AllModemVisitor \nConfigureForUnixVisitor ..|> ZoomVisitor \nHayes --|> Modem \nHayesVisitor --|> ModemVisitor \nZoom --|> Modem \nZoomVisitor --|> ModemVisitor \n@enduml"
  },
  {
    "path": "acyclic-visitor/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>acyclic-visitor</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <!-- Maven assembly plugin is invoked with default setting which we have \n        in parent pom and specifying the class having main method -->\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.acyclicvisitor.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/AllModemVisitor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\n/**\n * All ModemVisitor interface extends all visitor interfaces. This interface provides ease of use\n * when a visitor needs to visit all modem types.\n */\npublic interface AllModemVisitor extends ZoomVisitor, HayesVisitor {}\n"
  },
  {
    "path": "acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\n/**\n * The Acyclic Visitor pattern allows new functions to be added to existing class hierarchies\n * without affecting those hierarchies, and without creating the dependency cycles that are inherent\n * to the GoF Visitor pattern, by making the Visitor base class degenerate\n *\n * <p>In this example the visitor base class is {@link ModemVisitor}. The base class of the visited\n * hierarchy is {@link Modem} and has two children {@link Hayes} and {@link Zoom} each one having\n * its own visitor interface {@link HayesVisitor} and {@link ZoomVisitor} respectively. {@link\n * ConfigureForUnixVisitor} and {@link ConfigureForDosVisitor} implement each derivative's visit\n * method only if it is required\n */\npublic class App {\n\n  /** Program's entry point. */\n  public static void main(String[] args) {\n    var conUnix = new ConfigureForUnixVisitor();\n    var conDos = new ConfigureForDosVisitor();\n\n    var zoom = new Zoom();\n    var hayes = new Hayes();\n\n    hayes.accept(conDos); // Hayes modem with Dos configurator\n    zoom.accept(conDos); // Zoom modem with Dos configurator\n    hayes.accept(conUnix); // Hayes modem with Unix configurator\n    zoom.accept(conUnix); // Zoom modem with Unix configurator\n  }\n}\n"
  },
  {
    "path": "acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/ConfigureForDosVisitor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * ConfigureForDosVisitor class implements both zoom's and hayes' visit method for Dos manufacturer.\n */\n@Slf4j\npublic class ConfigureForDosVisitor implements AllModemVisitor {\n\n  @Override\n  public void visit(Hayes hayes) {\n    LOGGER.info(hayes + \" used with Dos configurator.\");\n  }\n\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Dos configurator.\");\n  }\n}\n"
  },
  {
    "path": "acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/ConfigureForUnixVisitor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * ConfigureForUnixVisitor class implements zoom's visit method for Unix manufacturer, unlike\n * traditional visitor pattern, this class may selectively implement visit for other modems.\n */\n@Slf4j\npublic class ConfigureForUnixVisitor implements ZoomVisitor {\n\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Unix configurator.\");\n  }\n}\n"
  },
  {
    "path": "acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/Hayes.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Hayes class implements its accept method. */\n@Slf4j\npublic class Hayes implements Modem {\n\n  /** Accepts all visitors but honors only HayesVisitor. */\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof HayesVisitor) {\n      ((HayesVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only HayesVisitor is allowed to visit Hayes modem\");\n    }\n  }\n\n  /** Hayes' modem's toString method. */\n  @Override\n  public String toString() {\n    return \"Hayes modem\";\n  }\n}\n"
  },
  {
    "path": "acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/HayesVisitor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\n/** HayesVisitor interface. */\npublic interface HayesVisitor extends ModemVisitor {\n  void visit(Hayes hayes);\n}\n"
  },
  {
    "path": "acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/Modem.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\n/** //Modem abstract class. converted to an interface */\npublic interface Modem {\n  void accept(ModemVisitor modemVisitor);\n}\n"
  },
  {
    "path": "acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/ModemVisitor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\n/**\n * ModemVisitor interface does not contain any visit methods so that it does not depend on the\n * visited hierarchy. Each derivative's visit method is declared in its own visitor interface\n */\npublic interface ModemVisitor {\n  // Visitor is a degenerate base class for all visitors.\n}\n"
  },
  {
    "path": "acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/Zoom.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Zoom class implements its accept method. */\n@Slf4j\npublic class Zoom implements Modem {\n\n  /** Accepts all visitors but honors only ZoomVisitor. */\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof ZoomVisitor) {\n      ((ZoomVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only ZoomVisitor is allowed to visit Zoom modem\");\n    }\n  }\n\n  /** Zoom modem's toString method. */\n  @Override\n  public String toString() {\n    return \"Zoom modem\";\n  }\n}\n"
  },
  {
    "path": "acyclic-visitor/src/main/java/com/iluwatar/acyclicvisitor/ZoomVisitor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\n/** ZoomVisitor interface. */\npublic interface ZoomVisitor extends ModemVisitor {\n  void visit(Zoom zoom);\n}\n"
  },
  {
    "path": "acyclic-visitor/src/test/java/com/iluwatar/acyclicvisitor/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that the Acyclic Visitor example runs without errors. */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "acyclic-visitor/src/test/java/com/iluwatar/acyclicvisitor/HayesTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.*;\n\nimport org.junit.jupiter.api.Test;\n\n/** Hayes test class */\nclass HayesTest {\n\n  @Test\n  void testAcceptForDos() {\n    var hayes = new Hayes();\n    var mockVisitor = mock(ConfigureForDosVisitor.class);\n\n    hayes.accept(mockVisitor);\n    verify((HayesVisitor) mockVisitor).visit(eq(hayes));\n  }\n\n  @Test\n  void testAcceptForUnix() {\n    var hayes = new Hayes();\n    var mockVisitor = mock(ConfigureForUnixVisitor.class);\n\n    hayes.accept(mockVisitor);\n\n    verifyNoMoreInteractions(mockVisitor);\n  }\n}\n"
  },
  {
    "path": "acyclic-visitor/src/test/java/com/iluwatar/acyclicvisitor/ZoomTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.acyclicvisitor;\n\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\n\nimport org.junit.jupiter.api.Test;\n\n/** Zoom test class */\nclass ZoomTest {\n\n  @Test\n  void testAcceptForDos() {\n    var zoom = new Zoom();\n    var mockVisitor = mock(ConfigureForDosVisitor.class);\n\n    zoom.accept(mockVisitor);\n    verify((ZoomVisitor) mockVisitor).visit(eq(zoom));\n  }\n\n  @Test\n  void testAcceptForUnix() {\n    var zoom = new Zoom();\n    var mockVisitor = mock(ConfigureForUnixVisitor.class);\n\n    zoom.accept(mockVisitor);\n    verify((ZoomVisitor) mockVisitor).visit(eq(zoom));\n  }\n}\n"
  },
  {
    "path": "adapter/README.md",
    "content": "---\ntitle: \"Adapter Pattern in Java: Seamless Integration of Incompatible Systems\"\nshortTitle: Adapter\ndescription: \"Learn how the Adapter Design Pattern works in Java with detailed examples and use cases. Understand how it enables compatibility between incompatible interfaces.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Compatibility\n  - Decoupling\n  - Gang of Four\n  - Interface\n  - Object composition\n  - Wrapping\n---\n\n## Also known as\n\n* Wrapper\n\n## Intent of Adapter Design Pattern\n\nThe Adapter Design Pattern in Java converts the interface of a class into another interface that clients expect, enabling compatibility.\n\n## Detailed Explanation of Adapter Pattern with Real-World Examples\n\nReal-world example\n\n> Consider that you have some pictures on your memory card and you need to transfer them to your computer. To transfer them, you need some kind of adapter that is compatible with your computer ports so that you can attach a memory card to your computer. In this case card reader is an adapter. Another example would be the famous power adapter; a three-legged plug can't be connected to a two-pronged outlet, it needs to use a power adapter that makes it compatible with the two-pronged outlets. Yet another example would be a translator translating words spoken by one person to another\n\nIn plain words\n\n> Adapter pattern lets you wrap an otherwise incompatible object in an adapter to make it compatible with another class.\n\nWikipedia says\n\n> In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code.\n\nSequence diagram\n\n![Adapter sequence diagram](./etc/adapter-sequence-diagram.png \"Adapter sequence diagram\")\n\n## Programmatic Example of Adapter Pattern in Java\n\nThe Adapter Pattern example in Java shows how a class with an incompatible interface can be adapted to work with another class.\n\nConsider a wannabe captain that can only use rowing boats but can't sail at all.\n\nFirst, we have interfaces `RowingBoat` and `FishingBoat`\n\n```java\npublic interface RowingBoat {\n    void row();\n}\n\n@Slf4j\npublic class FishingBoat {\n    public void sail() {\n        LOGGER.info(\"The fishing boat is sailing\");\n    }\n}\n```\n\nThe captain expects an implementation of `RowingBoat` interface to be able to move.\n\n```java\npublic class Captain {\n\n    private final RowingBoat rowingBoat;\n\n    // default constructor and setter for rowingBoat\n    public Captain(RowingBoat rowingBoat) {\n        this.rowingBoat = rowingBoat;\n    }\n\n    public void row() {\n        rowingBoat.row();\n    }\n}\n```\n\nNow, let's say the pirates are coming and our captain needs to escape but there is only a fishing boat available. We need to create an adapter that allows the captain to operate the fishing boat with his rowing boat skills.\n\n```java\n@Slf4j\npublic class FishingBoatAdapter implements RowingBoat {\n\n    private final FishingBoat boat;\n\n    public FishingBoatAdapter() {\n        boat = new FishingBoat();\n    }\n\n    @Override\n    public void row() {\n        boat.sail();\n    }\n}\n```\n\nNow the `Captain` can use the `FishingBoat` to escape the pirates.\n\n```java\n  public static void main(final String[] args) {\n    // The captain can only operate rowing boats but with adapter he is able to\n    // use fishing boats as well\n    var captain = new Captain(new FishingBoatAdapter());\n    captain.row();\n}\n```\n\nThe program outputs:\n\n```\n10:25:08.074 [main] INFO com.iluwatar.adapter.FishingBoat -- The fishing boat is sailing\n```\n\n## When to Use the Adapter Pattern in Java\n\nUse the Adapter pattern in Java when\n\n* You want to use an existing class, and its interface does not match the one you need\n* You want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don't necessarily have compatible interfaces\n* You need to use several existing subclasses, but it's impractical to adapt their interface by subclassing everyone. An object adapter can adapt the interface of its parent class.\n* Most of the applications using third-party libraries use adapters as a middle layer between the application and the 3rd party library to decouple the application from the library. If another library has to be used only an adapter for the new library is required without having to change the application code.\n\n## Adapter Pattern Java Tutorials\n\n* [Using the Adapter Design Pattern in Java (Dzone)](https://dzone.com/articles/adapter-design-pattern-in-java)\n* [Adapter in Java (Refactoring Guru)](https://refactoring.guru/design-patterns/adapter/java/example)\n* [The Adapter Pattern in Java (Baeldung)](https://www.baeldung.com/java-adapter-pattern)\n* [Adapter Design Pattern (GeeksForGeeks)](https://www.geeksforgeeks.org/adapter-pattern/)\n\n## Benefits and Trade-offs of Adapter Pattern\n\nClass and object adapters offer different benefits and drawbacks. A class adapter adapts the Adaptee to the Target by binding to a specific Adaptee class, which means it cannot adapt a class and all its subclasses. This type of adapter allows the Adapter to override some of the Adaptee’s behavior because the Adapter is a subclass of the Adaptee. Additionally, it introduces only one object without needing extra pointer indirection to reach the Adaptee.\n\nOn the other hand, an object adapter allows a single Adapter to work with multiple Adaptees, including the Adaptee and all its subclasses. This type of adapter can add functionality to all Adaptees simultaneously. However, it makes overriding the Adaptee’s behavior more difficult, as it requires subclassing the Adaptee and having the Adapter refer to this subclass instead of the Adaptee itself.\n\n## Real-World Applications of Adapter Pattern in Java\n\n* `java.io.InputStreamReader` and `java.io.OutputStreamWriter` in the Java IO library.\n* GUI component libraries that allow for plug-ins or adapters to convert between different GUI component interfaces.\n* [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)\n* [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)\n* [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-)\n* [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-)\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "adapter/etc/adapter.urm.puml",
    "content": "@startuml\npackage com.iluwatar.adapter {\n  class App {\n    - App()\n    + main(args : String[]) {static}\n  }\n  class Captain {\n    - rowingBoat : RowingBoat\n    + Captain()\n    + Captain(boat : RowingBoat)\n    ~ row()\n    ~ setRowingBoat(boat : RowingBoat)\n  }\n  ~class FishingBoat {\n    - LOGGER : Logger {static}\n    ~ FishingBoat()\n    ~ sail()\n  }\n  class FishingBoatAdapter {\n    - boat : FishingBoat\n    + FishingBoatAdapter()\n    + row()\n  }\n  interface RowingBoat {\n    + row() {abstract}\n  }\n}\nFishingBoatAdapter -->  \"-boat\" FishingBoat\nCaptain -->  \"-rowingBoat\" RowingBoat\nFishingBoatAdapter ..|> RowingBoat \n@enduml"
  },
  {
    "path": "adapter/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>adapter</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <!-- Maven assembly plugin is invoked with default setting which we have \n\t\t\t\tin parent pom and specifying the class having main method -->\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.adapter.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "adapter/src/main/java/com/iluwatar/adapter/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.adapter;\n\n/**\n * An adapter helps two incompatible interfaces to work together. This is the real world definition\n * for an adapter. Interfaces may be incompatible but the inner functionality should suit the need.\n * The Adapter design pattern allows otherwise incompatible classes to work together by converting\n * the interface of one class into an interface expected by the clients.\n *\n * <p>There are two variations of the Adapter pattern: The class adapter implements the adaptee's\n * interface whereas the object adapter uses composition to contain the adaptee in the adapter\n * object. This example uses the object adapter approach.\n *\n * <p>The Adapter ({@link FishingBoatAdapter}) converts the interface of the adaptee class ({@link\n * FishingBoat}) into a suitable one expected by the client ({@link RowingBoat}).\n *\n * <p>The story of this implementation is this. <br>\n * Pirates are coming! we need a {@link RowingBoat} to flee! We have a {@link FishingBoat} and our\n * captain. We have no time to make up a new ship! we need to reuse this {@link FishingBoat}. The\n * captain needs a rowing boat which he can operate. The spec is in {@link RowingBoat}. We will use\n * the Adapter pattern to reuse {@link FishingBoat}.\n */\npublic final class App {\n\n  private App() {}\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(final String[] args) {\n    // The captain can only operate rowing boats but with adapter he is able to\n    // use fishing boats as well\n    var captain = new Captain(new FishingBoatAdapter());\n    captain.row();\n  }\n}\n"
  },
  {
    "path": "adapter/src/main/java/com/iluwatar/adapter/Captain.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.adapter;\n\nimport lombok.AllArgsConstructor;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n/**\n * The Captain uses {@link RowingBoat} to sail. <br>\n * This is the client in the pattern.\n */\n@Setter\n@NoArgsConstructor\n@AllArgsConstructor\npublic final class Captain {\n\n  private RowingBoat rowingBoat;\n\n  void row() {\n    rowingBoat.row();\n  }\n}\n"
  },
  {
    "path": "adapter/src/main/java/com/iluwatar/adapter/FishingBoat.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.adapter;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Device class (adaptee in the pattern). We want to reuse this class. Fishing boat moves by\n * sailing.\n */\n@Slf4j\nfinal class FishingBoat {\n\n  void sail() {\n    LOGGER.info(\"The fishing boat is sailing\");\n  }\n}\n"
  },
  {
    "path": "adapter/src/main/java/com/iluwatar/adapter/FishingBoatAdapter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.adapter;\n\n/**\n * Adapter class. Adapts the interface of the device ({@link FishingBoat}) into {@link RowingBoat}\n * interface expected by the client ({@link Captain}).\n */\npublic class FishingBoatAdapter implements RowingBoat {\n\n  private final FishingBoat boat = new FishingBoat();\n\n  public final void row() {\n    boat.sail();\n  }\n}\n"
  },
  {
    "path": "adapter/src/main/java/com/iluwatar/adapter/RowingBoat.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.adapter;\n\n/**\n * The interface expected by the client.<br>\n * A rowing boat is rowed to move.\n */\npublic interface RowingBoat {\n\n  void row();\n}\n"
  },
  {
    "path": "adapter/src/main/java/com/iluwatar/adapter/package-info.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.adapter;\n"
  },
  {
    "path": "adapter/src/test/java/com/iluwatar/adapter/AdapterPatternTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.adapter;\n\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.verify;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for the adapter pattern. */\nclass AdapterPatternTest {\n\n  private Map<String, Object> beans;\n\n  private static final String FISHING_BEAN = \"fisher\";\n\n  private static final String ROWING_BEAN = \"captain\";\n\n  /** This method runs before the test execution and sets the bean objects in the beans Map. */\n  @BeforeEach\n  void setup() {\n    beans = new HashMap<>();\n\n    var fishingBoatAdapter = spy(new FishingBoatAdapter());\n    beans.put(FISHING_BEAN, fishingBoatAdapter);\n\n    var captain = new Captain();\n    captain.setRowingBoat((FishingBoatAdapter) beans.get(FISHING_BEAN));\n    beans.put(ROWING_BEAN, captain);\n  }\n\n  /**\n   * This test asserts that when we use the row() method on a captain bean(client), it is internally\n   * calling sail method on the fishing boat object. The Adapter ({@link FishingBoatAdapter} )\n   * converts the interface of the target class ( {@link FishingBoat}) into a suitable one expected\n   * by the client ({@link Captain} ).\n   */\n  @Test\n  void testAdapter() {\n    var captain = (Captain) beans.get(ROWING_BEAN);\n\n    // when captain moves\n    captain.row();\n\n    // the captain internally calls the battleship object to move\n    var adapter = (RowingBoat) beans.get(FISHING_BEAN);\n    verify(adapter).row();\n  }\n}\n"
  },
  {
    "path": "adapter/src/test/java/com/iluwatar/adapter/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.adapter;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Adapter example runs without errors. */\nclass AppTest {\n\n  /** Check whether the execution of the main method in {@link App} throws an exception. */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "ambassador/README.md",
    "content": "---\ntitle: \"Ambassador Pattern in Java: Simplifying Remote Resource Management\"\nshortTitle: Ambassador\ndescription: \"Explore the Ambassador Pattern in Java, its benefits, use cases, and practical examples. Learn how to decouple and offload common functionalities to improve system performance and maintainability.\"\ncategory: Integration\nlanguage: en\ntag:\n  - API design\n  - Decoupling\n  - Fault tolerance\n  - Proxy\n  - Resilience\n  - Scalability\n---\n\n## Intent of Ambassador Design Pattern\n\nThe Ambassador Pattern in Java helps offload common functionalities such as monitoring, logging, and routing from a shared resource to a helper service instance, enhancing performance and maintainability in distributed systems.\n\n## Detailed Explanation of Ambassador Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a busy hotel where guests frequently request restaurant reservations, event tickets, or transportation arrangements. Instead of each guest individually contacting these services, the hotel provides a concierge. The concierge handles these tasks on behalf of the guests, ensuring that reservations are made smoothly, tickets are booked on time, and transportation is scheduled efficiently.\n>\n> In this analogy, the guests are the client services, the external providers (restaurants, ticket vendors, transportation) are the remote services, and the concierge represents the ambassador service. This setup allows the guests to focus on enjoying their stay while the concierge manages the complexities of external interactions, providing a seamless and enhanced experience.\n\nIn plain words\n\n> With the Ambassador pattern, we can implement less-frequent polling from clients along with latency checks and logging.\n\nMicrosoft documentation states\n\n> An ambassador service can be thought of as an out-of-process proxy which is co-located with the client. This pattern can be useful for offloading common client connectivity tasks such as monitoring, logging, routing, security (such as TLS), and resiliency patterns in a language agnostic way. It is often used with legacy applications, or other applications that are difficult to modify, in order to extend their networking capabilities. It can also enable a specialized team to implement those features.\n\nSequence diagram\n\n![Ambassador sequence diagram](./etc/ambassador-sequence-diagram.png \"Ambassador sequence diagram\")\n\n## Programmatic Example of Ambassador Pattern in Java\n\nIn this example of the Ambassador Pattern in Java, we demonstrate how to implement latency checks, logging, and retry mechanisms to improve system reliability.\n\nA remote service has many clients accessing a function it provides. The service is a legacy application and is impossible to update. Large numbers of requests from users are causing connectivity issues. New rules for request frequency should be implemented along with latency checks and client-side logging.\n\nWith the above introduction in mind we will imitate the functionality in this example. We have an interface implemented by the remote service as well as the ambassador service.\n\n```java\ninterface RemoteServiceInterface {\n    long doRemoteFunction(int value) throws Exception;\n}\n```\n\nA remote services represented as a singleton.\n\n```java\n\n@Slf4j\npublic class RemoteService implements RemoteServiceInterface {\n    private static RemoteService service = null;\n\n    static synchronized RemoteService getRemoteService() {\n        if (service == null) {\n            service = new RemoteService();\n        }\n        return service;\n    }\n\n    private RemoteService() {\n    }\n\n    @Override\n    public long doRemoteFunction(int value) {\n        long waitTime = (long) Math.floor(Math.random() * 1000);\n\n        try {\n            sleep(waitTime);\n        } catch (InterruptedException e) {\n            LOGGER.error(\"Thread sleep interrupted\", e);\n        }\n\n        return waitTime >= 200 ? value * 10 : -1;\n    }\n}\n```\n\nA service ambassador adds additional features such as logging and latency checks.\n\n```java\n\n@Slf4j\npublic class ServiceAmbassador implements RemoteServiceInterface {\n    private static final int RETRIES = 3;\n    private static final int DELAY_MS = 3000;\n\n    ServiceAmbassador() {\n    }\n\n    @Override\n    public long doRemoteFunction(int value) {\n        return safeCall(value);\n    }\n\n    private long checkLatency(int value) {\n        var startTime = System.currentTimeMillis();\n        var result = RemoteService.getRemoteService().doRemoteFunction(value);\n        var timeTaken = System.currentTimeMillis() - startTime;\n\n        LOGGER.info(\"Time taken (ms): \" + timeTaken);\n        return result;\n    }\n\n    private long safeCall(int value) {\n        var retries = 0;\n        var result = (long) FAILURE;\n\n        for (int i = 0; i < RETRIES; i++) {\n            if (retries >= RETRIES) {\n                return FAILURE;\n            }\n\n            if ((result = checkLatency(value)) == FAILURE) {\n                LOGGER.info(\"Failed to reach remote: (\" + (i + 1) + \")\");\n                retries++;\n                try {\n                    sleep(DELAY_MS);\n                } catch (InterruptedException e) {\n                    LOGGER.error(\"Thread sleep state interrupted\", e);\n                }\n            } else {\n                break;\n            }\n        }\n        return result;\n    }\n}\n```\n\nA client has a local service ambassador used to interact with the remote service.\n\n```java\n\n@Slf4j\npublic class Client {\n    private final ServiceAmbassador serviceAmbassador = new ServiceAmbassador();\n\n    long useService(int value) {\n        var result = serviceAmbassador.doRemoteFunction(value);\n        LOGGER.info(\"Service result: \" + result);\n        return result;\n    }\n}\n```\n\nHere are two clients using the service.\n\n```java\npublic class App {\n    public static void main(String[] args) {\n        var host1 = new Client();\n        var host2 = new Client();\n        host1.useService(12);\n        host2.useService(73);\n    }\n}\n```\n\nHere's the output for running the example:\n\n```java\nTime taken(ms):111\nService result:120\nTime taken(ms):931\nFailed to reach remote:(1)\nTime taken(ms):665\nFailed to reach remote:(2)\nTime taken(ms):538\nFailed to reach remote:(3)\nService result:-1\n```\n\n## When to Use the Ambassador Pattern in Java\n\n* The Ambassador Pattern is particularly beneficial for Cloud Native and Microservices Architectures in Java. It helps in monitoring, logging, and securing inter-service communication, making it ideal for distributed systems.\n* Legacy System Integration: Facilitates communication with newer services by handling necessary but non-core functionalities.\n* Performance Enhancement: Can be used to cache results or compress data to improve communication efficiency.\n\nTypical use cases include:\n\n* Control access to another object\n* Implement logging\n* Implement circuit breaking\n* Offload remote service tasks\n* Facilitate network connection\n\n## Benefits and Trade-offs of Ambassador Pattern\n\nBenefits:\n\n* Separation of Concerns: Offloads cross-cutting concerns from the service logic, leading to cleaner, more maintainable code.\n* Reusable Infrastructure Logic: The ambassador pattern allows the same logic (e.g., logging, monitoring) to be reused across multiple services.\n* Improved Security: Centralizes security features like SSL termination or authentication, reducing the risk of misconfiguration.\n* Flexibility: Makes it easier to update or replace infrastructure concerns without modifying the service code.\n\nTrade-offs:\n\n* Increased Complexity: Adds another layer to the architecture, which can complicate the system design and debugging.\n* Potential Performance Overhead: The additional network hop can introduce latency and overhead, particularly if not optimized.\n* Deployment Overhead: Requires additional resources and management for deploying and scaling ambassador services.\n\n## Real-World Applications of Ambassador Pattern in Java\n\n* Service Mesh Implementations: In a service mesh architecture, like Istio or Linkerd, the Ambassador pattern is often employed as a sidecar proxy that handles inter-service communications. This includes tasks such as service discovery, routing, load balancing, telemetry (metrics and tracing), and security (authentication and authorization).\n* API Gateways: API gateways can use the Ambassador pattern to encapsulate common functionalities like rate limiting, caching, request shaping, and authentication. This allows backend services to focus on their core business logic without being burdened by these cross-cutting concerns.\n* Logging and Monitoring: An Ambassador can aggregate logs and metrics from various services and forward them to centralized monitoring tools like Prometheus or ELK Stack (Elasticsearch, Logstash, Kibana). This simplifies the logging and monitoring setup for each service and provides a unified view of the system's health.\n* Security: Security-related functionalities such as SSL/TLS termination, identity verification, and encryption can be managed by an Ambassador. This ensures consistent security practices across services and reduces the likelihood of security breaches due to misconfigurations.\n* Resilience: The Ambassador can implement resilience patterns like circuit breakers, retries, and timeouts. For instance, Netflix's Hystrix library can be used within an Ambassador to prevent cascading failures in a microservices ecosystem.\n* Database Proxy: Ambassadors can act as proxies for database connections, providing functionalities like connection pooling, read/write splitting for replicas, and query caching. This offloads significant complexity from the application services.\n* Legacy System Integration: In scenarios where modern microservices need to communicate with legacy systems, an Ambassador can serve as an intermediary that translates protocols, handles necessary transformations, and implements modern security practices, easing the integration process.\n* Network Optimization: For services deployed across different geographical locations or cloud regions, Ambassadors can optimize communication by compressing data, batching requests, or even implementing smart routing to reduce latency and costs.\n* [Kubernetes-native API gateway for microservices](https://github.com/datawire/ambassador)\n\n## Related Java Design Patterns\n\n* [Circuit Breaker](https://java-design-patterns.com/patterns/circuit-breaker/): Often used in conjunction to manage fault tolerance by stopping calls to an unresponsive service.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): The decorator pattern is used to add functionality to an object dynamically, while the ambassador pattern is used to offload functionality to a separate object.\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): Shares similarities with the proxy pattern, but the ambassador pattern specifically focuses on offloading ancillary functionalities.\n* Sidecar: A similar pattern used in the context of containerized applications, where a sidecar container provides additional functionality to the main application container.\n\n## References and Credits\n\n* [Building Microservices: Designing Fine-Grained Systems](https://amzn.to/43aGpSR)\n* [Cloud Native Patterns: Designing Change-tolerant Software](https://amzn.to/3wUAl4O)\n* [Designing Distributed Systems: Patterns and Paradigms for Scalable, Reliable Services](https://amzn.to/3T9g9Uj)\n* [Microservices Patterns: With examples in Java](https://amzn.to/3UyWD5O)\n* [Ambassador pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/patterns/ambassador)\n"
  },
  {
    "path": "ambassador/etc/ambassador.urm.puml",
    "content": "@startuml\npackage com.iluwatar.ambassador.util {\n  interface RandomProvider {\n    + random() : double {abstract}\n  }\n}\npackage com.iluwatar.ambassador {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Client {\n    - LOGGER : Logger {static}\n    - serviceAmbassador : ServiceAmbassador\n    + Client()\n    ~ useService(value : int) : long\n  }\n  class RemoteService {\n    - LOGGER : Logger {static}\n    - THRESHOLD : int {static}\n    - randomProvider : RandomProvider\n    - service : RemoteService {static}\n    - RemoteService()\n    ~ RemoteService(randomProvider : RandomProvider)\n    + doRemoteFunction(value : int) : long\n    ~ getRemoteService() : RemoteService {static}\n  }\n  ~interface RemoteServiceInterface {\n    + FAILURE : int {static}\n    + doRemoteFunction(int) : long {abstract}\n  }\n  class ServiceAmbassador {\n    - DELAY_MS : int {static}\n    - LOGGER : Logger {static}\n    - RETRIES : int {static}\n    ~ ServiceAmbassador()\n    - checkLatency(value : int) : long\n    + doRemoteFunction(value : int) : long\n    - safeCall(value : int) : long\n  }\n}\nRemoteService -->  \"-service\" RemoteService\nClient -->  \"-serviceAmbassador\" ServiceAmbassador\nRemoteService -->  \"-randomProvider\" RandomProvider\nRemoteService ..|> RemoteServiceInterface \nServiceAmbassador ..|> RemoteServiceInterface \n@enduml"
  },
  {
    "path": "ambassador/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>ambassador</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.ambassador.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "ambassador/src/main/java/com/iluwatar/ambassador/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.ambassador;\n\n/**\n * The ambassador pattern creates a helper service that sends network requests on behalf of a\n * client. It is often used in cloud-based applications to offload features of a remote service.\n *\n * <p>An ambassador service can be thought of as an out-of-process proxy that is co-located with the\n * client. Similar to the proxy design pattern, the ambassador service provides an interface for\n * another remote service. In addition to the interface, the ambassador provides extra functionality\n * and features, specifically offloaded common connectivity tasks. This usually consists of\n * monitoring, logging, routing, security etc. This is extremely useful in legacy applications where\n * the codebase is difficult to modify and allows for improvements in the application's networking\n * capabilities.\n *\n * <p>In this example, we will the ({@link ServiceAmbassador}) class represents the ambassador while\n * the ({@link RemoteService}) class represents a remote application.\n */\npublic class App {\n\n  /** Entry point. */\n  public static void main(String[] args) {\n    var host1 = new Client();\n    var host2 = new Client();\n    host1.useService(12);\n    host2.useService(73);\n  }\n}\n"
  },
  {
    "path": "ambassador/src/main/java/com/iluwatar/ambassador/Client.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.ambassador;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** A simple Client. */\n@Slf4j\npublic class Client {\n\n  private final ServiceAmbassador serviceAmbassador = new ServiceAmbassador();\n\n  long useService(int value) {\n    var result = serviceAmbassador.doRemoteFunction(value);\n    LOGGER.info(\"Service result: {}\", result);\n    return result;\n  }\n}\n"
  },
  {
    "path": "ambassador/src/main/java/com/iluwatar/ambassador/RemoteService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.ambassador;\n\nimport static java.lang.Thread.sleep;\n\nimport com.iluwatar.ambassador.util.RandomProvider;\nimport lombok.extern.slf4j.Slf4j;\n\n/** A remote legacy application represented by a Singleton implementation. */\n@Slf4j\npublic class RemoteService implements RemoteServiceInterface {\n  private static final int THRESHOLD = 200;\n  private static RemoteService service = null;\n  private final RandomProvider randomProvider;\n\n  static synchronized RemoteService getRemoteService() {\n    if (service == null) {\n      service = new RemoteService();\n    }\n    return service;\n  }\n\n  private RemoteService() {\n    this(Math::random);\n  }\n\n  /** This constructor is used for testing purposes only. */\n  RemoteService(RandomProvider randomProvider) {\n    this.randomProvider = randomProvider;\n  }\n\n  /**\n   * Remote function takes a value and multiplies it by 10 taking a random amount of time. Will\n   * sometimes return -1. This imitates connectivity issues a client might have to account for.\n   *\n   * @param value integer value to be multiplied.\n   * @return if waitTime is less than {@link RemoteService#THRESHOLD}, it returns value * 10,\n   *     otherwise {@link RemoteServiceStatus#FAILURE}.\n   */\n  @Override\n  public long doRemoteFunction(int value) {\n\n    long waitTime = (long) Math.floor(randomProvider.random() * 1000);\n\n    try {\n      sleep(waitTime);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Thread sleep state interrupted\", e);\n      Thread.currentThread().interrupt();\n    }\n    return waitTime <= THRESHOLD\n        ? value * 10\n        : RemoteServiceStatus.FAILURE.getRemoteServiceStatusValue();\n  }\n}\n"
  },
  {
    "path": "ambassador/src/main/java/com/iluwatar/ambassador/RemoteServiceInterface.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.ambassador;\n\n/** Interface shared by ({@link RemoteService}) and ({@link ServiceAmbassador}). */\ninterface RemoteServiceInterface {\n\n  long doRemoteFunction(int value);\n}\n"
  },
  {
    "path": "ambassador/src/main/java/com/iluwatar/ambassador/RemoteServiceStatus.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.ambassador;\n\nimport lombok.Getter;\n\n/**\n * Holds information regarding the status of the Remote Service.\n *\n * <p>This Enum replaces the integer value previously stored in {@link RemoteServiceInterface} as\n * SonarCloud was identifying it as an issue. All test cases have been checked after changes,\n * without failures.\n */\npublic enum RemoteServiceStatus {\n  FAILURE(-1);\n\n  @Getter private final long remoteServiceStatusValue;\n\n  RemoteServiceStatus(long remoteServiceStatusValue) {\n    this.remoteServiceStatusValue = remoteServiceStatusValue;\n  }\n}\n"
  },
  {
    "path": "ambassador/src/main/java/com/iluwatar/ambassador/ServiceAmbassador.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.ambassador;\n\nimport static com.iluwatar.ambassador.RemoteServiceStatus.FAILURE;\nimport static java.lang.Thread.sleep;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * ServiceAmbassador provides an interface for a ({@link Client}) to access ({@link RemoteService}).\n * The interface adds logging, latency testing and usage of the service in a safe way that will not\n * add stress to the remote service when connectivity issues occur.\n */\n@Slf4j\npublic class ServiceAmbassador implements RemoteServiceInterface {\n\n  private static final int RETRIES = 3;\n  private static final int DELAY_MS = 3000;\n\n  ServiceAmbassador() {}\n\n  @Override\n  public long doRemoteFunction(int value) {\n    return safeCall(value);\n  }\n\n  private long checkLatency(int value) {\n    var startTime = System.currentTimeMillis();\n    var result = RemoteService.getRemoteService().doRemoteFunction(value);\n    var timeTaken = System.currentTimeMillis() - startTime;\n\n    LOGGER.info(\"Time taken (ms): {}\", timeTaken);\n    return result;\n  }\n\n  private long safeCall(int value) {\n    var retries = 0;\n    var result = FAILURE.getRemoteServiceStatusValue();\n\n    for (int i = 0; i < RETRIES; i++) {\n      if (retries >= RETRIES) {\n        return FAILURE.getRemoteServiceStatusValue();\n      }\n\n      if ((result = checkLatency(value)) == FAILURE.getRemoteServiceStatusValue()) {\n        LOGGER.info(\"Failed to reach remote: ({})\", i + 1);\n        retries++;\n        try {\n          sleep(DELAY_MS);\n        } catch (InterruptedException e) {\n          LOGGER.error(\"Thread sleep state interrupted\", e);\n          Thread.currentThread().interrupt();\n        }\n      } else {\n        break;\n      }\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "ambassador/src/main/java/com/iluwatar/ambassador/util/RandomProvider.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.ambassador.util;\n\n/** An interface for randomness. Useful for testing purposes. */\npublic interface RandomProvider {\n  double random();\n}\n"
  },
  {
    "path": "ambassador/src/test/java/com/iluwatar/ambassador/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.ambassador;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "ambassador/src/test/java/com/iluwatar/ambassador/ClientTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.ambassador;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test for {@link Client} */\nclass ClientTest {\n\n  @Test\n  void test() {\n    Client client = new Client();\n    var result = client.useService(10);\n\n    assertTrue(\n        result == 100 || result == RemoteServiceStatus.FAILURE.getRemoteServiceStatusValue());\n  }\n}\n"
  },
  {
    "path": "ambassador/src/test/java/com/iluwatar/ambassador/RemoteServiceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.ambassador;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.ambassador.util.RandomProvider;\nimport org.junit.jupiter.api.Test;\n\n/** Test for {@link RemoteService} */\nclass RemoteServiceTest {\n\n  @Test\n  void testFailedCall() {\n    var remoteService = new RemoteService(new StaticRandomProvider(0.21));\n    var result = remoteService.doRemoteFunction(10);\n    assertEquals(RemoteServiceStatus.FAILURE.getRemoteServiceStatusValue(), result);\n  }\n\n  @Test\n  void testSuccessfulCall() {\n    var remoteService = new RemoteService(new StaticRandomProvider(0.2));\n    var result = remoteService.doRemoteFunction(10);\n    assertEquals(100, result);\n  }\n\n  private static class StaticRandomProvider implements RandomProvider {\n    private final double value;\n\n    StaticRandomProvider(double value) {\n      this.value = value;\n    }\n\n    @Override\n    public double random() {\n      return value;\n    }\n  }\n}\n"
  },
  {
    "path": "ambassador/src/test/java/com/iluwatar/ambassador/ServiceAmbassadorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.ambassador;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test for {@link ServiceAmbassador} */\nclass ServiceAmbassadorTest {\n\n  @Test\n  void test() {\n    long result = new ServiceAmbassador().doRemoteFunction(10);\n    assertTrue(\n        result == 100 || result == RemoteServiceStatus.FAILURE.getRemoteServiceStatusValue());\n  }\n}\n"
  },
  {
    "path": "anti-corruption-layer/README.md",
    "content": "---\ntitle: \"Anti-Corruption Layer Pattern in Java: Ensuring System Integrity Amidst Legacy Systems\"\nshortTitle: Anti-Corruption Layer\ndescription: \"Learn how the Anti-Corruption Layer design pattern helps in decoupling subsystems, preventing data corruption, and facilitating seamless integration in Java applications.\"\ncategory: Integration\nlanguage: en\ntag:\n  - Architecture\n  - Decoupling\n  - Integration\n  - Isolation\n  - Layered architecture\n  - Migration\n  - Modernization\n  - Refactoring\n  - Wrapping\n---\n\n## Also known as\n\n* ACL\n* Interface layer\n* Translation layer\n\n## Intent of Anti-Corruption Layer Design Pattern\n\nThe Anti-Corruption Layer (ACL) is a crucial design pattern in Java development, particularly for system integration and maintaining data integrity. Implement a façade or adapter layer between different subsystems that don't share the same semantics. It translates between different data formats and systems, ensuring that the integration between systems does not lead to corruption of business logic or data integrity.\n\n## Detailed Explanation of Anti-Corruption Layer Pattern with Real-World Examples\n\nReal-world example\n\n> This example demonstrates how the Anti-Corruption Layer ensures seamless integration between legacy systems and modern platforms, crucial for maintaining business logic integrity during system migration.\n> \n> Imagine a large retail company transitioning its inventory management system from an old legacy software to a new modern platform. The legacy system has been in use for decades and contains complex business rules and data formats that are incompatible with the new system. Instead of directly connecting the new system to the legacy one, the company implements an Anti-Corruption Layer (ACL).\n> \n> The ACL acts as a mediator, translating and adapting data between the two systems. When the new system requests inventory data, the ACL translates the request into a format the legacy system understands, retrieves the data, and then translates it back into a format suitable for the new system. This approach ensures that the new system remains unaffected by the intricacies of the legacy system, preventing corruption of data and business logic while facilitating a smooth transition.\n\nIn plain words\n\n> The Anti-Corruption Layer design pattern protects a system from the complexities and changes of external systems by providing an intermediary translation layer.\n\n[Microsoft's documentation](https://learn.microsoft.com/en-us/azure/architecture/patterns/anti-corruption-layer) says\n\n> Implement a façade or adapter layer between different subsystems that don't share the same semantics. This layer translates requests that one subsystem makes to the other subsystem. Use this pattern to ensure that an application's design is not limited by dependencies on outside subsystems. This pattern was first described by Eric Evans in Domain-Driven Design.\n\nSequence diagram\n\n![Anti-Corruption Layer sequence diagram](./etc/anti-corruption-layer-sequence-diagram.png \"Anti-Corruption Layer sequence diagram\")\n\n## Programmatic Example of Anti-Corruption Layer Pattern in Java\n\nThe ACL design pattern in Java provides an intermediary layer that translates data formats, ensuring that integration between different systems does not lead to data corruption.\n\nHere are 2 shop-ordering systems: `Legacy` and `Modern`.\n\nThe aforementioned systems have different domain models and have to operate simultaneously. Since they work independently the orders can come either from the `Legacy` or `Modern` system. Therefore, the system that receives the legacyOrder needs to check if the legacyOrder is valid and not present in the other system. Then it can place the legacyOrder in its own system.\n\nBut for that, the system needs to know the domain model of the other system and to avoid that, the anti-corruption layer(ACL) is introduced. The ACL is a layer that translates the domain model of the `Legacy` system to the domain model of the `Modern` system and vice versa. Also, it hides all other operations with the other system, uncoupling the systems.\n\nDomain model of the `Legacy` system:\n\n```java\npublic class LegacyOrder {\n    private String id;\n    private String customer;\n    private String item;\n    private String qty;\n    private String price;\n}\n```\n\nDomain model of the `Modern` system:\n\n```java\npublic class ModernOrder {\n    private String id;\n    private Customer customer;\n\n    private Shipment shipment;\n\n    private String extra;\n}\n\npublic class Customer {\n    private String address;\n}\n\npublic class Shipment {\n    private String item;\n    private String qty;\n    private String price;\n}\n```\n\nAnti-corruption layer:\n\n```java\npublic class AntiCorruptionLayer {\n\n    @Autowired\n    private ModernShop modernShop;\n\n    @Autowired\n    private LegacyShop legacyShop;\n\n    public Optional<LegacyOrder> findOrderInModernSystem(String id) {\n        return modernShop.findOrder(id).map(o -> /* map to legacyOrder*/);\n    }\n\n    public Optional<ModernOrder> findOrderInLegacySystem(String id) {\n        return legacyShop.findOrder(id).map(o -> /* map to modernOrder*/);\n    }\n\n}\n```\n\nThe connection between the systems. Wherever the `Legacy` or `Modern` system needs to communicate with the counterpart the ACL needs to be used to avoid corrupting the current domain model. The example below shows how the `Legacy` system places an order with a validation from the `Modern` system.\n\n```java\npublic class LegacyShop {\n    @Autowired\n    private AntiCorruptionLayer acl;\n\n    public void placeOrder(LegacyOrder legacyOrder) throws ShopException {\n\n        String id = legacyOrder.getId();\n\n        Optional<ModernOrder> orderInModernSystem = acl.findOrderInModernSystem(id);\n\n        if (orderInModernSystem.isPresent()) {\n            // order is already in the modern system\n        } else {\n            // place order in the current system\n        }\n    }\n}\n```\n\n## When to Use the Anti-Corruption Layer Pattern in Java\n\nUse this pattern when:\n\n* A migration is planned to happen over multiple stages, but integration between new and legacy systems needs to be maintained\n* Two or more subsystems have different semantics, but still need to communicate\n* When integrating with legacy systems or external systems where direct integration might pollute the domain model of the new system\n* In scenarios where different subsystems within a larger system use different data formats or structures\n* When there is a need to ensure loose coupling between different subsystems or external services to facilitate easier maintenance and scalability\n\n## Anti-Corruption Layer Pattern Java Tutorials\n\n* [Anti-Corruption Layer (Microsoft)](https://learn.microsoft.com/en-us/azure/architecture/patterns/anti-corruption-layer)\n* [Anti-Corruption Layer Pattern (Amazon)](https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/acl.html)\n\n## Real-World Applications of Anti-Corruption Layer Pattern in Java\n\n* Microservices architectures where individual services must communicate without being tightly coupled to each other’s data schemas\n* Enterprise systems integration, especially when integrating modern systems with legacy systems\n* In bounded contexts within Domain-Driven Design (DDD) to maintain the integrity of a domain model when interacting with external systems or subsystems\n\n## Benefits and Trade-offs of Anti-Corruption Layer Pattern\n\nBenefits:\n\n* Protects the integrity of the domain model by providing a clear boundary\n* Promotes loose coupling between systems, making the system more resilient to changes in external systems\n* Facilitates cleaner and more maintainable code by isolating integration code from business logic\n\nTrade-offs:\n\n* Introduces additional complexity and potential performance overhead due to the translation process\n* Requires extra effort in design and implementation to ensure the layer is effective without becoming a bottleneck\n* Can lead to duplication of models if not carefully managed\n\n## Related Java Design Patterns\n\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): The Anti-Corruption Layer can be implemented using the Adapter pattern to translate between different data formats or structures\n* [Facade](https://java-design-patterns.com/patterns/facade/): The Anti-Corruption Layer can be seen as a specialized form of the Facade pattern that is used to isolate different subsystems\n* [Gateway](https://java-design-patterns.com/patterns/gateway/): The Anti-Corruption Layer can be used as a Gateway to external systems to provide a unified interface\n\n## References and Credits\n\n* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3vptcJz)\n* [Implementing Domain-Driven Design](https://amzn.to/3ISOSRA)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "anti-corruption-layer/etc/anti-corruption-layer.urm.puml",
    "content": "@startuml\npackage com.iluwatar.corruption {\nclass LegacyShop {\n    private Store store;\n    private AntiCorruptionLayer acl;\n}\n\nclass ModernShop {\n    private Store store;\n    private AntiCorruptionLayer acl;\n}\n\nclass AntiCorruptionLayer{\n    private LegacyShop legacyShop;\n    private ModernShop modernShop;\n\n\n }\nLegacyShop --->  \"findOrderInModernSystem\" AntiCorruptionLayer\nModernShop --->  \"findOrderInLegacySystem\" AntiCorruptionLayer\nAntiCorruptionLayer ..|>   ModernShop\nAntiCorruptionLayer ..|> LegacyShop\n}\n\n@enduml"
  },
  {
    "path": "anti-corruption-layer/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>anti-corruption-layer</artifactId>\n  <packaging>jar</packaging>\n  <dependencies>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-test</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.corruption.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * This layer translates communications between the two systems, allowing one system to remain\n * unchanged while the other can avoid compromising its design and technological approach.\n */\n@SpringBootApplication\npublic class App {\n\n  public static void main(String[] args) {\n    SpringApplication.run(App.class, args);\n  }\n}\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/package-info.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/**\n * Context and problem Most applications rely on other systems for some data or functionality. For\n * example, when a legacy application is migrated to a modern system, it may still need existing\n * legacy resources. New features must be able to call the legacy system. This is especially true of\n * gradual migrations, where different features of a larger application are moved to a modern system\n * over time.\n *\n * <p>Often these legacy systems suffer from quality issues such as convoluted data schemas or\n * obsolete APIs. The features and technologies used in legacy systems can vary widely from more\n * modern systems. To interoperate with the legacy system, the new application may need to support\n * outdated infrastructure, protocols, data models, APIs, or other features that you wouldn't\n * otherwise put into a modern application.\n *\n * <p>Maintaining access between new and legacy systems can force the new system to adhere to at\n * least some of the legacy system's APIs or other semantics. When these legacy features have\n * quality issues, supporting them \"corrupts\" what might otherwise be a cleanly designed modern\n * application. Similar issues can arise with any external system that your development team doesn't\n * control, not just legacy systems.\n *\n * <p>Solution Isolate the different subsystems by placing an anti-corruption layer between them.\n * This layer translates communications between the two systems, allowing one system to remain\n * unchanged while the other can avoid compromising its design and technological approach.\n */\npackage com.iluwatar.corruption;\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/system/AntiCorruptionLayer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption.system;\n\nimport com.iluwatar.corruption.system.legacy.LegacyShop;\nimport com.iluwatar.corruption.system.modern.Customer;\nimport com.iluwatar.corruption.system.modern.ModernOrder;\nimport com.iluwatar.corruption.system.modern.Shipment;\nimport java.util.Optional;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * The class represents an anti-corruption layer. The main purpose of the class is to provide a\n * layer between the modern and legacy systems. The class is responsible for converting the data\n * from one system to another decoupling the systems to each other\n *\n * <p>It allows using one system a domain model of the other system without changing the domain\n * model of the system.\n */\n@Service\npublic class AntiCorruptionLayer {\n\n  @Autowired private LegacyShop legacyShop;\n\n  /**\n   * The method converts the order from the legacy system to the modern system.\n   *\n   * @param id the id of the order\n   * @return the order in the modern system\n   */\n  public Optional<ModernOrder> findOrderInLegacySystem(String id) {\n\n    return legacyShop\n        .findOrder(id)\n        .map(\n            o ->\n                new ModernOrder(\n                    o.getId(),\n                    new Customer(o.getCustomer()),\n                    new Shipment(o.getItem(), o.getQty(), o.getPrice()),\n                    \"\"));\n  }\n}\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/system/DataStore.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption.system;\n\nimport java.util.HashMap;\nimport java.util.Optional;\n\n/**\n * The class represents a data store for the modern system.\n *\n * @param <V> the type of the value stored in the data store\n */\npublic abstract class DataStore<V> {\n  private final HashMap<String, V> inner;\n\n  public DataStore() {\n    inner = new HashMap<>();\n  }\n\n  public Optional<V> get(String key) {\n    return Optional.ofNullable(inner.get(key));\n  }\n\n  public Optional<V> put(String key, V value) {\n    return Optional.ofNullable(inner.put(key, value));\n  }\n}\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/system/ShopException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption.system;\n\n/** The class represents a general exception for the shop. */\npublic class ShopException extends Exception {\n  public ShopException(String message) {\n    super(message);\n  }\n\n  /**\n   * Throws an exception that the order is already placed but has an incorrect data.\n   *\n   * @param lhs the incoming order\n   * @param rhs the existing order\n   * @return the exception\n   * @throws ShopException the exception\n   */\n  public static ShopException throwIncorrectData(String lhs, String rhs) throws ShopException {\n    throw new ShopException(\n        \"The order is already placed but has an incorrect data:\\n\"\n            + \"Incoming order:  \"\n            + lhs\n            + \"\\n\"\n            + \"Existing order:  \"\n            + rhs);\n  }\n}\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/system/legacy/LegacyOrder.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption.system.legacy;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\n/**\n * The class represents an order in the legacy system. The class is used by the legacy system to\n * store the data.\n */\n@Data\n@AllArgsConstructor\npublic class LegacyOrder {\n  private String id;\n  private String customer;\n\n  private String item;\n  private int qty;\n  private int price;\n}\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/system/legacy/LegacyShop.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption.system.legacy;\n\nimport java.util.Optional;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * The class represents a legacy shop system. The main purpose is to place the order from the\n * customers.\n */\n@Service\npublic class LegacyShop {\n  @Autowired private LegacyStore store;\n\n  /**\n   * Places the order in the legacy system. If the order is already present in the modern system,\n   * then the order is placed only if the data is the same. If the order is not present in the\n   * modern system, then the order is placed in the legacy system.\n   */\n  public void placeOrder(LegacyOrder legacyOrder) {\n    store.put(legacyOrder.getId(), legacyOrder);\n  }\n\n  /** Finds the order in the legacy system. */\n  public Optional<LegacyOrder> findOrder(String orderId) {\n    return store.get(orderId);\n  }\n}\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/system/legacy/LegacyStore.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption.system.legacy;\n\nimport com.iluwatar.corruption.system.DataStore;\nimport org.springframework.stereotype.Service;\n\n/**\n * The class represents a data store for the legacy system. The class is used by the legacy system\n * to store the data.\n */\n@Service\npublic class LegacyStore extends DataStore<LegacyOrder> {}\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/system/modern/Customer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption.system.modern;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\n/** The class represents a customer in the modern system. */\n@Data\n@AllArgsConstructor\npublic class Customer {\n  private String address;\n}\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/system/modern/ModernOrder.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption.system.modern;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\n/** The class represents an order in the modern system. */\n@Data\n@AllArgsConstructor\npublic class ModernOrder {\n  private String id;\n  private Customer customer;\n\n  private Shipment shipment;\n\n  private String extra;\n}\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/system/modern/ModernShop.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption.system.modern;\n\nimport com.iluwatar.corruption.system.AntiCorruptionLayer;\nimport com.iluwatar.corruption.system.ShopException;\nimport java.util.Optional;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * The class represents a modern shop system. The main purpose of the class is to place orders and\n * find orders.\n */\n@Service\npublic class ModernShop {\n  @Autowired private ModernStore store;\n\n  @Autowired private AntiCorruptionLayer acl;\n\n  /**\n   * Places the order in the modern system. If the order is already present in the legacy system,\n   * then no need to place it again.\n   */\n  public void placeOrder(ModernOrder order) throws ShopException {\n\n    String id = order.getId();\n    // check if the order is already present in the legacy system\n    Optional<ModernOrder> orderInObsoleteSystem = acl.findOrderInLegacySystem(id);\n\n    if (orderInObsoleteSystem.isPresent()) {\n      var legacyOrder = orderInObsoleteSystem.get();\n      if (!order.equals(legacyOrder)) {\n        throw ShopException.throwIncorrectData(legacyOrder.toString(), order.toString());\n      }\n    } else {\n      store.put(id, order);\n    }\n  }\n\n  /** Finds the order in the modern system. */\n  public Optional<ModernOrder> findOrder(String orderId) {\n    return store.get(orderId);\n  }\n}\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/system/modern/ModernStore.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption.system.modern;\n\nimport com.iluwatar.corruption.system.DataStore;\nimport org.springframework.stereotype.Service;\n\n/** The class represents a data store for the modern system. */\n@Service\npublic class ModernStore extends DataStore<ModernOrder> {}\n"
  },
  {
    "path": "anti-corruption-layer/src/main/java/com/iluwatar/corruption/system/modern/Shipment.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption.system.modern;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\n/**\n * The class represents a shipment in the modern system. The class is used by the modern system to\n * store the data.\n */\n@Data\n@AllArgsConstructor\npublic class Shipment {\n  private String item;\n  private int qty;\n  private int price;\n}\n"
  },
  {
    "path": "anti-corruption-layer/src/main/resources/application.properties",
    "content": ""
  },
  {
    "path": "anti-corruption-layer/src/test/java/com/iluwatar/corruption/system/AntiCorruptionLayerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.corruption.system;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport com.iluwatar.corruption.system.legacy.LegacyOrder;\nimport com.iluwatar.corruption.system.legacy.LegacyShop;\nimport com.iluwatar.corruption.system.modern.Customer;\nimport com.iluwatar.corruption.system.modern.ModernOrder;\nimport com.iluwatar.corruption.system.modern.ModernShop;\nimport com.iluwatar.corruption.system.modern.Shipment;\nimport java.util.Optional;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\n@ExtendWith(SpringExtension.class)\n@SpringBootTest\npublic class AntiCorruptionLayerTest {\n\n  @Autowired private LegacyShop legacyShop;\n\n  @Autowired private ModernShop modernShop;\n\n  /**\n   * Test the anti-corruption layer. Main intention is to demonstrate how the anti-corruption layer\n   * works. The 2 shops (modern and legacy) should operate independently and in the same time\n   * synchronize the data.\n   */\n  @Test\n  public void antiCorruptionLayerTest() throws ShopException {\n    // a new order comes to the legacy shop.\n    LegacyOrder legacyOrder = new LegacyOrder(\"1\", \"addr1\", \"item1\", 1, 1);\n    // place the order in the legacy shop.\n    legacyShop.placeOrder(legacyOrder);\n    // the order is placed as usual since there is no other orders with the id in the both systems.\n    Optional<LegacyOrder> legacyOrderWithIdOne = legacyShop.findOrder(\"1\");\n    assertEquals(Optional.of(legacyOrder), legacyOrderWithIdOne);\n\n    // a new order (or maybe just the same order) appears in the modern shop\n    ModernOrder modernOrder =\n        new ModernOrder(\"1\", new Customer(\"addr1\"), new Shipment(\"item1\", 1, 1), \"\");\n    // the system places it, but it checks if there is an order with the same id in the legacy shop.\n    modernShop.placeOrder(modernOrder);\n\n    Optional<ModernOrder> modernOrderWithIdOne = modernShop.findOrder(\"1\");\n    // there is no new order placed since there is already an order with the same id in the legacy\n    // shop.\n    assertTrue(modernOrderWithIdOne.isEmpty());\n  }\n\n  /**\n   * Test the anti-corruption layer when a conflict occurs between systems. This test ensures that\n   * an exception is thrown when conflicting orders are placed.\n   */\n  @Test\n  public void antiCorruptionLayerWithExTest() throws ShopException {\n    // a new order comes to the legacy shop.\n    LegacyOrder legacyOrder = new LegacyOrder(\"1\", \"addr1\", \"item1\", 1, 1);\n    // place the order in the legacy shop.\n    legacyShop.placeOrder(legacyOrder);\n    // the order is placed as usual since there is no other orders with the id in the both systems.\n    Optional<LegacyOrder> legacyOrderWithIdOne = legacyShop.findOrder(\"1\");\n    assertEquals(Optional.of(legacyOrder), legacyOrderWithIdOne);\n    // a new order but with the same id and different data appears in the modern shop\n    ModernOrder modernOrder =\n        new ModernOrder(\"1\", new Customer(\"addr1\"), new Shipment(\"item1\", 10, 1), \"\");\n    // the system rejects the order since there are 2 orders with contradiction there.\n    assertThrows(ShopException.class, () -> modernShop.placeOrder(modernOrder));\n  }\n}\n"
  },
  {
    "path": "arrange-act-assert/README.md",
    "content": "---\ntitle: \"Arrange/Act/Assert Pattern in Java: Enhance Testing Clarity and Simplicity\"\nshortTitle: Arrange/Act/Assert\ndescription: \"Learn how to use the Arrange/Act/Assert pattern to structure your unit tests in Java. Improve readability and maintainability of your code with clear testing phases.\"\ncategory: Testing\nlanguage: en\ntag:\n  - Code simplification\n  - Isolation\n  - Testing\n---\n\n## Also known as\n\n* Given/When/Then\n\n## Intent of Arrange/Act/Assert Design Pattern\n\nThe Arrange/Act/Assert pattern is essential in unit testing in Java. This testing method structures unit tests clearly by dividing them into three distinct sections: setup (Arrange), execution (Act), and verification (Assert).\n\n## Detailed Explanation of Arrange/Act/Assert Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine you are organizing a small event. To ensure everything runs smoothly, you follow a pattern similar to Arrange/Act/Assert:\n>\n> 1. **Arrange**: You set up the venue, prepare the guest list, arrange seating, and organize the catering.\n> 2. **Act**: You conduct the event according to the plan, welcoming guests, serving food, and following the schedule.\n> 3. **Assert**: After the event, you evaluate its success by checking guest feedback, ensuring all tasks were completed, and reviewing if everything went as planned.\n>\n> This clear separation of preparation, execution, and evaluation helps ensure the event is well-organized and successful, mirroring the structured approach of the Arrange/Act/Assert pattern in software testing.\n\nIn plain words\n\n> Arrange/Act/Assert is a testing pattern that organizes tests into three clear steps for easy maintenance.\n\nWikiWikiWeb says\n\n> Arrange/Act/Assert is a pattern for arranging and formatting code in UnitTest methods.\n\nFlowchart\n\n![Arrange/Act/Assert flowchart](./etc/arrange-act-assert-flowchart.png \"Arrange/Act/Assert flowchart\")\n\n## Programmatic Example of Arrange/Act/Assert Pattern in Java\n\nWe need to write comprehensive and clear unit test suite for a class. Using the Arrange/Act/Assert pattern in Java testing ensures clarity.\n\nLet's first introduce our `Cash` class to be unit tested.\n\n```java\npublic class Cash {\n\n    private int amount;\n\n    Cash(int amount) {\n        this.amount = amount;\n    }\n\n    void plus(int addend) {\n        amount += addend;\n    }\n\n    boolean minus(int subtrahend) {\n        if (amount >= subtrahend) {\n            amount -= subtrahend;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    int count() {\n        return amount;\n    }\n}\n```\n\nThen we write our unit tests according to Arrange/Act/Assert pattern. Notice the clearly separated steps for each unit test.\n\n```java\nclass CashAAATest {\n\n    @Test\n    void testPlus() {\n        //Arrange\n        var cash = new Cash(3);\n        //Act\n        cash.plus(4);\n        //Assert\n        assertEquals(7, cash.count());\n    }\n\n    @Test\n    void testMinus() {\n        //Arrange\n        var cash = new Cash(8);\n        //Act\n        var result = cash.minus(5);\n        //Assert\n        assertTrue(result);\n        assertEquals(3, cash.count());\n    }\n\n    @Test\n    void testInsufficientMinus() {\n        //Arrange\n        var cash = new Cash(1);\n        //Act\n        var result = cash.minus(6);\n        //Assert\n        assertFalse(result);\n        assertEquals(1, cash.count());\n    }\n\n    @Test\n    void testUpdate() {\n        //Arrange\n        var cash = new Cash(5);\n        //Act\n        cash.plus(6);\n        var result = cash.minus(3);\n        //Assert\n        assertTrue(result);\n        assertEquals(8, cash.count());\n    }\n}\n```\n\n## When to Use the Arrange/Act/Assert Pattern in Java\n\nUse Arrange/Act/Assert pattern when\n\n* Unit testing, especially within the context of TDD and BDD\n* Anywhere clarity and structure are needed in test cases\n\n## Real-World Applications of Arrange/Act/Assert Pattern in Java\n\n* This pattern is particularly useful when practicing TDD and/or BDD methodologies in Java.\n* Utilized in various programming languages and testing frameworks, such as JUnit (Java), NUnit (.NET), and xUnit frameworks.\n\n## Benefits and Trade-offs of Arrange/Act/Assert Pattern\n\nBenefits:\n\n* Improved readability of tests by clearly separating the setup, action, and verification steps.\n* Easier maintenance and understanding of tests, as each test is structured in a predictable way.\n* Facilitates debugging by isolating test failures to specific phases within the test.\n\nTrade-offs:\n\n* May introduce redundancy in tests, as similar arrangements may be repeated across tests.\n* Some complex tests might not fit neatly into this structure, requiring additional context or setup outside these three phases.\n\n## Related Java Design Patterns\n\n* [Page Object](https://java-design-patterns.com/patterns/page-object/): A pattern for organizing UI tests that can be used in conjunction with Arrange/Act/Assert.\n\n## References and Credits\n\n* [The Art of Unit Testing: with examples in C#](https://amzn.to/49IbdwO)\n* [Test Driven Development: By Example](https://amzn.to/3wEwKbF)\n* [Unit Testing Principles, Practices, and Patterns: Effective testing styles, patterns, and reliable automation for unit testing, mocking, and integration testing with examples in C#](https://amzn.to/4ayjpiM)\n* [xUnit Test Patterns: Refactoring Test Code](https://amzn.to/4dHGDpm)\n* [Arrange, Act, Assert: What is AAA Testing?](https://blog.ncrunch.net/post/arrange-act-assert-aaa-testing.aspx)\n* [Bill Wake: 3A – Arrange, Act, Assert (NCrunch)](https://xp123.com/articles/3a-arrange-act-assert/)\n* [GivenWhenThen (Martin Fowler)](https://martinfowler.com/bliki/GivenWhenThen.html)\n"
  },
  {
    "path": "arrange-act-assert/etc/arrange-act-assert.urm.puml",
    "content": "@startuml\npackage com.iluwatar.arrangeactassert {\n  class Cash {\n    - amount : int\n    ~ Cash(amount : int)\n    ~ count() : int\n    ~ minus(subtrahend : int) : boolean\n    ~ plus(addend : int)\n  }\n}\n@enduml"
  },
  {
    "path": "arrange-act-assert/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>arrange-act-assert</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n</project>\n"
  },
  {
    "path": "arrange-act-assert/src/main/java/com/iluwatar/arrangeactassert/Cash.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.arrangeactassert;\n\nimport lombok.AllArgsConstructor;\n\n/**\n * Arrange/Act/Assert (AAA) is a unit test pattern. In this simple example, we have a ({@link Cash})\n * object for plus, minus and counting amount.\n */\n@AllArgsConstructor\npublic class Cash {\n\n  private int amount;\n\n  // plus\n  void plus(int addend) {\n    amount += addend;\n  }\n\n  // minus\n  boolean minus(int subtrahend) {\n    if (amount >= subtrahend) {\n      amount -= subtrahend;\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  // count\n  int count() {\n    return amount;\n  }\n}\n"
  },
  {
    "path": "arrange-act-assert/src/test/java/com/iluwatar/arrangeactassert/CashAAATest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.arrangeactassert;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/**\n * Arrange/Act/Assert (AAA) is a pattern for organizing unit tests. It is a way to structure your\n * tests, so they're easier to read, maintain and enhance.\n *\n * <p>It breaks tests down into three clear and distinct steps:\n *\n * <p>1. Arrange: Perform the setup and initialization required for the test.\n *\n * <p>2. Act: Take action(s) required for the test.\n *\n * <p>3. Assert: Verify the outcome(s) of the test.\n *\n * <p>This pattern has several significant benefits. It creates a clear separation between a test's\n * setup, operations, and results. This structure makes the code easier to read and understand. If\n * you place the steps in order and format your code to separate them, you can scan a test and\n * quickly comprehend what it does.\n *\n * <p>It also enforces a certain degree of discipline when you write your tests. You have to think\n * clearly about the three steps your test will perform. But it makes tests more natural to write at\n * the same time since you already have an outline.\n *\n * <p>In ({@link CashAAATest}) we have four test methods. Each of them has only one reason to change\n * and one reason to fail. In a large and complicated code base, tests that honor the single\n * responsibility principle are much easier to troubleshoot.\n */\nclass CashAAATest {\n\n  @Test\n  void testPlus() {\n    // Arrange\n    var cash = new Cash(3);\n    // Act\n    cash.plus(4);\n    // Assert\n    assertEquals(7, cash.count());\n  }\n\n  @Test\n  void testMinus() {\n    // Arrange\n    var cash = new Cash(8);\n    // Act\n    var result = cash.minus(5);\n    // Assert\n    assertTrue(result);\n    assertEquals(3, cash.count());\n  }\n\n  @Test\n  void testInsufficientMinus() {\n    // Arrange\n    var cash = new Cash(1);\n    // Act\n    var result = cash.minus(6);\n    // Assert\n    assertFalse(result);\n    assertEquals(1, cash.count());\n  }\n\n  @Test\n  void testUpdate() {\n    // Arrange\n    var cash = new Cash(5);\n    // Act\n    cash.plus(6);\n    var result = cash.minus(3);\n    // Assert\n    assertTrue(result);\n    assertEquals(8, cash.count());\n  }\n}\n"
  },
  {
    "path": "arrange-act-assert/src/test/java/com/iluwatar/arrangeactassert/CashAntiAAATest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.arrangeactassert;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/**\n * ({@link CashAAATest}) is an anti-example of AAA pattern. This test is functionally correct, but\n * with the addition of a new feature, it needs refactoring. There are an awful lot of steps in that\n * test method, but it verifies the class' important behavior in just eleven lines. It violates the\n * single responsibility principle. If this test method failed after a small code change, it might\n * take some digging to discover why.\n */\nclass CashAntiAAATest {\n\n  @Test\n  void testCash() {\n    // initialize\n    var cash = new Cash(3);\n    // test plus\n    cash.plus(4);\n    assertEquals(7, cash.count());\n    // test minus\n    cash = new Cash(8);\n    assertTrue(cash.minus(5));\n    assertEquals(3, cash.count());\n    assertFalse(cash.minus(6));\n    assertEquals(3, cash.count());\n    // test update\n    cash.plus(5);\n    assertTrue(cash.minus(5));\n    assertEquals(3, cash.count());\n  }\n}\n"
  },
  {
    "path": "async-method-invocation/README.md",
    "content": "---\ntitle: \"Async Method Invocation Pattern in Java: Elevate Performance with Asynchronous Programming\"\nshortTitle: Async Method Invocation\ndescription: \"Learn about the Async Method Invocation pattern in Java for asynchronous method calls, enhancing concurrency, scalability, and responsiveness in your applications. Explore real-world examples and code implementations.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Asynchronous\n  - Decoupling\n  - Reactive\n  - Scalability\n  - Thread management\n---\n\n## Also known as\n\n* Asynchronous Procedure Call\n\n## Intent of Async Method Invocation Design Pattern\n\nThe Async Method Invocation pattern is designed to enhance concurrency by allowing methods to be called asynchronously. This pattern helps in executing parallel tasks, reducing wait times, and improving system throughput.\n\n## Detailed Explanation of Async Method Invocation Pattern with Real-World Examples\n\nReal-world example\n\n> Asynchronous method invocation enables non-blocking operations, allowing multiple processes to run concurrently. This pattern is particularly useful in applications requiring high scalability and performance, such as web servers and microservices.\n> \n> In the context of space rockets, an analogous example of the Async Method Invocation pattern can be seen in the communication between the mission control center and the onboard systems of the rocket. When mission control sends a command to the rocket to adjust its trajectory or perform a system check, they do not wait idly for the rocket to complete the task and report back. Instead, mission control continues to monitor other aspects of the mission and manage different tasks. The rocket executes the command asynchronously and sends a status update or result back to mission control once the operation is complete. This allows mission control to efficiently manage multiple concurrent operations without being blocked by any single task, similar to how asynchronous method invocation works in software systems.\n\nIn plain words\n\n> Asynchronous method invocation starts task processing and returns immediately before the task is ready. The results of the task processing are returned to the caller later.\n\nWikipedia says\n\n> In multithreaded computer programming, asynchronous method invocation (AMI), also known as asynchronous method calls or the asynchronous pattern is a design pattern in which the call site is not blocked while waiting for the called code to finish. Instead, the calling thread is notified when the reply arrives. Polling for a reply is an undesired option.\n\nSequence diagram\n\n![Async Method Invocation sequence diagram](./etc/async-method-invocation-sequence-diagram.png \"Async Method Invocation sequence diagram\")\n\n## Programmatic Example of Async Method Invocation Pattern in Java\n\nConsider a scenario where multiple tasks need to be executed simultaneously. Using the Async Method Invocation pattern, you can initiate these tasks without waiting for each to complete, thus optimizing resource usage and reducing latency.\n\nIn this example, we are launching space rockets and deploying lunar rovers.\n\nThe application demonstrates the async method invocation pattern. The key parts of the pattern are`AsyncResult` which is an intermediate container for an asynchronously evaluated value, `AsyncCallback` which can be provided to be executed on task completion and `AsyncExecutor` that manages the execution of the async tasks.\n\n```java\npublic interface AsyncResult<T> {\n    boolean isCompleted();\n\n    T getValue() throws ExecutionException;\n\n    void await() throws InterruptedException;\n}\n```\n\n```java\npublic interface AsyncCallback<T> {\n    void onComplete(T value);\n\n    void onError(Exception ex);\n}\n```\n\n```java\npublic interface AsyncExecutor {\n    <T> AsyncResult<T> startProcess(Callable<T> task);\n\n    <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback);\n\n    <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException;\n}\n```\n\n`ThreadAsyncExecutor` is an implementation of `AsyncExecutor`. Some of its key parts are highlighted next.\n\n```java\npublic class ThreadAsyncExecutor implements AsyncExecutor {\n\n    @Override\n    public <T> AsyncResult<T> startProcess(Callable<T> task) {\n        return startProcess(task, null);\n    }\n\n    @Override\n    public <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback) {\n        var result = new CompletableResult<>(callback);\n        new Thread(\n                () -> {\n                    try {\n                        result.setValue(task.call());\n                    } catch (Exception ex) {\n                        result.setException(ex);\n                    }\n                },\n                \"executor-\" + idx.incrementAndGet())\n                .start();\n        return result;\n    }\n\n    @Override\n    public <T> T endProcess(AsyncResult<T> asyncResult)\n            throws ExecutionException, InterruptedException {\n        if (!asyncResult.isCompleted()) {\n            asyncResult.await();\n        }\n        return asyncResult.getValue();\n    }\n}\n```\n\nThen we are ready to launch some rockets to see how everything works together.\n\n```java\n  public static void main(String[] args) throws Exception {\n    // construct a new executor that will run async tasks\n    var executor = new ThreadAsyncExecutor();\n\n    // start few async tasks with varying processing times, two last with callback handlers\n    final var asyncResult1 = executor.startProcess(lazyval(10, 500));\n    final var asyncResult2 = executor.startProcess(lazyval(\"test\", 300));\n    final var asyncResult3 = executor.startProcess(lazyval(50L, 700));\n    final var asyncResult4 = executor.startProcess(lazyval(20, 400),\n            callback(\"Deploying lunar rover\"));\n    final var asyncResult5 =\n            executor.startProcess(lazyval(\"callback\", 600), callback(\"Deploying lunar rover\"));\n\n    // emulate processing in the current thread while async tasks are running in their own threads\n    Thread.sleep(350); // Oh boy, we are working hard here\n    log(\"Mission command is sipping coffee\");\n\n    // wait for completion of the tasks\n    final var result1 = executor.endProcess(asyncResult1);\n    final var result2 = executor.endProcess(asyncResult2);\n    final var result3 = executor.endProcess(asyncResult3);\n    asyncResult4.await();\n    asyncResult5.await();\n\n    // log the results of the tasks, callbacks log immediately when complete\n    log(String.format(ROCKET_LAUNCH_LOG_PATTERN, result1));\n    log(String.format(ROCKET_LAUNCH_LOG_PATTERN, result2));\n    log(String.format(ROCKET_LAUNCH_LOG_PATTERN, result3));\n}\n```\n\nHere's the program console output.\n\n```\n21:47:08.227[executor-2]INFO com.iluwatar.async.method.invocation.App-Space rocket<test> launched successfully\n21:47:08.269[main]INFO com.iluwatar.async.method.invocation.App-Mission command is sipping coffee\n21:47:08.318[executor-4]INFO com.iluwatar.async.method.invocation.App-Space rocket<20>launched successfully\n21:47:08.335[executor-4]INFO com.iluwatar.async.method.invocation.App-Deploying lunar rover<20>\n21:47:08.414[executor-1]INFO com.iluwatar.async.method.invocation.App-Space rocket<10>launched successfully\n21:47:08.519[executor-5]INFO com.iluwatar.async.method.invocation.App-Space rocket<callback> launched successfully\n21:47:08.519[executor-5]INFO com.iluwatar.async.method.invocation.App-Deploying lunar rover<callback>\n21:47:08.616[executor-3]INFO com.iluwatar.async.method.invocation.App-Space rocket<50>launched successfully\n21:47:08.617[main]INFO com.iluwatar.async.method.invocation.App-Space rocket<10>launch complete\n21:47:08.617[main]INFO com.iluwatar.async.method.invocation.App-Space rocket<test> launch complete\n21:47:08.618[main]INFO com.iluwatar.async.method.invocation.App-Space rocket<50>launch complete\n```\n\n## When to Use the Async Method Invocation Pattern in Java\n\nThis pattern is ideal for applications needing to manage multiple parallel tasks efficiently. It is commonly used in scenarios such as handling background processes, improving user interface responsiveness, and managing asynchronous data processing.\n\nUse the async method invocation pattern when\n\n* When operations do not need to complete before proceeding with the next steps in a program.\n* For tasks that are resource-intensive or time-consuming, such as IO operations, network requests, or complex computations, where making the operation synchronous would significantly impact performance or user experience.\n* In GUI applications to prevent freezing or unresponsiveness during long-running tasks.\n* In web applications for non-blocking IO operations.\n\n## Real-World Applications of Async Method Invocation Pattern in Java\n\nMany modern applications leverage the Async Method Invocation pattern, including web servers handling concurrent requests, microservices architectures, and systems requiring intensive background processing.\n\n* Web servers handling HTTP requests asynchronously to improve throughput and reduce latency.\n* Desktop and mobile applications using background threads to perform time-consuming operations without blocking the user interface.\n* Microservices architectures where services perform asynchronous communications via messaging queues or event streams.\n* [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html)\n* [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)\n* [ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html)\n* [Task-based Asynchronous Pattern](https://msdn.microsoft.com/en-us/library/hh873175.aspx)\n\n## Benefits and Trade-offs of Async Method Invocation Pattern\n\nWhile this pattern offers significant performance benefits, it also introduces complexity in error handling and resource management. Proper implementation is essential to avoid potential pitfalls such as race conditions and deadlocks.\n\nBenefits:\n\n* Improved Responsiveness: The main thread or application flow remains unblocked, improving the user experience in GUI applications and overall responsiveness.\n* Better Resource Utilization: By enabling parallel execution, system resources (like CPU and IO) are utilized more efficiently, potentially improving the application's throughput.\n* Scalability: Easier to scale applications, as tasks can be distributed across available resources more effectively.\n\nTrade-offs:\n\n* Complexity: Introducing asynchronous operations can complicate the codebase, making it more challenging to understand, debug, and maintain.\n* Resource Management: Requires careful management of threads or execution contexts, which can introduce overhead and potential resource exhaustion issues.\n* Error Handling: Asynchronous operations can make error handling more complex, as exceptions may occur in different threads or at different times.\n\n## Related Java Design Patterns\n\nThe Async Method Invocation pattern often works well with other design patterns like the Command Pattern for encapsulating requests, the Observer Pattern for event handling, and the Promise Pattern for managing asynchronous results.\n\n* [Command](https://java-design-patterns.com/patterns/command/): Asynchronous method invocation can be used to implement the Command pattern, where commands are executed asynchronously.\n* [Observer](https://java-design-patterns.com/patterns/observer/): Asynchronous method invocation can be used to notify observers asynchronously when a subject's state changes.\n* [Promise](https://java-design-patterns.com/patterns/promise/): The AsyncResult interface can be considered a form of Promise, representing a value that may not be available yet.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3Ti1N4f)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Java Concurrency in Practice](https://amzn.to/4ab97VU)\n"
  },
  {
    "path": "async-method-invocation/etc/async-method-invocation.urm.puml",
    "content": "@startuml\npackage com.iluwatar.async.method.invocation {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    - callback(name : String) : AsyncCallback<T> {static}\n    - lazyval(value : T, delayMillis : long) : Callable<T> {static}\n    - log(msg : String) {static}\n    + main(args : String[]) {static}\n  }\n  interface AsyncCallback<T> {\n    + onComplete(T) {abstract}\n    + onError(Exception) {abstract}\n  }\n  interface AsyncExecutor {\n    + endProcess(AsyncResult<T>) : T {abstract}\n    + startProcess(Callable<T>) : AsyncResult<T> {abstract}\n    + startProcess(Callable<T>, AsyncCallback<T>) : AsyncResult<T> {abstract}\n  }\n  interface AsyncResult<T> {\n    + await() {abstract}\n    + getValue() : T {abstract}\n    + isCompleted() : boolean {abstract}\n  }\n  class ThreadAsyncExecutor {\n    - idx : AtomicInteger\n    + ThreadAsyncExecutor()\n    + endProcess(asyncResult : AsyncResult<T>) : T\n    + startProcess(task : Callable<T>) : AsyncResult<T>\n    + startProcess(task : Callable<T>, callback : AsyncCallback<T>) : AsyncResult<T>\n  }\n  -class CompletableResult<T> {\n    ~ COMPLETED : int {static}\n    ~ FAILED : int {static}\n    ~ RUNNING : int {static}\n    ~ callback : AsyncCallback<T>\n    ~ exception : Exception\n    ~ lock : Object\n    ~ state : int\n    ~ value : T\n    ~ CompletableResult<T>(callback : AsyncCallback<T>)\n    + await()\n    + getValue() : T\n    ~ hasCallback() : boolean\n    + isCompleted() : boolean\n    ~ setException(exception : Exception)\n    ~ setValue(value : T)\n  }\n}\nThreadAsyncExecutor ..|> AsyncCallback\nThreadAsyncExecutor ..|> AsyncResult\nThreadAsyncExecutor ..|> AsyncExecutor\nCompletableResult ..+ ThreadAsyncExecutor\nCompletableResult ..|> AsyncResult\n@enduml\n"
  },
  {
    "path": "async-method-invocation/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>async-method-invocation</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.async.method.invocation.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.async.method.invocation;\n\nimport java.util.concurrent.Callable;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * In this example, we are launching space rockets and deploying lunar rovers.\n *\n * <p>The application demonstrates the async method invocation pattern. The key parts of the pattern\n * are <code>AsyncResult</code> which is an intermediate container for an asynchronously evaluated\n * value, <code>AsyncCallback</code> which can be provided to be executed on task completion and\n * <code>AsyncExecutor</code> that manages the execution of the async tasks.\n *\n * <p>The main method shows example flow of async invocations. The main thread starts multiple tasks\n * with variable durations and then continues its own work. When the main thread has done it's job\n * it collects the results of the async tasks. Two of the tasks are handled with callbacks, meaning\n * the callbacks are executed immediately when the tasks complete.\n *\n * <p>Noteworthy difference of thread usage between the async results and callbacks is that the\n * async results are collected in the main thread but the callbacks are executed within the worker\n * threads. This should be noted when working with thread pools.\n *\n * <p>Java provides its own implementations of async method invocation pattern. FutureTask,\n * CompletableFuture and ExecutorService are the real world implementations of this pattern. But due\n * to the nature of parallel programming, the implementations are not trivial. This example does not\n * take all possible scenarios into account but rather provides a simple version that helps to\n * understand the pattern.\n *\n * @see AsyncResult\n * @see AsyncCallback\n * @see AsyncExecutor\n * @see java.util.concurrent.FutureTask\n * @see java.util.concurrent.CompletableFuture\n * @see java.util.concurrent.ExecutorService\n */\n@Slf4j\npublic class App {\n\n  private static final String ROCKET_LAUNCH_LOG_PATTERN = \"Space rocket <%s> launched successfully\";\n\n  /** Program entry point. */\n  public static void main(String[] args) throws Exception {\n    // construct a new executor that will run async tasks\n    var executor = new ThreadAsyncExecutor();\n\n    // start few async tasks with varying processing times, two last with callback handlers\n    final var asyncResult1 = executor.startProcess(lazyval(10, 500));\n    final var asyncResult2 = executor.startProcess(lazyval(\"test\", 300));\n    final var asyncResult3 = executor.startProcess(lazyval(50L, 700));\n    final var asyncResult4 =\n        executor.startProcess(lazyval(20, 400), callback(\"Deploying lunar rover\"));\n    final var asyncResult5 =\n        executor.startProcess(lazyval(\"callback\", 600), callback(\"Deploying lunar rover\"));\n\n    // emulate processing in the current thread while async tasks are running in their own threads\n    Thread.sleep(350); // Oh boy, we are working hard here\n    log(\"Mission command is sipping coffee\");\n\n    // wait for completion of the tasks\n    final var result1 = executor.endProcess(asyncResult1);\n    final var result2 = executor.endProcess(asyncResult2);\n    final var result3 = executor.endProcess(asyncResult3);\n    asyncResult4.await();\n    asyncResult5.await();\n\n    // log the results of the tasks, callbacks log immediately when complete\n    log(String.format(ROCKET_LAUNCH_LOG_PATTERN, result1));\n    log(String.format(ROCKET_LAUNCH_LOG_PATTERN, result2));\n    log(String.format(ROCKET_LAUNCH_LOG_PATTERN, result3));\n  }\n\n  /**\n   * Creates a callable that lazily evaluates to given value with artificial delay.\n   *\n   * @param value value to evaluate\n   * @param delayMillis artificial delay in milliseconds\n   * @return new callable for lazy evaluation\n   */\n  private static <T> Callable<T> lazyval(T value, long delayMillis) {\n    return () -> {\n      Thread.sleep(delayMillis);\n      log(String.format(ROCKET_LAUNCH_LOG_PATTERN, value));\n      return value;\n    };\n  }\n\n  /**\n   * Creates a simple callback that logs the complete status of the async result.\n   *\n   * @param name callback name\n   * @return new async callback\n   */\n  private static <T> AsyncCallback<T> callback(String name) {\n    return new AsyncCallback<>() {\n      @Override\n      public void onComplete(T value) {\n        log(name + \" <\" + value + \">\");\n      }\n\n      @Override\n      public void onError(Exception ex) {\n        log(name + \" failed: \" + ex.getMessage());\n      }\n    };\n  }\n\n  private static void log(String msg) {\n    LOGGER.info(msg);\n  }\n}\n"
  },
  {
    "path": "async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncCallback.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.async.method.invocation;\n\n/**\n * AsyncCallback interface.\n *\n * @param <T> Type of Result\n */\npublic interface AsyncCallback<T> {\n\n  /**\n   * Complete handler which is executed when async task is completed.\n   *\n   * @param value the evaluated value from async task\n   */\n  void onComplete(T value);\n\n  /**\n   * Error handler which is executed when async task fails execution.\n   *\n   * @param ex exception which was thrown during async task execution(non-null)\n   */\n  void onError(Exception ex);\n}\n"
  },
  {
    "path": "async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncExecutor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.async.method.invocation;\n\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutionException;\n\n/** AsyncExecutor interface. */\npublic interface AsyncExecutor {\n\n  /**\n   * Starts processing of an async task. Returns immediately with async result.\n   *\n   * @param task task to be executed asynchronously\n   * @return async result for the task\n   */\n  <T> AsyncResult<T> startProcess(Callable<T> task);\n\n  /**\n   * Starts processing of an async task. Returns immediately with async result. Executes callback\n   * when the task is completed.\n   *\n   * @param task task to be executed asynchronously\n   * @param callback callback to be executed on task completion\n   * @return async result for the task\n   */\n  <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback);\n\n  /**\n   * Ends processing of an async task. Blocks the current thread if necessary and returns the\n   * evaluated value of the completed task.\n   *\n   * @param asyncResult async result of a task\n   * @return evaluated value of the completed task\n   * @throws ExecutionException if execution has failed, containing the root cause\n   * @throws InterruptedException if the execution is interrupted\n   */\n  <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException;\n}\n"
  },
  {
    "path": "async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/AsyncResult.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.async.method.invocation;\n\nimport java.util.concurrent.ExecutionException;\n\n/**\n * AsyncResult interface.\n *\n * @param <T> parameter returned when getValue is invoked\n */\npublic interface AsyncResult<T> {\n\n  /**\n   * Status of the async task execution.\n   *\n   * @return <code>true</code> if execution is completed or failed\n   */\n  boolean isCompleted();\n\n  /**\n   * Gets the value of completed async task.\n   *\n   * @return evaluated value or throws ExecutionException if execution has failed\n   * @throws ExecutionException if execution has failed, containing the root cause\n   * @throws IllegalStateException if execution is not completed\n   */\n  T getValue() throws ExecutionException;\n\n  /**\n   * Blocks the current thread until the async task is completed.\n   *\n   * @throws InterruptedException if the execution is interrupted\n   */\n  void await() throws InterruptedException;\n}\n"
  },
  {
    "path": "async-method-invocation/src/main/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.async.method.invocation;\n\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/** Implementation of async executor that creates a new thread for every task. */\npublic class ThreadAsyncExecutor implements AsyncExecutor {\n\n  /** Index for thread naming. */\n  private final AtomicInteger idx = new AtomicInteger(0);\n\n  @Override\n  public <T> AsyncResult<T> startProcess(Callable<T> task) {\n    return startProcess(task, null);\n  }\n\n  @Override\n  public <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback) {\n    var result = new CompletableResult<>(callback);\n    new Thread(\n            () -> {\n              try {\n                result.setValue(task.call());\n              } catch (Exception ex) {\n                result.setException(ex);\n              }\n            },\n            \"executor-\" + idx.incrementAndGet())\n        .start();\n    return result;\n  }\n\n  @Override\n  public <T> T endProcess(AsyncResult<T> asyncResult)\n      throws ExecutionException, InterruptedException {\n    if (!asyncResult.isCompleted()) {\n      asyncResult.await();\n    }\n    return asyncResult.getValue();\n  }\n\n  /**\n   * Simple implementation of async result that allows completing it successfully with a value or\n   * exceptionally with an exception. A really simplified version from its real life cousins\n   * FutureTask and CompletableFuture.\n   *\n   * @see java.util.concurrent.FutureTask\n   * @see java.util.concurrent.CompletableFuture\n   */\n  private static class CompletableResult<T> implements AsyncResult<T> {\n\n    static final int RUNNING = 1;\n    static final int FAILED = 2;\n    static final int COMPLETED = 3;\n\n    final Object lock;\n    final AsyncCallback<T> callback;\n\n    volatile int state = RUNNING;\n    T value;\n    Exception exception;\n\n    CompletableResult(AsyncCallback<T> callback) {\n      this.lock = new Object();\n      this.callback = callback;\n    }\n\n    boolean hasCallback() {\n      return callback != null;\n    }\n\n    /**\n     * Sets the value from successful execution and executes callback if available. Notifies any\n     * thread waiting for completion.\n     *\n     * @param value value of the evaluated task\n     */\n    void setValue(T value) {\n      this.value = value;\n      this.state = COMPLETED;\n      if (hasCallback()) {\n        callback.onComplete(value);\n      }\n      synchronized (lock) {\n        lock.notifyAll();\n      }\n    }\n\n    /**\n     * Sets the exception from failed execution and executes callback if available. Notifies any\n     * thread waiting for completion.\n     *\n     * @param exception exception of the failed task\n     */\n    void setException(Exception exception) {\n      this.exception = exception;\n      this.state = FAILED;\n      if (hasCallback()) {\n        callback.onError(exception);\n      }\n      synchronized (lock) {\n        lock.notifyAll();\n      }\n    }\n\n    @Override\n    public boolean isCompleted() {\n      return state > RUNNING;\n    }\n\n    @Override\n    public T getValue() throws ExecutionException {\n      if (state == COMPLETED) {\n        return value;\n      } else if (state == FAILED) {\n        throw new ExecutionException(exception);\n      } else {\n        throw new IllegalStateException(\"Execution not completed yet\");\n      }\n    }\n\n    @Override\n    public void await() throws InterruptedException {\n      synchronized (lock) {\n        while (!isCompleted()) {\n          lock.wait();\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.async.method.invocation;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.async.method.invocation;\n\nimport static java.time.Duration.ofMillis;\nimport static org.junit.jupiter.api.Assertions.*;\nimport static org.mockito.ArgumentMatchers.*;\nimport static org.mockito.Mockito.timeout;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.internal.verification.VerificationModeFactory.times;\n\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutionException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Captor;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\n\n/** ThreadAsyncExecutorTest */\nclass ThreadAsyncExecutorTest {\n\n  @Captor private ArgumentCaptor<Exception> exceptionCaptor;\n\n  @Mock private Callable<Object> task;\n\n  @Mock private AsyncCallback<Object> callback;\n\n  @BeforeEach\n  void setUp() {\n    MockitoAnnotations.openMocks(this);\n  }\n\n  /** Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} */\n  @Test\n  void testSuccessfulTaskWithoutCallback() {\n    assertTimeout(\n        ofMillis(3000),\n        () -> {\n          // Instantiate a new executor and start a new 'null' task ...\n          final var executor = new ThreadAsyncExecutor();\n\n          final var result = new Object();\n          when(task.call()).thenReturn(result);\n\n          final var asyncResult = executor.startProcess(task);\n          assertNotNull(asyncResult);\n          asyncResult.await(); // Prevent timing issues, and wait until the result is available\n          assertTrue(asyncResult.isCompleted());\n\n          // Our task should only execute once ...\n          verify(task, times(1)).call();\n\n          // ... and the result should be exactly the same object\n          assertSame(result, asyncResult.getValue());\n        });\n  }\n\n  /**\n   * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable,\n   * AsyncCallback)}\n   */\n  @Test\n  void testSuccessfulTaskWithCallback() {\n    assertTimeout(\n        ofMillis(3000),\n        () -> {\n          // Instantiate a new executor and start a new 'null' task ...\n          final var executor = new ThreadAsyncExecutor();\n\n          final var result = new Object();\n          when(task.call()).thenReturn(result);\n\n          final var asyncResult = executor.startProcess(task, callback);\n          assertNotNull(asyncResult);\n          asyncResult.await(); // Prevent timing issues, and wait until the result is available\n          assertTrue(asyncResult.isCompleted());\n\n          // Our task should only execute once ...\n          verify(task, times(1)).call();\n\n          // ... same for the callback, we expect our object\n          verify(callback, times(1)).onComplete(eq(result));\n          verify(callback, times(0)).onError(exceptionCaptor.capture());\n\n          // ... and the result should be exactly the same object\n          assertSame(result, asyncResult.getValue());\n        });\n  }\n\n  /**\n   * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a\n   * task takes a while to execute\n   */\n  @Test\n  void testLongRunningTaskWithoutCallback() {\n    assertTimeout(\n        ofMillis(5000),\n        () -> {\n          // Instantiate a new executor and start a new 'null' task ...\n          final var executor = new ThreadAsyncExecutor();\n\n          final var result = new Object();\n          when(task.call())\n              .thenAnswer(\n                  i -> {\n                    Thread.sleep(1500);\n                    return result;\n                  });\n\n          final var asyncResult = executor.startProcess(task);\n          assertNotNull(asyncResult);\n          assertFalse(asyncResult.isCompleted());\n\n          try {\n            asyncResult.getValue();\n            fail(\n                \"Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task\");\n          } catch (IllegalStateException e) {\n            assertNotNull(e.getMessage());\n          }\n\n          // Our task should only execute once, but it can take a while ...\n          verify(task, timeout(3000).times(1)).call();\n\n          // Prevent timing issues, and wait until the result is available\n          asyncResult.await();\n          assertTrue(asyncResult.isCompleted());\n          verifyNoMoreInteractions(task);\n\n          // ... and the result should be exactly the same object\n          assertSame(result, asyncResult.getValue());\n        });\n  }\n\n  /**\n   * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable,\n   * AsyncCallback)} when a task takes a while to execute\n   */\n  @Test\n  void testLongRunningTaskWithCallback() {\n    assertTimeout(\n        ofMillis(5000),\n        () -> {\n          // Instantiate a new executor and start a new 'null' task ...\n          final var executor = new ThreadAsyncExecutor();\n\n          final var result = new Object();\n          when(task.call())\n              .thenAnswer(\n                  i -> {\n                    Thread.sleep(1500);\n                    return result;\n                  });\n\n          final var asyncResult = executor.startProcess(task, callback);\n          assertNotNull(asyncResult);\n          assertFalse(asyncResult.isCompleted());\n\n          verifyNoMoreInteractions(callback);\n\n          try {\n            asyncResult.getValue();\n            fail(\n                \"Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task\");\n          } catch (IllegalStateException e) {\n            assertNotNull(e.getMessage());\n          }\n\n          // Our task should only execute once, but it can take a while ...\n          verify(task, timeout(3000).times(1)).call();\n          verify(callback, timeout(3000).times(1)).onComplete(eq(result));\n          verify(callback, times(0)).onError(isA(Exception.class));\n\n          // Prevent timing issues, and wait until the result is available\n          asyncResult.await();\n          assertTrue(asyncResult.isCompleted());\n          verifyNoMoreInteractions(task, callback);\n\n          // ... and the result should be exactly the same object\n          assertSame(result, asyncResult.getValue());\n        });\n  }\n\n  /**\n   * Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)} when a\n   * task takes a while to execute, while waiting on the result using {@link\n   * ThreadAsyncExecutor#endProcess(AsyncResult)}\n   */\n  @Test\n  void testEndProcess() {\n    assertTimeout(\n        ofMillis(5000),\n        () -> {\n          // Instantiate a new executor and start a new 'null' task ...\n          final var executor = new ThreadAsyncExecutor();\n\n          final var result = new Object();\n          when(task.call())\n              .thenAnswer(\n                  i -> {\n                    Thread.sleep(1500);\n                    return result;\n                  });\n\n          final var asyncResult = executor.startProcess(task);\n          assertNotNull(asyncResult);\n          assertFalse(asyncResult.isCompleted());\n\n          try {\n            asyncResult.getValue();\n            fail(\n                \"Expected IllegalStateException when calling AsyncResult#getValue on a non-completed task\");\n          } catch (IllegalStateException e) {\n            assertNotNull(e.getMessage());\n          }\n\n          assertSame(result, executor.endProcess(asyncResult));\n          verify(task, times(1)).call();\n          assertTrue(asyncResult.isCompleted());\n\n          // Calling end process a second time while already finished should give the same result\n          assertSame(result, executor.endProcess(asyncResult));\n          verifyNoMoreInteractions(task);\n        });\n  }\n\n  /**\n   * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable)} when\n   * the callable is 'null'\n   */\n  @Test\n  void testNullTask() {\n    assertTimeout(\n        ofMillis(3000),\n        () -> {\n          // Instantiate a new executor and start a new 'null' task ...\n          final var executor = new ThreadAsyncExecutor();\n          final var asyncResult = executor.startProcess(null);\n\n          assertNotNull(\n              asyncResult,\n              \"The AsyncResult should not be 'null', even though the task was 'null'.\");\n          asyncResult.await(); // Prevent timing issues, and wait until the result is available\n          assertTrue(asyncResult.isCompleted());\n\n          try {\n            asyncResult.getValue();\n            fail(\"Expected ExecutionException with NPE as cause\");\n          } catch (final ExecutionException e) {\n            assertNotNull(e.getMessage());\n            assertNotNull(e.getCause());\n            assertEquals(NullPointerException.class, e.getCause().getClass());\n          }\n        });\n  }\n\n  /**\n   * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable,\n   * AsyncCallback)} when the callable is 'null', but the asynchronous callback is provided\n   */\n  @Test\n  void testNullTaskWithCallback() {\n    assertTimeout(\n        ofMillis(3000),\n        () -> {\n          // Instantiate a new executor and start a new 'null' task ...\n          final var executor = new ThreadAsyncExecutor();\n          final var asyncResult = executor.startProcess(null, callback);\n\n          assertNotNull(\n              asyncResult,\n              \"The AsyncResult should not be 'null', even though the task was 'null'.\");\n          asyncResult.await(); // Prevent timing issues, and wait until the result is available\n          assertTrue(asyncResult.isCompleted());\n          verify(callback, times(0)).onComplete(any());\n          verify(callback, times(1)).onError(exceptionCaptor.capture());\n\n          final var exception = exceptionCaptor.getValue();\n          assertNotNull(exception);\n\n          assertEquals(NullPointerException.class, exception.getClass());\n\n          try {\n            asyncResult.getValue();\n            fail(\"Expected ExecutionException with NPE as cause\");\n          } catch (final ExecutionException e) {\n            assertNotNull(e.getMessage());\n            assertNotNull(e.getCause());\n            assertEquals(NullPointerException.class, e.getCause().getClass());\n          }\n        });\n  }\n\n  /**\n   * Test used to verify the behaviour of {@link ThreadAsyncExecutor#startProcess(Callable,\n   * AsyncCallback)} when both the callable and the asynchronous callback are 'null'\n   */\n  @Test\n  void testNullTaskWithNullCallback() {\n    assertTimeout(\n        ofMillis(3000),\n        () -> {\n          // Instantiate a new executor and start a new 'null' task ...\n          final var executor = new ThreadAsyncExecutor();\n          final var asyncResult = executor.startProcess(null, null);\n\n          assertNotNull(\n              asyncResult,\n              \"The AsyncResult should not be 'null', even though the task and callback were 'null'.\");\n          asyncResult.await(); // Prevent timing issues, and wait until the result is available\n          assertTrue(asyncResult.isCompleted());\n\n          try {\n            asyncResult.getValue();\n            fail(\"Expected ExecutionException with NPE as cause\");\n          } catch (final ExecutionException e) {\n            assertNotNull(e.getMessage());\n            assertNotNull(e.getCause());\n            assertEquals(NullPointerException.class, e.getCause().getClass());\n          }\n        });\n  }\n}\n"
  },
  {
    "path": "backpressure/README.md",
    "content": "---\ntitle: \"Backpressure Pattern in Java: Gracefully regulate producer-to-consumer data flow to prevent overload.\"\nshortTitle: Backpressure\ndescription: \"Dive into the Backpressure design pattern in Java through practical examples, discovering how it prevents overload while ensuring stability and peak performance by aligning data flow with consumer capacity.\"\ncategory: Concurrency\nlanguage: en\ntag:\n    - Asynchronous\n    - Event-driven\n    - Reactive\n    - Resilience\n---\n\n## Also known as\n\n* Flow Control\n* Rate Limiting Mechanism\n\n## Intent of the Backpressure Design Pattern\n\nControl the rate of data production so downstream consumers are not overwhelmed by excessive load.\n\n## Detailed Explanation of Backpressure Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a busy coffee shop where multiple baristas brew drinks (producers), and a single barista is responsible for carefully crafting latte art (consumer). If drinks are brewed faster than the latte-art barista can decorate them, they pile up, risking quality issues or discarded drinks. By introducing a pacing system—only sending new cups once the latte-art barista is ready—everyone stays synchronized, ensuring minimal waste and a consistently enjoyable customer experience.\n\nIn plain words\n\n> The Backpressure design pattern is a flow control mechanism that prevents overwhelming a system by regulating data production based on the consumer’s processing capacity.\n\nWikipedia says\n\n> Back pressure (or backpressure) is the term for a resistance to the desired flow of fluid through pipes. Obstructions or tight bends create backpressure via friction loss and pressure drop. In distributed systems in particular event-driven architecture, back pressure is a technique to regulate flow of data, ensuring that components do not become overwhelmed.\n\nSequence diagram\n\n![Backpressure sequence diagram](./etc/backpressure-sequence-diagram.png)\n\n## Programmatic Example of Backpressure Pattern in Java\n\nThis example demonstrates how backpressure can be implemented using Project Reactor. We begin by creating a simple publisher that emits a stream of integers, introducing a small delay to mimic a slower production rate:\n\n```java\npublic class Publisher {\n    public static Flux<Integer> publish(int start, int count, int delay) {\n        return Flux.range(start, count).delayElements(Duration.ofMillis(delay)).log();\n    }\n}\n```\n\nNext, we define a custom subscriber by extending Reactor’s BaseSubscriber. It simulates slow processing by sleeping for 500ms per item. Initially, the subscriber requests ten items; for every five items processed, it requests five more:\n\n```java\npublic class Subscriber extends BaseSubscriber<Integer> {\n\n    private static final Logger logger = LoggerFactory.getLogger(Subscriber.class);\n\n    @Override\n    protected void hookOnSubscribe(@NonNull Subscription subscription) {\n        logger.info(\"subscribe()\");\n        request(10); //request 10 items initially\n    }\n\n    @Override\n    protected void hookOnNext(@NonNull Integer value) {\n        processItem();\n        logger.info(\"process({})\", value);\n        if (value % 5 == 0) {\n            // request for the next 5 items after processing first 5\n            request(5);\n        }\n    }\n\n    @Override\n    protected void hookOnComplete() {\n        //completed processing.\n    }\n\n    private void processItem() {\n        try {\n            Thread.sleep(500); // simulate slow processing\n        } catch (InterruptedException e) {\n            logger.error(e.getMessage(), e);\n        }\n    }\n}\n```\n\nFinally, in the `main` method, we publish a range of integers and subscribe using the custom subscriber. A short sleep in the main thread allows the emission, backpressure requests, and processing to be fully observed:\n\n```java\npublic static void main(String[] args) throws InterruptedException {\n    Subscriber sub = new Subscriber();\n    Publisher.publish(1, 8, 200).subscribe(sub);\n    Thread.sleep(5000); //wait for execution\n    \n}\n```\n\nBelow is an example of the program’s output. It shows the subscriber’s log entries, including when it requests more data and when each integer is processed:\n\n```\n23:09:55.746 [main] DEBUG reactor.util.Loggers -- Using Slf4j logging framework\n23:09:55.762 [main] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- onSubscribe(FluxConcatMapNoPrefetch.FluxConcatMapNoPrefetchSubscriber)\n23:09:55.762 [main] INFO com.iluwatar.backpressure.Subscriber -- subscribe()\n23:09:55.763 [main] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- request(10)\n23:09:55.969 [parallel-1] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- onNext(1)\n23:09:56.475 [parallel-1] INFO com.iluwatar.backpressure.Subscriber -- process(1)\n23:09:56.680 [parallel-2] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- onNext(2)\n23:09:57.185 [parallel-2] INFO com.iluwatar.backpressure.Subscriber -- process(2)\n23:09:57.389 [parallel-3] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- onNext(3)\n23:09:57.894 [parallel-3] INFO com.iluwatar.backpressure.Subscriber -- process(3)\n23:09:58.099 [parallel-4] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- onNext(4)\n23:09:58.599 [parallel-4] INFO com.iluwatar.backpressure.Subscriber -- process(4)\n23:09:58.805 [parallel-5] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- onNext(5)\n23:09:59.311 [parallel-5] INFO com.iluwatar.backpressure.Subscriber -- process(5)\n23:09:59.311 [parallel-5] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- request(5)\n23:09:59.516 [parallel-6] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- onNext(6)\n23:10:00.018 [parallel-6] INFO com.iluwatar.backpressure.Subscriber -- process(6)\n23:10:00.223 [parallel-7] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- onNext(7)\n23:10:00.729 [parallel-7] INFO com.iluwatar.backpressure.Subscriber -- process(7)\n23:10:00.930 [parallel-8] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- onNext(8)\n23:10:01.436 [parallel-8] INFO com.iluwatar.backpressure.Subscriber -- process(8)\n23:10:01.437 [parallel-8] INFO reactor.Flux.ConcatMapNoPrefetch.1 -- onComplete()\n```\n\n## When to Use the Backpressure Pattern In Java\n\n* Use in Java systems where data is produced at high velocity and consumers risk overload.\n* Applicable in reactive or event-driven architectures to maintain stability under varying load conditions.\n\n## Benefits and Trade-offs of Backpressure Pattern\n\nBenefits:\n\n* Protects consumers from saturation and resource exhaustion.\n\nTrade-offs:\n\n* Introduces possible delays if production must slow down to match consumer capacity.\n* Requires careful orchestration in complex systems with multiple concurrent data sources.\n\n## Related Java Design Patterns\n\n* [Observer Pattern](https://java-design-patterns.com/patterns/observer/): Both patterns involve a producer notifying consumers. Observer is synchronous and tightly coupled (observers know the subject).\n* [Publish-Subscribe Pattern](https://java-design-patterns.com/patterns/publish-subscribe/): Both patterns deal with asynchronous data flow and can work together to manage message distribution and consumption effectively.\n\n## References and Credits\n\n* [Backpressure Explained (RedHat Developers Blog)](https://developers.redhat.com/articles/backpressure-explained)\n* [Hands-On Reactive Programming in Spring 5](https://amzn.to/3YuYfyO)\n* [Reactive Programming with RxJava: Creating Asynchronous, Event-Based Applications](https://amzn.to/42negbf)\n* [Reactive Streams in Java](https://amzn.to/3RJjUzA)\n* [Reactive Streams Specification](https://www.reactive-streams.org/)\n"
  },
  {
    "path": "backpressure/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>backpressure</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>io.projectreactor</groupId>\n            <artifactId>reactor-core</artifactId>\n            <version>3.8.0-M1</version>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>io.projectreactor</groupId>\n            <artifactId>reactor-test</artifactId>\n            <version>3.8.0-RC1</version>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.backpressure.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>"
  },
  {
    "path": "backpressure/src/main/java/com/iluwatar/backpressure/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.backpressure;\n\nimport java.util.concurrent.CountDownLatch;\n\n/**\n * The Backpressure pattern is a flow control mechanism. It allows a consumer to signal to a\n * producer to slow down or stop sending data when it's overwhelmed.\n * <li>Prevents memory overflow, CPU thrashing, and resource exhaustion.\n * <li>Ensures fair usage of resources in distributed systems.\n * <li>Avoids buffer bloat and latency spikes. Key concepts of this design paradigm involves\n * <li>Publisher/Producer: Generates data.\n * <li>Subscriber/Consumer: Receives and processes data.\n *\n *     <p>In this example we will create a {@link Publisher} and a {@link Subscriber}. Publisher\n *     will emit a stream of integer values with a predefined delay. Subscriber takes 500 ms to\n *     process one integer. Since the subscriber can't process the items fast enough we apply\n *     backpressure to the publisher so that it will request 10 items first, process 5 items and\n *     request for the next 5 again. After processing 5 items subscriber will keep requesting for\n *     another 5 until the stream ends.\n */\npublic class App {\n\n  protected static CountDownLatch latch;\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) throws InterruptedException {\n\n    /*\n     * This custom subscriber applies backpressure:\n     * - Has a processing delay of 0.5 milliseconds\n     * - Requests 10 items initially\n     * - Process 5 items and request for the next 5 items\n     */\n    Subscriber sub = new Subscriber();\n    // slow publisher emit 15 numbers with a delay of 200 milliseconds\n    Publisher.publish(1, 17, 200).subscribe(sub);\n\n    latch = new CountDownLatch(1);\n    latch.await();\n\n    sub = new Subscriber();\n    // fast publisher emit 15 numbers with a delay of 1 millisecond\n    Publisher.publish(1, 17, 1).subscribe(sub);\n\n    latch = new CountDownLatch(1);\n    latch.await();\n  }\n}\n"
  },
  {
    "path": "backpressure/src/main/java/com/iluwatar/backpressure/Publisher.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.backpressure;\n\nimport java.time.Duration;\nimport reactor.core.publisher.Flux;\n\n/** This class is the publisher that generates the data stream. */\npublic class Publisher {\n\n  private Publisher() {}\n\n  /**\n   * On message method will trigger when the subscribed event is published.\n   *\n   * @param start starting integer\n   * @param count how many integers to emit\n   * @param delay delay between each item in milliseconds\n   * @return a flux stream of integers\n   */\n  public static Flux<Integer> publish(int start, int count, int delay) {\n    return Flux.range(start, count).delayElements(Duration.ofMillis(delay)).log();\n  }\n}\n"
  },
  {
    "path": "backpressure/src/main/java/com/iluwatar/backpressure/Subscriber.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.backpressure;\n\nimport lombok.NonNull;\nimport lombok.extern.slf4j.Slf4j;\nimport org.reactivestreams.Subscription;\nimport reactor.core.publisher.BaseSubscriber;\n\n/** This class is the custom subscriber that subscribes to the data stream. */\n@Slf4j\npublic class Subscriber extends BaseSubscriber<Integer> {\n\n  @Override\n  protected void hookOnSubscribe(@NonNull Subscription subscription) {\n    request(10); // request 10 items initially\n  }\n\n  @Override\n  protected void hookOnNext(@NonNull Integer value) {\n    processItem();\n    LOGGER.info(\"process({})\", value);\n    if (value % 5 == 0) {\n      // request for the next 5 items after processing first 5\n      request(5);\n    }\n  }\n\n  @Override\n  protected void hookOnComplete() {\n    App.latch.countDown();\n  }\n\n  private void processItem() {\n    try {\n      Thread.sleep(500); // simulate slow processing\n    } catch (InterruptedException e) {\n      LOGGER.error(e.getMessage(), e);\n      Thread.currentThread().interrupt();\n    }\n  }\n}\n"
  },
  {
    "path": "backpressure/src/test/java/com/iluwatar/backpressure/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.backpressure;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\npublic class AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "backpressure/src/test/java/com/iluwatar/backpressure/LoggerExtension.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.backpressure;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.read.ListAppender;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport org.junit.jupiter.api.extension.AfterEachCallback;\nimport org.junit.jupiter.api.extension.BeforeEachCallback;\nimport org.junit.jupiter.api.extension.ExtensionContext;\nimport org.slf4j.LoggerFactory;\n\npublic class LoggerExtension implements BeforeEachCallback, AfterEachCallback {\n\n  private final ListAppender<ILoggingEvent> listAppender = new ListAppender<>();\n  private final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);\n\n  @Override\n  public void afterEach(ExtensionContext extensionContext) {\n    listAppender.stop();\n    listAppender.list.clear();\n    logger.detachAppender(listAppender);\n  }\n\n  @Override\n  public void beforeEach(ExtensionContext extensionContext) {\n    logger.addAppender(listAppender);\n    listAppender.start();\n  }\n\n  public List<String> getFormattedMessages() {\n    return listAppender.list.stream()\n        .map(ILoggingEvent::getFormattedMessage)\n        .collect(Collectors.toList());\n  }\n}\n"
  },
  {
    "path": "backpressure/src/test/java/com/iluwatar/backpressure/PublisherTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.backpressure;\n\nimport static com.iluwatar.backpressure.Publisher.publish;\n\nimport java.time.Duration;\nimport org.junit.jupiter.api.Test;\nimport reactor.core.publisher.Flux;\nimport reactor.test.StepVerifier;\n\npublic class PublisherTest {\n\n  @Test\n  public void testPublish() {\n\n    Flux<Integer> flux = publish(1, 3, 200);\n\n    StepVerifier.withVirtualTime(() -> flux)\n        .expectSubscription()\n        .expectNoEvent(Duration.ofMillis(200))\n        .expectNext(1)\n        .expectNoEvent(Duration.ofSeconds(200))\n        .expectNext(2)\n        .expectNoEvent(Duration.ofSeconds(200))\n        .expectNext(3)\n        .verifyComplete();\n  }\n}\n"
  },
  {
    "path": "backpressure/src/test/java/com/iluwatar/backpressure/SubscriberTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.backpressure;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.concurrent.CountDownLatch;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.RegisterExtension;\n\npublic class SubscriberTest {\n\n  @RegisterExtension public LoggerExtension loggerExtension = new LoggerExtension();\n\n  @Test\n  public void testSubscribe() throws InterruptedException {\n\n    Subscriber sub = new Subscriber();\n    Publisher.publish(1, 8, 100).subscribe(sub);\n\n    App.latch = new CountDownLatch(1);\n    App.latch.await();\n\n    String result = String.join(\",\", loggerExtension.getFormattedMessages());\n    assertTrue(\n        result.endsWith(\n            \"onSubscribe(FluxConcatMapNoPrefetch.\"\n                + \"FluxConcatMapNoPrefetchSubscriber),request(10),onNext(1),process(1),onNext(2),\"\n                + \"process(2),onNext(3),process(3),onNext(4),process(4),onNext(5),process(5),request(5),\"\n                + \"onNext(6),process(6),onNext(7),process(7),onNext(8),process(8),onComplete()\"));\n  }\n}\n"
  },
  {
    "path": "balking/README.md",
    "content": "---\ntitle: \"Balking Pattern in Java: Smart Control Over Java Execution\"\nshortTitle: Balking\ndescription: \"Learn the Balking design pattern in Java, a concurrency pattern that prevents code execution in inappropriate states. Discover examples, use cases, and benefits.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Concurrency\n  - Decoupling\n  - Fault tolerance\n  - Synchronization\n---\n\n## Intent of Balking Design Pattern\n\nThe Balking Pattern in Java is a concurrency design pattern that prevents an object from executing certain code if it is in an incomplete or inappropriate state. This pattern is crucial for managing state and concurrency in multithreaded Java applications.\n\n## Detailed Explanation of Balking Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy of the Balking design pattern can be seen in a laundry service. Imagine a washing machine at a laundromat that only starts washing clothes if the door is properly closed and locked. If a user tries to start the machine while the door is open, the machine balks and does nothing. This ensures that the washing process only begins when it is safe to do so, preventing water spillage and potential damage to the machine. Similarly, the Balking pattern in software design ensures that operations are only executed when the object is in an appropriate state, preventing erroneous actions and maintaining system stability.\n\nIn plain words\n\n> Using the balking pattern, a certain code executes only if the object is in particular state.\n\nWikipedia says\n\n> The balking pattern is a software design pattern that only executes an action on an object when the object is in a particular state. For example, if an object reads ZIP files and a calling method invokes a get method on the object when the ZIP file is not open, the object would \"balk\" at the request.\n\nFlowchart\n\n![Balking flowchart](./etc/balking-flowchart.png)\n\n## Programmatic Example of Balking Pattern in Java\n\nThis example demonstrates the Balking Pattern in a multithreaded Java application, highlighting state management and concurrency control. The Balking Pattern is exemplified by a washing machine's start button that initiates washing only if the machine is idle. This ensures state management and prevents concurrent issues.\n\nThere's a start-button in a washing machine to initiate the laundry washing. When the washing machine is inactive the button works as expected, but if it's already washing the button does nothing.\n\nIn this example implementation, `WashingMachine` is an object that has two states in which it can be: ENABLED and WASHING. If the machine is ENABLED, the state changes to WASHING using a thread-safe method. On the other hand, if it already has been washing and any other thread executes `wash`it won't do that and returns without doing anything.\n\nHere are the relevant parts of the `WashingMachine` class.\n\n```java\n\n@Slf4j\npublic class WashingMachine {\n\n    private final DelayProvider delayProvider;\n    private WashingMachineState washingMachineState;\n\n    public WashingMachine(DelayProvider delayProvider) {\n        this.delayProvider = delayProvider;\n        this.washingMachineState = WashingMachineState.ENABLED;\n    }\n\n    public WashingMachineState getWashingMachineState() {\n        return washingMachineState;\n    }\n\n    public void wash() {\n        synchronized (this) {\n            var machineState = getWashingMachineState();\n            LOGGER.info(\"{}: Actual machine state: {}\", Thread.currentThread().getName(), machineState);\n            if (this.washingMachineState == WashingMachineState.WASHING) {\n                LOGGER.error(\"Cannot wash if the machine has been already washing!\");\n                return;\n            }\n            this.washingMachineState = WashingMachineState.WASHING;\n        }\n        LOGGER.info(\"{}: Doing the washing\", Thread.currentThread().getName());\n        this.delayProvider.executeAfterDelay(50, TimeUnit.MILLISECONDS, this::endOfWashing);\n    }\n\n    public synchronized void endOfWashing() {\n        washingMachineState = WashingMachineState.ENABLED;\n        LOGGER.info(\"{}: Washing completed.\", Thread.currentThread().getId());\n    }\n}\n```\n\nHere's the simple `DelayProvider` interface used by the `WashingMachine`.\n\n```java\npublic interface DelayProvider {\n    void executeAfterDelay(long interval, TimeUnit timeUnit, Runnable task);\n}\n```\n\nNow, we introduce the application using the `WashingMachine`.\n\n```java\npublic static void main(String... args) {\n    final var washingMachine = new WashingMachine();\n    var executorService = Executors.newFixedThreadPool(3);\n    for (int i = 0; i < 3; i++) {\n        executorService.execute(washingMachine::wash);\n    }\n    executorService.shutdown();\n    try {\n        if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {\n            executorService.shutdownNow();\n        }\n    } catch (InterruptedException ie) {\n        LOGGER.error(\"ERROR: Waiting on executor service shutdown!\");\n        Thread.currentThread().interrupt();\n    }\n}\n```\n\nHere is the console output of the program.\n\n```\n14:02:52.268 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Actual machine state: ENABLED\n14:02:52.272 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Doing the washing\n14:02:52.272 [pool-1-thread-3] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-3: Actual machine state: WASHING\n14:02:52.273 [pool-1-thread-3] ERROR com.iluwatar.balking.WashingMachine - Cannot wash if the machine has been already washing!\n14:02:52.273 [pool-1-thread-1] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-1: Actual machine state: WASHING\n14:02:52.273 [pool-1-thread-1] ERROR com.iluwatar.balking.WashingMachine - Cannot wash if the machine has been already washing!\n14:02:52.324 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - 14: Washing completed.\n```\n\n## When to Use the Balking Pattern in Java\n\nUse the Balking pattern when\n\n* You want to invoke an action on an object only when it is in a particular state\n* Objects are generally only in a state that is prone to balking temporarily but for an unknown amount of time\n* In multithreaded applications where certain actions should only proceed when specific conditions are met, and those conditions are expected to change over time due to external factors or concurrent operations.\n\n## Real-World Applications of Balking Pattern in Java\n\n* Resource pooling, where resources are only allocated if they are in a valid state for allocation.\n* Thread management, where threads only proceed with tasks if certain conditions (like task availability or resource locks) are met.\n\n## Benefits and Trade-offs of Balking Pattern\n\nBenefits:\n\n* Reduces unnecessary lock acquisitions in situations where actions cannot proceed, enhancing performance in concurrent applications.\n* Encourages clear separation of state management and behavior, leading to cleaner code.\n* Simplifies the handling of operations that should only be performed under certain conditions without cluttering the caller code with state checks.\n\nTrade-offs:\n\n* Can introduce complexity by obscuring the conditions under which actions are taken or ignored, potentially making the system harder to debug and understand.\n* May lead to missed opportunities or actions if the state changes are not properly monitored or if the balking condition is too restrictive.\n\n## Related Java Design Patterns\n\n* [Double-Checked Locking](https://java-design-patterns.com/patterns/double-checked-locking/): Ensures that initialization occurs only when necessary and avoids unnecessary locking, which is related to Balking in terms of conditionally executing logic based on the object's state.\n* [Guarded Suspension](https://java-design-patterns.com/patterns/guarded-suspension/): Similar in ensuring actions are only performed when an object is in a certain state, but typically involves waiting until the state is valid.\n* [State](https://java-design-patterns.com/patterns/state/): The State pattern can be used in conjunction with Balking to manage the states and transitions of the object.\n\n## References and Credits\n\n* [Concurrent Programming in Java : Design Principles and Patterns](https://amzn.to/4dIBqxL)\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n* [Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML](https://amzn.to/4bOtzwF)\n"
  },
  {
    "path": "balking/etc/balking.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.13\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" \n  generalizations=\"true\" realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" \n  router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.balking.App\" project=\"balking\" \n    file=\"/balking/src/main/java/com/iluwatar/balking/App.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"113\" width=\"114\" x=\"135\" y=\"103\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.balking.WashingMachine\" project=\"balking\" \n    file=\"/balking/src/main/java/com/iluwatar/balking/WashingMachine.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"149\" width=\"268\" x=\"289\" y=\"103\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <enumeration id=\"3\" language=\"java\" name=\"com.iluwatar.balking.WashingMachineState\" project=\"balking\" \n    file=\"/balking/src/main/java/com/iluwatar/balking/WashingMachineState.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"113\" width=\"192\" x=\"289\" y=\"292\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <association id=\"4\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"5\" name=\"washingMachineState\"/>      \n      <multiplicity id=\"6\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "balking/etc/balking.urm.puml",
    "content": "@startuml\npackage com.iluwatar.balking {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  interface DelayProvider {\n    + executeAfterDelay(long, TimeUnit, Runnable) {abstract}\n  }\n  class WashingMachine {\n    - LOGGER : Logger {static}\n    - delayProvider : DelayProvider\n    - washingMachineState : WashingMachineState\n    + WashingMachine()\n    + WashingMachine(delayProvider : DelayProvider)\n    + endOfWashing()\n    + getWashingMachineState() : WashingMachineState\n    + wash()\n  }\n  enum WashingMachineState {\n    + ENABLED {static}\n    + WASHING {static}\n    + valueOf(name : String) : WashingMachineState {static}\n    + values() : WashingMachineState[] {static}\n  }\n}\nWashingMachine -->  \"-washingMachineState\" WashingMachineState\nWashingMachine -->  \"-delayProvider\" DelayProvider\n@enduml"
  },
  {
    "path": "balking/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>balking</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.balking.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "balking/src/main/java/com/iluwatar/balking/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.balking;\n\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * In Balking Design Pattern if an object’s method is invoked when it is in an inappropriate state,\n * then the method will return without doing anything. Objects that use this pattern are generally\n * only in a state that is prone to balking temporarily but for an unknown amount of time\n *\n * <p>In this example implementation, {@link WashingMachine} is an object that has two states in\n * which it can be: ENABLED and WASHING. If the machine is ENABLED, the state changes to WASHING\n * using a thread-safe method. On the other hand, if it already has been washing and any other\n * thread executes {@link WashingMachine#wash()} it won't do that and returns without doing\n * anything.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Entry Point.\n   *\n   * @param args the command line arguments - not used\n   */\n  public static void main(String... args) {\n    final var washingMachine = new WashingMachine();\n    var executorService = Executors.newFixedThreadPool(3);\n    for (int i = 0; i < 3; i++) {\n      executorService.execute(washingMachine::wash);\n    }\n    executorService.shutdown();\n    try {\n      if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {\n        executorService.shutdownNow();\n      }\n    } catch (InterruptedException ie) {\n      LOGGER.error(\"ERROR: Waiting on executor service shutdown!\");\n      Thread.currentThread().interrupt();\n    }\n  }\n}\n"
  },
  {
    "path": "balking/src/main/java/com/iluwatar/balking/DelayProvider.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.balking;\n\nimport java.util.concurrent.TimeUnit;\n\n/** An interface to simulate delay while executing some work. */\npublic interface DelayProvider {\n  void executeAfterDelay(long interval, TimeUnit timeUnit, Runnable task);\n}\n"
  },
  {
    "path": "balking/src/main/java/com/iluwatar/balking/WashingMachine.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.balking;\n\nimport java.util.concurrent.TimeUnit;\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Washing machine class. */\n@Slf4j\npublic class WashingMachine {\n\n  private final DelayProvider delayProvider;\n\n  @Getter private WashingMachineState washingMachineState;\n\n  /** Creates a new instance of WashingMachine. */\n  public WashingMachine() {\n    this(\n        (interval, timeUnit, task) -> {\n          try {\n            Thread.sleep(timeUnit.toMillis(interval));\n          } catch (InterruptedException ie) {\n            LOGGER.error(\"\", ie);\n            Thread.currentThread().interrupt();\n          }\n          task.run();\n        });\n  }\n\n  /**\n   * Creates a new instance of WashingMachine using provided delayProvider. This constructor is used\n   * only for unit testing purposes.\n   */\n  public WashingMachine(DelayProvider delayProvider) {\n    this.delayProvider = delayProvider;\n    this.washingMachineState = WashingMachineState.ENABLED;\n  }\n\n  /** Method responsible for washing if the object is in appropriate state. */\n  public void wash() {\n    synchronized (this) {\n      var machineState = getWashingMachineState();\n      LOGGER.info(\"{}: Actual machine state: {}\", Thread.currentThread().getName(), machineState);\n      if (this.washingMachineState == WashingMachineState.WASHING) {\n        LOGGER.error(\"Cannot wash if the machine has been already washing!\");\n        return;\n      }\n      this.washingMachineState = WashingMachineState.WASHING;\n    }\n    LOGGER.info(\"{}: Doing the washing\", Thread.currentThread().getName());\n\n    this.delayProvider.executeAfterDelay(50, TimeUnit.MILLISECONDS, this::endOfWashing);\n  }\n\n  /** Method is responsible for ending the washing by changing machine state. */\n  public synchronized void endOfWashing() {\n    washingMachineState = WashingMachineState.ENABLED;\n    LOGGER.info(\"{}: Washing completed.\", Thread.currentThread().getId());\n  }\n}\n"
  },
  {
    "path": "balking/src/main/java/com/iluwatar/balking/WashingMachineState.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.balking;\n\n/**\n * WashingMachineState enum describes in which state machine is, it can be enabled and ready to work\n * as well as during washing.\n */\npublic enum WashingMachineState {\n  ENABLED,\n  WASHING\n}\n"
  },
  {
    "path": "balking/src/test/java/com/iluwatar/balking/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.balking;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.function.Executable;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow((Executable) App::main);\n  }\n}\n"
  },
  {
    "path": "balking/src/test/java/com/iluwatar/balking/WashingMachineTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.balking;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.concurrent.TimeUnit;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for {@link WashingMachine} */\nclass WashingMachineTest {\n\n  private final FakeDelayProvider fakeDelayProvider = new FakeDelayProvider();\n\n  @Test\n  void wash() {\n    var washingMachine = new WashingMachine(fakeDelayProvider);\n\n    washingMachine.wash();\n    washingMachine.wash();\n\n    var machineStateGlobal = washingMachine.getWashingMachineState();\n\n    fakeDelayProvider.task.run();\n\n    // washing machine remains in washing state\n    assertEquals(WashingMachineState.WASHING, machineStateGlobal);\n\n    // washing machine goes back to enabled state\n    assertEquals(WashingMachineState.ENABLED, washingMachine.getWashingMachineState());\n  }\n\n  @Test\n  void endOfWashing() {\n    var washingMachine = new WashingMachine();\n    washingMachine.wash();\n    assertEquals(WashingMachineState.ENABLED, washingMachine.getWashingMachineState());\n  }\n\n  private static class FakeDelayProvider implements DelayProvider {\n    private Runnable task;\n\n    @Override\n    public void executeAfterDelay(long interval, TimeUnit timeUnit, Runnable task) {\n      this.task = task;\n    }\n  }\n}\n"
  },
  {
    "path": "bloc/README.md",
    "content": "---\ntitle: \"Bloc Pattern in Java: State Management Simplified\"\nshortTitle: Bloc\ndescription: \"Learn how the Bloc pattern helps manage state changes in Java applications. This guide covers dynamic listener management, real-world examples, and clean code practices for state management.\"\ncategory: Architectural\nlanguage: en\ntag:\n    - Abstraction\n    - Data binding\n    - Decoupling\n    - Event-driven\n    - Presentation\n    - Reactive\n    - Reusability\n    - State tracking\n---\n\n## Also known as\n\n* Business Logic Component\n* Business Logic Controller\n\n## Intent of the Bloc Pattern\n\nThe Bloc pattern manages the state of an object and allows for dynamically notifying interested listeners about state changes. It separates state management logic from the rest of the application, improving code organization and flexibility.\n\n## Detailed explanation of the Bloc pattern with real-World examples\n\nReal-world example\n\n> Consider a digital counter application where multiple parts of the UI need to be updated whenever the counter changes. For example, a label displaying the counter value and an activity log showing changes. Instead of directly modifying these UI components, the Bloc pattern manages the counter state and notifies all registered listeners about the state change. Listeners can dynamically subscribe or unsubscribe from receiving updates.\n\nIn plain words\n\n> The Bloc pattern manages a single state object and dynamically notifies registered listeners whenever the state changes.\n\nWikipedia says\n\n> While not a formalized \"Gang of Four\" design pattern, Bloc is widely used in state-driven applications. It centralizes state management and propagates state changes to registered observers, following principles of separation of concerns.\n\nSequence diagram\n\n![Bloc sequence diagram](./etc/bloc-sequence-diagram.png)\n\n## Programmatic Example of the Bloc Pattern in Java\n\nThis example demonstrates how to implement the Bloc pattern using Java and Swing. The pattern separates the state of the application from UI components, and provides a reactive, event-driven approach to managing updates.\n\nCore components of the Bloc Pattern include a `State` object, a `Bloc` class responsible for managing and updating that state, and interfaces (`StateListener` and `ListenerManager`) for subscribing to changes.\n\nThe `State` class represents the application's data at any given time.\n\n```java\npublic record State(int value) {}\n```\n\nThe `ListenerManager` interface declares methods to add and remove listeners, as well as retrieve them.\n\n```java\npublic interface ListenerManager<T> {\n  void addListener(StateListener<T> listener);\n  void removeListener(StateListener<T> listener);\n  List<StateListener<T>> getListeners();\n}\n```\n\nThe `StateListener` interface defines how a listener reacts to state changes.\n\n```java\npublic interface StateListener<T> {\n  void onStateChange(T state);\n}\n```\n\nThe `Bloc` class maintains the current state and notifies listeners of updates. It provides `increment` and `decrement` methods to update state and automatically notify registered listeners.\n\n```java\npublic class Bloc implements ListenerManager<State> {\n\n  private State currentState;\n  private final List<StateListener<State>> listeners = new ArrayList<>();\n\n  public Bloc() {\n    this.currentState = new State(0);\n  }\n\n  @Override\n  public void addListener(StateListener<State> listener) {\n    listeners.add(listener);\n    listener.onStateChange(currentState);\n  }\n\n  @Override\n  public void removeListener(StateListener<State> listener) {\n    listeners.remove(listener);\n  }\n\n  @Override\n  public List<StateListener<State>> getListeners() {\n    return Collections.unmodifiableList(listeners);\n  }\n\n  private void emitState(State newState) {\n    currentState = newState;\n    for (StateListener<State> listener : listeners) {\n      listener.onStateChange(currentState);\n    }\n  }\n\n  public void increment() {\n    emitState(new State(currentState.value() + 1));\n  }\n\n  public void decrement() {\n    emitState(new State(currentState.value() - 1));\n  }\n}\n```\n\nThis class demonstrates how to integrate the Bloc pattern with a simple Swing GUI. It sets up a counter, buttons to change the state, and a toggle to enable or disable the listener dynamically.\n\n```java\npublic class Main {\n  public static void main(String[] args) {\n    BlocUi blocUi = new BlocUi();\n    blocUi.createAndShowUi();\n  }\n}\n\npublic class BlocUi {\n\n  public void createAndShowUi() {\n    final Bloc bloc = new Bloc();\n\n    JFrame frame = new JFrame(\"BloC example\");\n    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);\n    frame.setSize(400, 300);\n\n    JLabel counterLabel = new JLabel(\"Counter: 0\", SwingConstants.CENTER);\n    counterLabel.setFont(new Font(\"Arial\", Font.BOLD, 20));\n\n    JButton decrementButton = new JButton(\"Decrement\");\n    JButton toggleListenerButton = new JButton(\"Disable Listener\");\n    JButton incrementButton = new JButton(\"Increment\");\n\n    frame.setLayout(new BorderLayout());\n    frame.add(counterLabel, BorderLayout.CENTER);\n    frame.add(incrementButton, BorderLayout.NORTH);\n    frame.add(decrementButton, BorderLayout.SOUTH);\n    frame.add(toggleListenerButton, BorderLayout.EAST);\n\n    StateListener<State> stateListener = state -> counterLabel.setText(\"Counter: \" + state.value());\n\n    bloc.addListener(stateListener);\n\n    toggleListenerButton.addActionListener(\n            e -> {\n              if (bloc.getListeners().contains(stateListener)) {\n                bloc.removeListener(stateListener);\n                toggleListenerButton.setText(\"Enable Listener\");\n              } else {\n                bloc.addListener(stateListener);\n                toggleListenerButton.setText(\"Disable Listener\");\n              }\n            });\n\n    incrementButton.addActionListener(e -> bloc.increment());\n    decrementButton.addActionListener(e -> bloc.decrement());\n\n    frame.setVisible(true);\n  }\n}\n```\n\n### Program Output\n\n- **On Increment**  \n  `Counter: 1`\n\n- **On Decrement**  \n  `Counter: 0`\n\n- **Dynamic Listener Toggle**  \n  - Listener disabled: Counter stops updating.  \n  - Listener enabled: Counter updates again.\n\n## When to Use the Bloc Pattern\n\nUse the Bloc pattern when:\n\n* When you want a clean separation of business logic and UI in Java applications\n* When you need a reactive approach to updating UI based on state changes\n* When you want to avoid coupling controllers or presenters directly to data manipulation\n* When multiple UI elements need access to the same business logic\n\n## Real-World Applications of Bloc Pattern\n\n* Java-based desktop applications that require real-time UI updates\n* Backend-driven Java frameworks that separate service layers from presentation\n* Cross-platform applications where the logic must remain consistent regardless of the UI technology\n\n## Benefits and Trade-offs of Bloc Pattern\n\nBenefits:\n\n* Simplifies UI components by removing direct business logic\n* Improves testability by isolating state and behavior\n* Encourages code reuse by centralizing data flows\n* Enhances maintainability through clear separation of concerns\n\nTrade-offs:\n\n* May introduce additional boilerplate code for managing streams or observers\n* Requires careful design to avoid a monolithic “god” component\n* Demands consistent reactive programming practices to be effective\n\n## Related Patterns\n\n- [Observer](https://java-design-patterns.com/patterns/observer/): Bloc is a specialized implementation of the Observer pattern.\n- [Mediator](https://java-design-patterns.com/patterns/mediator/): Orchestrates interactions among multiple objects through a central component\n- [MVC](https://java-design-patterns.com/patterns/model-view-controller/): Shares the idea of separating concerns between layers\n\n## References and Credits\n\n* [Bloc architecture(bloclibrary.dev)](https://bloclibrary.dev/architecture/)\n* [Clean Architecture: A Craftsman's Guide to Software Structure and Design](https://amzn.to/3UoKkaR)\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Event-Driven Programming in Java (Oracle)](https://www.oracle.com/java/)\n* [Java Swing Documentation (Oracle)](https://docs.oracle.com/javase/tutorial/uiswing/)\n"
  },
  {
    "path": "bloc/etc/bloc.puml",
    "content": "@startuml\npackage com.iluwatar.bloc {\n\n    class State {\n        - value : int\n        + State(value : int)\n        + getValue() : int\n    }\n\n    interface StateListener<T> {\n        + onStateChange(state : T)\n    }\n\n    interface ListenerManager<T> {\n        + addListener(listener : StateListener<T>)\n        + removeListener(listener : StateListener<T>)\n        + getListeners() : List<StateListener<T>>\n    }\n\n    class BloC {\n        - currentState : State\n        - listeners : List<StateListener<State>>\n        + BloC()\n        + addListener(listener : StateListener<State>)\n        + removeListener(listener : StateListener<State>)\n        + getListeners() : List<StateListener<State>>\n        - emitState(newState : State)\n        + increment()\n        + decrement()\n    }\n\n    class Main {\n        + main(args : String[])\n    }\n\n    ListenerManager <|.. BloC\n    StateListener <|.. BloC\n    BloC o-- State\n    BloC *--  StateListener\n}\n@enduml\n"
  },
  {
    "path": "bloc/etc/bloc.urm.puml",
    "content": "@startuml\npackage com.iluwatar.bloc {\n  class Bloc {\n    - currentState : State\n    - listeners : List<StateListener<State>>\n    + Bloc()\n    + addListener(listener : StateListener<State>)\n    + decrement()\n    - emitState(newState : State)\n    + getListeners() : List<StateListener<State>>\n    + increment()\n    + removeListener(listener : StateListener<State>)\n  }\n  class BlocUi {\n    + BlocUi()\n    + createAndShowUi()\n  }\n  interface ListenerManager<T> {\n    + addListener(StateListener<T>) {abstract}\n    + getListeners() : List<StateListener<T>> {abstract}\n    + removeListener(StateListener<T>) {abstract}\n  }\n  class Main {\n    + Main()\n    + main(args : String[]) {static}\n  }\n  interface StateListener<T> {\n    + onStateChange(T) {abstract}\n  }\n}\nBloc ..|> ListenerManager \n@enduml"
  },
  {
    "path": "bloc/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>bloc</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.testng</groupId>\n            <artifactId>testng</artifactId>\n            <version>7.11.0</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.assertj</groupId>\n            <artifactId>assertj-core</artifactId>\n            <version>3.27.3</version>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.bloc.Main</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "bloc/src/main/java/com/iluwatar/bloc/Bloc.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bloc;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * The Bloc class is responsible for managing the current state and notifying registered listeners\n * whenever the state changes. It implements the ListenerManager interface, allowing listeners to be\n * added, removed, and notified of state changes.\n */\npublic class Bloc implements ListenerManager<State> {\n\n  private State currentState;\n  private final List<StateListener<State>> listeners = new ArrayList<>();\n\n  /** Constructs a new Bloc instance with an initial state of value 0. */\n  public Bloc() {\n    this.currentState = new State(0);\n  }\n\n  /**\n   * Adds a listener to receive state change notifications.\n   *\n   * @param listener the listener to add\n   */\n  @Override\n  public void addListener(StateListener<State> listener) {\n    listeners.add(listener);\n    listener.onStateChange(currentState);\n  }\n\n  /**\n   * Removes a listener from receiving state change notifications.\n   *\n   * @param listener the listener to remove\n   */\n  @Override\n  public void removeListener(StateListener<State> listener) {\n    listeners.remove(listener);\n  }\n\n  /**\n   * Returns an unmodifiable list of all registered listeners.\n   *\n   * @return an unmodifiable list of listeners\n   */\n  @Override\n  public List<StateListener<State>> getListeners() {\n    return Collections.unmodifiableList(listeners);\n  }\n\n  /**\n   * Emits a new state and notifies all registered listeners of the change.\n   *\n   * @param newState the new state to emit\n   */\n  private void emitState(State newState) {\n    currentState = newState;\n    for (StateListener<State> listener : listeners) {\n      listener.onStateChange(currentState);\n    }\n  }\n\n  /** Increments the current state value by 1 and notifies listeners of the change. */\n  public void increment() {\n    emitState(new State(currentState.value() + 1));\n  }\n\n  /** Decrements the current state value by 1 and notifies listeners of the change. */\n  public void decrement() {\n    emitState(new State(currentState.value() - 1));\n  }\n}\n"
  },
  {
    "path": "bloc/src/main/java/com/iluwatar/bloc/BlocUi.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bloc;\n\nimport java.awt.BorderLayout;\nimport java.awt.Font;\nimport javax.swing.JButton;\nimport javax.swing.JFrame;\nimport javax.swing.JLabel;\nimport javax.swing.SwingConstants;\nimport javax.swing.WindowConstants;\n\n/** The BlocUI class handles the creation and management of the UI components. */\npublic class BlocUi {\n\n  /** Creates and shows the UI. */\n  public void createAndShowUi() {\n    // Create a Bloc instance to manage the state\n    final Bloc bloc = new Bloc();\n\n    // setting up a frame window with a title\n    JFrame frame = new JFrame(\"BloC example\");\n    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);\n    frame.setSize(400, 300);\n\n    //  label to display the counter value\n    JLabel counterLabel = new JLabel(\"Counter: 0\", SwingConstants.CENTER);\n    counterLabel.setFont(new Font(\"Arial\", Font.BOLD, 20));\n\n    // buttons for increment, decrement, and toggling listener\n    JButton decrementButton = new JButton(\"Decrement\");\n    JButton toggleListenerButton = new JButton(\"Disable Listener\");\n    JButton incrementButton = new JButton(\"Increment\");\n\n    frame.setLayout(new BorderLayout());\n    frame.add(counterLabel, BorderLayout.CENTER);\n    frame.add(incrementButton, BorderLayout.NORTH);\n    frame.add(decrementButton, BorderLayout.SOUTH);\n    frame.add(toggleListenerButton, BorderLayout.EAST);\n\n    // making a state listener to update the counter label when the state changes\n    StateListener<State> stateListener = state -> counterLabel.setText(\"Counter: \" + state.value());\n\n    // adding the listener to the Bloc instance\n    bloc.addListener(stateListener);\n\n    toggleListenerButton.addActionListener(\n        e -> {\n          if (bloc.getListeners().contains(stateListener)) {\n            bloc.removeListener(stateListener);\n            toggleListenerButton.setText(\"Enable Listener\");\n          } else {\n            bloc.addListener(stateListener);\n            toggleListenerButton.setText(\"Disable Listener\");\n          }\n        });\n\n    incrementButton.addActionListener(e -> bloc.increment());\n    decrementButton.addActionListener(e -> bloc.decrement());\n\n    frame.setVisible(true);\n  }\n}\n"
  },
  {
    "path": "bloc/src/main/java/com/iluwatar/bloc/ListenerManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bloc;\n\nimport java.util.List;\n\n/**\n * Interface for managing listeners for state changes.\n *\n * @param <T> The type of state to be handled by the listeners.\n */\npublic interface ListenerManager<T> {\n\n  /**\n   * Adds a listener that will be notified of state changes.\n   *\n   * @param listener the listener to be added\n   */\n  void addListener(StateListener<T> listener);\n\n  /**\n   * Removes a listener so that it no longer receives state change notifications.\n   *\n   * @param listener the listener to be removed\n   */\n  void removeListener(StateListener<T> listener);\n\n  /**\n   * Returns a list of all listeners currently registered for state changes.\n   *\n   * @return a list of registered listeners\n   */\n  List<StateListener<T>> getListeners();\n}\n"
  },
  {
    "path": "bloc/src/main/java/com/iluwatar/bloc/Main.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bloc;\n\n/**\n * The BLoC (Business Logic Component) pattern is a software design pattern primarily used in\n * Flutter applications. It facilitates the separation of business logic from UI code, making the\n * application more modular, testable, and scalable. The BLoC pattern uses streams to manage the\n * flow of data and state changes, allowing widgets to react to new states as they arrive. In the\n * BLoC pattern, the application is divided into three key components: - Input streams: Represent\n * user interactions or external events fed into the BLoC. - Business logic: Processes the input and\n * determines the resulting state or actions. - Output streams: Emit the updated state for the UI to\n * consume. The BLoC pattern is especially useful in reactive programming scenarios and aligns well\n * with the declarative nature of Flutter. By using this pattern, developers can ensure a clear\n * separation of concerns, enhance reusability, and maintain consistent state management throughout\n * the application.\n */\npublic class Main {\n\n  /**\n   * The entry point of the application. Initializes the GUI.\n   *\n   * @param args command-line arguments (not used in this example)\n   */\n  public static void main(String[] args) {\n    BlocUi blocUi = new BlocUi();\n    blocUi.createAndShowUi();\n  }\n}\n"
  },
  {
    "path": "bloc/src/main/java/com/iluwatar/bloc/State.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bloc;\n\n/**\n * The {@code State} class represents a state with an integer value. This class encapsulates the\n * value and provides methods to retrieve it.\n */\npublic record State(int value) {}\n"
  },
  {
    "path": "bloc/src/main/java/com/iluwatar/bloc/StateListener.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bloc;\n\n/**\n * The {@code StateListener} interface defines the contract for listening to state changes.\n * Implementations of this interface should handle state changes and define actions to take when the\n * state changes.\n *\n * @param <T> the type of state that this listener will handle\n */\npublic interface StateListener<T> {\n\n  /**\n   * This method is called when the state has changed.\n   *\n   * @param state the updated state\n   */\n  void onStateChange(T state);\n}\n"
  },
  {
    "path": "bloc/src/test/java/com/iluwatar/bloc/BlocTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bloc;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.concurrent.atomic.AtomicInteger;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass BlocTest {\n  private Bloc bloc;\n  private AtomicInteger stateValue;\n\n  @BeforeEach\n  void setUp() {\n    bloc = new Bloc();\n    stateValue = new AtomicInteger(0);\n  }\n\n  @Test\n  void initialState() {\n    assertTrue(bloc.getListeners().isEmpty(), \"No listeners should be present initially.\");\n  }\n\n  @Test\n  void IncrementUpdateState() {\n    bloc.addListener(state -> stateValue.set(state.value()));\n    bloc.increment();\n    assertEquals(1, stateValue.get(), \"State should increment to 1\");\n  }\n\n  @Test\n  void DecrementUpdateState() {\n    bloc.addListener(state -> stateValue.set(state.value()));\n    bloc.decrement();\n    assertEquals(-1, stateValue.get(), \"State should decrement to -1\");\n  }\n\n  @Test\n  void addingListener() {\n    bloc.addListener(state -> {});\n    assertEquals(1, bloc.getListeners().size(), \"Listener count should be 1.\");\n  }\n\n  @Test\n  void removingListener() {\n    StateListener<State> listener = state -> {};\n    bloc.addListener(listener);\n    bloc.removeListener(listener);\n    assertTrue(bloc.getListeners().isEmpty(), \"Listener count should be 0 after removal.\");\n  }\n\n  @Test\n  void multipleListeners() {\n    AtomicInteger secondValue = new AtomicInteger();\n    bloc.addListener(state -> stateValue.set(state.value()));\n    bloc.addListener(state -> secondValue.set(state.value()));\n    bloc.increment();\n    assertEquals(1, stateValue.get(), \"First listener should receive state 1.\");\n    assertEquals(1, secondValue.get(), \"Second listener should receive state 1.\");\n  }\n}\n"
  },
  {
    "path": "bloc/src/test/java/com/iluwatar/bloc/BlocUiTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bloc;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.awt.*;\nimport javax.swing.*;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass BlocUiTest {\n\n  private JFrame frame;\n  private JLabel counterLabel;\n  private JButton incrementButton;\n  private JButton decrementButton;\n  private JButton toggleListenerButton;\n  private Bloc bloc;\n  private StateListener<State> stateListener;\n\n  @BeforeEach\n  void setUp() {\n    bloc = new Bloc(); // Re-initialize the Bloc for each test\n\n    frame = new JFrame(\"BloC example\");\n    frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);\n    frame.setSize(400, 300);\n\n    counterLabel = new JLabel(\"Counter: 0\", SwingConstants.CENTER);\n    counterLabel.setFont(new Font(\"Arial\", Font.BOLD, 20));\n\n    incrementButton = new JButton(\"Increment\");\n    decrementButton = new JButton(\"Decrement\");\n    toggleListenerButton = new JButton(\"Disable Listener\");\n\n    frame.setLayout(new BorderLayout());\n    frame.add(counterLabel, BorderLayout.CENTER);\n    frame.add(incrementButton, BorderLayout.NORTH);\n    frame.add(decrementButton, BorderLayout.SOUTH);\n    frame.add(toggleListenerButton, BorderLayout.EAST);\n\n    stateListener = state -> counterLabel.setText(\"Counter: \" + state.value());\n    bloc.addListener(stateListener);\n\n    incrementButton.addActionListener(e -> bloc.increment());\n    decrementButton.addActionListener(e -> bloc.decrement());\n    toggleListenerButton.addActionListener(\n        e -> {\n          if (bloc.getListeners().contains(stateListener)) {\n            bloc.removeListener(stateListener);\n            toggleListenerButton.setText(\"Enable Listener\");\n          } else {\n            bloc.addListener(stateListener);\n            toggleListenerButton.setText(\"Disable Listener\");\n          }\n        });\n\n    frame.setVisible(true);\n  }\n\n  @AfterEach\n  void tearDown() {\n    frame.dispose();\n    bloc = new Bloc(); // Reset Bloc state after each test to avoid state carryover\n  }\n\n  @Test\n  void testIncrementButton() {\n    simulateButtonClick(incrementButton);\n    assertEquals(\"Counter: 1\", counterLabel.getText());\n  }\n\n  @Test\n  void testDecrementButton() {\n    simulateButtonClick(decrementButton);\n    assertEquals(\"Counter: -1\", counterLabel.getText());\n  }\n\n  @Test\n  void testToggleListenerButton() {\n    // Disable listener\n    simulateButtonClick(toggleListenerButton);\n    simulateButtonClick(incrementButton);\n    assertEquals(\"Counter: 0\", counterLabel.getText()); // Listener is disabled\n\n    // Enable listener\n    simulateButtonClick(toggleListenerButton);\n    simulateButtonClick(incrementButton);\n    assertEquals(\"Counter: 2\", counterLabel.getText()); // Listener is re-enabled\n  }\n\n  private void simulateButtonClick(JButton button) {\n    for (var listener : button.getActionListeners()) {\n      listener.actionPerformed(null);\n    }\n  }\n}\n"
  },
  {
    "path": "bridge/README.md",
    "content": "---\ntitle: \"Bridge Pattern in Java: Decouple Abstraction from Implementation\"\nshortTitle: Bridge\ndescription: \"Learn about the Bridge design pattern in Java. Decouple abstraction from implementation to enhance flexibility and extensibility. Explore real-world examples, class diagrams, and use cases.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Abstraction\n  - Decoupling\n  - Extensibility\n  - Gang of Four\n  - Object composition\n---\n\n## Also known as\n\n* Handle/Body\n\n## Intent of Bridge Design Pattern\n\nThe Bridge design pattern is a structural pattern in Java that decouples an abstraction from its implementation, allowing both to vary independently. This pattern is essential for developing flexible and extensible software systems.\n\n## Detailed Explanation of Bridge Pattern with Real-World Examples\n\nReal-world example\n\n> In Java, the Bridge pattern is commonly used in GUI frameworks, database drivers, and device drivers. For instance, a universal remote control (abstraction) can operate various TV brands (implementations) through a consistent interface.\n>\n> Imagine a universal remote control (abstraction) that can operate different brands and types of televisions (implementations). The remote control provides a consistent interface for operations like turning on/off, changing channels, and adjusting the volume. Each television brand or type has its own specific implementation of these operations. By using the Bridge pattern, the remote control interface is decoupled from the television implementations, allowing the remote control to work with any television regardless of its brand or internal workings. This separation allows new television models to be added without changing the remote control's code, and different remote controls can be developed to work with the same set of televisions.\n\nIn Plain Words\n\n> Bridge pattern is about preferring composition to inheritance. Implementation details are pushed from a hierarchy to another object with a separate hierarchy.\n\nWikipedia says\n\n> The bridge pattern is a design pattern used in software engineering that is meant to \"decouple an abstraction from its implementation so that the two can vary independently\"\n\nSequence diagram\n\n![Bridge sequence diagram](./etc/bridge-sequence-diagram.png)\n\n## Programmatic Example of Bridge Pattern in Java\n\nImagine you have a weapon that can have various enchantments, and you need to combine different weapons with different enchantments. How would you handle this? Would you create multiple copies of each weapon, each with a different enchantment, or would you create separate enchantments and apply them to the weapon as needed? The Bridge pattern enables you to do the latter.\n\nHere we have the `Weapon` hierarchy:\n\n```java\npublic interface Weapon {\n    void wield();\n\n    void swing();\n\n    void unwield();\n\n    Enchantment getEnchantment();\n}\n\npublic class Sword implements Weapon {\n\n    private final Enchantment enchantment;\n\n    public Sword(Enchantment enchantment) {\n        this.enchantment = enchantment;\n    }\n\n    @Override\n    public void wield() {\n        LOGGER.info(\"The sword is wielded.\");\n        enchantment.onActivate();\n    }\n\n    @Override\n    public void swing() {\n        LOGGER.info(\"The sword is swung.\");\n        enchantment.apply();\n    }\n\n    @Override\n    public void unwield() {\n        LOGGER.info(\"The sword is unwielded.\");\n        enchantment.onDeactivate();\n    }\n\n    @Override\n    public Enchantment getEnchantment() {\n        return enchantment;\n    }\n}\n\npublic class Hammer implements Weapon {\n\n    private final Enchantment enchantment;\n\n    public Hammer(Enchantment enchantment) {\n        this.enchantment = enchantment;\n    }\n\n    @Override\n    public void wield() {\n        LOGGER.info(\"The hammer is wielded.\");\n        enchantment.onActivate();\n    }\n\n    @Override\n    public void swing() {\n        LOGGER.info(\"The hammer is swung.\");\n        enchantment.apply();\n    }\n\n    @Override\n    public void unwield() {\n        LOGGER.info(\"The hammer is unwielded.\");\n        enchantment.onDeactivate();\n    }\n\n    @Override\n    public Enchantment getEnchantment() {\n        return enchantment;\n    }\n}\n```\n\nHere's the separate `Enchantment` hierarchy:\n\n```java\npublic interface Enchantment {\n    void onActivate();\n\n    void apply();\n\n    void onDeactivate();\n}\n\npublic class FlyingEnchantment implements Enchantment {\n\n    @Override\n    public void onActivate() {\n        LOGGER.info(\"The item begins to glow faintly.\");\n    }\n\n    @Override\n    public void apply() {\n        LOGGER.info(\"The item flies and strikes the enemies finally returning to owner's hand.\");\n    }\n\n    @Override\n    public void onDeactivate() {\n        LOGGER.info(\"The item's glow fades.\");\n    }\n}\n\npublic class SoulEatingEnchantment implements Enchantment {\n\n    @Override\n    public void onActivate() {\n        LOGGER.info(\"The item spreads bloodlust.\");\n    }\n\n    @Override\n    public void apply() {\n        LOGGER.info(\"The item eats the soul of enemies.\");\n    }\n\n    @Override\n    public void onDeactivate() {\n        LOGGER.info(\"Bloodlust slowly disappears.\");\n    }\n}\n```\n\nHere are both hierarchies in action:\n\n```java\npublic static void main(String[] args) {\n    LOGGER.info(\"The knight receives an enchanted sword.\");\n    var enchantedSword = new Sword(new SoulEatingEnchantment());\n    enchantedSword.wield();\n    enchantedSword.swing();\n    enchantedSword.unwield();\n\n    LOGGER.info(\"The valkyrie receives an enchanted hammer.\");\n    var hammer = new Hammer(new FlyingEnchantment());\n    hammer.wield();\n    hammer.swing();\n    hammer.unwield();\n}\n```\n\nHere's the console output.\n\n```\nThe knight receives an enchanted sword.\nThe sword is wielded.\nThe item spreads bloodlust.\nThe sword is swung.\nThe item eats the soul of enemies.\nThe sword is unwielded.\nBloodlust slowly disappears.\nThe valkyrie receives an enchanted hammer.\nThe hammer is wielded.\nThe item begins to glow faintly.\nThe hammer is swung.\nThe item flies and strikes the enemies finally returning to owner's hand.\nThe hammer is unwielded.\nThe item's glow fades.\n```\n\n## When to Use the Bridge Pattern in Java\n\nConsider using the Bridge pattern when:\n\n* You need to avoid a permanent binding between an abstraction and its implementation, such as when the implementation must be chosen or switched at runtime.\n* Both the abstractions and their implementations should be extendable via subclassing, allowing independent extension of each component.\n* Changes to the implementation of an abstraction should not affect clients, meaning their code should not require recompilation.\n* You encounter a large number of classes in your hierarchy, indicating the need to split an object into two parts, a concept referred to as \"nested generalizations\" by Rumbaugh.\n* You want to share an implementation among multiple objects, potentially using reference counting, while keeping this detail hidden from the client, as exemplified by Coplien's String class, where multiple objects can share the same string representation.\n\n## Bridge Pattern Java Tutorials\n\n* [Bridge Pattern Tutorial (DigitalOcean)](https://www.digitalocean.com/community/tutorials/bridge-design-pattern-java)\n\n## Real-World Applications of Bridge Pattern in Java\n\n* GUI Frameworks where the abstraction is the window, and the implementation could be the underlying OS windowing system.\n* Database Drivers where the abstraction is a generic database interface, and the implementations are database-specific drivers.\n* Device Drivers where the abstraction is the device-independent code, and the implementation is the device-dependent code.\n\n## Benefits and Trade-offs of Bridge Pattern\n\nBenefits:\n\n* Decoupling Interface and Implementation: The Bridge pattern enhances modularity by separating the interface (the high-level operations) from the implementation (the low-level operations).\n* Improved Extensibility: You can extend the abstraction and implementation hierarchies independently.\n* Hiding Implementation Details: Clients only see the abstraction's interface, not its implementation.\n\nTrade-offs:\n\n* Increased Complexity: The pattern can complicate the system architecture and code, especially for clients unfamiliar with the pattern.\n* Runtime Overhead: The extra layer of abstraction can introduce a performance penalty, although it is often negligible in practice.\n\n## Related Java Design Patterns\n\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): The Abstract Factory pattern can be used along with the Bridge pattern to create platforms that are independent of the concrete classes used to create their objects.\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): The Adapter pattern is used to provide a different interface to an object, while the Bridge pattern is used to separate an object's interface from its implementation.\n* [Composite](https://java-design-patterns.com/patterns/composite/): The Bridge pattern is often used with the Composite pattern to model the implementation details of a component.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): The Strategy pattern is like the Bridge pattern, but with a different intent. Both patterns are based on composition: Strategy uses composition to change the behavior of a class, while Bridge uses composition to separate an abstraction from its implementation.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n* [Pattern-Oriented Software Architecture Volume 1: A System of Patterns](https://amzn.to/3TEnhtl)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "bridge/etc/bridge.urm.puml",
    "content": "@startuml\npackage com.iluwatar.bridge {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  interface Enchantment {\n    + apply() {abstract}\n    + onActivate() {abstract}\n    + onDeactivate() {abstract}\n  }\n  class FlyingEnchantment {\n    - LOGGER : Logger {static}\n    + FlyingEnchantment()\n    + apply()\n    + onActivate()\n    + onDeactivate()\n  }\n  class Hammer {\n    - LOGGER : Logger {static}\n    - enchantment : Enchantment\n    + Hammer(enchantment : Enchantment)\n    + getEnchantment() : Enchantment\n    + swing()\n    + unwield()\n    + wield()\n  }\n  class SoulEatingEnchantment {\n    - LOGGER : Logger {static}\n    + SoulEatingEnchantment()\n    + apply()\n    + onActivate()\n    + onDeactivate()\n  }\n  class Sword {\n    - LOGGER : Logger {static}\n    - enchantment : Enchantment\n    + Sword(enchantment : Enchantment)\n    + getEnchantment() : Enchantment\n    + swing()\n    + unwield()\n    + wield()\n  }\n  interface Weapon {\n    + getEnchantment() : Enchantment {abstract}\n    + swing() {abstract}\n    + unwield() {abstract}\n    + wield() {abstract}\n  }\n}\nSword -->  \"-enchantment\" Enchantment\nHammer -->  \"-enchantment\" Enchantment\nFlyingEnchantment ..|> Enchantment \nHammer ..|> Weapon \nSoulEatingEnchantment ..|> Enchantment \nSword ..|> Weapon \n@enduml"
  },
  {
    "path": "bridge/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>bridge</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.bridge.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "bridge/src/main/java/com/iluwatar/bridge/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bridge;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Composition over inheritance. The Bridge pattern can also be thought of as two layers of\n * abstraction. With Bridge, you can decouple an abstraction from its implementation so that the two\n * can vary independently.\n *\n * <p>In Bridge pattern both abstraction ({@link Weapon}) and implementation ( {@link Enchantment})\n * have their own class hierarchies. The interface of the implementations can be changed without\n * affecting the clients.\n *\n * <p>In this example we have two class hierarchies. One of weapons and another one of enchantments.\n * We can easily combine any weapon with any enchantment using composition instead of creating deep\n * class hierarchy.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    LOGGER.info(\"The knight receives an enchanted sword.\");\n    var enchantedSword = new Sword(new SoulEatingEnchantment());\n    enchantedSword.wield();\n    enchantedSword.swing();\n    enchantedSword.unwield();\n\n    LOGGER.info(\"The valkyrie receives an enchanted hammer.\");\n    var hammer = new Hammer(new FlyingEnchantment());\n    hammer.wield();\n    hammer.swing();\n    hammer.unwield();\n  }\n}\n"
  },
  {
    "path": "bridge/src/main/java/com/iluwatar/bridge/Enchantment.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bridge;\n\n/** Enchantment. */\npublic interface Enchantment {\n\n  void onActivate();\n\n  void apply();\n\n  void onDeactivate();\n}\n"
  },
  {
    "path": "bridge/src/main/java/com/iluwatar/bridge/FlyingEnchantment.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bridge;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** FlyingEnchantment. */\n@Slf4j\npublic class FlyingEnchantment implements Enchantment {\n\n  @Override\n  public void onActivate() {\n    LOGGER.info(\"The item begins to glow faintly.\");\n  }\n\n  @Override\n  public void apply() {\n    LOGGER.info(\"The item flies and strikes the enemies finally returning to owner's hand.\");\n  }\n\n  @Override\n  public void onDeactivate() {\n    LOGGER.info(\"The item's glow fades.\");\n  }\n}\n"
  },
  {
    "path": "bridge/src/main/java/com/iluwatar/bridge/Hammer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bridge;\n\nimport lombok.AllArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Hammer. */\n@Slf4j\n@AllArgsConstructor\npublic class Hammer implements Weapon {\n\n  private final Enchantment enchantment;\n\n  @Override\n  public void wield() {\n    LOGGER.info(\"The hammer is wielded.\");\n    enchantment.onActivate();\n  }\n\n  @Override\n  public void swing() {\n    LOGGER.info(\"The hammer is swung.\");\n    enchantment.apply();\n  }\n\n  @Override\n  public void unwield() {\n    LOGGER.info(\"The hammer is unwielded.\");\n    enchantment.onDeactivate();\n  }\n\n  @Override\n  public Enchantment getEnchantment() {\n    return enchantment;\n  }\n}\n"
  },
  {
    "path": "bridge/src/main/java/com/iluwatar/bridge/SoulEatingEnchantment.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bridge;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** SoulEatingEnchantment. */\n@Slf4j\npublic class SoulEatingEnchantment implements Enchantment {\n\n  @Override\n  public void onActivate() {\n    LOGGER.info(\"The item spreads bloodlust.\");\n  }\n\n  @Override\n  public void apply() {\n    LOGGER.info(\"The item eats the soul of enemies.\");\n  }\n\n  @Override\n  public void onDeactivate() {\n    LOGGER.info(\"Bloodlust slowly disappears.\");\n  }\n}\n"
  },
  {
    "path": "bridge/src/main/java/com/iluwatar/bridge/Sword.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bridge;\n\nimport lombok.AllArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Sword. */\n@Slf4j\n@AllArgsConstructor\npublic class Sword implements Weapon {\n\n  private final Enchantment enchantment;\n\n  @Override\n  public void wield() {\n    LOGGER.info(\"The sword is wielded.\");\n    enchantment.onActivate();\n  }\n\n  @Override\n  public void swing() {\n    LOGGER.info(\"The sword is swung.\");\n    enchantment.apply();\n  }\n\n  @Override\n  public void unwield() {\n    LOGGER.info(\"The sword is unwielded.\");\n    enchantment.onDeactivate();\n  }\n\n  @Override\n  public Enchantment getEnchantment() {\n    return enchantment;\n  }\n}\n"
  },
  {
    "path": "bridge/src/main/java/com/iluwatar/bridge/Weapon.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bridge;\n\n/** Weapon. */\npublic interface Weapon {\n\n  void wield();\n\n  void swing();\n\n  void unwield();\n\n  Enchantment getEnchantment();\n}\n"
  },
  {
    "path": "bridge/src/test/java/com/iluwatar/bridge/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bridge;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "bridge/src/test/java/com/iluwatar/bridge/HammerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bridge;\n\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.spy;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests for hammer */\nclass HammerTest extends WeaponTest {\n\n  /**\n   * Invoke all possible actions on the weapon and check if the actions are executed on the actual\n   * underlying weapon implementation.\n   */\n  @Test\n  void testHammer() {\n    final var hammer = spy(new Hammer(mock(FlyingEnchantment.class)));\n    testBasicWeaponActions(hammer);\n  }\n}\n"
  },
  {
    "path": "bridge/src/test/java/com/iluwatar/bridge/SwordTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bridge;\n\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.spy;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests for sword */\nclass SwordTest extends WeaponTest {\n\n  /**\n   * Invoke all possible actions on the weapon and check if the actions are executed on the actual\n   * underlying weapon implementation.\n   */\n  @Test\n  void testSword() {\n    final var sword = spy(new Sword(mock(FlyingEnchantment.class)));\n    testBasicWeaponActions(sword);\n  }\n}\n"
  },
  {
    "path": "bridge/src/test/java/com/iluwatar/bridge/WeaponTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bridge;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\n/** Base class for weapon tests */\nabstract class WeaponTest {\n\n  /**\n   * Invoke the basic actions of the given weapon, and test if the underlying enchantment\n   * implementation is invoked\n   */\n  final void testBasicWeaponActions(final Weapon weapon) {\n    assertNotNull(weapon);\n    var enchantment = weapon.getEnchantment();\n    assertNotNull(enchantment);\n    assertNotNull(weapon.getEnchantment());\n\n    weapon.swing();\n    verify(enchantment).apply();\n    verifyNoMoreInteractions(enchantment);\n\n    weapon.wield();\n    verify(enchantment).onActivate();\n    verifyNoMoreInteractions(enchantment);\n\n    weapon.unwield();\n    verify(enchantment).onDeactivate();\n    verifyNoMoreInteractions(enchantment);\n  }\n}\n"
  },
  {
    "path": "builder/.gitignore",
    "content": "/target/\n"
  },
  {
    "path": "builder/README.md",
    "content": "---\ntitle: \"Builder Pattern in Java: Crafting Custom Objects with Clarity\"\nshortTitle: Builder\ndescription: \"Discover the Builder design pattern in Java, a powerful creational pattern that simplifies object construction. Learn how to separate the construction of a complex object from its representation with practical examples and use cases.\"\ncategory: Creational\nlanguage: en\ntag:\n  - Gang of Four\n  - Instantiation\n  - Object composition\n---\n\n## Intent of Builder Design Pattern\n\nThe Builder design pattern in Java, a fundamental creational pattern, allows for the step-by-step construction of complex objects. It separates the construction of a complex object from its representation so that the same construction process can create different representations.\n\n## Detailed Explanation of Builder Pattern with Real-World Examples\n\nReal-world example\n\n> The Java Builder pattern is particularly useful in scenarios where object creation involves numerous parameters.\n> \n> Imagine you are building a customizable sandwich at a deli. The Builder design pattern in this context would involve a SandwichBuilder that allows you to specify each component of the sandwich, such as the type of bread, meat, cheese, vegetables, and condiments. Instead of having to know how to construct the sandwich from scratch, you use the SandwichBuilder to add each desired component step-by-step, ensuring you get exactly the sandwich you want. This separation of construction from the final product representation ensures that the same construction process can yield different types of sandwiches based on the specified components.\n\nIn plain words\n\n> Allows you to create different flavors of an object while avoiding constructor pollution. Useful when there could be several flavors of an object. Or when there are a lot of steps involved in creation of an object.\n\nWikipedia says\n\n> The builder pattern is an object creation software design pattern with the intentions of finding a solution to the telescoping constructor antipattern.\n\nWith that in mind, let's explain what the telescoping constructor antipattern is. At some point, we have all encountered a constructor like the one below:\n\n```java\npublic Hero(Profession profession,String name,HairType hairType,HairColor hairColor,Armor armor,Weapon weapon){\n    // Value assignments\n}\n```\n\nAs you can see, the number of constructor parameters can quickly become overwhelming, making it difficult to understand their arrangement. Additionally, this list of parameters might continue to grow if you decide to add more options in the future. This is known as the telescoping constructor antipattern.\n\nSequence diagram\n\n![Builder sequence diagram](./etc/builder-sequence-diagram.png)\n\n## Programmatic Example of Builder Pattern in Java\n\nIn this Java Builder pattern example, we construct different types of `Hero` objects with varying attributes.\n\nImagine a character generator for a role-playing game. The simplest option is to let the computer generate the character for you. However, if you prefer to manually select character details such as profession, gender, hair color, etc., the character creation becomes a step-by-step process that concludes once all selections are made.\n\nA more sensible approach is to use the Builder pattern. First, let's consider the `Hero` that we want to create:\n\n```java\npublic final class Hero {\n    private final Profession profession;\n    private final String name;\n    private final HairType hairType;\n    private final HairColor hairColor;\n    private final Armor armor;\n    private final Weapon weapon;\n\n    private Hero(Builder builder) {\n        this.profession = builder.profession;\n        this.name = builder.name;\n        this.hairColor = builder.hairColor;\n        this.hairType = builder.hairType;\n        this.weapon = builder.weapon;\n        this.armor = builder.armor;\n    }\n}\n```\n\nThen we have the `Builder`:\n\n```java\n  public static class Builder {\n    private final Profession profession;\n    private final String name;\n    private HairType hairType;\n    private HairColor hairColor;\n    private Armor armor;\n    private Weapon weapon;\n\n    public Builder(Profession profession, String name) {\n        if (profession == null || name == null) {\n            throw new IllegalArgumentException(\"profession and name can not be null\");\n        }\n        this.profession = profession;\n        this.name = name;\n    }\n\n    public Builder withHairType(HairType hairType) {\n        this.hairType = hairType;\n        return this;\n    }\n\n    public Builder withHairColor(HairColor hairColor) {\n        this.hairColor = hairColor;\n        return this;\n    }\n\n    public Builder withArmor(Armor armor) {\n        this.armor = armor;\n        return this;\n    }\n\n    public Builder withWeapon(Weapon weapon) {\n        this.weapon = weapon;\n        return this;\n    }\n\n    public Hero build() {\n        return new Hero(this);\n    }\n}\n```\n\nThen it can be used as:\n\n```java\n  public static void main(String[] args) {\n\n    var mage = new Hero.Builder(Profession.MAGE, \"Riobard\")\n            .withHairColor(HairColor.BLACK)\n            .withWeapon(Weapon.DAGGER)\n            .build();\n    LOGGER.info(mage.toString());\n\n    var warrior = new Hero.Builder(Profession.WARRIOR, \"Amberjill\")\n            .withHairColor(HairColor.BLOND)\n            .withHairType(HairType.LONG_CURLY).withArmor(Armor.CHAIN_MAIL).withWeapon(Weapon.SWORD)\n            .build();\n    LOGGER.info(warrior.toString());\n\n    var thief = new Hero.Builder(Profession.THIEF, \"Desmond\")\n            .withHairType(HairType.BALD)\n            .withWeapon(Weapon.BOW)\n            .build();\n    LOGGER.info(thief.toString());\n}\n```\n\nProgram output:\n\n```\n16:28:06.058 [main] INFO com.iluwatar.builder.App -- This is a mage named Riobard with black hair and wielding a dagger.\n16:28:06.060 [main] INFO com.iluwatar.builder.App -- This is a warrior named Amberjill with blond long curly hair wearing chain mail and wielding a sword.\n16:28:06.060 [main] INFO com.iluwatar.builder.App -- This is a thief named Desmond with bald head and wielding a bow.\n```\n\n## When to Use the Builder Pattern in Java\n\nUse the Builder pattern when\n\n* The Builder pattern is ideal for Java applications requiring complex object creation.\n* The algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled\n* The construction process must allow different representations for the object that's constructed\n* It's particularly useful when a product requires a lot of steps to be created and when these steps need to be executed in a specific sequence\n\n## Builder Pattern Java Tutorials\n\n* [Builder Design Pattern in Java (DigitalOcean)](https://www.journaldev.com/1425/builder-design-pattern-in-java)\n* [Builder (Refactoring Guru)](https://refactoring.guru/design-patterns/builder)\n* [Exploring Joshua Bloch’s Builder design pattern in Java (Java Magazine)](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java)\n\n## Real-World Applications of Builder Pattern in Java\n\n* StringBuilder in Java for constructing strings.\n* java.lang.StringBuffer used to create mutable string objects.\n* Java.nio.ByteBuffer as well as similar buffers such as FloatBuffer, IntBuffer, and others\n* javax.swing.GroupLayout.Group#addComponent()\n* Various GUI builders in IDEs that construct UI components.\n* All implementations of [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)\n* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)\n* [Apache Commons Option.Builder](https://commons.apache.org/proper/commons-cli/apidocs/org/apache/commons/cli/Option.Builder.html)\n\n## Benefits and Trade-offs of Builder Pattern\n\nBenefits:\n\n* More control over the construction process compared to other creational patterns\n* Supports constructing objects step-by-step, defer construction steps or run steps recursively\n* Can construct objects that require a complex assembly of sub-objects. The final product is detached from the parts that make it up, as well as their assembly process\n* Single Responsibility Principle. You can isolate complex construction code from the business logic of the product\n\nTrade-offs:\n\n* The overall complexity of the code can increase since the pattern requires creating multiple new classes\n* May increase memory usage due to the necessity of creating multiple builder objects\n\n## Related Java Design Patterns\n\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): Can be used in conjunction with Builder to build parts of a complex object.\n* [Prototype](https://java-design-patterns.com/patterns/prototype/): Builders often create objects from a prototype.\n* [Step Builder](https://java-design-patterns.com/patterns/step-builder/): It is a variation of the Builder pattern that generates a complex object using a step-by-step approach. The Step Builder pattern is a good choice when you need to build an object with a large number of optional parameters, and you want to avoid the telescoping constructor antipattern.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "builder/etc/builder.urm.puml",
    "content": "@startuml\npackage com.iluwatar.builder {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  enum Armor {\n    + CHAIN_MAIL {static}\n    + CLOTHES {static}\n    + LEATHER {static}\n    + PLATE_MAIL {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Armor {static}\n    + values() : Armor[] {static}\n  }\n  enum HairColor {\n    + BLACK {static}\n    + BLOND {static}\n    + BROWN {static}\n    + RED {static}\n    + WHITE {static}\n    + toString() : String\n    + valueOf(name : String) : HairColor {static}\n    + values() : HairColor[] {static}\n  }\n  enum HairType {\n    + BALD {static}\n    + CURLY {static}\n    + LONG_CURLY {static}\n    + LONG_STRAIGHT {static}\n    + SHORT {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : HairType {static}\n    + values() : HairType[] {static}\n  }\n  class Hero {\n    - armor : Armor\n    - hairColor : HairColor\n    - hairType : HairType\n    - name : String\n    - profession : Profession\n    - weapon : Weapon\n    - Hero(builder : Builder)\n    + getArmor() : Armor\n    + getHairColor() : HairColor\n    + getHairType() : HairType\n    + getName() : String\n    + getProfession() : Profession\n    + getWeapon() : Weapon\n    + toString() : String\n  }\n  class Builder {\n    - armor : Armor\n    - hairColor : HairColor\n    - hairType : HairType\n    - name : String\n    - profession : Profession\n    - weapon : Weapon\n    + Builder(profession : Profession, name : String)\n    + build() : Hero\n    + withArmor(armor : Armor) : Builder\n    + withHairColor(hairColor : HairColor) : Builder\n    + withHairType(hairType : HairType) : Builder\n    + withWeapon(weapon : Weapon) : Builder\n  }\n  enum Profession {\n    + MAGE {static}\n    + PRIEST {static}\n    + THIEF {static}\n    + WARRIOR {static}\n    + toString() : String\n    + valueOf(name : String) : Profession {static}\n    + values() : Profession[] {static}\n  }\n  enum Weapon {\n    + AXE {static}\n    + BOW {static}\n    + DAGGER {static}\n    + SWORD {static}\n    + WARHAMMER {static}\n    + toString() : String\n    + valueOf(name : String) : Weapon {static}\n    + values() : Weapon[] {static}\n  }\n}\nHero -->  \"-profession\" Profession\nBuilder ..+ Hero\nHero -->  \"-armor\" Armor\nBuilder -->  \"-hairColor\" HairColor\nBuilder -->  \"-weapon\" Weapon\nBuilder -->  \"-hairType\" HairType\nHero -->  \"-hairColor\" HairColor\nBuilder -->  \"-profession\" Profession\nHero -->  \"-weapon\" Weapon\nHero -->  \"-hairType\" HairType\nBuilder -->  \"-armor\" Armor\n@enduml"
  },
  {
    "path": "builder/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>builder</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.builder.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "builder/src/main/java/com/iluwatar/builder/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.builder;\n\nimport com.iluwatar.builder.Hero.Builder;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The intention of the Builder pattern is to find a solution to the telescoping constructor\n * antipattern. The telescoping constructor antipattern occurs when the increase of object\n * constructor parameter combination leads to an exponential list of constructors. Instead of using\n * numerous constructors, the builder pattern uses another object, a builder, that receives each\n * initialization parameter step by step and then returns the resulting constructed object at once.\n *\n * <p>The Builder pattern has another benefit. It can be used for objects that contain flat data\n * (html code, SQL query, X.509 certificate...), that is to say, data that can't be easily edited.\n * This type of data cannot be edited step by step and must be edited at once. The best way to\n * construct such an object is to use a builder class.\n *\n * <p>In this example we have the Builder pattern variation as described by Joshua Bloch in\n * Effective Java 2nd Edition.\n *\n * <p>We want to build {@link Hero} objects, but its construction is complex because of the many\n * parameters needed. To aid the user we introduce {@link Builder} class. {@link Hero.Builder} takes\n * the minimum parameters to build {@link Hero} object in its constructor. After that additional\n * configuration for the {@link Hero} object can be done using the fluent {@link Builder} interface.\n * When configuration is ready the build method is called to receive the final {@link Hero} object.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var mage =\n        new Hero.Builder(Profession.MAGE, \"Riobard\")\n            .withHairColor(HairColor.BLACK)\n            .withWeapon(Weapon.DAGGER)\n            .build();\n    LOGGER.info(mage.toString());\n\n    var warrior =\n        new Hero.Builder(Profession.WARRIOR, \"Amberjill\")\n            .withHairColor(HairColor.BLOND)\n            .withHairType(HairType.LONG_CURLY)\n            .withArmor(Armor.CHAIN_MAIL)\n            .withWeapon(Weapon.SWORD)\n            .build();\n    LOGGER.info(warrior.toString());\n\n    var thief =\n        new Hero.Builder(Profession.THIEF, \"Desmond\")\n            .withHairType(HairType.BALD)\n            .withWeapon(Weapon.BOW)\n            .build();\n    LOGGER.info(thief.toString());\n  }\n}\n"
  },
  {
    "path": "builder/src/main/java/com/iluwatar/builder/Armor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.builder;\n\nimport lombok.AllArgsConstructor;\n\n/** Armor enumeration. */\n@AllArgsConstructor\npublic enum Armor {\n  CLOTHES(\"clothes\"),\n  LEATHER(\"leather\"),\n  CHAIN_MAIL(\"chain mail\"),\n  PLATE_MAIL(\"plate mail\");\n\n  private final String title;\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "builder/src/main/java/com/iluwatar/builder/HairColor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.builder;\n\n/** HairColor enumeration. */\npublic enum HairColor {\n  WHITE,\n  BLOND,\n  RED,\n  BROWN,\n  BLACK;\n\n  @Override\n  public String toString() {\n    return name().toLowerCase();\n  }\n}\n"
  },
  {
    "path": "builder/src/main/java/com/iluwatar/builder/HairType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.builder;\n\nimport lombok.AllArgsConstructor;\n\n/** HairType enumeration. */\n@AllArgsConstructor\npublic enum HairType {\n  BALD(\"bald\"),\n  SHORT(\"short\"),\n  CURLY(\"curly\"),\n  LONG_STRAIGHT(\"long straight\"),\n  LONG_CURLY(\"long curly\");\n\n  private final String title;\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "builder/src/main/java/com/iluwatar/builder/Hero.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.builder;\n\n/** Hero,the record class. */\npublic record Hero(\n    Profession profession,\n    String name,\n    HairType hairType,\n    HairColor hairColor,\n    Armor armor,\n    Weapon weapon) {\n\n  private Hero(Builder builder) {\n    this(\n        builder.profession,\n        builder.name,\n        builder.hairType,\n        builder.hairColor,\n        builder.armor,\n        builder.weapon);\n  }\n\n  @Override\n  public String toString() {\n\n    var sb = new StringBuilder();\n    sb.append(\"This is a \").append(profession).append(\" named \").append(name);\n    if (hairColor != null || hairType != null) {\n      sb.append(\" with \");\n      if (hairColor != null) {\n        sb.append(hairColor).append(' ');\n      }\n      if (hairType != null) {\n        sb.append(hairType).append(' ');\n      }\n      sb.append(hairType != HairType.BALD ? \"hair\" : \"head\");\n    }\n    if (armor != null) {\n      sb.append(\" wearing \").append(armor);\n    }\n    if (weapon != null) {\n      sb.append(\" and wielding a \").append(weapon);\n    }\n    sb.append('.');\n    return sb.toString();\n  }\n\n  /** The builder class. */\n  public static class Builder {\n\n    private final Profession profession;\n    private final String name;\n    private HairType hairType;\n    private HairColor hairColor;\n    private Armor armor;\n    private Weapon weapon;\n\n    /** Constructor. */\n    public Builder(Profession profession, String name) {\n      if (profession == null || name == null) {\n        throw new IllegalArgumentException(\"profession and name can not be null\");\n      }\n      this.profession = profession;\n      this.name = name;\n    }\n\n    public Builder withHairType(HairType hairType) {\n      this.hairType = hairType;\n      return this;\n    }\n\n    public Builder withHairColor(HairColor hairColor) {\n      this.hairColor = hairColor;\n      return this;\n    }\n\n    public Builder withArmor(Armor armor) {\n      this.armor = armor;\n      return this;\n    }\n\n    public Builder withWeapon(Weapon weapon) {\n      this.weapon = weapon;\n      return this;\n    }\n\n    public Hero build() {\n      return new Hero(this);\n    }\n  }\n}\n"
  },
  {
    "path": "builder/src/main/java/com/iluwatar/builder/Profession.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.builder;\n\n/** Profession enumeration. */\npublic enum Profession {\n  WARRIOR,\n  THIEF,\n  MAGE,\n  PRIEST;\n\n  @Override\n  public String toString() {\n    return name().toLowerCase();\n  }\n}\n"
  },
  {
    "path": "builder/src/main/java/com/iluwatar/builder/Weapon.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.builder;\n\n/** Weapon enumeration. */\npublic enum Weapon {\n  DAGGER,\n  SWORD,\n  AXE,\n  WARHAMMER,\n  BOW;\n\n  @Override\n  public String toString() {\n    return name().toLowerCase();\n  }\n}\n"
  },
  {
    "path": "builder/src/test/java/com/iluwatar/builder/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.builder;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "builder/src/test/java/com/iluwatar/builder/HeroTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.builder;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nimport org.junit.jupiter.api.Test;\n\n/** HeroTest */\nclass HeroTest {\n\n  /** Test if we get the expected exception when trying to create a hero without a profession */\n  @Test\n  void testMissingProfession() {\n    assertThrows(IllegalArgumentException.class, () -> new Hero.Builder(null, \"Sir without a job\"));\n  }\n\n  /** Test if we get the expected exception when trying to create a hero without a name */\n  @Test\n  void testMissingName() {\n    assertThrows(IllegalArgumentException.class, () -> new Hero.Builder(Profession.THIEF, null));\n  }\n\n  /** Test if the hero build by the builder has the correct attributes, as requested */\n  @Test\n  void testBuildHero() {\n    final String heroName = \"Sir Lancelot\";\n\n    final var hero =\n        new Hero.Builder(Profession.WARRIOR, heroName)\n            .withArmor(Armor.CHAIN_MAIL)\n            .withWeapon(Weapon.SWORD)\n            .withHairType(HairType.LONG_CURLY)\n            .withHairColor(HairColor.BLOND)\n            .build();\n\n    assertNotNull(hero);\n    assertNotNull(hero.toString());\n    assertEquals(Profession.WARRIOR, hero.profession());\n    assertEquals(heroName, hero.name());\n    assertEquals(Armor.CHAIN_MAIL, hero.armor());\n    assertEquals(Weapon.SWORD, hero.weapon());\n    assertEquals(HairType.LONG_CURLY, hero.hairType());\n    assertEquals(HairColor.BLOND, hero.hairColor());\n  }\n}\n"
  },
  {
    "path": "business-delegate/README.md",
    "content": "---\ntitle: \"Business Delegate Pattern in Java: Simplifying Business Service Interaction\"\nshortTitle: Business Delegate\ndescription: \"Learn about the Business Delegate pattern in Java. This design pattern adds an abstraction layer between presentation and business tiers, ensuring loose coupling and easier service interaction. Includes examples and class diagrams.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Business\n  - Decoupling\n  - Delegation\n  - Enterprise patterns\n  - Layered architecture\n---\n\n## Also known as\n\n* Service Representative\n\n## Intent of Business Delegate Design Pattern\n\nThe Business Delegate pattern is a structural design pattern in Java that adds an abstraction layer between the presentation and business tiers. By using the pattern we gain loose coupling between the tiers and encapsulate knowledge about how to locate, connect to, and interact with the business objects that make up the application.\n\n## Detailed Explanation of Business Delegate Pattern with Real-World Examples\n\nReal-world example\n\n> In an Enterprise application using Java EE, the Business Delegate pattern helps manage interactions between different business services.\n> \n> Imagine a restaurant where the waitstaff serves as intermediaries between the customers and the kitchen. When a customer places an order, the waiter takes the order to the kitchen, relays any specific requests, and later brings the prepared food back to the customer. The waitstaff abstracts the complexity of the kitchen operations from the customers, allowing the chefs to focus solely on cooking without needing to interact directly with customers. This setup allows both the customer service (presentation tier) and the kitchen (business service) to operate independently and efficiently. The waitstaff acts as the Business Delegate, managing communication and ensuring smooth interactions between the two distinct areas.\n\nIn Plain Words\n\n> Business Delegate adds an abstraction layer between the presentation and business tiers.\n\nWikipedia says\n\n> Business Delegate is a Java EE design pattern. This pattern is directing to reduce the coupling in between business services and the connected presentation tier, and to hide the implementation details of services (including lookup and accessibility of EJB architecture). Business Delegates acts as an adaptor to invoke business objects from the presentation tier.\n\nSequence diagram\n\n![Business Delegate sequence diagram](./etc/business-delegate-sequence-diagram.png)\n\n## Programmatic Example of Business Delegate Pattern in Java\n\nThe following Java code demonstrates how to implement the Business Delegate pattern. This pattern is particularly useful in applications requiring loose coupling and efficient service interaction.\n\nA mobile phone application promises to stream any movie in existence to your device. It captures the user's search string and passes this on to the Business Delegate. The Business Delegate selects the most suitable video streaming service and plays the video from there.\n\nFirst, we have an abstraction for video streaming services and a couple of implementations.\n\n```java\npublic interface VideoStreamingService {\n    void doProcessing();\n}\n\n@Slf4j\npublic class NetflixService implements VideoStreamingService {\n    @Override\n    public void doProcessing() {\n        LOGGER.info(\"NetflixService is now processing\");\n    }\n}\n\n@Slf4j\npublic class YouTubeService implements VideoStreamingService {\n    @Override\n    public void doProcessing() {\n        LOGGER.info(\"YouTubeService is now processing\");\n    }\n}\n```\n\nThen, we have a lookup service that decides which video streaming service to use.\n\n```java\n\n@Setter\npublic class BusinessLookup {\n\n    private NetflixService netflixService;\n    private YouTubeService youTubeService;\n\n    public VideoStreamingService getBusinessService(String movie) {\n        if (movie.toLowerCase(Locale.ROOT).contains(\"die hard\")) {\n            return netflixService;\n        } else {\n            return youTubeService;\n        }\n    }\n}\n```\n\nThe Business Delegate uses a business lookup to route movie playback requests to a suitable video streaming service.\n\n```java\n\n@Setter\npublic class BusinessDelegate {\n\n    private BusinessLookup lookupService;\n\n    public void playbackMovie(String movie) {\n        VideoStreamingService videoStreamingService = lookupService.getBusinessService(movie);\n        videoStreamingService.doProcessing();\n    }\n}\n```\n\nThe mobile client utilizes Business Delegate to call the business tier.\n\n```java\npublic class MobileClient {\n\n    private final BusinessDelegate businessDelegate;\n\n    public MobileClient(BusinessDelegate businessDelegate) {\n        this.businessDelegate = businessDelegate;\n    }\n\n    public void playbackMovie(String movie) {\n        businessDelegate.playbackMovie(movie);\n    }\n}\n```\n\nFinally, we can demonstrate the complete example in action.\n\n```java\npublic static void main(String[] args) {\n\n    // prepare the objects\n    var businessDelegate = new BusinessDelegate();\n    var businessLookup = new BusinessLookup();\n    businessLookup.setNetflixService(new NetflixService());\n    businessLookup.setYouTubeService(new YouTubeService());\n    businessDelegate.setLookupService(businessLookup);\n\n    // create the client and use the business delegate\n    var client = new MobileClient(businessDelegate);\n    client.playbackMovie(\"Die Hard 2\");\n    client.playbackMovie(\"Maradona: The Greatest Ever\");\n}\n```\n\nHere is the console output.\n\n```\n21:15:33.790 [main] INFO com.iluwatar.business.delegate.NetflixService - NetflixService is now processing\n21:15:33.794 [main] INFO com.iluwatar.business.delegate.YouTubeService - YouTubeService is now processing\n```\n\n## When to Use the Business Delegate Pattern in Java\n\nUse the Business Delegate pattern when\n\n* You need loose coupling between presentation and business tiers or need to abstract service lookups.\n* You want to orchestrate calls to multiple business services\n* You want to encapsulate service lookups and service calls\n* There is a need to abstract and encapsulate the communication between the client tier and business services\n\n## Business Delegate Pattern Java Tutorials\n\n* [Design Patterns - Business Delegate Pattern (TutorialsPoint)](https://www.tutorialspoint.com/design_pattern/business_delegate_pattern.htm)\n\n## Real-World Applications of Business Delegate Pattern in Java\n\n* Enterprise applications using Java EE (Java Platform, Enterprise Edition)\n* Applications requiring remote access to business services\n\n## Benefits and Trade-offs of Business Delegate Pattern\n\nBenefits:\n\n* Decoupling of Presentation and Business Tiers: Allows the client tier and business services to evolve independently.\n* Location Transparency: Clients remain unaffected by changes in the location or the instantiation of business services.\n* Reuse and Scalability: Business Delegate objects can be reused by multiple clients, and the pattern supports load balancing and scalability.\n\nTrade-offs:\n\n* Complexity: Introduces additional layers and abstractions, which may increase complexity.\n* Performance Overhead: The additional indirection may incur a slight performance penalty.\n\n## Related Java Design Patterns\n\n* [Service Locator](https://java-design-patterns.com/patterns/service-locator/): Business Delegate uses Service Locator to locate business services.\n* [Session Facade](https://java-design-patterns.com/patterns/session-facade/): Business Delegate may use Session Facade to provide a unified interface to a set of business services.\n* [Composite Entity](https://java-design-patterns.com/patterns/composite-entity/): Business Delegate may use Composite Entity to manage the state of business services.\n\n## References and Credits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "business-delegate/etc/business-delegate.urm.puml",
    "content": "@startuml\npackage com.iluwatar.business.delegate {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class BusinessDelegate {\n    - lookupService : BusinessLookup\n    + BusinessDelegate()\n    + playbackMovie(movie : String)\n    + setLookupService(lookupService : BusinessLookup)\n  }\n  class BusinessLookup {\n    - netflixService : NetflixService\n    - youTubeService : YouTubeService\n    + BusinessLookup()\n    + getBusinessService(movie : String) : VideoStreamingService\n    + setNetflixService(netflixService : NetflixService)\n    + setYouTubeService(youTubeService : YouTubeService)\n  }\n  class MobileClient {\n    - businessDelegate : BusinessDelegate\n    + MobileClient(businessDelegate : BusinessDelegate)\n    + playbackMovie(movie : String)\n  }\n  class NetflixService {\n    - LOGGER : Logger {static}\n    + NetflixService()\n    + doProcessing()\n  }\n  interface VideoStreamingService {\n    + doProcessing() {abstract}\n  }\n  class YouTubeService {\n    - LOGGER : Logger {static}\n    + YouTubeService()\n    + doProcessing()\n  }\n}\nBusinessLookup -->  \"-netflixService\" NetflixService\nBusinessLookup -->  \"-youTubeService\" YouTubeService\nMobileClient -->  \"-businessDelegate\" BusinessDelegate\nBusinessDelegate -->  \"-lookupService\" BusinessLookup\nNetflixService ..|> VideoStreamingService \nYouTubeService ..|> VideoStreamingService \n@enduml"
  },
  {
    "path": "business-delegate/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>business-delegate</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.business.delegate.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "business-delegate/src/main/java/com/iluwatar/business/delegate/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.business.delegate;\n\n/**\n * The Business Delegate pattern adds an abstraction layer between the presentation and business\n * tiers. By using the pattern we gain loose coupling between the tiers. The Business Delegate\n * encapsulates knowledge about how to locate, connect to, and interact with the business objects\n * that make up the application.\n *\n * <p>Some of the services the Business Delegate uses are instantiated directly, and some can be\n * retrieved through service lookups. The Business Delegate itself may contain business logic too\n * potentially tying together multiple service calls, exception handling, retrying etc.\n *\n * <p>In this example the client ({@link MobileClient}) utilizes a business delegate ( {@link\n * BusinessDelegate}) to search for movies in video streaming services. The Business Delegate then\n * selects the appropriate service and makes the service call.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    // prepare the objects\n    var businessDelegate = new BusinessDelegate();\n    var businessLookup = new BusinessLookup();\n    businessLookup.setNetflixService(new NetflixService());\n    businessLookup.setYouTubeService(new YouTubeService());\n    businessDelegate.setLookupService(businessLookup);\n\n    // create the client and use the business delegate\n    var client = new MobileClient(businessDelegate);\n    client.playbackMovie(\"Die Hard 2\");\n    client.playbackMovie(\"Maradona: The Greatest Ever\");\n  }\n}\n"
  },
  {
    "path": "business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessDelegate.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.business.delegate;\n\nimport lombok.Setter;\n\n/** BusinessDelegate separates the presentation and business tiers. */\n@Setter\npublic class BusinessDelegate {\n\n  private BusinessLookup lookupService;\n\n  public void playbackMovie(String movie) {\n    VideoStreamingService videoStreamingService = lookupService.getBusinessService(movie);\n    videoStreamingService.doProcessing();\n  }\n}\n"
  },
  {
    "path": "business-delegate/src/main/java/com/iluwatar/business/delegate/BusinessLookup.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.business.delegate;\n\nimport java.util.Locale;\nimport lombok.Setter;\n\n/** Class for performing service lookups. */\n@Setter\npublic class BusinessLookup {\n\n  private NetflixService netflixService;\n\n  private YouTubeService youTubeService;\n\n  /**\n   * Gets service instance based on given movie search string.\n   *\n   * @param movie Search string for the movie.\n   * @return Service instance.\n   */\n  public VideoStreamingService getBusinessService(String movie) {\n    if (movie.toLowerCase(Locale.ROOT).contains(\"die hard\")) {\n      return netflixService;\n    } else {\n      return youTubeService;\n    }\n  }\n}\n"
  },
  {
    "path": "business-delegate/src/main/java/com/iluwatar/business/delegate/MobileClient.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.business.delegate;\n\n/** MobileClient utilizes BusinessDelegate to call the business tier. */\npublic class MobileClient {\n\n  private final BusinessDelegate businessDelegate;\n\n  public MobileClient(BusinessDelegate businessDelegate) {\n    this.businessDelegate = businessDelegate;\n  }\n\n  public void playbackMovie(String movie) {\n    businessDelegate.playbackMovie(movie);\n  }\n}\n"
  },
  {
    "path": "business-delegate/src/main/java/com/iluwatar/business/delegate/NetflixService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.business.delegate;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** NetflixService implementation. */\n@Slf4j\npublic class NetflixService implements VideoStreamingService {\n\n  @Override\n  public void doProcessing() {\n    LOGGER.info(\"NetflixService is now processing\");\n  }\n}\n"
  },
  {
    "path": "business-delegate/src/main/java/com/iluwatar/business/delegate/VideoStreamingService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.business.delegate;\n\n/** Interface for video streaming service implementations. */\npublic interface VideoStreamingService {\n\n  void doProcessing();\n}\n"
  },
  {
    "path": "business-delegate/src/main/java/com/iluwatar/business/delegate/YouTubeService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.business.delegate;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** YouTubeService implementation. */\n@Slf4j\npublic class YouTubeService implements VideoStreamingService {\n\n  @Override\n  public void doProcessing() {\n    LOGGER.info(\"YouTubeService is now processing\");\n  }\n}\n"
  },
  {
    "path": "business-delegate/src/test/java/com/iluwatar/business/delegate/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.business.delegate;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Business Delegate example runs without errors. */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "business-delegate/src/test/java/com/iluwatar/business/delegate/BusinessDelegateTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.business.delegate;\n\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for the {@link BusinessDelegate} */\nclass BusinessDelegateTest {\n\n  private NetflixService netflixService;\n\n  private YouTubeService youTubeService;\n\n  private BusinessDelegate businessDelegate;\n\n  /**\n   * This method sets up the instance variables of this test class. It is executed before the\n   * execution of every test.\n   */\n  @BeforeEach\n  void setup() {\n    netflixService = spy(new NetflixService());\n    youTubeService = spy(new YouTubeService());\n\n    BusinessLookup businessLookup = spy(new BusinessLookup());\n    businessLookup.setNetflixService(netflixService);\n    businessLookup.setYouTubeService(youTubeService);\n\n    businessDelegate = spy(new BusinessDelegate());\n    businessDelegate.setLookupService(businessLookup);\n  }\n\n  /**\n   * In this example the client ({@link MobileClient}) utilizes a business delegate ( {@link\n   * BusinessDelegate}) to execute a task. The Business Delegate then selects the appropriate\n   * service and makes the service call.\n   */\n  @Test\n  void testBusinessDelegate() {\n\n    // setup a client object\n    var client = new MobileClient(businessDelegate);\n\n    // action\n    client.playbackMovie(\"Die hard\");\n\n    // verifying that the businessDelegate was used by client during playbackMovie() method.\n    verify(businessDelegate).playbackMovie(anyString());\n    verify(netflixService).doProcessing();\n\n    // action\n    client.playbackMovie(\"Maradona\");\n\n    // verifying that the businessDelegate was used by client during doTask() method.\n    verify(businessDelegate, times(2)).playbackMovie(anyString());\n    verify(youTubeService).doProcessing();\n  }\n}\n"
  },
  {
    "path": "bytecode/README.md",
    "content": "---\ntitle: \"Bytecode Pattern in Java: Interpreting Instructions with Custom Virtual Machines\"\nshortTitle: Bytecode\ndescription: \"Explore the Bytecode design pattern in Java, including its implementation, real-world examples, and use cases for efficient virtual machine instruction handling.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Abstraction\n  - Code simplification\n  - Encapsulation\n  - Game programming\n  - Performance\n  - Runtime\n---\n\n## Intent of Bytecode Design Pattern\n\nThe Bytecode design pattern in Java allows encoding behavior as instructions for a virtual machine, making it a powerful tool in game development and other applications.\n\n## Detailed Explanation of Bytecode Pattern with Real-World Examples\n\nReal-world example\n\n> An analogous real-world example of the Bytecode design pattern can be seen in the process of translating a book into multiple languages. Instead of directly translating the book from the original language into every other language, the book is first translated into a common intermediate language, like Esperanto. This intermediate version is easier to translate because it is simpler and more structured. Translators for each target language then translate from Esperanto into their specific languages. This approach ensures consistency, reduces errors, and simplifies the translation process, similar to how bytecode serves as an intermediate representation to optimize and facilitate the execution of high-level programming languages across different platforms.\n\nIn plain words\n\n> Bytecode pattern enables behavior driven by data instead of code.\n\n[gameprogrammingpatterns.com](https://gameprogrammingpatterns.com/bytecode.html) documentation states:\n\n> An instruction set defines the low-level operations that can be performed. A series of instructions is encoded as a sequence of bytes. A virtual machine executes these instructions one at a time, using a stack for intermediate values. By combining instructions, complex high-level behavior can be defined.\n\nSequence diagram\n\n![Bytecode sequence diagram](./etc/bytecode-sequence-diagram.png)\n\n## Programmatic Example of Bytecode Pattern in Java\n\nIn this programmatic example, we show how the Bytecode pattern in Java can simplify the execution of complex virtual machine instructions through a well-defined set of operations. This real-world example demonstrates how the Bytecode design pattern in Java can streamline game programming by allowing wizards' behavior to be easily adjusted through bytecode instructions.\n\nA team is working on a new game where wizards battle against each other. The wizard behavior needs to be carefully adjusted and iterated hundreds of times through playtesting. It's not optimal to ask the programmer to make changes each time the game designer wants to vary the behavior, so the wizard behavior is implemented as a data-driven virtual machine.\n\nOne of the most important game objects is the `Wizard` class.\n\n```java\n\n@AllArgsConstructor\n@Setter\n@Getter\n@Slf4j\npublic class Wizard {\n\n    private int health;\n    private int agility;\n    private int wisdom;\n    private int numberOfPlayedSounds;\n    private int numberOfSpawnedParticles;\n\n    public void playSound() {\n        LOGGER.info(\"Playing sound\");\n        numberOfPlayedSounds++;\n    }\n\n    public void spawnParticles() {\n        LOGGER.info(\"Spawning particles\");\n        numberOfSpawnedParticles++;\n    }\n}\n```\n\nNext, we show the available instructions for our virtual machine. Each of the instructions has its own semantics on how it operates with the stack data. For example, the ADD instruction takes the top two items from the stack, adds them together and pushes the result to the stack.\n\n```java\n\n@AllArgsConstructor\n@Getter\npublic enum Instruction {\n\n    LITERAL(1),         // e.g. \"LITERAL 0\", push 0 to stack\n    SET_HEALTH(2),      // e.g. \"SET_HEALTH\", pop health and wizard number, call set health\n    SET_WISDOM(3),      // e.g. \"SET_WISDOM\", pop wisdom and wizard number, call set wisdom\n    SET_AGILITY(4),     // e.g. \"SET_AGILITY\", pop agility and wizard number, call set agility\n    PLAY_SOUND(5),      // e.g. \"PLAY_SOUND\", pop value as wizard number, call play sound\n    SPAWN_PARTICLES(6), // e.g. \"SPAWN_PARTICLES\", pop value as wizard number, call spawn particles\n    GET_HEALTH(7),      // e.g. \"GET_HEALTH\", pop value as wizard number, push wizard's health\n    GET_AGILITY(8),     // e.g. \"GET_AGILITY\", pop value as wizard number, push wizard's agility\n    GET_WISDOM(9),      // e.g. \"GET_WISDOM\", pop value as wizard number, push wizard's wisdom\n    ADD(10),            // e.g. \"ADD\", pop 2 values, push their sum\n    DIVIDE(11);         // e.g. \"DIVIDE\", pop 2 values, push their division\n    \n    // Other properties and methods...\n}\n```\n\nAt the heart of our example is the `VirtualMachine` class. It takes instructions as input and executes them to provide the game object behavior.\n\n```java\n\n@Getter\n@Slf4j\npublic class VirtualMachine {\n\n    private final Stack<Integer> stack = new Stack<>();\n\n    private final Wizard[] wizards = new Wizard[2];\n\n    public VirtualMachine() {\n        wizards[0] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),\n                0, 0);\n        wizards[1] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),\n                0, 0);\n    }\n\n    public VirtualMachine(Wizard wizard1, Wizard wizard2) {\n        wizards[0] = wizard1;\n        wizards[1] = wizard2;\n    }\n\n    public void execute(int[] bytecode) {\n        for (var i = 0; i < bytecode.length; i++) {\n            Instruction instruction = Instruction.getInstruction(bytecode[i]);\n            switch (instruction) {\n                case LITERAL:\n                    // Read the next byte from the bytecode.\n                    int value = bytecode[++i];\n                    // Push the next value to stack\n                    stack.push(value);\n                    break;\n                case SET_AGILITY:\n                    var amount = stack.pop();\n                    var wizard = stack.pop();\n                    setAgility(wizard, amount);\n                    break;\n                case SET_WISDOM:\n                    amount = stack.pop();\n                    wizard = stack.pop();\n                    setWisdom(wizard, amount);\n                    break;\n                case SET_HEALTH:\n                    amount = stack.pop();\n                    wizard = stack.pop();\n                    setHealth(wizard, amount);\n                    break;\n                case GET_HEALTH:\n                    wizard = stack.pop();\n                    stack.push(getHealth(wizard));\n                    break;\n                case GET_AGILITY:\n                    wizard = stack.pop();\n                    stack.push(getAgility(wizard));\n                    break;\n                case GET_WISDOM:\n                    wizard = stack.pop();\n                    stack.push(getWisdom(wizard));\n                    break;\n                case ADD:\n                    var a = stack.pop();\n                    var b = stack.pop();\n                    stack.push(a + b);\n                    break;\n                case DIVIDE:\n                    a = stack.pop();\n                    b = stack.pop();\n                    stack.push(b / a);\n                    break;\n                case PLAY_SOUND:\n                    wizard = stack.pop();\n                    getWizards()[wizard].playSound();\n                    break;\n                case SPAWN_PARTICLES:\n                    wizard = stack.pop();\n                    getWizards()[wizard].spawnParticles();\n                    break;\n                default:\n                    throw new IllegalArgumentException(\"Invalid instruction value\");\n            }\n            LOGGER.info(\"Executed \" + instruction.name() + \", Stack contains \" + getStack());\n        }\n    }\n\n    public void setHealth(int wizard, int amount) {\n        wizards[wizard].setHealth(amount);\n    }\n\n    // Other properties and methods...\n}\n```\n\nNow we can show the full example utilizing the virtual machine.\n\n```java\npublic static void main(String[] args) {\n\n    var vm = new VirtualMachine(\n            new Wizard(45, 7, 11, 0, 0),\n            new Wizard(36, 18, 8, 0, 0));\n\n    vm.execute(InstructionConverterUtil.convertToByteCode(LITERAL_0));\n    vm.execute(InstructionConverterUtil.convertToByteCode(LITERAL_0));\n    vm.execute(InstructionConverterUtil.convertToByteCode(String.format(HEALTH_PATTERN, \"GET\")));\n    vm.execute(InstructionConverterUtil.convertToByteCode(LITERAL_0));\n    vm.execute(InstructionConverterUtil.convertToByteCode(GET_AGILITY));\n    vm.execute(InstructionConverterUtil.convertToByteCode(LITERAL_0));\n    vm.execute(InstructionConverterUtil.convertToByteCode(GET_WISDOM));\n    vm.execute(InstructionConverterUtil.convertToByteCode(ADD));\n    vm.execute(InstructionConverterUtil.convertToByteCode(LITERAL_2));\n    vm.execute(InstructionConverterUtil.convertToByteCode(DIVIDE));\n    vm.execute(InstructionConverterUtil.convertToByteCode(ADD));\n    vm.execute(InstructionConverterUtil.convertToByteCode(String.format(HEALTH_PATTERN, \"SET\")));\n}\n```\n\nHere is the console output.\n\n```\n16:20:10.193 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0]\n16:20:10.196 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_HEALTH, Stack contains [0, 45]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_AGILITY, Stack contains [0, 45, 7]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 7, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_WISDOM, Stack contains [0, 45, 7, 11]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 45, 18]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 18, 2]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed DIVIDE, Stack contains [0, 45, 9]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 54]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed SET_HEALTH, Stack contains []\n```\n\nUtilizing the Bytecode design pattern in Java can significantly enhance the flexibility and maintainability of your virtual machine-based applications.\n\n## When to Use the Bytecode Pattern in Java\n\nUse the Bytecode pattern when you have a lot of behavior you need to define and your game’s implementation language isn’t a good fit because:\n\n* It’s too low-level, making it tedious or error-prone to program in.\n* Iterating on it takes too long due to slow compile times or other tooling issues.\n* It has too much trust. If you want to ensure the behavior being defined can’t break the game, you need to sandbox it from the rest of the codebase.\n\n## Real-World Applications of Bytecode Pattern in Java\n\n* Java Virtual Machine (JVM) uses bytecode to allow Java programs to run on any device that has JVM installed\n* Python compiles its scripts to bytecode which is then interpreted by Python Virtual Machine\n* The .NET Framework uses a form of bytecode called Microsoft Intermediate Language (MSIL)\n\n## Benefits and Trade-offs of Bytecode Pattern\n\nBenefits:\n\n* Portability: Programs can run on any platform that has a compatible VM.\n* Security: The VM can enforce security checks on the bytecode.\n* Performance: JIT compilers can optimize bytecode at runtime, potentially improving performance over interpreted code.\n\nTrade-offs:\n\n* Overhead: Running bytecode typically involves more overhead than running native code, potentially affecting performance.\n* Complexity: Implementing and maintaining a VM adds complexity to the system.\n\n## Related Java Design Patterns\n\n* [Interpreter](https://java-design-patterns.com/patterns/interpreter/) is often used within the implementation of VMs to interpret bytecode instructions\n* [Command](https://java-design-patterns.com/patterns/command/): Bytecode instructions can be seen as commands executed by the VM.\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): VMs may use factory methods to instantiate operations or instructions defined in the bytecode.\n\n## References and Credits\n\n* [Game Programming Patterns](https://amzn.to/3K96fOn)\n* [Programming Language Pragmatics](https://amzn.to/49Tusnn)\n* [Bytecode (Game Programming Patterns)](http://gameprogrammingpatterns.com/bytecode.html)\n"
  },
  {
    "path": "bytecode/etc/bytecode.urm.puml",
    "content": "@startuml\npackage com.iluwatar.bytecode {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  enum Instruction {\n    + ADD {static}\n    + DIVIDE {static}\n    + GET_AGILITY {static}\n    + GET_HEALTH {static}\n    + GET_WISDOM {static}\n    + LITERAL {static}\n    + PLAY_SOUND {static}\n    + SET_AGILITY {static}\n    + SET_HEALTH {static}\n    + SET_WISDOM {static}\n    + SPAWN_PARTICLES {static}\n    - intValue : int\n    + getInstruction(value : int) : Instruction {static}\n    + getIntValue() : int\n    + valueOf(name : String) : Instruction {static}\n    + values() : Instruction[] {static}\n  }\n  class VirtualMachine {\n    - LOGGER : Logger {static}\n    - stack : Stack<Integer>\n    - wizards : Wizard[]\n    + VirtualMachine()\n    + VirtualMachine(wizard1 : Wizard, wizard2 : Wizard)\n    + execute(bytecode : int[])\n    + getAgility(wizard : int) : int\n    + getHealth(wizard : int) : int\n    + getStack() : Stack<Integer>\n    + getWisdom(wizard : int) : int\n    + getWizards() : Wizard[]\n    - randomInt(min : int, max : int) : int\n    + setAgility(wizard : int, amount : int)\n    + setHealth(wizard : int, amount : int)\n    + setWisdom(wizard : int, amount : int)\n  }\n  class Wizard {\n    - LOGGER : Logger {static}\n    - agility : int\n    - health : int\n    - numberOfPlayedSounds : int\n    - numberOfSpawnedParticles : int\n    - wisdom : int\n    + Wizard(health : int, agility : int, wisdom : int, numberOfPlayedSounds : int, numberOfSpawnedParticles : int)\n    + getAgility() : int\n    + getHealth() : int\n    + getNumberOfPlayedSounds() : int\n    + getNumberOfSpawnedParticles() : int\n    + getWisdom() : int\n    + playSound()\n    + setAgility(agility : int)\n    + setHealth(health : int)\n    + setNumberOfPlayedSounds(numberOfPlayedSounds : int)\n    + setNumberOfSpawnedParticles(numberOfSpawnedParticles : int)\n    + setWisdom(wisdom : int)\n    + spawnParticles()\n  }\n}\npackage com.iluwatar.bytecode.util {\n  class InstructionConverterUtil {\n    + InstructionConverterUtil()\n    + convertToByteCode(instructions : String) : int[] {static}\n    - isValidInstruction(instruction : String) : boolean {static}\n    - isValidInt(value : String) : boolean {static}\n  }\n}\n@enduml"
  },
  {
    "path": "bytecode/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>bytecode</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.bytecode.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "bytecode/src/main/java/com/iluwatar/bytecode/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bytecode;\n\nimport com.iluwatar.bytecode.util.InstructionConverterUtil;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The intention of Bytecode pattern is to give behavior the flexibility of data by encoding it as\n * instructions for a virtual machine. An instruction set defines the low-level operations that can\n * be performed. A series of instructions is encoded as a sequence of bytes. A virtual machine\n * executes these instructions one at a time, using a stack for intermediate values. By combining\n * instructions, complex high-level behavior can be defined.\n *\n * <p>This pattern should be used when there is a need to define high number of behaviours and\n * implementation engine is not a good choice because It is too lowe level Iterating on it takes too\n * long due to slow compile times or other tooling issues. It has too much trust. If you want to\n * ensure the behavior being defined can’t break the game, you need to sandbox it from the rest of\n * the codebase.\n */\n@Slf4j\npublic class App {\n\n  private static final String LITERAL_0 = \"LITERAL 0\";\n  private static final String HEALTH_PATTERN = \"%s_HEALTH\";\n  private static final String GET_AGILITY = \"GET_AGILITY\";\n  private static final String GET_WISDOM = \"GET_WISDOM\";\n  private static final String ADD = \"ADD\";\n  private static final String LITERAL_2 = \"LITERAL 2\";\n  private static final String DIVIDE = \"DIVIDE\";\n\n  /**\n   * Main app method.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var vm = new VirtualMachine(new Wizard(45, 7, 11, 0, 0), new Wizard(36, 18, 8, 0, 0));\n\n    vm.execute(InstructionConverterUtil.convertToByteCode(LITERAL_0));\n    vm.execute(InstructionConverterUtil.convertToByteCode(LITERAL_0));\n    vm.execute(InstructionConverterUtil.convertToByteCode(String.format(HEALTH_PATTERN, \"GET\")));\n    vm.execute(InstructionConverterUtil.convertToByteCode(LITERAL_0));\n    vm.execute(InstructionConverterUtil.convertToByteCode(GET_AGILITY));\n    vm.execute(InstructionConverterUtil.convertToByteCode(LITERAL_0));\n    vm.execute(InstructionConverterUtil.convertToByteCode(GET_WISDOM));\n    vm.execute(InstructionConverterUtil.convertToByteCode(ADD));\n    vm.execute(InstructionConverterUtil.convertToByteCode(LITERAL_2));\n    vm.execute(InstructionConverterUtil.convertToByteCode(DIVIDE));\n    vm.execute(InstructionConverterUtil.convertToByteCode(ADD));\n    vm.execute(InstructionConverterUtil.convertToByteCode(String.format(HEALTH_PATTERN, \"SET\")));\n  }\n}\n"
  },
  {
    "path": "bytecode/src/main/java/com/iluwatar/bytecode/Instruction.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bytecode;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\n/** Representation of instructions understandable by virtual machine. */\n@AllArgsConstructor\n@Getter\npublic enum Instruction {\n  LITERAL(1), // e.g. \"LITERAL 0\", push 0 to stack\n  SET_HEALTH(2), // e.g. \"SET_HEALTH\", pop health and wizard number, call set health\n  SET_WISDOM(3), // e.g. \"SET_WISDOM\", pop wisdom and wizard number, call set wisdom\n  SET_AGILITY(4), // e.g. \"SET_AGILITY\", pop agility and wizard number, call set agility\n  PLAY_SOUND(5), // e.g. \"PLAY_SOUND\", pop value as wizard number, call play sound\n  SPAWN_PARTICLES(6), // e.g. \"SPAWN_PARTICLES\", pop value as wizard number, call spawn particles\n  GET_HEALTH(7), // e.g. \"GET_HEALTH\", pop value as wizard number, push wizard's health\n  GET_AGILITY(8), // e.g. \"GET_AGILITY\", pop value as wizard number, push wizard's agility\n  GET_WISDOM(9), // e.g. \"GET_WISDOM\", pop value as wizard number, push wizard's wisdom\n  ADD(10), // e.g. \"ADD\", pop 2 values, push their sum\n  DIVIDE(11); // e.g. \"DIVIDE\", pop 2 values, push their division\n\n  private final int intValue;\n\n  /**\n   * Converts integer value to Instruction.\n   *\n   * @param value value of instruction\n   * @return representation of the instruction\n   */\n  public static Instruction getInstruction(int value) {\n    for (var i = 0; i < Instruction.values().length; i++) {\n      if (Instruction.values()[i].getIntValue() == value) {\n        return Instruction.values()[i];\n      }\n    }\n    throw new IllegalArgumentException(\"Invalid instruction value\");\n  }\n}\n"
  },
  {
    "path": "bytecode/src/main/java/com/iluwatar/bytecode/VirtualMachine.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bytecode;\n\nimport java.util.Stack;\nimport java.util.concurrent.ThreadLocalRandom;\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Implementation of virtual machine. */\n@Getter\n@Slf4j\npublic class VirtualMachine {\n\n  private final Stack<Integer> stack = new Stack<>();\n\n  private final Wizard[] wizards = new Wizard[2];\n\n  /** No-args constructor. */\n  public VirtualMachine() {\n    wizards[0] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32), 0, 0);\n    wizards[1] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32), 0, 0);\n  }\n\n  /** Constructor taking the wizards as arguments. */\n  public VirtualMachine(Wizard wizard1, Wizard wizard2) {\n    wizards[0] = wizard1;\n    wizards[1] = wizard2;\n  }\n\n  /**\n   * Executes provided bytecode.\n   *\n   * @param bytecode to execute\n   */\n  public void execute(int[] bytecode) {\n    for (var i = 0; i < bytecode.length; i++) {\n      Instruction instruction = Instruction.getInstruction(bytecode[i]);\n      switch (instruction) {\n        case LITERAL -> { // Read the next byte from the bytecode.\n          int value = bytecode[++i];\n          // Push the next value to stack\n          stack.push(value);\n        }\n        case SET_AGILITY -> {\n          var amount = stack.pop();\n          var wizard = stack.pop();\n          setAgility(wizard, amount);\n        }\n        case SET_WISDOM -> {\n          var amount = stack.pop();\n          var wizard = stack.pop();\n          setWisdom(wizard, amount);\n        }\n        case SET_HEALTH -> {\n          var amount = stack.pop();\n          var wizard = stack.pop();\n          setHealth(wizard, amount);\n        }\n        case GET_HEALTH -> {\n          var wizard = stack.pop();\n          stack.push(getHealth(wizard));\n        }\n        case GET_AGILITY -> {\n          var wizard = stack.pop();\n          stack.push(getAgility(wizard));\n        }\n        case GET_WISDOM -> {\n          var wizard = stack.pop();\n          stack.push(getWisdom(wizard));\n        }\n        case ADD -> {\n          var a = stack.pop();\n          var b = stack.pop();\n          stack.push(a + b);\n        }\n        case DIVIDE -> {\n          var a = stack.pop();\n          var b = stack.pop();\n          stack.push(b / a);\n        }\n        case PLAY_SOUND -> {\n          var wizard = stack.pop();\n          getWizards()[wizard].playSound();\n        }\n        case SPAWN_PARTICLES -> {\n          var wizard = stack.pop();\n          getWizards()[wizard].spawnParticles();\n        }\n        default -> {\n          throw new IllegalArgumentException(\"Invalid instruction value\");\n        }\n      }\n      LOGGER.info(\"Executed \" + instruction.name() + \", Stack contains \" + getStack());\n    }\n  }\n\n  public void setHealth(int wizard, int amount) {\n    wizards[wizard].setHealth(amount);\n  }\n\n  public void setWisdom(int wizard, int amount) {\n    wizards[wizard].setWisdom(amount);\n  }\n\n  public void setAgility(int wizard, int amount) {\n    wizards[wizard].setAgility(amount);\n  }\n\n  public int getHealth(int wizard) {\n    return wizards[wizard].getHealth();\n  }\n\n  public int getWisdom(int wizard) {\n    return wizards[wizard].getWisdom();\n  }\n\n  public int getAgility(int wizard) {\n    return wizards[wizard].getAgility();\n  }\n\n  private int randomInt(int min, int max) {\n    return ThreadLocalRandom.current().nextInt(min, max + 1);\n  }\n}\n"
  },
  {
    "path": "bytecode/src/main/java/com/iluwatar/bytecode/Wizard.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bytecode;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This class represent game objects which properties can be changed by instructions interpreted by\n * virtual machine.\n */\n@AllArgsConstructor\n@Setter\n@Getter\n@Slf4j\npublic class Wizard {\n\n  private int health;\n  private int agility;\n  private int wisdom;\n  private int numberOfPlayedSounds;\n  private int numberOfSpawnedParticles;\n\n  public void playSound() {\n    LOGGER.info(\"Playing sound\");\n    numberOfPlayedSounds++;\n  }\n\n  public void spawnParticles() {\n    LOGGER.info(\"Spawning particles\");\n    numberOfSpawnedParticles++;\n  }\n}\n"
  },
  {
    "path": "bytecode/src/main/java/com/iluwatar/bytecode/util/InstructionConverterUtil.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bytecode.util;\n\nimport com.iluwatar.bytecode.Instruction;\n\n/** Utility class used for instruction validation and conversion. */\npublic class InstructionConverterUtil {\n  /**\n   * Converts instructions represented as String.\n   *\n   * @param instructions to convert\n   * @return array of int representing bytecode\n   */\n  public static int[] convertToByteCode(String instructions) {\n    if (instructions == null || instructions.trim().length() == 0) {\n      return new int[0];\n    }\n\n    var splitedInstructions = instructions.trim().split(\" \");\n    var bytecode = new int[splitedInstructions.length];\n    for (var i = 0; i < splitedInstructions.length; i++) {\n      if (isValidInstruction(splitedInstructions[i])) {\n        bytecode[i] = Instruction.valueOf(splitedInstructions[i]).getIntValue();\n      } else if (isValidInt(splitedInstructions[i])) {\n        bytecode[i] = Integer.parseInt(splitedInstructions[i]);\n      } else {\n        var errorMessage = \"Invalid instruction or number: \" + splitedInstructions[i];\n        throw new IllegalArgumentException(errorMessage);\n      }\n    }\n\n    return bytecode;\n  }\n\n  private static boolean isValidInstruction(String instruction) {\n    try {\n      Instruction.valueOf(instruction);\n      return true;\n    } catch (IllegalArgumentException e) {\n      return false;\n    }\n  }\n\n  private static boolean isValidInt(String value) {\n    try {\n      Integer.parseInt(value);\n      return true;\n    } catch (NumberFormatException e) {\n      return false;\n    }\n  }\n}\n"
  },
  {
    "path": "bytecode/src/test/java/com/iluwatar/bytecode/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bytecode;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "bytecode/src/test/java/com/iluwatar/bytecode/VirtualMachineTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bytecode;\n\nimport static com.iluwatar.bytecode.Instruction.*;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test for {@link VirtualMachine} */\nclass VirtualMachineTest {\n\n  @Test\n  void testLiteral() {\n    var bytecode = new int[2];\n    bytecode[0] = LITERAL.getIntValue();\n    bytecode[1] = 10;\n\n    var vm = new VirtualMachine();\n    vm.execute(bytecode);\n\n    assertEquals(1, vm.getStack().size());\n    assertEquals(Integer.valueOf(10), vm.getStack().pop());\n  }\n\n  @Test\n  void testSetHealth() {\n    var wizardNumber = 0;\n    var bytecode = new int[5];\n    bytecode[0] = LITERAL.getIntValue();\n    bytecode[1] = wizardNumber;\n    bytecode[2] = LITERAL.getIntValue();\n    bytecode[3] = 50; // health amount\n    bytecode[4] = SET_HEALTH.getIntValue();\n\n    var vm = new VirtualMachine();\n    vm.execute(bytecode);\n\n    assertEquals(50, vm.getWizards()[wizardNumber].getHealth());\n  }\n\n  @Test\n  void testSetAgility() {\n    var wizardNumber = 0;\n    var bytecode = new int[5];\n    bytecode[0] = LITERAL.getIntValue();\n    bytecode[1] = wizardNumber;\n    bytecode[2] = LITERAL.getIntValue();\n    bytecode[3] = 50; // agility amount\n    bytecode[4] = SET_AGILITY.getIntValue();\n\n    var vm = new VirtualMachine();\n    vm.execute(bytecode);\n\n    assertEquals(50, vm.getWizards()[wizardNumber].getAgility());\n  }\n\n  @Test\n  void testSetWisdom() {\n    var wizardNumber = 0;\n    var bytecode = new int[5];\n    bytecode[0] = LITERAL.getIntValue();\n    bytecode[1] = wizardNumber;\n    bytecode[2] = LITERAL.getIntValue();\n    bytecode[3] = 50; // wisdom amount\n    bytecode[4] = SET_WISDOM.getIntValue();\n\n    var vm = new VirtualMachine();\n    vm.execute(bytecode);\n\n    assertEquals(50, vm.getWizards()[wizardNumber].getWisdom());\n  }\n\n  @Test\n  void testGetHealth() {\n    var wizardNumber = 0;\n    var bytecode = new int[8];\n    bytecode[0] = LITERAL.getIntValue();\n    bytecode[1] = wizardNumber;\n    bytecode[2] = LITERAL.getIntValue();\n    bytecode[3] = 50; // health amount\n    bytecode[4] = SET_HEALTH.getIntValue();\n    bytecode[5] = LITERAL.getIntValue();\n    bytecode[6] = wizardNumber;\n    bytecode[7] = GET_HEALTH.getIntValue();\n\n    var vm = new VirtualMachine();\n    vm.execute(bytecode);\n\n    assertEquals(Integer.valueOf(50), vm.getStack().pop());\n  }\n\n  @Test\n  void testPlaySound() {\n    var wizardNumber = 0;\n    var bytecode = new int[3];\n    bytecode[0] = LITERAL.getIntValue();\n    bytecode[1] = wizardNumber;\n    bytecode[2] = PLAY_SOUND.getIntValue();\n\n    var vm = new VirtualMachine();\n    vm.execute(bytecode);\n\n    assertEquals(0, vm.getStack().size());\n    assertEquals(1, vm.getWizards()[0].getNumberOfPlayedSounds());\n  }\n\n  @Test\n  void testSpawnParticles() {\n    var wizardNumber = 0;\n    var bytecode = new int[3];\n    bytecode[0] = LITERAL.getIntValue();\n    bytecode[1] = wizardNumber;\n    bytecode[2] = SPAWN_PARTICLES.getIntValue();\n\n    var vm = new VirtualMachine();\n    vm.execute(bytecode);\n\n    assertEquals(0, vm.getStack().size());\n    assertEquals(1, vm.getWizards()[0].getNumberOfSpawnedParticles());\n  }\n\n  @Test\n  void testInvalidInstruction() {\n    var bytecode = new int[1];\n    bytecode[0] = 999;\n    var vm = new VirtualMachine();\n\n    assertThrows(IllegalArgumentException.class, () -> vm.execute(bytecode));\n  }\n}\n"
  },
  {
    "path": "bytecode/src/test/java/com/iluwatar/bytecode/util/InstructionConverterUtilTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.bytecode.util;\n\nimport com.iluwatar.bytecode.Instruction;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\n/** Test for {@link InstructionConverterUtil} */\nclass InstructionConverterUtilTest {\n\n  @Test\n  void testEmptyInstruction() {\n    var instruction = \"\";\n\n    var bytecode = InstructionConverterUtil.convertToByteCode(instruction);\n\n    Assertions.assertEquals(0, bytecode.length);\n  }\n\n  @Test\n  void testInstructions() {\n    var instructions =\n        \"LITERAL 35 SET_HEALTH SET_WISDOM SET_AGILITY PLAY_SOUND\"\n            + \" SPAWN_PARTICLES GET_HEALTH ADD DIVIDE\";\n\n    var bytecode = InstructionConverterUtil.convertToByteCode(instructions);\n\n    Assertions.assertEquals(10, bytecode.length);\n    Assertions.assertEquals(Instruction.LITERAL.getIntValue(), bytecode[0]);\n    Assertions.assertEquals(35, bytecode[1]);\n    Assertions.assertEquals(Instruction.SET_HEALTH.getIntValue(), bytecode[2]);\n    Assertions.assertEquals(Instruction.SET_WISDOM.getIntValue(), bytecode[3]);\n    Assertions.assertEquals(Instruction.SET_AGILITY.getIntValue(), bytecode[4]);\n    Assertions.assertEquals(Instruction.PLAY_SOUND.getIntValue(), bytecode[5]);\n    Assertions.assertEquals(Instruction.SPAWN_PARTICLES.getIntValue(), bytecode[6]);\n    Assertions.assertEquals(Instruction.GET_HEALTH.getIntValue(), bytecode[7]);\n    Assertions.assertEquals(Instruction.ADD.getIntValue(), bytecode[8]);\n    Assertions.assertEquals(Instruction.DIVIDE.getIntValue(), bytecode[9]);\n  }\n}\n"
  },
  {
    "path": "caching/.gitignore",
    "content": "/target/\n"
  },
  {
    "path": "caching/README.md",
    "content": "---\ntitle: \"Caching Pattern in Java: Accelerating Data Access Speeds\"\nshortTitle: Caching\ndescription: \"Learn how to optimize performance with the Java Caching Design Pattern. Explore various caching strategies, real-world examples, and implementation techniques for efficient resource management.\"\ncategory: Performance optimization\nlanguage: en\ntag:\n  - Caching\n  - Data access\n  - Performance\n  - Resource management\n---\n\n## Also known as\n\n* Cache\n* Temporary Storage\n\n## Intent of Caching Design Pattern\n\nThe Java Caching Design Pattern is crucial for performance optimization and resource management. It involves various caching strategies such as write-through, read-through, and LRU cache to ensure efficient data access. The caching pattern avoids expensive re-acquisition of resources by not releasing them immediately after use. The resources retain their identity, are kept in some fast-access storage, and are re-used to avoid having to acquire them again.\n\n## Detailed Explanation of Caching Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world example of the Caching Design Pattern in Java is a library's catalog system. By caching frequently searched book results, the system reduces database load and enhances performance. When patrons frequently search for popular books, the system can cache the results of these searches. Instead of querying the database every time a user searches for a popular book, the system quickly retrieves the results from the cache. This reduces the load on the database and provides faster response times for users, enhancing their overall experience. However, the system must also ensure that the cache is updated when new books are added or existing ones are checked out, to maintain accurate information.\n\nIn plain words\n\n> Caching pattern keeps frequently needed data in fast-access storage to improve performance.\n\nWikipedia says\n\n> In computing, a cache is a hardware or software component that stores data so that future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation or a copy of data stored elsewhere. A cache hit occurs when the requested data can be found in a cache, while a cache miss occurs when it cannot. Cache hits are served by reading data from the cache, which is faster than recomputing a result or reading from a slower data store; thus, the more requests that can be served from the cache, the faster the system performs.\n\nFlowchart\n\n![Caching flowchart](./etc/caching-flowchart.png)\n\n## Programmatic Example of Caching Pattern in Java\n\nIn this programmatic example, we demonstrate different Java caching strategies, including write-through, write-around, and write-behind, using a user account management system.\n\nA team is working on a website that provides new homes for abandoned cats. People can post their cats on the website after registering, but all the new posts require approval from one of the site moderators. The user accounts of the site moderators contain a specific flag and the data is stored in a MongoDB database. Checking for the moderator flag each time a post is viewed becomes expensive, and it's a good idea to utilize caching here.\n\nLet's first look at the data layer of our application. The interesting classes are `UserAccount` which is a simple Java object containing the user account details, and `DbManager` interface which handles reading and writing of these objects to/from database.\n\n```java\n\n@Data\n@AllArgsConstructor\n@ToString\n@EqualsAndHashCode\npublic class UserAccount {\n    private String userId;\n    private String userName;\n    private String additionalInfo;\n}\n\npublic interface DbManager {\n\n    void connect();\n\n    void disconnect();\n\n    UserAccount readFromDb(String userId);\n\n    UserAccount writeToDb(UserAccount userAccount);\n\n    UserAccount updateDb(UserAccount userAccount);\n\n    UserAccount upsertDb(UserAccount userAccount);\n}\n```\n\nIn the example, we are demonstrating various different caching policies. The following caching strategies are implemented in Java: Write-through, Write-around, Write-behind, and Cache-aside. Each strategy offers unique benefits for improving performance and reducing load on the database.\n\n* Write-through writes data to the cache and DB in a single transaction\n* Write-around writes data immediately into the DB instead of the cache\n* Write-behind writes data into the cache initially whilst the data is only written into the DB when the cache is full\n* Cache-aside pushes the responsibility of keeping the data synchronized in both data sources to the application itself\n* Read-through strategy is also included in the aforementioned strategies, and it returns data from the cache to the caller if it exists, otherwise queries from DB and stores it into the cache for future use.\n\nThe cache implementation in `LruCache` is a hash table accompanied by a doubly linked-list. The linked-list helps in capturing and maintaining the LRU data in the cache. When data is queried (from the cache), added (to the cache), or updated, the data is moved to the front of the list to depict itself as the most-recently-used data. The LRU data is always at the end of the list.\n\n```java\n\n@Slf4j\npublic class LruCache {\n\n    static class Node {\n        String userId;\n        UserAccount userAccount;\n        Node previous;\n        Node next;\n\n        public Node(String userId, UserAccount userAccount) {\n            this.userId = userId;\n            this.userAccount = userAccount;\n        }\n    }\n\n    // Other properties and methods...\n\n    public LruCache(int capacity) {\n        this.capacity = capacity;\n    }\n\n    public UserAccount get(String userId) {\n        if (cache.containsKey(userId)) {\n            var node = cache.get(userId);\n            remove(node);\n            setHead(node);\n            return node.userAccount;\n        }\n        return null;\n    }\n\n    public void set(String userId, UserAccount userAccount) {\n        if (cache.containsKey(userId)) {\n            var old = cache.get(userId);\n            old.userAccount = userAccount;\n            remove(old);\n            setHead(old);\n        } else {\n            var newNode = new Node(userId, userAccount);\n            if (cache.size() >= capacity) {\n                LOGGER.info(\"# Cache is FULL! Removing {} from cache...\", end.userId);\n                cache.remove(end.userId); // remove LRU data from cache.\n                remove(end);\n                setHead(newNode);\n            } else {\n                setHead(newNode);\n            }\n            cache.put(userId, newNode);\n        }\n    }\n\n    public boolean contains(String userId) {\n        return cache.containsKey(userId);\n    }\n\n    public void remove(Node node) { /* ... */ }\n\n    public void setHead(Node node) { /* ... */ }\n\n    public void invalidate(String userId) { /* ... */ }\n\n    public boolean isFull() { /* ... */ }\n\n    public UserAccount getLruData() { /* ... */ }\n\n    public void clear() { /* ... */ }\n\n    public List<UserAccount> getCacheDataInListForm() { /* ... */ }\n\n    public void setCapacity(int newCapacity) { /* ... */ }\n}\n```\n\nThe next layer we are going to look at is `CacheStore` which implements the different caching strategies.\n\n```java\n\n@Slf4j\npublic class CacheStore {\n\n    private static final int CAPACITY = 3;\n    private static LruCache cache;\n    private final DbManager dbManager;\n\n    // Other properties and methods...\n\n    public UserAccount readThrough(final String userId) {\n        if (cache.contains(userId)) {\n            LOGGER.info(\"# Found in Cache!\");\n            return cache.get(userId);\n        }\n        LOGGER.info(\"# Not found in cache! Go to DB!!\");\n        UserAccount userAccount = dbManager.readFromDb(userId);\n        cache.set(userId, userAccount);\n        return userAccount;\n    }\n\n    public void writeThrough(final UserAccount userAccount) {\n        if (cache.contains(userAccount.getUserId())) {\n            dbManager.updateDb(userAccount);\n        } else {\n            dbManager.writeToDb(userAccount);\n        }\n        cache.set(userAccount.getUserId(), userAccount);\n    }\n\n    public void writeAround(final UserAccount userAccount) {\n        if (cache.contains(userAccount.getUserId())) {\n            dbManager.updateDb(userAccount);\n            // Cache data has been updated -- remove older\n            cache.invalidate(userAccount.getUserId());\n            // version from cache.\n        } else {\n            dbManager.writeToDb(userAccount);\n        }\n    }\n\n    public static void clearCache() {\n        if (cache != null) {\n            cache.clear();\n        }\n    }\n\n    public static void flushCache() {\n        LOGGER.info(\"# flushCache...\");\n        Optional.ofNullable(cache)\n                .map(LruCache::getCacheDataInListForm)\n                .orElse(List.of())\n                .forEach(DbManager::updateDb);\n    }\n\n    // ... omitted the implementation of other caching strategies ...\n\n}\n```\n\n`AppManager` helps to bridge the gap in communication between the main class and the application's back-end. DB connection is initialized through this class. The chosen caching strategy/policy is also initialized here. Before the cache can be used, the size of the cache has to be set. Depending on the chosen caching policy, `AppManager` will call the appropriate function in the `CacheStore` class.\n\n```java\n\n@Slf4j\npublic final class AppManager {\n\n    private static CachingPolicy cachingPolicy;\n    private final DbManager dbManager;\n    private final CacheStore cacheStore;\n\n    private AppManager() {\n    }\n\n    public void initDb() { /* ... */ }\n\n    public static void initCachingPolicy(CachingPolicy policy) { /* ... */ }\n\n    public static void initCacheCapacity(int capacity) { /* ... */ }\n\n    public UserAccount find(final String userId) {\n        LOGGER.info(\"Trying to find {} in cache\", userId);\n        if (cachingPolicy == CachingPolicy.THROUGH\n                || cachingPolicy == CachingPolicy.AROUND) {\n            return cacheStore.readThrough(userId);\n        } else if (cachingPolicy == CachingPolicy.BEHIND) {\n            return cacheStore.readThroughWithWriteBackPolicy(userId);\n        } else if (cachingPolicy == CachingPolicy.ASIDE) {\n            return findAside(userId);\n        }\n        return null;\n    }\n\n    public void save(final UserAccount userAccount) {\n        LOGGER.info(\"Save record!\");\n        if (cachingPolicy == CachingPolicy.THROUGH) {\n            cacheStore.writeThrough(userAccount);\n        } else if (cachingPolicy == CachingPolicy.AROUND) {\n            cacheStore.writeAround(userAccount);\n        } else if (cachingPolicy == CachingPolicy.BEHIND) {\n            cacheStore.writeBehind(userAccount);\n        } else if (cachingPolicy == CachingPolicy.ASIDE) {\n            saveAside(userAccount);\n        }\n    }\n\n    public static String printCacheContent() {\n        return CacheStore.print();\n    }\n\n    // Other properties and methods...\n}\n```\n\nHere is what we do in the main class of the application.\n\n```java\n\n@Slf4j\npublic class App {\n\n    public static void main(final String[] args) {\n        boolean isDbMongo = isDbMongo(args);\n        if (isDbMongo) {\n            LOGGER.info(\"Using the Mongo database engine to run the application.\");\n        } else {\n            LOGGER.info(\"Using the 'in Memory' database to run the application.\");\n        }\n        App app = new App(isDbMongo);\n        app.useReadAndWriteThroughStrategy();\n        String splitLine = \"==============================================\";\n        LOGGER.info(splitLine);\n        app.useReadThroughAndWriteAroundStrategy();\n        LOGGER.info(splitLine);\n        app.useReadThroughAndWriteBehindStrategy();\n        LOGGER.info(splitLine);\n        app.useCacheAsideStategy();\n        LOGGER.info(splitLine);\n    }\n\n    public void useReadAndWriteThroughStrategy() {\n        LOGGER.info(\"# CachingPolicy.THROUGH\");\n        appManager.initCachingPolicy(CachingPolicy.THROUGH);\n\n        var userAccount1 = new UserAccount(\"001\", \"John\", \"He is a boy.\");\n\n        appManager.save(userAccount1);\n        LOGGER.info(appManager.printCacheContent());\n        appManager.find(\"001\");\n        appManager.find(\"001\");\n    }\n\n    public void useReadThroughAndWriteAroundStrategy() { /* ... */ }\n\n    public void useReadThroughAndWriteBehindStrategy() { /* ... */ }\n\n    public void useCacheAsideStrategy() { /* ... */ }\n}\n```\n\nThe program output:\n\n```\n17:00:56.302 [main] INFO com.iluwatar.caching.App -- Using the 'in Memory' database to run the application.\n17:00:56.304 [main] INFO com.iluwatar.caching.App -- # CachingPolicy.THROUGH\n17:00:56.305 [main] INFO com.iluwatar.caching.AppManager -- Save record!\n17:00:56.308 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\nUserAccount(userId=001, userName=John, additionalInfo=He is a boy.)\n----\n17:00:56.308 [main] INFO com.iluwatar.caching.AppManager -- Trying to find 001 in cache\n17:00:56.309 [main] INFO com.iluwatar.caching.CacheStore -- # Found in Cache!\n17:00:56.309 [main] INFO com.iluwatar.caching.AppManager -- Trying to find 001 in cache\n17:00:56.309 [main] INFO com.iluwatar.caching.CacheStore -- # Found in Cache!\n17:00:56.309 [main] INFO com.iluwatar.caching.App -- ==============================================\n17:00:56.309 [main] INFO com.iluwatar.caching.App -- # CachingPolicy.AROUND\n17:00:56.309 [main] INFO com.iluwatar.caching.AppManager -- Save record!\n17:00:56.309 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\n----\n17:00:56.309 [main] INFO com.iluwatar.caching.AppManager -- Trying to find 002 in cache\n17:00:56.309 [main] INFO com.iluwatar.caching.CacheStore -- # Not found in cache! Go to DB!!\n17:00:56.309 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\nUserAccount(userId=002, userName=Jane, additionalInfo=She is a girl.)\n----\n17:00:56.309 [main] INFO com.iluwatar.caching.AppManager -- Trying to find 002 in cache\n17:00:56.309 [main] INFO com.iluwatar.caching.CacheStore -- # Found in Cache!\n17:00:56.309 [main] INFO com.iluwatar.caching.AppManager -- Save record!\n17:00:56.309 [main] INFO com.iluwatar.caching.LruCache -- # 002 has been updated! Removing older version from cache...\n17:00:56.309 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\n----\n17:00:56.309 [main] INFO com.iluwatar.caching.AppManager -- Trying to find 002 in cache\n17:00:56.309 [main] INFO com.iluwatar.caching.CacheStore -- # Not found in cache! Go to DB!!\n17:00:56.309 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\nUserAccount(userId=002, userName=Jane G., additionalInfo=She is a girl.)\n----\n17:00:56.309 [main] INFO com.iluwatar.caching.AppManager -- Trying to find 002 in cache\n17:00:56.309 [main] INFO com.iluwatar.caching.CacheStore -- # Found in Cache!\n17:00:56.309 [main] INFO com.iluwatar.caching.App -- ==============================================\n17:00:56.309 [main] INFO com.iluwatar.caching.App -- # CachingPolicy.BEHIND\n17:00:56.309 [main] INFO com.iluwatar.caching.AppManager -- Save record!\n17:00:56.309 [main] INFO com.iluwatar.caching.AppManager -- Save record!\n17:00:56.310 [main] INFO com.iluwatar.caching.AppManager -- Save record!\n17:00:56.310 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\nUserAccount(userId=005, userName=Isaac, additionalInfo=He is allergic to mustard.)\nUserAccount(userId=004, userName=Rita, additionalInfo=She hates cats.)\nUserAccount(userId=003, userName=Adam, additionalInfo=He likes food.)\n----\n17:00:56.310 [main] INFO com.iluwatar.caching.AppManager -- Trying to find 003 in cache\n17:00:56.310 [main] INFO com.iluwatar.caching.CacheStore -- # Found in cache!\n17:00:56.310 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\nUserAccount(userId=003, userName=Adam, additionalInfo=He likes food.)\nUserAccount(userId=005, userName=Isaac, additionalInfo=He is allergic to mustard.)\nUserAccount(userId=004, userName=Rita, additionalInfo=She hates cats.)\n----\n17:00:56.310 [main] INFO com.iluwatar.caching.AppManager -- Save record!\n17:00:56.310 [main] INFO com.iluwatar.caching.CacheStore -- # Cache is FULL! Writing LRU data to DB...\n17:00:56.310 [main] INFO com.iluwatar.caching.LruCache -- # Cache is FULL! Removing 004 from cache...\n17:00:56.310 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\nUserAccount(userId=006, userName=Yasha, additionalInfo=She is an only child.)\nUserAccount(userId=003, userName=Adam, additionalInfo=He likes food.)\nUserAccount(userId=005, userName=Isaac, additionalInfo=He is allergic to mustard.)\n----\n17:00:56.310 [main] INFO com.iluwatar.caching.AppManager -- Trying to find 004 in cache\n17:00:56.310 [main] INFO com.iluwatar.caching.CacheStore -- # Not found in Cache!\n17:00:56.310 [main] INFO com.iluwatar.caching.CacheStore -- # Cache is FULL! Writing LRU data to DB...\n17:00:56.310 [main] INFO com.iluwatar.caching.LruCache -- # Cache is FULL! Removing 005 from cache...\n17:00:56.310 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\nUserAccount(userId=004, userName=Rita, additionalInfo=She hates cats.)\nUserAccount(userId=006, userName=Yasha, additionalInfo=She is an only child.)\nUserAccount(userId=003, userName=Adam, additionalInfo=He likes food.)\n----\n17:00:56.310 [main] INFO com.iluwatar.caching.App -- ==============================================\n17:00:56.310 [main] INFO com.iluwatar.caching.App -- # CachingPolicy.ASIDE\n17:00:56.310 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\n----\n17:00:56.310 [main] INFO com.iluwatar.caching.AppManager -- Save record!\n17:00:56.310 [main] INFO com.iluwatar.caching.AppManager -- Save record!\n17:00:56.310 [main] INFO com.iluwatar.caching.AppManager -- Save record!\n17:00:56.310 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\n----\n17:00:56.310 [main] INFO com.iluwatar.caching.AppManager -- Trying to find 003 in cache\n17:00:56.313 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\nUserAccount(userId=003, userName=Adam, additionalInfo=He likes food.)\n----\n17:00:56.313 [main] INFO com.iluwatar.caching.AppManager -- Trying to find 004 in cache\n17:00:56.313 [main] INFO com.iluwatar.caching.App -- \n--CACHE CONTENT--\nUserAccount(userId=004, userName=Rita, additionalInfo=She hates cats.)\nUserAccount(userId=003, userName=Adam, additionalInfo=He likes food.)\n----\n17:00:56.313 [main] INFO com.iluwatar.caching.App -- ==============================================\n17:00:56.314 [Thread-0] INFO com.iluwatar.caching.CacheStore -- # flushCache...\n```\n\nImplementing the Java Caching Design Pattern using various strategies like LRU cache and write-through caching significantly enhances application performance and scalability.\n\n## When to Use the Caching Pattern in Java\n\nUse the Caching pattern when\n\n* Repetitious acquisition, initialization, and release of the same resource cause unnecessary performance overhead\n* In scenarios where the cost of recomputing or re-fetching data is significantly higher than storing and retrieving it from cache\n* For read-heavy applications with relatively static data or data that changes infrequently\n\n## Real-World Applications of Caching Pattern in Java\n\n* Web page caching to reduce server load and improve response time\n* Database query caching to avoid repeated expensive SQL queries\n* Caching results of CPU-intensive computations\n* Content Delivery Networks (CDNs) for caching static resources like images, CSS, and JavaScript files closer to the end users\n\n## Benefits and Trade-offs of Caching Pattern\n\nBenefits:\n\n* Improved Performance: Significantly reduces data access latency, leading to faster application performance\n* Reduced Load: Decreases the load on the underlying data source, which can lead to cost savings and increased longevity of the resource\n* Scalability: Enhances the scalability of applications by efficiently handling increases in load without proportional increases in resource utilization\n\nTrade-Offs:\n\n* Complexity: Introduces complexity in terms of cache invalidation, consistency, and synchronization\n* Resource Utilization: Requires additional memory or storage resources to maintain the cache\n* Stale Data: There's a risk of serving outdated data if the cache is not properly invalidated or updated when the underlying data changes\n\n## Related Java Design Patterns\n\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): Caching can be implemented using the Proxy pattern, where the proxy object intercepts requests and returns cached data if available\n* [Observer](https://java-design-patterns.com/patterns/observer/): Can be used to notify the cache when the underlying data changes, so that it can be updated or invalidated accordingly\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Can be used to add caching behavior to an existing object without modifying its code\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Different caching strategies can be implemented using the Strategy pattern, allowing the application to switch between them at runtime\n\n## References and Credits\n\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [High Performance Browser Networking](https://amzn.to/3TiNNY4)\n* [Java EE 8 High Performance](https://amzn.to/44T8vmH)\n* [Java Performance: In-Depth Advice for Tuning and Programming Java 8, 11, and Beyond](https://amzn.to/3yyD58W)\n* [Java Performance: The Definitive Guide: Getting the Most Out of Your Code](https://amzn.to/3Wu5neF)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3PMAHRZ)\n* [Scalable Internet Architectures](https://amzn.to/48V3ni9)\n* [Write-through, write-around, write-back: Cache explained (ComputerWeekly)](http://www.computerweekly.com/feature/Write-through-write-around-write-back-Cache-explained)\n* [Cache-Aside Pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/patterns/cache-aside)\n"
  },
  {
    "path": "caching/docker-compose.yml",
    "content": "#\n# This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n#\n# The MIT License\n# Copyright © 2014-2022 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nversion: '3.7'\nservices:\n  mongodb_container:\n    image: mongo:latest\n    environment:\n      MONGO_INITDB_ROOT_USERNAME: root\n      MONGO_INITDB_ROOT_PASSWORD: rootpassword\n    ports:\n      - '27017:27017'\n    volumes:\n      - ./mongo-data/:/data/db\n"
  },
  {
    "path": "caching/etc/caching.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.11\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\"\n  generalizations=\"true\" realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\"\n  router=\"FAN\">\n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.caching.CacheStore\" project=\"caching\"\n    file=\"/caching/src/main/java/com/iluwatar/caching/CacheStore.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"322\" y=\"444\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.caching.LruCache\" project=\"caching\"\n    file=\"/caching/src/main/java/com/iluwatar/caching/LruCache.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"700\" y=\"446\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <enumeration id=\"3\" language=\"java\" name=\"com.iluwatar.caching.CachingPolicy\" project=\"caching\"\n    file=\"/caching/src/main/java/com/iluwatar/caching/CachingPolicy.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"943\" y=\"122\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </enumeration>\n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.caching.DbManager\" project=\"caching\"\n    file=\"/caching/src/main/java/com/iluwatar/caching/DbManager.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"1011\" y=\"426\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.caching.App\" project=\"caching\"\n    file=\"/caching/src/main/java/com/iluwatar/caching/App.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"304\" y=\"95\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.caching.AppManager\" project=\"caching\"\n    file=\"/caching/src/main/java/com/iluwatar/caching/AppManager.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"604\" y=\"122\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.caching.UserAccount\" project=\"caching\"\n    file=\"/caching/src/main/java/com/iluwatar/caching/UserAccount.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"1161\" y=\"139\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>  \n  <association id=\"8\">\n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">\n      <attribute id=\"9\" name=\"cache\"/>\n      <multiplicity id=\"10\" minimum=\"0\" maximum=\"1\"/>\n    </end>\n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <association id=\"11\">\n    <end type=\"SOURCE\" refId=\"6\" navigable=\"false\">\n      <attribute id=\"12\" name=\"cachingPolicy\"/>\n      <multiplicity id=\"13\" minimum=\"0\" maximum=\"1\"/>\n    </end>\n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n  </classifier-display>\n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>\n"
  },
  {
    "path": "caching/etc/caching.urm.puml",
    "content": "@startuml\npackage com.iluwatar.caching.constants {\n  class CachingConstants {\n    + ADD_INFO : String {static}\n    + USER_ACCOUNT : String {static}\n    + USER_ID : String {static}\n    + USER_NAME : String {static}\n    + CachingConstants()\n  }\n}\npackage com.iluwatar.caching {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n    + useCacheAsideStrategy()\n    + useReadAndWriteThroughStrategy()\n    + useReadThroughAndWriteAroundStrategy()\n    + useReadThroughAndWriteBehindStrategy()\n  }\n  class AppManager {\n    - cachingPolicy : CachingPolicy {static}\n    - AppManager()\n    + find(userId : String) : UserAccount {static}\n    - findAside(userId : String) : UserAccount {static}\n    + initCacheCapacity(capacity : int) {static}\n    + initCachingPolicy(policy : CachingPolicy) {static}\n    + initDb(useMongoDb : boolean) {static}\n    + printCacheContent() : String {static}\n    + save(userAccount : UserAccount) {static}\n    - saveAside(userAccount : UserAccount) {static}\n  }\n  class CacheStore {\n    - LOGGER : Logger {static}\n    - cache : LruCache {static}\n    - CacheStore()\n    + clearCache() {static}\n    + flushCache() {static}\n    + get(userId : String) : UserAccount {static}\n    + initCapacity(capacity : int) {static}\n    + invalidate(userId : String) {static}\n    + print() : String {static}\n    + readThrough(userId : String) : UserAccount {static}\n    + readThroughWithWriteBackPolicy(userId : String) : UserAccount {static}\n    + set(userId : String, userAccount : UserAccount) {static}\n    + writeAround(userAccount : UserAccount) {static}\n    + writeBehind(userAccount : UserAccount) {static}\n    + writeThrough(userAccount : UserAccount) {static}\n  }\n  enum CachingPolicy {\n    + AROUND {static}\n    + ASIDE {static}\n    + BEHIND {static}\n    + THROUGH {static}\n    - policy : String\n    + getPolicy() : String\n    + valueOf(name : String) : CachingPolicy {static}\n    + values() : CachingPolicy[] {static}\n  }\n  class DbManager {\n    - db : MongoDatabase {static}\n    - mongoClient : MongoClient {static}\n    - useMongoDB : boolean {static}\n    - virtualDB : Map<String, UserAccount> {static}\n    - DbManager()\n    + connect() {static}\n    + createVirtualDb() {static}\n    + readFromDb(userId : String) : UserAccount {static}\n    + updateDb(userAccount : UserAccount) {static}\n    + upsertDb(userAccount : UserAccount) {static}\n    + writeToDb(userAccount : UserAccount) {static}\n  }\n  class LruCache {\n    - LOGGER : Logger {static}\n    ~ cache : Map<String, Node>\n    ~ capacity : int\n    ~ end : Node\n    ~ head : Node\n    + LruCache(capacity : int)\n    + clear()\n    + contains(userId : String) : boolean\n    + get(userId : String) : UserAccount\n    + getCacheDataInListForm() : List<UserAccount>\n    + getLruData() : UserAccount\n    + invalidate(userId : String)\n    + isFull() : boolean\n    + remove(node : Node)\n    + set(userId : String, userAccount : UserAccount)\n    + setCapacity(newCapacity : int)\n    + setHead(node : Node)\n  }\n  ~class Node {\n    ~ next : Node\n    ~ previous : Node\n    ~ userAccount : UserAccount\n    ~ userId : String\n    + Node(this$0 : String, userId : UserAccount)\n  }\n  class UserAccount {\n    - additionalInfo : String\n    - userId : String\n    - userName : String\n    + UserAccount(userId : String, userName : String, additionalInfo : String)\n    + getAdditionalInfo() : String\n    + getUserId() : String\n    + getUserName() : String\n    + setAdditionalInfo(additionalInfo : String)\n    + setUserId(userId : String)\n    + setUserName(userName : String)\n    + toString() : String\n  }\n}\nNode --+ LruCache\nLruCache -->  \"-head\" Node\nNode -->  \"-previous\" Node\nAppManager -->  \"-cachingPolicy\" CachingPolicy\nNode -->  \"-userAccount\" UserAccount\nCacheStore -->  \"-cache\" LruCache\n@enduml\n"
  },
  {
    "path": "caching/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>caching</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mongodb</groupId>\n      <artifactId>bson</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.mongodb</groupId>\n      <artifactId>mongodb-driver-legacy</artifactId>\n    </dependency>\n  </dependencies>\n  <!--\n    Due to the use of MongoDB in the test of this pattern, TRAVIS and/or MAVEN might fail if the DB connection is\n    not open for the JUnit test. To avoid disrupting the compilation process, the surefire plug-in was used\n    to SKIP the running of the JUnit tests for this pattern. To ACTIVATE the running of the tests, change the\n    skipTests (below) flag to 'false' and vice-versa.\n  -->\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-surefire-plugin</artifactId>\n        <configuration>\n          <skipTests>false</skipTests>\n        </configuration>\n      </plugin>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.caching.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching;\n\nimport com.iluwatar.caching.database.DbManager;\nimport com.iluwatar.caching.database.DbManagerFactory;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Caching pattern describes how to avoid expensive re-acquisition of resources by not releasing\n * the resources immediately after their use. The resources retain their identity, are kept in some\n * fast-access storage, and are re-used to avoid having to acquire them again. There are four main\n * caching strategies/techniques in this pattern; each with their own pros and cons. They are <code>\n * write-through</code> which writes data to the cache and DB in a single transaction, <code>\n * write-around</code> which writes data immediately into the DB instead of the cache, <code>\n * write-behind</code> which writes data into the cache initially whilst the data is only written\n * into the DB when the cache is full, and <code>cache-aside</code> which pushes the responsibility\n * of keeping the data synchronized in both data sources to the application itself. The <code>\n * read-through</code> strategy is also included in the mentioned four strategies -- returns data\n * from the cache to the caller <b>if</b> it exists <b>else</b> queries from DB and stores it into\n * the cache for future use. These strategies determine when the data in the cache should be written\n * back to the backing store (i.e. Database) and help keep both data sources\n * synchronized/up-to-date. This pattern can improve performance and also helps to\n * maintainconsistency between data held in the cache and the data in the underlying data store.\n *\n * <p>In this example, the user account ({@link UserAccount}) entity is used as the underlying\n * application data. The cache itself is implemented as an internal (Java) data structure. It adopts\n * a Least-Recently-Used (LRU) strategy for evicting data from itself when its full. The four\n * strategies are individually tested. The testing of the cache is restricted towards saving and\n * querying of user accounts from the underlying data store( {@link DbManager}). The main class (\n * {@link App} is not aware of the underlying mechanics of the application (i.e. save and query) and\n * whether the data is coming from the cache or the DB (i.e. separation of concern). The AppManager\n * ({@link AppManager}) handles the transaction of data to-and-from the underlying data store\n * (depending on the preferred caching policy/strategy).\n *\n * <p><i>{@literal App --> AppManager --> CacheStore/LRUCache/CachingPolicy --> DBManager} </i>\n *\n * <p>There are 2 ways to launch the application. - to use \"in Memory\" database. - to use the\n * MongoDb as a database\n *\n * <p>To run the application with \"in Memory\" database, just launch it without parameters Example:\n * 'java -jar app.jar'\n *\n * <p>To run the application with MongoDb you need to be installed the MongoDb in your system, or to\n * launch it in the docker container. You may launch docker container from the root of current\n * module with command: 'docker-compose up' Then you can start the application with parameter\n * --mongo Example: 'java -jar app.jar --mongo'\n *\n * @see CacheStore\n * @see LruCache\n * @see CachingPolicy\n */\n@Slf4j\npublic class App {\n  /** Constant parameter name to use mongoDB. */\n  private static final String USE_MONGO_DB = \"--mongo\";\n\n  /** Application manager. */\n  private final AppManager appManager;\n\n  /**\n   * Constructor of current App.\n   *\n   * @param isMongo boolean\n   */\n  public App(final boolean isMongo) {\n    DbManager dbManager = DbManagerFactory.initDb(isMongo);\n    appManager = new AppManager(dbManager);\n    appManager.initDb();\n  }\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(final String[] args) {\n    // VirtualDB (instead of MongoDB) was used in running the JUnit tests\n    // and the App class to avoid Maven compilation errors. Set flag to\n    // true to run the tests with MongoDB (provided that MongoDB is\n    // installed and socket connection is open).\n    boolean isDbMongo = isDbMongo(args);\n    if (isDbMongo) {\n      LOGGER.info(\"Using the Mongo database engine to run the application.\");\n    } else {\n      LOGGER.info(\"Using the 'in Memory' database to run the application.\");\n    }\n    App app = new App(isDbMongo);\n    app.useReadAndWriteThroughStrategy();\n    String splitLine = \"==============================================\";\n    LOGGER.info(splitLine);\n    app.useReadThroughAndWriteAroundStrategy();\n    LOGGER.info(splitLine);\n    app.useReadThroughAndWriteBehindStrategy();\n    LOGGER.info(splitLine);\n    app.useCacheAsideStrategy();\n    LOGGER.info(splitLine);\n  }\n\n  /**\n   * Check the input parameters. if\n   *\n   * @param args input params\n   * @return true if there is \"--mongo\" parameter in arguments\n   */\n  private static boolean isDbMongo(final String[] args) {\n    for (String arg : args) {\n      if (arg.equals(USE_MONGO_DB)) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /** Read-through and write-through. */\n  public void useReadAndWriteThroughStrategy() {\n    LOGGER.info(\"# CachingPolicy.THROUGH\");\n    appManager.initCachingPolicy(CachingPolicy.THROUGH);\n\n    var userAccount1 = new UserAccount(\"001\", \"John\", \"He is a boy.\");\n\n    appManager.save(userAccount1);\n    LOGGER.info(appManager.printCacheContent());\n    appManager.find(\"001\");\n    appManager.find(\"001\");\n  }\n\n  /** Read-through and write-around. */\n  public void useReadThroughAndWriteAroundStrategy() {\n    LOGGER.info(\"# CachingPolicy.AROUND\");\n    appManager.initCachingPolicy(CachingPolicy.AROUND);\n\n    var userAccount2 = new UserAccount(\"002\", \"Jane\", \"She is a girl.\");\n\n    appManager.save(userAccount2);\n    LOGGER.info(appManager.printCacheContent());\n    appManager.find(\"002\");\n    LOGGER.info(appManager.printCacheContent());\n    userAccount2 = appManager.find(\"002\");\n    userAccount2.setUserName(\"Jane G.\");\n    appManager.save(userAccount2);\n    LOGGER.info(appManager.printCacheContent());\n    appManager.find(\"002\");\n    LOGGER.info(appManager.printCacheContent());\n    appManager.find(\"002\");\n  }\n\n  /** Read-through and write-behind. */\n  public void useReadThroughAndWriteBehindStrategy() {\n    LOGGER.info(\"# CachingPolicy.BEHIND\");\n    appManager.initCachingPolicy(CachingPolicy.BEHIND);\n\n    var userAccount3 = new UserAccount(\"003\", \"Adam\", \"He likes food.\");\n    var userAccount4 = new UserAccount(\"004\", \"Rita\", \"She hates cats.\");\n    var userAccount5 = new UserAccount(\"005\", \"Isaac\", \"He is allergic to mustard.\");\n\n    appManager.save(userAccount3);\n    appManager.save(userAccount4);\n    appManager.save(userAccount5);\n    LOGGER.info(appManager.printCacheContent());\n    appManager.find(\"003\");\n    LOGGER.info(appManager.printCacheContent());\n    UserAccount userAccount6 = new UserAccount(\"006\", \"Yasha\", \"She is an only child.\");\n    appManager.save(userAccount6);\n    LOGGER.info(appManager.printCacheContent());\n    appManager.find(\"004\");\n    LOGGER.info(appManager.printCacheContent());\n  }\n\n  /** Cache-Aside. */\n  public void useCacheAsideStrategy() {\n    LOGGER.info(\"# CachingPolicy.ASIDE\");\n    appManager.initCachingPolicy(CachingPolicy.ASIDE);\n    LOGGER.info(appManager.printCacheContent());\n\n    var userAccount3 = new UserAccount(\"003\", \"Adam\", \"He likes food.\");\n    var userAccount4 = new UserAccount(\"004\", \"Rita\", \"She hates cats.\");\n    var userAccount5 = new UserAccount(\"005\", \"Isaac\", \"He is allergic to mustard.\");\n    appManager.save(userAccount3);\n    appManager.save(userAccount4);\n    appManager.save(userAccount5);\n\n    LOGGER.info(appManager.printCacheContent());\n    appManager.find(\"003\");\n    LOGGER.info(appManager.printCacheContent());\n    appManager.find(\"004\");\n    LOGGER.info(appManager.printCacheContent());\n  }\n}\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/AppManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching;\n\nimport com.iluwatar.caching.database.DbManager;\nimport java.util.Optional;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * AppManager helps to bridge the gap in communication between the main class and the application's\n * back-end. DB connection is initialized through this class. The chosen caching strategy/policy is\n * also initialized here. Before the cache can be used, the size of the cache has to be set.\n * Depending on the chosen caching policy, AppManager will call the appropriate function in the\n * CacheStore class.\n */\n@Slf4j\npublic class AppManager {\n  /** Caching Policy. */\n  private CachingPolicy cachingPolicy;\n\n  /** Database Manager. */\n  private final DbManager dbManager;\n\n  /** Cache Store. */\n  private final CacheStore cacheStore;\n\n  /**\n   * Constructor.\n   *\n   * @param newDbManager database manager\n   */\n  public AppManager(final DbManager newDbManager) {\n    this.dbManager = newDbManager;\n    this.cacheStore = new CacheStore(newDbManager);\n  }\n\n  /**\n   * Developer/Tester is able to choose whether the application should use MongoDB as its underlying\n   * data storage or a simple Java data structure to (temporarily) store the data/objects during\n   * runtime.\n   */\n  public void initDb() {\n    dbManager.connect();\n  }\n\n  /**\n   * Initialize caching policy.\n   *\n   * @param policy is a {@link CachingPolicy}\n   */\n  public void initCachingPolicy(final CachingPolicy policy) {\n    cachingPolicy = policy;\n    if (cachingPolicy == CachingPolicy.BEHIND) {\n      Runtime.getRuntime().addShutdownHook(new Thread(cacheStore::flushCache));\n    }\n    cacheStore.clearCache();\n  }\n\n  /**\n   * Find user account.\n   *\n   * @param userId String\n   * @return {@link UserAccount}\n   */\n  public UserAccount find(final String userId) {\n    LOGGER.info(\"Trying to find {} in cache\", userId);\n    if (cachingPolicy == CachingPolicy.THROUGH || cachingPolicy == CachingPolicy.AROUND) {\n      return cacheStore.readThrough(userId);\n    } else if (cachingPolicy == CachingPolicy.BEHIND) {\n      return cacheStore.readThroughWithWriteBackPolicy(userId);\n    } else if (cachingPolicy == CachingPolicy.ASIDE) {\n      return findAside(userId);\n    }\n    return null;\n  }\n\n  /**\n   * Save user account.\n   *\n   * @param userAccount {@link UserAccount}\n   */\n  public void save(final UserAccount userAccount) {\n    LOGGER.info(\"Save record!\");\n    if (cachingPolicy == CachingPolicy.THROUGH) {\n      cacheStore.writeThrough(userAccount);\n    } else if (cachingPolicy == CachingPolicy.AROUND) {\n      cacheStore.writeAround(userAccount);\n    } else if (cachingPolicy == CachingPolicy.BEHIND) {\n      cacheStore.writeBehind(userAccount);\n    } else if (cachingPolicy == CachingPolicy.ASIDE) {\n      saveAside(userAccount);\n    }\n  }\n\n  /**\n   * Returns String.\n   *\n   * @return String\n   */\n  public String printCacheContent() {\n    return cacheStore.print();\n  }\n\n  /**\n   * Cache-Aside save user account helper.\n   *\n   * @param userAccount {@link UserAccount}\n   */\n  private void saveAside(final UserAccount userAccount) {\n    dbManager.updateDb(userAccount);\n    cacheStore.invalidate(userAccount.getUserId());\n  }\n\n  /**\n   * Cache-Aside find user account helper.\n   *\n   * @param userId String\n   * @return {@link UserAccount}\n   */\n  private UserAccount findAside(final String userId) {\n    return Optional.ofNullable(cacheStore.get(userId))\n        .or(\n            () -> {\n              Optional<UserAccount> userAccount = Optional.ofNullable(dbManager.readFromDb(userId));\n              userAccount.ifPresent(account -> cacheStore.set(userId, account));\n              return userAccount;\n            })\n        .orElse(null);\n  }\n}\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/CacheStore.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching;\n\nimport com.iluwatar.caching.database.DbManager;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.stream.Collectors;\nimport lombok.extern.slf4j.Slf4j;\n\n/** The caching strategies are implemented in this class. */\n@Slf4j\npublic class CacheStore {\n  /** Cache capacity. */\n  private static final int CAPACITY = 3;\n\n  /** Lru cache see {@link LruCache}. */\n  private LruCache cache;\n\n  /** DbManager. */\n  private final DbManager dbManager;\n\n  /**\n   * Cache Store.\n   *\n   * @param dataBaseManager {@link DbManager}\n   */\n  public CacheStore(final DbManager dataBaseManager) {\n    this.dbManager = dataBaseManager;\n    initCapacity(CAPACITY);\n  }\n\n  /**\n   * Init cache capacity.\n   *\n   * @param capacity int\n   */\n  public void initCapacity(final int capacity) {\n    if (cache == null) {\n      cache = new LruCache(capacity);\n    } else {\n      cache.setCapacity(capacity);\n    }\n  }\n\n  /**\n   * Get user account using read-through cache.\n   *\n   * @param userId {@link String}\n   * @return {@link UserAccount}\n   */\n  public UserAccount readThrough(final String userId) {\n    if (cache.contains(userId)) {\n      LOGGER.info(\"# Found in Cache!\");\n      return cache.get(userId);\n    }\n    LOGGER.info(\"# Not found in cache! Go to DB!!\");\n    UserAccount userAccount = dbManager.readFromDb(userId);\n    cache.set(userId, userAccount);\n    return userAccount;\n  }\n\n  /**\n   * Get user account using write-through cache.\n   *\n   * @param userAccount {@link UserAccount}\n   */\n  public void writeThrough(final UserAccount userAccount) {\n    if (cache.contains(userAccount.getUserId())) {\n      dbManager.updateDb(userAccount);\n    } else {\n      dbManager.writeToDb(userAccount);\n    }\n    cache.set(userAccount.getUserId(), userAccount);\n  }\n\n  /**\n   * Get user account using write-around cache.\n   *\n   * @param userAccount {@link UserAccount}\n   */\n  public void writeAround(final UserAccount userAccount) {\n    if (cache.contains(userAccount.getUserId())) {\n      dbManager.updateDb(userAccount);\n      // Cache data has been updated -- remove older\n      cache.invalidate(userAccount.getUserId());\n      // version from cache.\n    } else {\n      dbManager.writeToDb(userAccount);\n    }\n  }\n\n  /**\n   * Get user account using read-through cache with write-back policy.\n   *\n   * @param userId {@link String}\n   * @return {@link UserAccount}\n   */\n  public UserAccount readThroughWithWriteBackPolicy(final String userId) {\n    if (cache.contains(userId)) {\n      LOGGER.info(\"# Found in cache!\");\n      return cache.get(userId);\n    }\n    LOGGER.info(\"# Not found in Cache!\");\n    UserAccount userAccount = dbManager.readFromDb(userId);\n    if (cache.isFull()) {\n      LOGGER.info(\"# Cache is FULL! Writing LRU data to DB...\");\n      UserAccount toBeWrittenToDb = cache.getLruData();\n      dbManager.upsertDb(toBeWrittenToDb);\n    }\n    cache.set(userId, userAccount);\n    return userAccount;\n  }\n\n  /**\n   * Set user account.\n   *\n   * @param userAccount {@link UserAccount}\n   */\n  public void writeBehind(final UserAccount userAccount) {\n    if (cache.isFull() && !cache.contains(userAccount.getUserId())) {\n      LOGGER.info(\"# Cache is FULL! Writing LRU data to DB...\");\n      UserAccount toBeWrittenToDb = cache.getLruData();\n      dbManager.upsertDb(toBeWrittenToDb);\n    }\n    cache.set(userAccount.getUserId(), userAccount);\n  }\n\n  /** Clears cache. */\n  public void clearCache() {\n    if (cache != null) {\n      cache.clear();\n    }\n  }\n\n  /** Writes remaining content in the cache into the DB. */\n  public void flushCache() {\n    LOGGER.info(\"# flushCache...\");\n    Optional.ofNullable(cache)\n        .map(LruCache::getCacheDataInListForm)\n        .orElse(List.of())\n        .forEach(dbManager::updateDb);\n    dbManager.disconnect();\n  }\n\n  /**\n   * Print user accounts.\n   *\n   * @return {@link String}\n   */\n  public String print() {\n    return Optional.ofNullable(cache)\n        .map(LruCache::getCacheDataInListForm)\n        .orElse(List.of())\n        .stream()\n        .map(userAccount -> userAccount.toString() + \"\\n\")\n        .collect(Collectors.joining(\"\", \"\\n--CACHE CONTENT--\\n\", \"----\"));\n  }\n\n  /**\n   * Delegate to backing cache store.\n   *\n   * @param userId {@link String}\n   * @return {@link UserAccount}\n   */\n  public UserAccount get(final String userId) {\n    return cache.get(userId);\n  }\n\n  /**\n   * Delegate to backing cache store.\n   *\n   * @param userId {@link String}\n   * @param userAccount {@link UserAccount}\n   */\n  public void set(final String userId, final UserAccount userAccount) {\n    cache.set(userId, userAccount);\n  }\n\n  /**\n   * Delegate to backing cache store.\n   *\n   * @param userId {@link String}\n   */\n  public void invalidate(final String userId) {\n    cache.invalidate(userId);\n  }\n}\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/CachingPolicy.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\n/** Enum class containing the four caching strategies implemented in the pattern. */\n@AllArgsConstructor\n@Getter\npublic enum CachingPolicy {\n  /** Through. */\n  THROUGH(\"through\"),\n  /** AROUND. */\n  AROUND(\"around\"),\n  /** BEHIND. */\n  BEHIND(\"behind\"),\n  /** ASIDE. */\n  ASIDE(\"aside\");\n\n  /** Policy value. */\n  private final String policy;\n}\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/LruCache.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Data structure/implementation of the application's cache. The data structure consists of a hash\n * table attached with a doubly linked-list. The linked-list helps in capturing and maintaining the\n * LRU data in the cache. When a data is queried (from the cache), added (to the cache), or updated,\n * the data is moved to the front of the list to depict itself as the most-recently-used data. The\n * LRU data is always at the end of the list.\n */\n@Slf4j\npublic class LruCache {\n  /** Static class Node. */\n  static class Node {\n    /** user id. */\n    private final String userId;\n\n    /** User Account. */\n    private UserAccount userAccount;\n\n    /** previous. */\n    private Node previous;\n\n    /** next. */\n    private Node next;\n\n    /**\n     * Node definition.\n     *\n     * @param id String\n     * @param account {@link UserAccount}\n     */\n    Node(final String id, final UserAccount account) {\n      this.userId = id;\n      this.userAccount = account;\n    }\n  }\n\n  /** Capacity of Cache. */\n  private int capacity;\n\n  /** Cache {@link HashMap}. */\n  private Map<String, Node> cache = new HashMap<>();\n\n  /** Head. */\n  private Node head;\n\n  /** End. */\n  private Node end;\n\n  /**\n   * Constructor.\n   *\n   * @param cap Integer.\n   */\n  public LruCache(final int cap) {\n    this.capacity = cap;\n  }\n\n  /**\n   * Get user account.\n   *\n   * @param userId String\n   * @return {@link UserAccount}\n   */\n  public UserAccount get(final String userId) {\n    if (cache.containsKey(userId)) {\n      var node = cache.get(userId);\n      remove(node);\n      setHead(node);\n      return node.userAccount;\n    }\n    return null;\n  }\n\n  /**\n   * Remove node from linked list.\n   *\n   * @param node {@link Node}\n   */\n  public void remove(final Node node) {\n    if (node.previous != null) {\n      node.previous.next = node.next;\n    } else {\n      head = node.next;\n    }\n    if (node.next != null) {\n      node.next.previous = node.previous;\n    } else {\n      end = node.previous;\n    }\n  }\n\n  /**\n   * Move node to the front of the list.\n   *\n   * @param node {@link Node}\n   */\n  public void setHead(final Node node) {\n    node.next = head;\n    node.previous = null;\n    if (head != null) {\n      head.previous = node;\n    }\n    head = node;\n    if (end == null) {\n      end = head;\n    }\n  }\n\n  /**\n   * Set user account.\n   *\n   * @param userAccount {@link UserAccount}\n   * @param userId {@link String}\n   */\n  public void set(final String userId, final UserAccount userAccount) {\n    if (cache.containsKey(userId)) {\n      var old = cache.get(userId);\n      old.userAccount = userAccount;\n      remove(old);\n      setHead(old);\n    } else {\n      var newNode = new Node(userId, userAccount);\n      if (cache.size() >= capacity) {\n        LOGGER.info(\"# Cache is FULL! Removing {} from cache...\", end.userId);\n        cache.remove(end.userId); // remove LRU data from cache.\n        remove(end);\n        setHead(newNode);\n      } else {\n        setHead(newNode);\n      }\n      cache.put(userId, newNode);\n    }\n  }\n\n  /**\n   * Check if Cache contains the userId.\n   *\n   * @param userId {@link String}\n   * @return boolean\n   */\n  public boolean contains(final String userId) {\n    return cache.containsKey(userId);\n  }\n\n  /**\n   * Invalidate cache for user.\n   *\n   * @param userId {@link String}\n   */\n  public void invalidate(final String userId) {\n    var toBeRemoved = cache.remove(userId);\n    if (toBeRemoved != null) {\n      LOGGER.info(\"# {} has been updated! \" + \"Removing older version from cache...\", userId);\n      remove(toBeRemoved);\n    }\n  }\n\n  /**\n   * Check if the cache is full.\n   *\n   * @return boolean\n   */\n  public boolean isFull() {\n    return cache.size() >= capacity;\n  }\n\n  /**\n   * Get LRU data.\n   *\n   * @return {@link UserAccount}\n   */\n  public UserAccount getLruData() {\n    return end.userAccount;\n  }\n\n  /** Clear cache. */\n  public void clear() {\n    head = null;\n    end = null;\n    cache.clear();\n  }\n\n  /**\n   * Returns cache data in list form.\n   *\n   * @return {@link List}\n   */\n  public List<UserAccount> getCacheDataInListForm() {\n    var listOfCacheData = new ArrayList<UserAccount>();\n    var temp = head;\n    while (temp != null) {\n      listOfCacheData.add(temp.userAccount);\n      temp = temp.next;\n    }\n    return listOfCacheData;\n  }\n\n  /**\n   * Set cache capacity.\n   *\n   * @param newCapacity int\n   */\n  public void setCapacity(final int newCapacity) {\n    if (capacity > newCapacity) {\n      // Behavior can be modified to accommodate\n      // for decrease in cache size. For now, we'll\n      clear();\n      // just clear the cache.\n    } else {\n      this.capacity = newCapacity;\n    }\n  }\n}\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/UserAccount.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.ToString;\n\n/** Entity class (stored in cache and DB) used in the application. */\n@Data\n@AllArgsConstructor\n@ToString\n@EqualsAndHashCode\npublic class UserAccount {\n  /** User Id. */\n  private String userId;\n\n  /** User Name. */\n  private String userName;\n\n  /** Additional Info. */\n  private String additionalInfo;\n}\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/constants/CachingConstants.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching.constants;\n\n/** Constant class for defining constants. */\npublic final class CachingConstants {\n  /** User Account. */\n  public static final String USER_ACCOUNT = \"user_accounts\";\n\n  /** User ID. */\n  public static final String USER_ID = \"userID\";\n\n  /** User Name. */\n  public static final String USER_NAME = \"userName\";\n\n  /** Additional Info. */\n  public static final String ADD_INFO = \"additionalInfo\";\n\n  /** Constructor. */\n  private CachingConstants() {}\n}\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/constants/package-info.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/** Constants. */\npackage com.iluwatar.caching.constants;\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/database/DbManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching.database;\n\nimport com.iluwatar.caching.UserAccount;\n\n/**\n * DBManager handles the communication with the underlying data store i.e. Database. It contains the\n * implemented methods for querying, inserting, and updating data. MongoDB was used as the database\n * for the application.\n */\npublic interface DbManager {\n  /** Connect to DB. */\n  void connect();\n\n  /** Disconnect from DB. */\n  void disconnect();\n\n  /**\n   * Read from DB.\n   *\n   * @param userId {@link String}\n   * @return {@link UserAccount}\n   */\n  UserAccount readFromDb(String userId);\n\n  /**\n   * Write to DB.\n   *\n   * @param userAccount {@link UserAccount}\n   * @return {@link UserAccount}\n   */\n  UserAccount writeToDb(UserAccount userAccount);\n\n  /**\n   * Update record.\n   *\n   * @param userAccount {@link UserAccount}\n   * @return {@link UserAccount}\n   */\n  UserAccount updateDb(UserAccount userAccount);\n\n  /**\n   * Update record or Insert if not exists.\n   *\n   * @param userAccount {@link UserAccount}\n   * @return {@link UserAccount}\n   */\n  UserAccount upsertDb(UserAccount userAccount);\n}\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/database/DbManagerFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching.database;\n\n/** Creates the database connection according the input parameter. */\npublic final class DbManagerFactory {\n  /** Private constructor. */\n  private DbManagerFactory() {}\n\n  /**\n   * Init database.\n   *\n   * @param isMongo boolean\n   * @return {@link DbManager}\n   */\n  public static DbManager initDb(final boolean isMongo) {\n    if (isMongo) {\n      return new MongoDb();\n    }\n    return new VirtualDb();\n  }\n}\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/database/MongoDb.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching.database;\n\nimport static com.iluwatar.caching.constants.CachingConstants.ADD_INFO;\nimport static com.iluwatar.caching.constants.CachingConstants.USER_ACCOUNT;\nimport static com.iluwatar.caching.constants.CachingConstants.USER_ID;\nimport static com.iluwatar.caching.constants.CachingConstants.USER_NAME;\n\nimport com.iluwatar.caching.UserAccount;\nimport com.iluwatar.caching.constants.CachingConstants;\nimport com.mongodb.MongoClient;\nimport com.mongodb.MongoClientOptions;\nimport com.mongodb.MongoCredential;\nimport com.mongodb.ServerAddress;\nimport com.mongodb.client.MongoDatabase;\nimport com.mongodb.client.model.UpdateOptions;\nimport lombok.extern.slf4j.Slf4j;\nimport org.bson.Document;\n\n/** Implementation of DatabaseManager. implements base methods to work with MongoDb. */\n@Slf4j\npublic class MongoDb implements DbManager {\n  private static final String DATABASE_NAME = \"admin\";\n  private static final String MONGO_USER = \"root\";\n  private static final String MONGO_PASSWORD = \"rootpassword\";\n  private MongoClient client;\n  private MongoDatabase db;\n\n  void setDb(MongoDatabase db) {\n    this.db = db;\n  }\n\n  /** Connect to Db. Check th connection */\n  @Override\n  public void connect() {\n    MongoCredential mongoCredential =\n        MongoCredential.createCredential(MONGO_USER, DATABASE_NAME, MONGO_PASSWORD.toCharArray());\n    MongoClientOptions options = MongoClientOptions.builder().build();\n    client = new MongoClient(new ServerAddress(), mongoCredential, options);\n    db = client.getDatabase(DATABASE_NAME);\n  }\n\n  @Override\n  public void disconnect() {\n    client.close();\n  }\n\n  /**\n   * Read data from DB.\n   *\n   * @param userId {@link String}\n   * @return {@link UserAccount}\n   */\n  @Override\n  public UserAccount readFromDb(final String userId) {\n    var iterable =\n        db.getCollection(CachingConstants.USER_ACCOUNT).find(new Document(USER_ID, userId));\n    if (iterable.first() == null) {\n      return null;\n    }\n    Document doc = iterable.first();\n    if (doc != null) {\n      String userName = doc.getString(USER_NAME);\n      String appInfo = doc.getString(ADD_INFO);\n      return new UserAccount(userId, userName, appInfo);\n    } else {\n      return null;\n    }\n  }\n\n  /**\n   * Write data to DB.\n   *\n   * @param userAccount {@link UserAccount}\n   * @return {@link UserAccount}\n   */\n  @Override\n  public UserAccount writeToDb(final UserAccount userAccount) {\n    db.getCollection(USER_ACCOUNT)\n        .insertOne(\n            new Document(USER_ID, userAccount.getUserId())\n                .append(USER_NAME, userAccount.getUserName())\n                .append(ADD_INFO, userAccount.getAdditionalInfo()));\n    return userAccount;\n  }\n\n  /**\n   * Update DB.\n   *\n   * @param userAccount {@link UserAccount}\n   * @return {@link UserAccount}\n   */\n  @Override\n  public UserAccount updateDb(final UserAccount userAccount) {\n    Document id = new Document(USER_ID, userAccount.getUserId());\n    Document dataSet =\n        new Document(USER_NAME, userAccount.getUserName())\n            .append(ADD_INFO, userAccount.getAdditionalInfo());\n    db.getCollection(CachingConstants.USER_ACCOUNT).updateOne(id, new Document(\"$set\", dataSet));\n    return userAccount;\n  }\n\n  /**\n   * Update data if exists.\n   *\n   * @param userAccount {@link UserAccount}\n   * @return {@link UserAccount}\n   */\n  @Override\n  public UserAccount upsertDb(final UserAccount userAccount) {\n    String userId = userAccount.getUserId();\n    String userName = userAccount.getUserName();\n    String additionalInfo = userAccount.getAdditionalInfo();\n    db.getCollection(CachingConstants.USER_ACCOUNT)\n        .updateOne(\n            new Document(USER_ID, userId),\n            new Document(\n                \"$set\",\n                new Document(USER_ID, userId)\n                    .append(USER_NAME, userName)\n                    .append(ADD_INFO, additionalInfo)),\n            new UpdateOptions().upsert(true));\n    return userAccount;\n  }\n}\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/database/VirtualDb.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching.database;\n\nimport com.iluwatar.caching.UserAccount;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/** Implementation of DatabaseManager. implements base methods to work with hashMap as database. */\npublic class VirtualDb implements DbManager {\n  /** Virtual DataBase. */\n  private Map<String, UserAccount> db;\n\n  /** Creates new HashMap. */\n  @Override\n  public void connect() {\n    db = new HashMap<>();\n  }\n\n  @Override\n  public void disconnect() {\n    db = null;\n  }\n\n  /**\n   * Read from Db.\n   *\n   * @param userId {@link String}\n   * @return {@link UserAccount}\n   */\n  @Override\n  public UserAccount readFromDb(final String userId) {\n    if (db.containsKey(userId)) {\n      return db.get(userId);\n    }\n    return null;\n  }\n\n  /**\n   * Write to DB.\n   *\n   * @param userAccount {@link UserAccount}\n   * @return {@link UserAccount}\n   */\n  @Override\n  public UserAccount writeToDb(final UserAccount userAccount) {\n    db.put(userAccount.getUserId(), userAccount);\n    return userAccount;\n  }\n\n  /**\n   * Update reecord in DB.\n   *\n   * @param userAccount {@link UserAccount}\n   * @return {@link UserAccount}\n   */\n  @Override\n  public UserAccount updateDb(final UserAccount userAccount) {\n    return writeToDb(userAccount);\n  }\n\n  /**\n   * Update.\n   *\n   * @param userAccount {@link UserAccount}\n   * @return {@link UserAccount}\n   */\n  @Override\n  public UserAccount upsertDb(final UserAccount userAccount) {\n    return updateDb(userAccount);\n  }\n}\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/database/package-info.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/** Database classes. */\npackage com.iluwatar.caching.database;\n"
  },
  {
    "path": "caching/src/main/java/com/iluwatar/caching/package-info.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching;\n"
  },
  {
    "path": "caching/src/test/java/com/iluwatar/caching/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Caching example runs without errors. */\nclass AppTest {\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "caching/src/test/java/com/iluwatar/caching/CachingTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass CachingTest {\n  private App app;\n\n  /** Setup of application test includes: initializing DB connection and cache size/capacity. */\n  @BeforeEach\n  void setUp() {\n    // VirtualDB (instead of MongoDB) was used in running the JUnit tests\n    // to avoid Maven compilation errors. Set flag to true to run the\n    // tests with MongoDB (provided that MongoDB is installed and socket\n    // connection is open).\n    app = new App(false);\n  }\n\n  @Test\n  void testReadAndWriteThroughStrategy() {\n    assertNotNull(app);\n    app.useReadAndWriteThroughStrategy();\n  }\n\n  @Test\n  void testReadThroughAndWriteAroundStrategy() {\n    assertNotNull(app);\n    app.useReadThroughAndWriteAroundStrategy();\n  }\n\n  @Test\n  void testReadThroughAndWriteBehindStrategy() {\n    assertNotNull(app);\n    app.useReadThroughAndWriteBehindStrategy();\n  }\n\n  @Test\n  void testCacheAsideStrategy() {\n    assertNotNull(app);\n    app.useCacheAsideStrategy();\n  }\n}\n"
  },
  {
    "path": "caching/src/test/java/com/iluwatar/caching/database/MongoDbTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.caching.database;\n\nimport static com.iluwatar.caching.constants.CachingConstants.ADD_INFO;\nimport static com.iluwatar.caching.constants.CachingConstants.USER_ID;\nimport static com.iluwatar.caching.constants.CachingConstants.USER_NAME;\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.*;\n\nimport com.iluwatar.caching.UserAccount;\nimport com.iluwatar.caching.constants.CachingConstants;\nimport com.mongodb.client.FindIterable;\nimport com.mongodb.client.MongoCollection;\nimport com.mongodb.client.MongoDatabase;\nimport org.bson.Document;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mock;\n\nclass MongoDbTest {\n  private static final String ID = \"123\";\n  private static final String NAME = \"Some user\";\n  private static final String ADDITIONAL_INFO = \"Some app Info\";\n\n  @Mock MongoDatabase db;\n  private MongoDb mongoDb = new MongoDb();\n\n  private UserAccount userAccount;\n\n  @BeforeEach\n  void init() {\n    db = mock(MongoDatabase.class);\n    mongoDb.setDb(db);\n    userAccount = new UserAccount(ID, NAME, ADDITIONAL_INFO);\n  }\n\n  @Test\n  void connect() {\n    assertDoesNotThrow(() -> mongoDb.connect());\n  }\n\n  @Test\n  void readFromDb() {\n    Document document =\n        new Document(USER_ID, ID).append(USER_NAME, NAME).append(ADD_INFO, ADDITIONAL_INFO);\n    MongoCollection<Document> mongoCollection = mock(MongoCollection.class);\n    when(db.getCollection(CachingConstants.USER_ACCOUNT)).thenReturn(mongoCollection);\n\n    FindIterable<Document> findIterable = mock(FindIterable.class);\n    when(mongoCollection.find(any(Document.class))).thenReturn(findIterable);\n\n    when(findIterable.first()).thenReturn(document);\n\n    assertEquals(mongoDb.readFromDb(ID), userAccount);\n  }\n\n  @Test\n  void writeToDb() {\n    MongoCollection<Document> mongoCollection = mock(MongoCollection.class);\n    when(db.getCollection(CachingConstants.USER_ACCOUNT)).thenReturn(mongoCollection);\n    assertDoesNotThrow(\n        () -> {\n          mongoDb.writeToDb(userAccount);\n        });\n  }\n\n  @Test\n  void updateDb() {\n    MongoCollection<Document> mongoCollection = mock(MongoCollection.class);\n    when(db.getCollection(CachingConstants.USER_ACCOUNT)).thenReturn(mongoCollection);\n    assertDoesNotThrow(\n        () -> {\n          mongoDb.updateDb(userAccount);\n        });\n  }\n\n  @Test\n  void upsertDb() {\n    MongoCollection<Document> mongoCollection = mock(MongoCollection.class);\n    when(db.getCollection(CachingConstants.USER_ACCOUNT)).thenReturn(mongoCollection);\n    assertDoesNotThrow(\n        () -> {\n          mongoDb.upsertDb(userAccount);\n        });\n  }\n}\n"
  },
  {
    "path": "callback/README.md",
    "content": "---\ntitle: \"Callback Pattern in Java: Mastering Asynchronous Communication\"\nshortTitle: Callback\ndescription: \"Learn about the Java Callback Design Pattern, including its intent, usage scenarios, benefits, trade-offs, and real-world examples. Understand how to implement and effectively use callbacks in your Java applications.\"\ncategory: Functional\nlanguage: en\ntag:\n  - Asynchronous\n  - Decoupling\n  - Idiom\n  - Reactive\n---\n\n## Also known as\n\n* Call-After\n* Event-Subscription\n* Listener\n\n## Intent of Callback Design Pattern\n\nThe Java Callback Design Pattern is a piece of executable code passed as an argument to other code, which is expected to call back (execute) the argument at a convenient time.\n\n## Detailed Explanation of Callback Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy for the Callback design pattern can be found in the restaurant industry. Imagine a situation where you place an order at a busy restaurant. Instead of waiting at the counter for your food to be ready, you provide the cashier with your phone number. Once your order is prepared, the kitchen staff calls or sends a text message to notify you that your meal is ready for pickup.\n>\n> In this analogy, placing your order is analogous to initiating an asynchronous task. Providing your phone number is akin to passing a callback function. The kitchen preparing your order represents the asynchronous processing, and the notification you receive is the callback being executed, allowing you to retrieve your meal without having to wait idly. This separation of task initiation and task completion is the essence of the Callback design pattern.\n\nIn plain words\n\n> Callback is a method passed to an executor which will be called at a defined moment.\n\nWikipedia says\n\n> In computer programming, a callback, also known as a \"call-after\" function, is any executable code that is passed as an argument to other code; that other code is expected to call back (execute) the argument at a given time.\n\nSequence diagram\n\n![Callback sequence diagram](./etc/callback-sequence-diagram.png)\n\n## Programmatic Example of Callback Pattern in Java\n\nWe need to be notified after the executing task has finished. We pass a callback method for the executor and wait for it to call back on us.\n\n`Callback` is a simple interface with single method.\n\n```java\npublic interface Callback {\n\n    void call();\n}\n```\n\nNext we define `Task` that will execute the callback after the task execution has finished.\n\n```java\npublic abstract class Task {\n\n    final void executeWith(Callback callback) {\n        execute();\n        Optional.ofNullable(callback).ifPresent(Callback::call);\n    }\n\n    public abstract void execute();\n}\n\n@Slf4j\npublic final class SimpleTask extends Task {\n\n    @Override\n    public void execute() {\n        LOGGER.info(\"Perform some important activity and after call the callback method.\");\n    }\n}\n```\n\nFinally, here's how we execute a task and receive a callback when it's finished.\n\n```java\npublic static void main(final String[] args) {\n    var task = new SimpleTask();\n    task.executeWith(() -> LOGGER.info(\"I'm done now.\"));\n}\n```\n\nProgram output:\n\n```\n17:12:11.680 [main] INFO com.iluwatar.callback.SimpleTask -- Perform some important activity and after call the callback method.\n17:12:11.682 [main] INFO com.iluwatar.callback.App -- I'm done now.\n```\n\n## When to Use the Callback Pattern in Java\n\nUse the Callback pattern when\n\n* Asynchronous event handling in GUI applications or event-driven systems\n* Implementing notification mechanisms where certain events need to trigger actions in other components.\n* Decoupling modules or components that need to interact without having a direct dependency on each other\n\n## Real-World Applications of Callback Pattern in Java\n\n* GUI frameworks often use callbacks for event handling, such as user interactions (clicks, key presses)\n* Node.js heavily relies on callbacks for non-blocking I/O operations\n* Frameworks that deal with asynchronous operations, like Promises in JavaScript, use callbacks to handle the resolution or rejection of asynchronous tasks\n* [CyclicBarrier](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29) constructor can accept a callback that will be triggered every time a barrier is tripped.\n\n## Benefits and Trade-offs of Callback Pattern\n\nBenefits:\n\n* Decouples the execution logic of an operation from the signaling or notification logic, enhancing modularity and reusability\n* Facilitates asynchronous processing, improving the responsiveness and scalability of applications\n* Enables a reactive programming model where components can react to events as they occur\n\nTrade-offs:\n\n* Callback hell or pyramid of doom: Deeply nested callbacks can lead to code that is hard to read and maintain\n* Inversion of control can lead to harder-to-follow code flow, making debugging more challenging\n* Potential issues with error handling, especially in languages or environments where exceptions are used, as errors might need to be propagated through callbacks\n\n## Related Java Design Patterns\n\n* [Command](https://java-design-patterns.com/patterns/command/): Callbacks can be implemented as Command objects in scenarios where more flexibility or statefulness is required in the callback operation\n* [Observer](https://java-design-patterns.com/patterns/observer/): Callbacks can be seen as a more dynamic and lightweight form of the Observer pattern, with the ability to subscribe and unsubscribe callback functions dynamically\n* [Promise](https://java-design-patterns.com/patterns/promise/): In some languages or frameworks, Promises or Futures can be used to handle asynchronous operations more cleanly, often using callbacks for success or failure cases\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n"
  },
  {
    "path": "callback/etc/callback.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <interface id=\"1\" language=\"java\" name=\"com.iluwatar.callback.Callback\" project=\"callback\" \n    file=\"/callback/src/main/java/com/iluwatar/callback/Callback.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"204\" y=\"292\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.callback.SimpleTask\" project=\"callback\" \n    file=\"/callback/src/main/java/com/iluwatar/callback/SimpleTask.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"380\" y=\"464\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.callback.Task\" project=\"callback\" \n    file=\"/callback/src/main/java/com/iluwatar/callback/Task.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"380\" y=\"309\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <generalization id=\"4\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </generalization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "callback/etc/callback.urm.puml",
    "content": "@startuml\npackage com.iluwatar.callback {\n  class App {\n    - LOGGER : Logger {static}\n    - App()\n    + main(args : String[]) {static}\n  }\n  interface Callback {\n    + call() {abstract}\n  }\n  class SimpleTask {\n    - LOGGER : Logger {static}\n    + SimpleTask()\n    + execute()\n  }\n  abstract class Task {\n    + Task()\n    + execute() {abstract}\n    ~ executeWith(callback : Callback)\n  }\n}\nSimpleTask --|> Task \n@enduml"
  },
  {
    "path": "callback/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>callback</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.callback.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "callback/src/main/java/com/iluwatar/callback/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.callback;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Callback pattern is more native for functional languages where functions are treated as\n * first-class citizens. Prior to Java 8 callbacks can be simulated using simple (alike command)\n * interfaces.\n */\n@Slf4j\npublic final class App {\n\n  private App() {}\n\n  /** Program entry point. */\n  public static void main(final String[] args) {\n    var task = new SimpleTask();\n    task.executeWith(() -> LOGGER.info(\"I'm done now.\"));\n  }\n}\n"
  },
  {
    "path": "callback/src/main/java/com/iluwatar/callback/Callback.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.callback;\n\n/** Callback interface. */\npublic interface Callback {\n\n  void call();\n}\n"
  },
  {
    "path": "callback/src/main/java/com/iluwatar/callback/SimpleTask.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.callback;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Implementation of task that need to be executed. */\n@Slf4j\npublic final class SimpleTask extends Task {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"Perform some important activity and after call the callback method.\");\n  }\n}\n"
  },
  {
    "path": "callback/src/main/java/com/iluwatar/callback/Task.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.callback;\n\nimport java.util.Optional;\n\n/** Template-method class for callback hook execution. */\npublic abstract class Task {\n\n  /** Execute with callback. */\n  final void executeWith(Callback callback) {\n    execute();\n    Optional.ofNullable(callback).ifPresent(Callback::call);\n  }\n\n  public abstract void execute();\n}\n"
  },
  {
    "path": "callback/src/main/java/com/iluwatar/callback/package-info.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.callback;\n"
  },
  {
    "path": "callback/src/test/java/com/iluwatar/callback/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.callback;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Callback example runs without errors. */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "callback/src/test/java/com/iluwatar/callback/CallbackTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.callback;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/**\n * Add a field as a counter. Every time the callback method is called increment this field. Unit\n * test checks that the field is being incremented.\n *\n * <p>Could be done with mock objects as well where the call method call is verified.\n */\nclass CallbackTest {\n\n  private Integer callingCount = 0;\n\n  @Test\n  void test() {\n    Callback callback = () -> callingCount++;\n\n    var task = new SimpleTask();\n\n    assertEquals(Integer.valueOf(0), callingCount, \"Initial calling count of 0\");\n\n    task.executeWith(callback);\n\n    assertEquals(Integer.valueOf(1), callingCount, \"Callback called once\");\n\n    task.executeWith(callback);\n\n    assertEquals(Integer.valueOf(2), callingCount, \"Callback called twice\");\n  }\n}\n"
  },
  {
    "path": "chain-of-responsibility/README.md",
    "content": "---\ntitle: \"Chain of Responsibility Pattern in Java: Building Robust Request Handling Mechanisms\"\nshortTitle: Chain of Responsibility\ndescription: \"Learn the Chain of Responsibility design pattern in Java with real-world examples, code snippets, and class diagrams. Enhance your coding skills with our detailed explanations.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Decoupling\n  - Event-driven\n  - Gang of Four\n  - Messaging\n---\n\n## Also known as\n\n* Chain of Command\n* Chain of Objects\n* Responsibility Chain\n\n## Intent of Chain of Responsibility Design Pattern\n\nThe Chain of Responsibility pattern in Java is a behavioral design pattern that decouples the sender of a request from its receivers by giving more than one object a chance to handle the request. The receiving objects are chained and the request is passed along the chain until an object handles it.\n\n## Detailed Explanation of Chain of Responsibility Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world example of the Chain of Responsibility pattern in Java is a technical support call center. When implementing this Java design pattern, each level of support represents a handler in the chain. When a customer calls in with an issue, the call is first received by a front-line support representative. If the issue is simple, the representative handles it directly. If the issue is more complex, the representative forwards the call to a second-level support technician. This process continues, with the call being escalated through multiple levels of support until it reaches a specialist who can resolve the problem. Each level of support represents a handler in the chain, and the call is passed along the chain until it finds an appropriate handler, thereby decoupling the request from the specific receiver.\n\nIn plain words\n\n> It helps to build a chain of objects. A request enters from one end and keeps going from an object to another until it finds a suitable handler.\n\nWikipedia says\n\n> In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain.\n\nFlowchart\n\n![Chain of Responsibility flowchart](./etc/chain-of-responsibility-flowchart.png)\n\n## Programmatic Example of Chain of Responsibility Pattern\n\nIn this Java example, the Orc King gives orders which are processed by a chain of command representing the Chain of Responsibility pattern. Learn how to implement this design pattern in Java with the following code snippet.\n\nThe Orc King gives loud orders to his army. The closest one to react is the commander, then an officer, and then a soldier. The commander, officer, and soldier form a chain of responsibility.\n\nFirst, we have the `Request` class:\n\n```java\n@Getter\npublic class Request {\n\n    private final RequestType requestType;\n    private final String requestDescription;\n    private boolean handled;\n\n    public Request(final RequestType requestType, final String requestDescription) {\n        this.requestType = Objects.requireNonNull(requestType);\n        this.requestDescription = Objects.requireNonNull(requestDescription);\n    }\n\n    public void markHandled() {\n        this.handled = true;\n    }\n\n    @Override\n    public String toString() {\n        return getRequestDescription();\n    }\n}\n\npublic enum RequestType {\n    DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX\n}\n```\n\nNext, we show the `RequestHandler` hierarchy.\n\n```java\npublic interface RequestHandler {\n\n    boolean canHandleRequest(Request req);\n\n    int getPriority();\n\n    void handle(Request req);\n\n    String name();\n}\n\n@Slf4j\npublic class OrcCommander implements RequestHandler {\n    @Override\n    public boolean canHandleRequest(Request req) {\n        return req.getRequestType() == RequestType.DEFEND_CASTLE;\n    }\n\n    @Override\n    public int getPriority() {\n        return 2;\n    }\n\n    @Override\n    public void handle(Request req) {\n        req.markHandled();\n        LOGGER.info(\"{} handling request \\\"{}\\\"\", name(), req);\n    }\n\n    @Override\n    public String name() {\n        return \"Orc commander\";\n    }\n}\n\n// OrcOfficer and OrcSoldier are defined similarly as OrcCommander ...\n\n```\n\nThe `OrcKing` gives the orders and forms the chain.\n\n```java\npublic class OrcKing {\n\n    private List<RequestHandler> handlers;\n\n    public OrcKing() {\n        buildChain();\n    }\n\n    private void buildChain() {\n        handlers = Arrays.asList(new OrcCommander(), new OrcOfficer(), new OrcSoldier());\n    }\n\n    public void makeRequest(Request req) {\n        handlers\n                .stream()\n                .sorted(Comparator.comparing(RequestHandler::getPriority))\n                .filter(handler -> handler.canHandleRequest(req))\n                .findFirst()\n                .ifPresent(handler -> handler.handle(req));\n    }\n}\n```\n\nThe chain of responsibility in action.\n\n```java\n  public static void main(String[] args) {\n\n    var king = new OrcKing();\n    king.makeRequest(new Request(RequestType.DEFEND_CASTLE, \"defend castle\"));\n    king.makeRequest(new Request(RequestType.TORTURE_PRISONER, \"torture prisoner\"));\n    king.makeRequest(new Request(RequestType.COLLECT_TAX, \"collect tax\"));\n}\n```\n\nThe console output:\n\n```\nOrc commander handling request \"defend castle\"\nOrc officer handling request \"torture prisoner\"\nOrc soldier handling request \"collect tax\"\n```\n\n## When to Use the Chain of Responsibility Pattern in Java\n\nUse Chain of Responsibility when\n\n* More than one object may handle a request, and the handler isn't known a priori. The handler should be ascertained automatically.\n* You want to issue a request to one of several objects without specifying the receiver explicitly.\n* The set of objects that can handle a request should be specified dynamically.\n\n## Real-World Applications of Chain of Responsibility Pattern in Java\n\n* Event bubbling in GUI frameworks where an event might be handled at multiple levels of a UI component hierarchy\n* Middleware frameworks where a request passes through a chain of processing objects\n* Logging frameworks where messages can be passed through a series of loggers, each possibly handling them differently\n* [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29)\n* [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html)\n* [javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-)\n\n## Benefits and Trade-offs of Chain of Responsibility Pattern\n\nBenefits:\n\n* Reduced coupling. The sender of a request does not need to know the concrete handler that will process the request.\n* Increased flexibility in assigning responsibilities to objects. You can add or change responsibilities for handling a request by changing the members and order of the chain.\n* Allows you to set a default handler if no concrete handler can handle the request.\n\nTrade-Offs:\n\n* It can be challenging to debug and understand the flow, especially if the chain is long and complex.\n* The request might end up unhandled if the chain doesn't include a catch-all handler.\n* Performance concerns might arise due to potentially going through several handlers before finding the right one, or not finding it at all.\n\n## Related Java Design Patterns\n\n* [Command](https://java-design-patterns.com/patterns/command/): can be used to encapsulate a request as an object, which might be passed along the chain.\n* [Composite](https://java-design-patterns.com/patterns/composite/): the Chain of Responsibility is often applied in conjunction with the Composite pattern.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): decorators can be chained in a similar manner as responsibilities in the Chain of Responsibility pattern.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/3PAJUg5)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n* [Pattern languages of program design 3](https://amzn.to/4a4NxTH)\n"
  },
  {
    "path": "chain-of-responsibility/etc/chain-of-responsibility.urm.puml",
    "content": "@startuml\npackage com.iluwatar.chain {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class OrcCommander {\n    - LOGGER : Logger {static}\n    + OrcCommander()\n    + canHandleRequest(req : Request) : boolean\n    + getPriority() : int\n    + handle(req : Request)\n    + name() : String\n  }\n  class OrcKing {\n    - handlers : List<RequestHandler>\n    + OrcKing()\n    - buildChain()\n    + makeRequest(req : Request)\n  }\n  class OrcOfficer {\n    - LOGGER : Logger {static}\n    + OrcOfficer()\n    + canHandleRequest(req : Request) : boolean\n    + getPriority() : int\n    + handle(req : Request)\n    + name() : String\n  }\n  class OrcSoldier {\n    - LOGGER : Logger {static}\n    + OrcSoldier()\n    + canHandleRequest(req : Request) : boolean\n    + getPriority() : int\n    + handle(req : Request)\n    + name() : String\n  }\n  class Request {\n    - handled : boolean\n    - requestDescription : String\n    - requestType : RequestType\n    + Request(requestType : RequestType, requestDescription : String)\n    + getRequestDescription() : String\n    + getRequestType() : RequestType\n    + isHandled() : boolean\n    + markHandled()\n    + toString() : String\n  }\n  interface RequestHandler {\n    + canHandleRequest(Request) : boolean {abstract}\n    + getPriority() : int {abstract}\n    + handle(Request) {abstract}\n    + name() : String {abstract}\n  }\n  enum RequestType {\n    + COLLECT_TAX {static}\n    + DEFEND_CASTLE {static}\n    + TORTURE_PRISONER {static}\n    + valueOf(name : String) : RequestType {static}\n    + values() : RequestType[] {static}\n  }\n}\nOrcKing -->  \"-handlers\" RequestHandler\nRequest -->  \"-requestType\" RequestType\nOrcCommander ..|> RequestHandler \nOrcOfficer ..|> RequestHandler \nOrcSoldier ..|> RequestHandler \n@enduml"
  },
  {
    "path": "chain-of-responsibility/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>chain-of-responsibility</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.chain.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "chain-of-responsibility/src/main/java/com/iluwatar/chain/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.chain;\n\n/**\n * The Chain of Responsibility pattern is a design pattern consisting of command objects and a\n * series of processing objects. Each processing object contains logic that defines the types of\n * command objects that it can handle; the rest are passed to the next processing object in the\n * chain. A mechanism also exists for adding new processing objects to the end of this chain.\n *\n * <p>In this example we organize the request handlers ({@link RequestHandler}) into a chain where\n * each handler has a chance to act on the request on its turn. Here the king ({@link OrcKing})\n * makes requests and the military orcs ({@link OrcCommander}, {@link OrcOfficer}, {@link\n * OrcSoldier}) form the handler chain.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var king = new OrcKing();\n    king.makeRequest(new Request(RequestType.DEFEND_CASTLE, \"defend castle\"));\n    king.makeRequest(new Request(RequestType.TORTURE_PRISONER, \"torture prisoner\"));\n    king.makeRequest(new Request(RequestType.COLLECT_TAX, \"collect tax\"));\n  }\n}\n"
  },
  {
    "path": "chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcCommander.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.chain;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** OrcCommander. */\n@Slf4j\npublic class OrcCommander implements RequestHandler {\n  @Override\n  public boolean canHandleRequest(Request req) {\n    return req.getRequestType() == RequestType.DEFEND_CASTLE;\n  }\n\n  @Override\n  public int getPriority() {\n    return 2;\n  }\n\n  @Override\n  public void handle(Request req) {\n    req.markHandled();\n    LOGGER.info(\"{} handling request \\\"{}\\\"\", name(), req);\n  }\n\n  @Override\n  public String name() {\n    return \"Orc commander\";\n  }\n}\n"
  },
  {
    "path": "chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcKing.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.chain;\n\nimport java.util.Arrays;\nimport java.util.Comparator;\nimport java.util.List;\n\n/** OrcKing makes requests that are handled by the chain. */\npublic class OrcKing {\n\n  private List<RequestHandler> handlers;\n\n  public OrcKing() {\n    buildChain();\n  }\n\n  private void buildChain() {\n    handlers = Arrays.asList(new OrcCommander(), new OrcOfficer(), new OrcSoldier());\n  }\n\n  /** Handle request by the chain. */\n  public void makeRequest(Request req) {\n    handlers.stream()\n        .sorted(Comparator.comparing(RequestHandler::getPriority))\n        .filter(handler -> handler.canHandleRequest(req))\n        .findFirst()\n        .ifPresent(handler -> handler.handle(req));\n  }\n}\n"
  },
  {
    "path": "chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcOfficer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.chain;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** OrcOfficer. */\n@Slf4j\npublic class OrcOfficer implements RequestHandler {\n  @Override\n  public boolean canHandleRequest(Request req) {\n    return req.getRequestType() == RequestType.TORTURE_PRISONER;\n  }\n\n  @Override\n  public int getPriority() {\n    return 3;\n  }\n\n  @Override\n  public void handle(Request req) {\n    req.markHandled();\n    LOGGER.info(\"{} handling request \\\"{}\\\"\", name(), req);\n  }\n\n  @Override\n  public String name() {\n    return \"Orc officer\";\n  }\n}\n"
  },
  {
    "path": "chain-of-responsibility/src/main/java/com/iluwatar/chain/OrcSoldier.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.chain;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** OrcSoldier. */\n@Slf4j\npublic class OrcSoldier implements RequestHandler {\n  @Override\n  public boolean canHandleRequest(Request req) {\n    return req.getRequestType() == RequestType.COLLECT_TAX;\n  }\n\n  @Override\n  public int getPriority() {\n    return 1;\n  }\n\n  @Override\n  public void handle(Request req) {\n    req.markHandled();\n    LOGGER.info(\"{} handling request \\\"{}\\\"\", name(), req);\n  }\n\n  @Override\n  public String name() {\n    return \"Orc soldier\";\n  }\n}\n"
  },
  {
    "path": "chain-of-responsibility/src/main/java/com/iluwatar/chain/Request.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.chain;\n\nimport java.util.Objects;\nimport lombok.Getter;\n\n/** Request. */\n@Getter\npublic class Request {\n\n  /**\n   * The type of this request, used by each item in the chain to see if they should or can handle\n   * this particular request.\n   */\n  private final RequestType requestType;\n\n  /** A description of the request. */\n  private final String requestDescription;\n\n  /**\n   * Indicates if the request is handled or not. A request can only switch state from unhandled to\n   * handled, there's no way to 'unhandle' a request.\n   */\n  private boolean handled;\n\n  /**\n   * Create a new request of the given type and accompanied description.\n   *\n   * @param requestType The type of request\n   * @param requestDescription The description of the request\n   */\n  public Request(final RequestType requestType, final String requestDescription) {\n    this.requestType = Objects.requireNonNull(requestType);\n    this.requestDescription = Objects.requireNonNull(requestDescription);\n  }\n\n  /** Mark the request as handled. */\n  public void markHandled() {\n    this.handled = true;\n  }\n\n  @Override\n  public String toString() {\n    return getRequestDescription();\n  }\n}\n"
  },
  {
    "path": "chain-of-responsibility/src/main/java/com/iluwatar/chain/RequestHandler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.chain;\n\n/** RequestHandler. */\npublic interface RequestHandler {\n\n  boolean canHandleRequest(Request req);\n\n  int getPriority();\n\n  void handle(Request req);\n\n  String name();\n}\n"
  },
  {
    "path": "chain-of-responsibility/src/main/java/com/iluwatar/chain/RequestType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.chain;\n\n/** RequestType enumeration. */\npublic enum RequestType {\n  DEFEND_CASTLE,\n  TORTURE_PRISONER,\n  COLLECT_TAX\n}\n"
  },
  {
    "path": "chain-of-responsibility/src/test/java/com/iluwatar/chain/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.chain;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "chain-of-responsibility/src/test/java/com/iluwatar/chain/OrcKingTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.chain;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\n\n/** OrcKingTest */\nclass OrcKingTest {\n\n  /** All possible requests */\n  private static final List<Request> REQUESTS =\n      List.of(\n          new Request(RequestType.DEFEND_CASTLE, \"Don't let the barbarians enter my castle!!\"),\n          new Request(RequestType.TORTURE_PRISONER, \"Don't just stand there, tickle him!\"),\n          new Request(RequestType.COLLECT_TAX, \"Don't steal, the King hates competition ...\"));\n\n  @Test\n  void testMakeRequest() {\n    final var king = new OrcKing();\n\n    REQUESTS.forEach(\n        request -> {\n          king.makeRequest(request);\n          assertTrue(\n              request.isHandled(),\n              \"Expected all requests from King to be handled, but [\" + request + \"] was not!\");\n        });\n  }\n}\n"
  },
  {
    "path": "checkstyle-suppressions.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE suppressions PUBLIC \"-//Puppy Crawl//DTD Suppressions 1.1//EN\" \"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd\">\n<suppressions>\n  <suppress checks=\"AvoidStarImport\" files=\"[\\\\/]src[\\\\/]test[\\\\/]java[\\\\/]\" />\n  <suppress checks=\"[a-zA-Z0-9]*\" files=\"[\\\\/]src[\\\\/]test[\\\\/]resources[\\\\/]\" />\n  <suppress checks=\"[a-zA-Z0-9]*\" files=\"[\\\\/]build[\\\\/]generated-sources[\\\\/]\" />\n  <suppress checks=\"[a-zA-Z0-9]*\" files=\"[\\\\/]src[\\\\/]main[\\\\/]resources[\\\\/]\" />\n  <suppress checks=\"LineLength\" files=\".\" />\n  <suppress checks=\"EmptyLineSeparator\" files=\".\" />\n  <suppress checks=\"RequireEmptyLineBeforeBlockTagGroup\" files=\".*\\.java\"/>\n</suppressions>\n"
  },
  {
    "path": "circuit-breaker/README.md",
    "content": "---\ntitle: \"Circuit Breaker Pattern in Java: Enhancing System Resilience\"\nshortTitle: Circuit Breaker\ndescription: \"Learn about the Circuit Breaker pattern in Java design, which ensures fault tolerance and prevents cascading failures in distributed systems and microservices architectures.\"\ncategory: Resilience\nlanguage: en\ntag:\n  - Cloud distributed\n  - Fault tolerance\n  - Microservices\n  - Retry\n---\n\n## Also known as\n\n* Fault Tolerance Switch\n\n## Intent of Circuit Breaker Design Pattern\n\nThe Circuit Breaker pattern is a critical Java design pattern that helps ensure fault tolerance and resilience in microservices and distributed systems. Using Circuit Breaker, it is possible to prevent a system from repeatedly trying to execute an operation likely to fail, allowing it to recover from faults and prevent cascading failures.\n\n## Detailed Explanation of Circuit Breaker Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a real-world example of an e-commerce website that depends on multiple external payment gateways to process transactions. If one of the payment gateways becomes unresponsive or slow, the Circuit Breaker pattern can be used to detect the failure and prevent the system from repeatedly attempting to use the problematic gateway. Instead, it can quickly switch to alternative payment gateways or display an error message to the user, ensuring that the rest of the website remains functional and responsive. This avoids resource exhaustion and provides a better user experience by allowing transactions to be processed through other available services. This way, the Circuit Breaker pattern handles external API failures, ensuring the system remains functional.\n\nIn plain words\n\n> Circuit Breaker allows graceful handling of failed remote services. It's especially useful when all parts of our application are highly decoupled from each other, and failure of one component doesn't mean the other parts will stop working.\n\nWikipedia says\n\n> Circuit breaker is a design pattern used in modern software development. It is used to detect failures and encapsulates the logic of preventing a failure from constantly recurring, during maintenance, temporary external system failure or unexpected system difficulties.\n\nFlowchart\n\n![Circuit Breaker flowchart](./etc/circuit-breaker-flowchart.png)\n\n## Programmatic Example of Circuit Breaker Pattern in Java\n\nThis Java example demonstrates how the Circuit Breaker pattern can manage remote service failures and maintain system stability.\n\nImagine a web application that uses both local files/images and remote services to fetch data. Remote services can become slow or unresponsive, which may cause the application to hang due to thread starvation. The Circuit Breaker pattern can help detect such failures and allow the application to degrade gracefully.\n\n1. **Simulating a Delayed Remote Service**\n\n```java\n// The DelayedRemoteService simulates a remote service that responds after a certain delay.\nvar delayedService = new DelayedRemoteService(serverStartTime, 5);\n```\n\n2. **Setting Up the Circuit Breaker**\n\n```java\n// The DefaultCircuitBreaker wraps the remote service and monitors for failures.\nvar delayedServiceCircuitBreaker = new DefaultCircuitBreaker(delayedService, 3000, 2, 2000 * 1000 * 1000);\n```\n\n3. **Monitoring Service to Handle Requests**\n\n```java\n// The MonitoringService is responsible for calling the remote services.\nvar monitoringService = new MonitoringService(delayedServiceCircuitBreaker, quickServiceCircuitBreaker);\n\n// Fetch response from local resource\nLOGGER.info(monitoringService.localResourceResponse());\n\n// Fetch response from delayed service 2 times to meet the failure threshold\nLOGGER.info(monitoringService.delayedServiceResponse());\nLOGGER.info(monitoringService.delayedServiceResponse());\n```\n\n4. **Handling Circuit Breaker States**\n\n```java\n// Fetch current state of delayed service circuit breaker after crossing failure threshold limit\nLOGGER.info(delayedServiceCircuitBreaker.getState()); // Should be OPEN\n\n// Meanwhile, the delayed service is down, fetch response from the healthy quick service\nLOGGER.info(monitoringService.quickServiceResponse());\nLOGGER.info(quickServiceCircuitBreaker.getState());\n```\n\n5. **Recovering from Failure**\n\n```java\n// Wait for the delayed service to become responsive\ntry {\n  LOGGER.info(\"Waiting for delayed service to become responsive\");\n  Thread.sleep(5000);\n} catch (InterruptedException e) {\n  LOGGER.error(\"An error occurred: \", e);\n}\n\n// Check the state of delayed circuit breaker, should be HALF_OPEN\nLOGGER.info(delayedServiceCircuitBreaker.getState());\n\n// Fetch response from delayed service, which should be healthy by now\nLOGGER.info(monitoringService.delayedServiceResponse());\n\n// As successful response is fetched, it should be CLOSED again.\nLOGGER.info(delayedServiceCircuitBreaker.getState());\n```\n\n6. **Full example**\n\n```java\npublic static void main(String[] args) {\n\n    var serverStartTime = System.nanoTime();\n\n    var delayedService = new DelayedRemoteService(serverStartTime, 5);\n    var delayedServiceCircuitBreaker = new DefaultCircuitBreaker(delayedService, 3000, 2,\n        2000 * 1000 * 1000);\n\n    var quickService = new QuickRemoteService();\n    var quickServiceCircuitBreaker = new DefaultCircuitBreaker(quickService, 3000, 2,\n        2000 * 1000 * 1000);\n\n    //Create an object of monitoring service which makes both local and remote calls\n    var monitoringService = new MonitoringService(delayedServiceCircuitBreaker,\n        quickServiceCircuitBreaker);\n\n    //Fetch response from local resource\n    LOGGER.info(monitoringService.localResourceResponse());\n\n    //Fetch response from delayed service 2 times, to meet the failure threshold\n    LOGGER.info(monitoringService.delayedServiceResponse());\n    LOGGER.info(monitoringService.delayedServiceResponse());\n\n    //Fetch current state of delayed service circuit breaker after crossing failure threshold limit\n    //which is OPEN now\n    LOGGER.info(delayedServiceCircuitBreaker.getState());\n\n    //Meanwhile, the delayed service is down, fetch response from the healthy quick service\n    LOGGER.info(monitoringService.quickServiceResponse());\n    LOGGER.info(quickServiceCircuitBreaker.getState());\n\n    //Wait for the delayed service to become responsive\n    try {\n      LOGGER.info(\"Waiting for delayed service to become responsive\");\n      Thread.sleep(5000);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"An error occurred: \", e);\n    }\n    //Check the state of delayed circuit breaker, should be HALF_OPEN\n    LOGGER.info(delayedServiceCircuitBreaker.getState());\n\n    //Fetch response from delayed service, which should be healthy by now\n    LOGGER.info(monitoringService.delayedServiceResponse());\n    //As successful response is fetched, it should be CLOSED again.\n    LOGGER.info(delayedServiceCircuitBreaker.getState());\n}\n```\n\nSummary of the example\n\n- Initialize the Circuit Breaker with parameters: `timeout`, `failureThreshold`, and `retryTimePeriod`.\n- Start in the `closed` state.\n- On successful calls, reset the state.\n- On failures exceeding the threshold, transition to the `open` state to prevent further calls.\n- After the retry timeout, transition to the `half-open` state to test the service.\n- On success in `half-open` state, transition back to `closed`. On failure, return to `open`.\n\nProgram output:\n\n```\n16:59:19.767 [main] INFO com.iluwatar.circuitbreaker.App -- Local Service is working\n16:59:19.769 [main] INFO com.iluwatar.circuitbreaker.App -- Delayed service is down\n16:59:19.769 [main] INFO com.iluwatar.circuitbreaker.App -- Delayed service is down\n16:59:19.769 [main] INFO com.iluwatar.circuitbreaker.App -- OPEN\n16:59:19.769 [main] INFO com.iluwatar.circuitbreaker.App -- Quick Service is working\n16:59:19.769 [main] INFO com.iluwatar.circuitbreaker.App -- CLOSED\n16:59:19.769 [main] INFO com.iluwatar.circuitbreaker.App -- Waiting for delayed service to become responsive\n16:59:24.779 [main] INFO com.iluwatar.circuitbreaker.App -- HALF_OPEN\n16:59:24.780 [main] INFO com.iluwatar.circuitbreaker.App -- Delayed service is working\n16:59:24.780 [main] INFO com.iluwatar.circuitbreaker.App -- CLOSED\n```\n\nThis example demonstrates how the Circuit Breaker pattern can help maintain application stability and resilience by managing remote service failures.\n\n## When to Use the Circuit Breaker Pattern in Java\n\nThe Circuit Breaker pattern is applicable:\n\n* In distributed systems where individual service failures can lead to cascading system-wide failures\n* For applications that interact with third-party services or databases that might become unresponsive or slow\n* In microservices architectures where the failure of one service can affect the availability of others\n\n## Real-World Applications of Circuit Breaker Pattern in Java\n\n* Cloud-based services to gracefully handle the failure of external services\n* E-commerce platforms to manage high volumes of transactions and dependency on external APIs\n* Microservices architectures for maintaining system stability and responsiveness\n* [Spring Circuit Breaker module](https://spring.io/guides/gs/circuit-breaker)\n* [Netflix Hystrix API](https://github.com/Netflix/Hystrix)\n\n## Benefits and Trade-offs of Circuit Breaker Pattern\n\nBenefits:\n\n* Prevents the system from performing futile operations that are likely to fail, thus saving resources\n* Helps in maintaining the system stability and performance of the application during partial system failures\n* Facilitates faster system recovery by avoiding the overwhelming of failing services with repeated requests\n\nTrade-Offs:\n\n* The complexity of the system increases as the pattern requires additional logic to detect failures and manage the state of the circuit breaker\n* May lead to system degradation if not properly configured, as legitimate requests might be blocked if the circuit is open\n* Requires careful tuning of thresholds and timeout periods to balance between responsiveness and protection\n\n## Related Patterns\n\n- Bulkhead: Can be used to isolate different parts of the system to prevent failures from spreading across the system\n- [Retry Pattern](https://github.com/iluwatar/java-design-patterns/tree/master/retry): Can be used in conjunction with the Circuit Breaker pattern to retry failed operations before opening the circuit\n\n## References and Credits\n\n* [Building Microservices: Designing Fine-Grained Systems](https://amzn.to/43Dx86g)\n* [Microservices Patterns: With examples in Java](https://amzn.to/3xaZwk0)\n* [Release It! Design and Deploy Production-Ready Software](https://amzn.to/4aqTNEP)\n* [Understand CircuitBreaker Design Pattern with Simple Practical Example (ITNEXT)](https://itnext.io/understand-circuitbreaker-design-pattern-with-simple-practical-example-92a752615b42)\n* [Circuit Breaker (Martin Fowler)](https://martinfowler.com/bliki/CircuitBreaker.html)\n* [Fault tolerance in a high volume, distributed system (Netflix)](https://medium.com/netflix-techblog/fault-tolerance-in-a-high-volume-distributed-system-91ab4faae74a)\n* [Circuit Breaker pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker)\n"
  },
  {
    "path": "circuit-breaker/etc/circuit-breaker.urm.puml",
    "content": "@startuml\npackage com.iluwatar.circuitbreaker {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  interface CircuitBreaker {\n    + attemptRequest() : String {abstract}\n    + getState() : String {abstract}\n    + recordFailure(String) {abstract}\n    + recordSuccess() {abstract}\n    + setState(State) {abstract}\n  }\n  class DefaultCircuitBreaker {\n    ~ failureCount : int\n    - failureThreshold : int\n    - futureTime : long\n    - lastFailureResponse : String\n    ~ lastFailureTime : long\n    - retryTimePeriod : long\n    - service : RemoteService\n    - state : State\n    - timeout : long\n    ~ DefaultCircuitBreaker(serviceToCall : RemoteService, timeout : long, failureThreshold : int, retryTimePeriod : long)\n    + attemptRequest() : String\n    # evaluateState()\n    + getState() : String\n    + recordFailure(response : String)\n    + recordSuccess()\n    + setState(state : State)\n  }\n  class DelayedRemoteService {\n    - delay : int\n    - serverStartTime : long\n    + DelayedRemoteService()\n    + DelayedRemoteService(serverStartTime : long, delay : int)\n    + call() : String\n  }\n  class MonitoringService {\n    - delayedService : CircuitBreaker\n    - quickService : CircuitBreaker\n    + MonitoringService(delayedService : CircuitBreaker, quickService : CircuitBreaker)\n    + delayedServiceResponse() : String\n    + localResourceResponse() : String\n    + quickServiceResponse() : String\n  }\n  class QuickRemoteService {\n    + QuickRemoteService()\n    + call() : String\n  }\n  interface RemoteService {\n    + call() : String {abstract}\n  }\n  enum State {\n    + CLOSED {static}\n    + HALF_OPEN {static}\n    + OPEN {static}\n    + valueOf(name : String) : State {static}\n    + values() : State[] {static}\n  }\n}\nDefaultCircuitBreaker -->  \"-state\" State\nMonitoringService -->  \"-delayedService\" CircuitBreaker\nDefaultCircuitBreaker -->  \"-service\" RemoteService\nDefaultCircuitBreaker ..|> CircuitBreaker \nDelayedRemoteService ..|> RemoteService \nQuickRemoteService ..|> RemoteService \n@enduml"
  },
  {
    "path": "circuit-breaker/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>circuit-breaker</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.circuitbreaker.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The intention of the Circuit Builder pattern is to handle remote failures robustly, which is to\n * mean that if a service is dependent on n number of other services, and m of them fail, we should\n * be able to recover from that failure by ensuring that the user can still use the services that\n * are actually functional, and resources are not tied up by uselessly by the services which are not\n * working. However, we should also be able to detect when any of the m failing services become\n * operational again, so that we can use it\n *\n * <p>In this example, the circuit breaker pattern is demonstrated by using three services: {@link\n * DelayedRemoteService}, {@link QuickRemoteService} and {@link MonitoringService}. The monitoring\n * service is responsible for calling three services: a local service, a quick remove service {@link\n * QuickRemoteService} and a delayed remote service {@link DelayedRemoteService} , and by using the\n * circuit breaker construction we ensure that if the call to remote service is going to fail, we\n * are going to save our resources and not make the function call at all, by wrapping our call to\n * the remote services in the {@link DefaultCircuitBreaker} implementation object.\n *\n * <p>This works as follows: The {@link DefaultCircuitBreaker} object can be in one of three states:\n * <b>Open</b>, <b>Closed</b> and <b>Half-Open</b>, which represents the real world circuits. If the\n * state is closed (initial), we assume everything is alright and perform the function call.\n * However, every time the call fails, we note it and once it crosses a threshold, we set the state\n * to Open, preventing any further calls to the remote server. Then, after a certain retry period\n * (during which we expect thee service to recover), we make another call to the remote server and\n * this state is called the Half-Open state, where it stays till the service is down, and once it\n * recovers, it goes back to the closed state and the cycle continues.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var serverStartTime = System.nanoTime();\n\n    var delayedService = new DelayedRemoteService(serverStartTime, 5);\n    var delayedServiceCircuitBreaker =\n        new DefaultCircuitBreaker(delayedService, 3000, 2, 2000 * 1000 * 1000);\n\n    var quickService = new QuickRemoteService();\n    var quickServiceCircuitBreaker =\n        new DefaultCircuitBreaker(quickService, 3000, 2, 2000 * 1000 * 1000);\n\n    // Create an object of monitoring service which makes both local and remote calls\n    var monitoringService =\n        new MonitoringService(delayedServiceCircuitBreaker, quickServiceCircuitBreaker);\n\n    // Fetch response from local resource\n    LOGGER.info(monitoringService.localResourceResponse());\n\n    // Fetch response from delayed service 2 times, to meet the failure threshold\n    LOGGER.info(monitoringService.delayedServiceResponse());\n    LOGGER.info(monitoringService.delayedServiceResponse());\n\n    // Fetch current state of delayed service circuit breaker after crossing failure threshold limit\n    // which is OPEN now\n    LOGGER.info(delayedServiceCircuitBreaker.getState());\n\n    // Meanwhile, the delayed service is down, fetch response from the healthy quick service\n    LOGGER.info(monitoringService.quickServiceResponse());\n    LOGGER.info(quickServiceCircuitBreaker.getState());\n\n    // Wait for the delayed service to become responsive\n    try {\n      LOGGER.info(\"Waiting for delayed service to become responsive\");\n      Thread.sleep(5000);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"An error occurred: \", e);\n    }\n    // Check the state of delayed circuit breaker, should be HALF_OPEN\n    LOGGER.info(delayedServiceCircuitBreaker.getState());\n\n    // Fetch response from delayed service, which should be healthy by now\n    LOGGER.info(monitoringService.delayedServiceResponse());\n    // As successful response is fetched, it should be CLOSED again.\n    LOGGER.info(delayedServiceCircuitBreaker.getState());\n  }\n}\n"
  },
  {
    "path": "circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/CircuitBreaker.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\n/** The Circuit breaker interface. */\npublic interface CircuitBreaker {\n\n  // Success response. Reset everything to defaults\n  void recordSuccess();\n\n  // Failure response. Handle accordingly with response and change state if required.\n  void recordFailure(String response);\n\n  // Get the current state of circuit breaker\n  String getState();\n\n  // Set the specific state manually.\n  void setState(State state);\n\n  // Attempt to fetch response from the remote service.\n  String attemptRequest() throws RemoteServiceException;\n}\n"
  },
  {
    "path": "circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/DefaultCircuitBreaker.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\n/**\n * The delay based Circuit breaker implementation that works in a\n * CLOSED->OPEN-(retry_time_period)->HALF_OPEN->CLOSED flow with some retry time period for failed\n * services and a failure threshold for service to open circuit.\n */\npublic class DefaultCircuitBreaker implements CircuitBreaker {\n\n  private final long timeout;\n  private final long retryTimePeriod;\n  private final RemoteService service;\n  long lastFailureTime;\n  private String lastFailureResponse;\n  int failureCount;\n  private final int failureThreshold;\n  private State state;\n  // Future time offset, in nanoseconds\n  private final long futureTime = 1_000_000_000_000L;\n\n  /**\n   * Constructor to create an instance of Circuit Breaker.\n   *\n   * @param timeout Timeout for the API request. Not necessary for this simple example\n   * @param failureThreshold Number of failures we receive from the depended on service before\n   *     changing state to 'OPEN'\n   * @param retryTimePeriod Time, in nanoseconds, period after which a new request is made to remote\n   *     service for status check.\n   */\n  DefaultCircuitBreaker(\n      RemoteService serviceToCall, long timeout, int failureThreshold, long retryTimePeriod) {\n    this.service = serviceToCall;\n    // We start in a closed state hoping that everything is fine\n    this.state = State.CLOSED;\n    this.failureThreshold = failureThreshold;\n    // Timeout for the API request.\n    // Used to break the calls made to remote resource if it exceeds the limit\n    this.timeout = timeout;\n    this.retryTimePeriod = retryTimePeriod;\n    // An absurd amount of time in future which basically indicates the last failure never happened\n    this.lastFailureTime = System.nanoTime() + futureTime;\n    this.failureCount = 0;\n  }\n\n  // Reset everything to defaults\n  @Override\n  public void recordSuccess() {\n    this.failureCount = 0;\n    this.lastFailureTime = System.nanoTime() + futureTime;\n    this.state = State.CLOSED;\n  }\n\n  @Override\n  public void recordFailure(String response) {\n    failureCount = failureCount + 1;\n    this.lastFailureTime = System.nanoTime();\n    // Cache the failure response for returning on open state\n    this.lastFailureResponse = response;\n  }\n\n  // Evaluate the current state based on failureThreshold, failureCount and lastFailureTime.\n  protected void evaluateState() {\n    if (failureCount >= failureThreshold) { // Then something is wrong with remote service\n      if ((System.nanoTime() - lastFailureTime) > retryTimePeriod) {\n        // We have waited long enough and should try checking if service is up\n        state = State.HALF_OPEN;\n      } else {\n        // Service would still probably be down\n        state = State.OPEN;\n      }\n    } else {\n      // Everything is working fine\n      state = State.CLOSED;\n    }\n  }\n\n  @Override\n  public String getState() {\n    evaluateState();\n    return state.name();\n  }\n\n  /**\n   * Break the circuit beforehand if it is known service is down Or connect the circuit manually if\n   * service comes online before expected.\n   *\n   * @param state State at which circuit is in\n   */\n  @Override\n  public void setState(State state) {\n    this.state = state;\n    switch (state) {\n      case OPEN -> {\n        this.failureCount = failureThreshold;\n        this.lastFailureTime = System.nanoTime();\n      }\n      case HALF_OPEN -> {\n        this.failureCount = failureThreshold;\n        this.lastFailureTime = System.nanoTime() - retryTimePeriod;\n      }\n      default -> this.failureCount = 0;\n    }\n  }\n\n  /**\n   * Executes service call.\n   *\n   * @return Value from the remote resource, stale response or a custom exception\n   */\n  @Override\n  public String attemptRequest() throws RemoteServiceException {\n    evaluateState();\n    if (state == State.OPEN) {\n      // return cached response if the circuit is in OPEN state\n      return this.lastFailureResponse;\n    } else {\n      // Make the API request if the circuit is not OPEN\n      try {\n        // In a real application, this would be run in a thread and the timeout\n        // parameter of the circuit breaker would be utilized to know if service\n        // is working. Here, we simulate that based on server response itself\n        var response = service.call();\n        // Yay!! the API responded fine. Let's reset everything.\n        recordSuccess();\n        return response;\n      } catch (RemoteServiceException ex) {\n        recordFailure(ex.getMessage());\n        throw ex;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/DelayedRemoteService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\n/**\n * This simulates the remote service It responds only after a certain timeout period (default set to\n * 20 seconds).\n */\npublic class DelayedRemoteService implements RemoteService {\n\n  private final long serverStartTime;\n  private final int delay;\n\n  /**\n   * Constructor to create an instance of DelayedService, which is down for first few seconds.\n   *\n   * @param delay the delay after which service would behave properly, in seconds\n   */\n  public DelayedRemoteService(long serverStartTime, int delay) {\n    this.serverStartTime = serverStartTime;\n    this.delay = delay;\n  }\n\n  public DelayedRemoteService() {\n    this.serverStartTime = System.nanoTime();\n    this.delay = 20;\n  }\n\n  /**\n   * Responds based on delay, current time and server start time if the service is down / working.\n   *\n   * @return The state of the service\n   */\n  @Override\n  public String call() throws RemoteServiceException {\n    var currentTime = System.nanoTime();\n    // Since currentTime and serverStartTime are both in nanoseconds, we convert it to\n    // seconds by diving by 10e9 and ensure floating point division by multiplying it\n    // with 1.0 first. We then check if it is greater or less than specified delay and then\n    // send the reply\n    if ((currentTime - serverStartTime) * 1.0 / (1000 * 1000 * 1000) < delay) {\n      // Can use Thread.sleep() here to block and simulate a hung server\n      throw new RemoteServiceException(\"Delayed service is down\");\n    }\n    return \"Delayed service is working\";\n  }\n}\n"
  },
  {
    "path": "circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/MonitoringService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\n/**\n * The service class which makes local and remote calls Uses {@link DefaultCircuitBreaker} object to\n * ensure remote calls don't use up resources.\n */\npublic class MonitoringService {\n\n  private final CircuitBreaker delayedService;\n\n  private final CircuitBreaker quickService;\n\n  public MonitoringService(CircuitBreaker delayedService, CircuitBreaker quickService) {\n    this.delayedService = delayedService;\n    this.quickService = quickService;\n  }\n\n  // Assumption: Local service won't fail, no need to wrap it in a circuit breaker logic\n  public String localResourceResponse() {\n    return \"Local Service is working\";\n  }\n\n  /**\n   * Fetch response from the delayed service (with some simulated startup time).\n   *\n   * @return response string\n   */\n  public String delayedServiceResponse() {\n    try {\n      return this.delayedService.attemptRequest();\n    } catch (RemoteServiceException e) {\n      return e.getMessage();\n    }\n  }\n\n  /**\n   * Fetches response from a healthy service without any failure.\n   *\n   * @return response string\n   */\n  public String quickServiceResponse() {\n    try {\n      return this.quickService.attemptRequest();\n    } catch (RemoteServiceException e) {\n      return e.getMessage();\n    }\n  }\n}\n"
  },
  {
    "path": "circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/QuickRemoteService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\n/** A quick response remote service, that responds healthy without any delay or failure. */\npublic class QuickRemoteService implements RemoteService {\n\n  @Override\n  public String call() throws RemoteServiceException {\n    return \"Quick Service is working\";\n  }\n}\n"
  },
  {
    "path": "circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/RemoteService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\n/**\n * The Remote service interface, used by {@link CircuitBreaker} for fetching response from remote\n * services.\n */\npublic interface RemoteService {\n\n  // Fetch response from remote service.\n  String call() throws RemoteServiceException;\n}\n"
  },
  {
    "path": "circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/RemoteServiceException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\n/** Exception thrown when {@link RemoteService} does not respond successfully. */\npublic class RemoteServiceException extends Exception {\n\n  public RemoteServiceException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "circuit-breaker/src/main/java/com/iluwatar/circuitbreaker/State.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\n/** Enumeration for states the circuit breaker could be in. */\npublic enum State {\n  CLOSED,\n  OPEN,\n  HALF_OPEN\n}\n"
  },
  {
    "path": "circuit-breaker/src/test/java/com/iluwatar/circuitbreaker/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** App Test showing usage of circuit breaker. */\nclass AppTest {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(AppTest.class);\n\n  // Startup delay for delayed service (in seconds)\n  private static final int STARTUP_DELAY = 4;\n\n  // Number of failed requests for circuit breaker to open\n  private static final int FAILURE_THRESHOLD = 1;\n\n  // Time period in seconds for circuit breaker to retry service\n  private static final int RETRY_PERIOD = 2;\n\n  private MonitoringService monitoringService;\n\n  private CircuitBreaker delayedServiceCircuitBreaker;\n\n  private CircuitBreaker quickServiceCircuitBreaker;\n\n  /**\n   * Set up the circuit breakers and services, where {@link DelayedRemoteService} will be start with\n   * a delay of 4 seconds and a {@link QuickRemoteService} responding healthy. Both services are\n   * wrapped in a {@link DefaultCircuitBreaker} implementation with failure threshold of 1 failure\n   * and retry time period of 2 seconds.\n   */\n  @BeforeEach\n  void setupCircuitBreakers() {\n    var delayedService = new DelayedRemoteService(System.nanoTime(), STARTUP_DELAY);\n    // Set the circuit Breaker parameters\n    delayedServiceCircuitBreaker =\n        new DefaultCircuitBreaker(\n            delayedService, 3000, FAILURE_THRESHOLD, RETRY_PERIOD * 1000 * 1000 * 1000);\n\n    var quickService = new QuickRemoteService();\n    // Set the circuit Breaker parameters\n    quickServiceCircuitBreaker =\n        new DefaultCircuitBreaker(\n            quickService, 3000, FAILURE_THRESHOLD, RETRY_PERIOD * 1000 * 1000 * 1000);\n\n    monitoringService =\n        new MonitoringService(delayedServiceCircuitBreaker, quickServiceCircuitBreaker);\n  }\n\n  @Test\n  void testFailure_OpenStateTransition() {\n    // Calling delayed service, which will be unhealthy till 4 seconds\n    assertEquals(\"Delayed service is down\", monitoringService.delayedServiceResponse());\n    // As failure threshold is \"1\", the circuit breaker is changed to OPEN\n    assertEquals(\"OPEN\", delayedServiceCircuitBreaker.getState());\n    // As circuit state is OPEN, we expect a quick fallback response from circuit breaker.\n    assertEquals(\"Delayed service is down\", monitoringService.delayedServiceResponse());\n\n    // Meanwhile, the quick service is responding and the circuit state is CLOSED\n    assertEquals(\"Quick Service is working\", monitoringService.quickServiceResponse());\n    assertEquals(\"CLOSED\", quickServiceCircuitBreaker.getState());\n  }\n\n  @Test\n  void testFailure_HalfOpenStateTransition() {\n    // Calling delayed service, which will be unhealthy till 4 seconds\n    assertEquals(\"Delayed service is down\", monitoringService.delayedServiceResponse());\n    // As failure threshold is \"1\", the circuit breaker is changed to OPEN\n    assertEquals(\"OPEN\", delayedServiceCircuitBreaker.getState());\n\n    // Waiting for recovery period of 2 seconds for circuit breaker to retry service.\n    try {\n      LOGGER.info(\"Waiting 2s for delayed service to become responsive\");\n      Thread.sleep(2000);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"An error occurred: \", e);\n    }\n    // After 2 seconds, the circuit breaker should move to \"HALF_OPEN\" state and retry fetching\n    // response from service again\n    assertEquals(\"HALF_OPEN\", delayedServiceCircuitBreaker.getState());\n  }\n\n  @Test\n  void testRecovery_ClosedStateTransition() {\n    // Calling delayed service, which will be unhealthy till 4 seconds\n    assertEquals(\"Delayed service is down\", monitoringService.delayedServiceResponse());\n    // As failure threshold is \"1\", the circuit breaker is changed to OPEN\n    assertEquals(\"OPEN\", delayedServiceCircuitBreaker.getState());\n\n    // Waiting for 4 seconds, which is enough for DelayedService to become healthy and respond\n    // successfully.\n    try {\n      LOGGER.info(\"Waiting 4s for delayed service to become responsive\");\n      Thread.sleep(4000);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"An error occurred: \", e);\n    }\n    // As retry period is 2 seconds (<4 seconds of wait), hence the circuit breaker should be back\n    // in HALF_OPEN state.\n    assertEquals(\"HALF_OPEN\", delayedServiceCircuitBreaker.getState());\n    // Check the success response from delayed service.\n    assertEquals(\"Delayed service is working\", monitoringService.delayedServiceResponse());\n    // As the response is success, the state should be CLOSED\n    assertEquals(\"CLOSED\", delayedServiceCircuitBreaker.getState());\n  }\n}\n"
  },
  {
    "path": "circuit-breaker/src/test/java/com/iluwatar/circuitbreaker/DefaultCircuitBreakerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Circuit Breaker test */\nclass DefaultCircuitBreakerTest {\n\n  // long timeout, int failureThreshold, long retryTimePeriod\n  @Test\n  void testEvaluateState() {\n    var circuitBreaker = new DefaultCircuitBreaker(null, 1, 1, 100);\n    // Right now, failureCount<failureThreshold, so state should be closed\n    assertEquals(circuitBreaker.getState(), \"CLOSED\");\n    circuitBreaker.failureCount = 4;\n    circuitBreaker.lastFailureTime = System.nanoTime();\n    circuitBreaker.evaluateState();\n    // Since failureCount>failureThreshold, and lastFailureTime is nearly equal to current time,\n    // state should be half-open\n    assertEquals(circuitBreaker.getState(), \"HALF_OPEN\");\n    // Since failureCount>failureThreshold, and lastFailureTime is much lesser current time,\n    // state should be open\n    circuitBreaker.lastFailureTime = System.nanoTime() - 1000 * 1000 * 1000 * 1000;\n    circuitBreaker.evaluateState();\n    assertEquals(circuitBreaker.getState(), \"OPEN\");\n    // Now set it back again to closed to test idempotency\n    circuitBreaker.failureCount = 0;\n    circuitBreaker.evaluateState();\n    assertEquals(circuitBreaker.getState(), \"CLOSED\");\n  }\n\n  @Test\n  void testSetStateForBypass() {\n    var circuitBreaker = new DefaultCircuitBreaker(null, 1, 1, 2000 * 1000 * 1000);\n    // Right now, failureCount<failureThreshold, so state should be closed\n    // Bypass it and set it to open\n    circuitBreaker.setState(State.OPEN);\n    assertEquals(circuitBreaker.getState(), \"OPEN\");\n  }\n\n  @Test\n  void testApiResponses() throws RemoteServiceException {\n    RemoteService mockService =\n        new RemoteService() {\n          @Override\n          public String call() throws RemoteServiceException {\n            return \"Remote Success\";\n          }\n        };\n    var circuitBreaker = new DefaultCircuitBreaker(mockService, 1, 1, 100);\n    // Call with the parameter start_time set to huge amount of time in past so that service\n    // replies with \"Ok\". Also, state is CLOSED in start\n    var serviceStartTime = System.nanoTime() - 60 * 1000 * 1000 * 1000;\n    var response = circuitBreaker.attemptRequest();\n    assertEquals(response, \"Remote Success\");\n  }\n}\n"
  },
  {
    "path": "circuit-breaker/src/test/java/com/iluwatar/circuitbreaker/DelayedRemoteServiceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\n/** Monitoring Service test */\nclass DelayedRemoteServiceTest {\n\n  /**\n   * Testing immediate response of the delayed service.\n   *\n   * @throws RemoteServiceException\n   */\n  @Test\n  void testDefaultConstructor() throws RemoteServiceException {\n    Assertions.assertThrows(\n        RemoteServiceException.class,\n        () -> {\n          var obj = new DelayedRemoteService();\n          obj.call();\n        });\n  }\n\n  /**\n   * Testing server started in past (2 seconds ago) and with a simulated delay of 1 second.\n   *\n   * @throws RemoteServiceException\n   */\n  @Test\n  void testParameterizedConstructor() throws RemoteServiceException {\n    var obj = new DelayedRemoteService(System.nanoTime() - 2000 * 1000 * 1000, 1);\n    assertEquals(\"Delayed service is working\", obj.call());\n  }\n}\n"
  },
  {
    "path": "circuit-breaker/src/test/java/com/iluwatar/circuitbreaker/MonitoringServiceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.circuitbreaker;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Monitoring Service test */\nclass MonitoringServiceTest {\n\n  // long timeout, int failureThreshold, long retryTimePeriod\n  @Test\n  void testLocalResponse() {\n    var monitoringService = new MonitoringService(null, null);\n    var response = monitoringService.localResourceResponse();\n    assertEquals(response, \"Local Service is working\");\n  }\n\n  @Test\n  void testDelayedRemoteResponseSuccess() {\n    var delayedService = new DelayedRemoteService(System.nanoTime() - 2 * 1000 * 1000 * 1000, 2);\n    var delayedServiceCircuitBreaker =\n        new DefaultCircuitBreaker(delayedService, 3000, 1, 2 * 1000 * 1000 * 1000);\n\n    var monitoringService = new MonitoringService(delayedServiceCircuitBreaker, null);\n    // Set time in past to make the server work\n    var response = monitoringService.delayedServiceResponse();\n    assertEquals(response, \"Delayed service is working\");\n  }\n\n  @Test\n  void testDelayedRemoteResponseFailure() {\n    var delayedService = new DelayedRemoteService(System.nanoTime(), 2);\n    var delayedServiceCircuitBreaker =\n        new DefaultCircuitBreaker(delayedService, 3000, 1, 2 * 1000 * 1000 * 1000);\n    var monitoringService = new MonitoringService(delayedServiceCircuitBreaker, null);\n    // Set time as current time as initially server fails\n    var response = monitoringService.delayedServiceResponse();\n    assertEquals(response, \"Delayed service is down\");\n  }\n\n  @Test\n  void testQuickRemoteServiceResponse() {\n    var delayedService = new QuickRemoteService();\n    var delayedServiceCircuitBreaker =\n        new DefaultCircuitBreaker(delayedService, 3000, 1, 2 * 1000 * 1000 * 1000);\n    var monitoringService = new MonitoringService(delayedServiceCircuitBreaker, null);\n    // Set time as current time as initially server fails\n    var response = monitoringService.delayedServiceResponse();\n    assertEquals(response, \"Quick Service is working\");\n  }\n}\n"
  },
  {
    "path": "clean-architecture/README.md",
    "content": "---\ntitle: \"Clean Architecture - A Software Maintainable Architectural style.\"\nshortTitle: Clean Architecture\ndescription: \"Learn the Clean Architecture Style in Java with real-world examples, code snippets, and class diagrams. Enhance your coding skills with our detailed explanations.\"\ncategory: Architectural\nlanguage: en\ntag:\n    - Architecture\n    - Decoupling\n    - Domain\n    - Inversion of control\n    - Layered architecture\n    - Modularity\n    - Testing\n---\n\n## Intent of Clean Architecture.\n\nTo organize the system so that the core business logic remains independent from external concerns and frameworks.\n\n## Detailed Explanation of Clean Architecture Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a large pizza chain with multiple ordering channels—web, mobile app, phone calls, and in-store kiosks. The core “pizza domain” logic (calculating prices, preparing orders, managing loyalty points) is kept entirely separate from the user interfaces and storage mechanisms. As a result, the chain can add or change the ordering channel (for example, introducing a chatbot or swapping out the database) without altering the fundamental pizza-ordering rules, thanks to the layered boundaries and strict dependency rules of Clean Architecture.\n\nIn plain words\n\n> Clean Architecture is a software design approach that isolates the core business logic from external concerns (like databases, frameworks, or UI) through strict layering and clear boundaries, ensuring that changes in one layer don't ripple through the entire system.\n\nWikipedia says\n\n> The clean architecture proposed by Robert C. Martin in 2012 combines the principles of the hexagonal architecture, the onion architecture and several other variants. It provides additional levels of detail of the component, which are presented as concentric rings. It isolates adapters and interfaces (user interface, databases, external systems, devices) in the outer rings of the architecture and leaves the inner rings for use cases and entities. The clean architecture uses the principle of dependency inversion with the strict rule that dependencies shall only exist between an outer ring to an inner ring and never the contrary.\n\nMind map\n\n![Clean Architecture Mind Map](./etc/clean-architecture-mind-map.png)\n\nFlowchart\n\n![Clean Architecture Flowchart](./etc/clean-architecture-flowchart.png)\n\n## Programmatic Example of Clean Architecture Pattern\n\nFirst, we define the core domain entities: `Product`, `Order`, and `Cart`. These classes capture the fundamental business logic and state.\n\n```java\npublic class Product {\n    private String id;\n    private String name;\n    private double price;\n\n    public Product(String id, String name, double price) {\n        this.id = id;\n        this.name = name;\n        this.price = price;\n    }\n}\n```\n\n```java\npublic class Cart {\n    private Product product;\n    private int quantity;\n\n    public CartItem(Product product, int quantity) {\n        this.product = product;\n        this.quantity = quantity;\n    }\n\n    public double getTotalPrice() {\n        return product.getPrice() * quantity;\n    }\n}\n```\n\n```java\npublic class Order {\n    private String orderId;\n    private List<CartItem> items;\n    private double totalPrice;\n\n    public Order(String orderId, List<CartItem> items) {\n        this.orderId = orderId;\n        this.items = items;\n        this.totalPrice = items.stream().mapToDouble(CartItem::getTotalPrice).sum();\n    }\n}\n```\n\nThe repository interfaces are created to abstract data operations for each domain object, allowing us to switch out storage or persistence mechanisms without changing higher-level logic.\n\n```java\npublic interface CartRepository {\n    void addItemToCart(String userId, Product product, int quantity);\n    void removeItemFromCart(String userId, String productId);\n    List<Cart> getItemsInCart(String userId);\n    double calculateTotal(String userId);\n    void clearCart(String userId);\n}\n```\n```java\npublic interface ProductRepository {\n    Product getProductById(String productId);\n}\n```\n```java\npublic interface OrderRepository {\n    void saveOrder(Order order);\n}\n```\n\nThe in-memory data store implementations use simple collections to hold state. They demonstrate how easily we can replace or extend the data layer (e.g., swapping in a database) without affecting the domain logic.\n\n```java\npublic class InMemoryCartRepository implements CartRepository {\n  private final Map<String, List<Cart>> userCarts = new HashMap<>();\n\n  @Override\n  public void addItemToCart(String userId, Product product, int quantity) {\n    List<Cart> cart = userCarts.getOrDefault(userId, new ArrayList<>());\n    cart.add(new Cart(product, quantity));\n    userCarts.put(userId, cart);\n  }\n\n  @Override\n  public void removeItemFromCart(String userId, String productId) {\n    List<Cart> cart = userCarts.get(userId);\n    if (cart != null) {\n      cart.removeIf(item -> item.getProduct().getId().equals(productId));\n    }\n  }\n\n  @Override\n  public List<Cart> getItemsInCart(String userId) {\n    return userCarts.getOrDefault(userId, new ArrayList<>());\n  }\n\n  @Override\n  public double calculateTotal(String userId) {\n    return userCarts.getOrDefault(userId, new ArrayList<>())\n        .stream()\n        .mapToDouble(Cart::getTotalPrice)\n        .sum();\n  }\n\n  @Override\n  public void clearCart(String userId) {\n    userCarts.remove(userId);\n  }\n}\n```\n```java\npublic class InMemoryOrderRepository implements OrderRepository {\n    private final List<Order> orders = new ArrayList<>();\n\n    @Override\n    public void saveOrder(Order order) {\n        orders.add(order);\n    }\n}\n```\n\n```java\npublic class InMemoryProductRepository implements ProductRepository {\n    private final Map<String, Product> products = new HashMap<>();\n\n    public InMemoryProductRepository() {\n        products.put(\"1\", new Product(\"1\", \"Laptop\", 1000.0));\n        products.put(\"2\", new Product(\"2\", \"Smartphone\", 500.0));\n    }\n\n    @Override\n    public Product getProductById(String productId) {\n        return products.get(productId);\n    }\n}\n```\n\nThe order controller coordinates the checkout process by using the use-case or service layer (`ShoppingCartService`).\n\n```java\npublic class OrderController{\n  private final ShoppingCartService shoppingCartUseCase;\n\n  public OrderController(ShoppingCartService shoppingCartUseCase) {\n    this.shoppingCartUseCase = shoppingCartUseCase;\n  }\n\n  public Order checkout(String userId) {\n    return shoppingCartUseCase.checkout(userId);\n  }\n}\n```\n\nThe cart controller focuses on cart-related actions like adding or removing items and calculating totals.\n\n\n```java\npublic class CartController {\n  private final ShoppingCartService shoppingCartUseCase;\n\n  public CartController(ShoppingCartService shoppingCartUseCase) {\n    this.shoppingCartUseCase = shoppingCartUseCase;\n  }\n\n  public void addItemToCart(String userId, String productId, int quantity) {\n    shoppingCartUseCase.addItemToCart(userId, productId, quantity);\n  }\n\n  public void removeItemFromCart(String userId, String productId) {\n    shoppingCartUseCase.removeItemFromCart(userId, productId);\n  }\n\n  public double calculateTotal(String userId) {\n    return shoppingCartUseCase.calculateTotal(userId);\n  }\n}\n```\n\nThe clean architecture in action. In the `main` method, we wire up everything, simulating a typical user flow: items are added to the cart, the total is calculated, and finally an order is placed.\n\n```java\npublic static void main(String[] args) {\n\n    ProductRepository productRepository = new InMemoryProductRepository();\n    CartRepository cartRepository = new InMemoryCartRepository();\n    OrderRepository orderRepository = new InMemoryOrderRepository();\n\n    ShoppingCartService shoppingCartUseCase =\n        new ShoppingCartService(productRepository, cartRepository, orderRepository);\n\n    CartController cartController = new CartController(shoppingCartUseCase);\n    OrderController orderController = new OrderController(shoppingCartUseCase);\n\n    String userId = \"user123\";\n    cartController.addItemToCart(userId, \"1\", 1); \n    cartController.addItemToCart(userId, \"2\", 2);\n\n    System.out.println(\"Total: $\" + cartController.calculateTotal(userId));\n\n    Order order = orderController.checkout(userId);\n    System.out.println(\n        \"Order placed! Order ID: \" + order.getOrderId() + \", Total: $\" + order.getTotalPrice());\n  }\n```\n\nThe output of the code.\n\n```md\nTotal: $2000.0\nOrder placed! Order ID: ORDER-1743349969254, Total: $2000.0\n```\n\n## When to Use the Clean Architecture Pattern in Java\n\n* When you want to keep business rules independent of UI, database, or any other external agency\n* When you need a high level of maintainability and testability in large Java applications\n* When you aim to enforce clear boundaries among application layers\n\n## Real-World Applications of Clean Architecture Pattern in Java\n\n* Large-scale enterprise systems in finance and insurance domains\n* Microservices-based architectures that prioritize decoupling and modular design\n* Java systems requiring stringent separation of concerns and domain-centered design\n\n## Benefits and Trade-offs of Clean Architecture Pattern\n\nBenefits: \n\n* High maintainability by isolating core logic from infrastructure details\n* Enhanced testability through clear boundaries around the domain model\n* Flexibility in replacing or upgrading external components without affecting core logic\n\nTrade-Offs:\n\n* Initial complexity from enforcing strict layers and boundaries\n* Potential overhead in smaller projects not requiring such rigid separation\n* Requires disciplined team adherence to architecture rules\n\n## Related Java Design Patterns\n\n* [Dependency Injection](https://java-design-patterns.com/patterns/dependency-injection/): Facilitates decoupling layers by injecting dependencies rather than hard-coding them\n* [Layered Architecture](https://java-design-patterns.com/patterns/layered-architecture/): Both separate concerns into distinct tiers but Clean Architecture emphasizes strict dependency rules\n* [Hexagonal Architecture](https://java-design-patterns.com/patterns/hexagonal-architecture/): Similar focus on isolating core logic with ports and adapters\n\n## References and Credits\n\n* [Clean Architecture: A Craftsman's Guide to Software Structure and Design](https://amzn.to/3UoKkaR)\n* [Clean Code: A Handbook of Agile Software Craftsmanship](https://amzn.to/3wRnjp5)\n* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3wlDrze)\n"
  },
  {
    "path": "clean-architecture/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>clean-architecture</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.cleanarchitecture.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Clean Architecture ensures separation of concerns by organizing code, into layers and making it\n * scalable and maintainable.\n *\n * <p>In the example there are Entities (Core Models) – Product, Cart, Order handle business logic.\n * Use Cases (Application Logic) – ShoppingCartService manages operations like adding items and\n * checkout. Interfaces & Adapters – Repositories (CartRepository, OrderRepository) abstract data\n * handling, while controllers (CartController, OrderController) manage interactions.\n */\n@Slf4j\npublic final class App {\n\n  private App() {\n    throw new UnsupportedOperationException(\"Utility class\");\n  }\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(final String[] args) {\n    ProductRepository productRepository = new InMemoryProductRepository();\n    CartRepository cartRepository = new InMemoryCartRepository();\n    OrderRepository orderRepository = new InMemoryOrderRepository();\n\n    ShoppingCartService shoppingCartUseCase =\n        new ShoppingCartService(productRepository, cartRepository, orderRepository);\n\n    CartController cartController = new CartController(shoppingCartUseCase);\n    OrderController orderController = new OrderController(shoppingCartUseCase);\n\n    String userId = \"user123\";\n    cartController.addItemToCart(userId, \"1\", 1);\n    cartController.addItemToCart(userId, \"2\", 2);\n\n    Order order = orderController.checkout(userId);\n    LOGGER.info(\"Total: ${}\", cartController.calculateTotal(userId));\n\n    LOGGER.info(\n        \"Order placed! Order ID: {}, Total: ${}\", order.getOrderId(), order.getTotalPrice());\n  }\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Cart.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\nimport lombok.Getter;\n\n/**\n * Represents a shopping cart containing a product and its quantity. This class calculates the total\n * price of the product based on its price and quantity.\n */\n@Getter\npublic class Cart {\n  /** The product in the cart. It holds the product details such as name, price, and description. */\n  private final Product product;\n\n  /**\n   * The quantity of the product in the cart. It represents how many units of the product are added\n   * to the cart.\n   */\n  private final int quantity;\n\n  /**\n   * Constructs a new Cart instance with a specified product and quantity.\n   *\n   * @param prod the product to be added to the cart.\n   * @param qty the quantity of the product in the cart.\n   */\n  public Cart(final Product prod, final int qty) {\n    this.product = prod;\n    this.quantity = qty;\n  }\n\n  /**\n   * Calculates the total price of the products in the cart. The total price is the product's price\n   * multiplied by the quantity.\n   *\n   * @return the total price of the products in the cart.\n   */\n  public double getTotalPrice() {\n    return product.getPrice() * quantity;\n  }\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\n/**\n * Controller class for handling shopping cart operations.\n *\n * <p>This class provides methods to add, remove, and calculate the total price of items in a user's\n * shopping cart.\n */\npublic class CartController {\n\n  /** Service layer responsible for cart operations. */\n  private final ShoppingCartService shoppingCartUseCase;\n\n  /**\n   * Constructs a CartController with the specified shopping cart service.\n   *\n   * @param shoppingCart The shopping cart service to handle cart operations.\n   */\n  public CartController(final ShoppingCartService shoppingCart) {\n    this.shoppingCartUseCase = shoppingCart;\n  }\n\n  /**\n   * Adds an item to the user's cart.\n   *\n   * @param userId The ID of the user.\n   * @param productId The ID of the product to be added.\n   * @param quantity The quantity of the product.\n   */\n  public void addItemToCart(final String userId, final String productId, final int quantity) {\n    shoppingCartUseCase.addItemToCart(userId, productId, quantity);\n  }\n\n  /**\n   * Removes an item from the user's cart.\n   *\n   * @param userId The ID of the user.\n   * @param productId The ID of the product to be removed.\n   */\n  public void removeItemFromCart(final String userId, final String productId) {\n    shoppingCartUseCase.removeItemFromCart(userId, productId);\n  }\n\n  /**\n   * Calculates the total cost of items in the user's cart.\n   *\n   * @param userId The ID of the user.\n   * @return The total price of all items in the cart.\n   */\n  public double calculateTotal(final String userId) {\n    return shoppingCartUseCase.calculateTotal(userId);\n  }\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/CartRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\nimport java.util.List;\n\n/** CartRepository. */\npublic interface CartRepository {\n  /**\n   * Adds an item to the user's cart.\n   *\n   * @param userId The ID of the user.\n   * @param product The product to be added.\n   * @param quantity The quantity of the product.\n   */\n  void addItemToCart(String userId, Product product, int quantity);\n\n  /**\n   * Removes an item from the user's cart.\n   *\n   * @param userId The ID of the user.\n   * @param productId The ID of the product to be removed.\n   */\n  void removeItemFromCart(String userId, String productId);\n\n  /**\n   * Retrieves the list of items in the user's cart.\n   *\n   * @param userId The ID of the user.\n   * @return A list of items in the cart.\n   */\n  List<Cart> getItemsInCart(String userId);\n\n  /**\n   * Calculates the total price of the items in the user's cart.\n   *\n   * @param userId The ID of the user.\n   * @return The total price of all items in the cart.\n   */\n  double calculateTotal(String userId);\n\n  /**\n   * Clears all items from the user's cart.\n   *\n   * @param userId The ID of the user.\n   */\n  void clearCart(String userId);\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryCartRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Implementation of {@link CartRepository} that stores cart items in memory.\n *\n * <p>This class maintains a map of user carts where each user has a list of cart items.\n */\npublic class InMemoryCartRepository implements CartRepository {\n  /** A map storing user carts with their respective cart items. */\n  private final Map<String, List<Cart>> userCarts = new HashMap<>();\n\n  /**\n   * Adds an item to the user's cart.\n   *\n   * @param userId The ID of the user.\n   * @param product The product to be added.\n   * @param quantity The quantity of the product.\n   */\n  @Override\n  public void addItemToCart(final String userId, final Product product, final int quantity) {\n    List<Cart> cart = userCarts.getOrDefault(userId, new ArrayList<>());\n    cart.add(new Cart(product, quantity));\n    userCarts.put(userId, cart);\n  }\n\n  /**\n   * Removes an item from the user's cart.\n   *\n   * @param userId The ID of the user.\n   * @param productId The ID of the product to be removed.\n   */\n  @Override\n  public void removeItemFromCart(final String userId, final String productId) {\n    List<Cart> cart = userCarts.get(userId);\n    if (cart != null) {\n      cart.removeIf(item -> item.getProduct().getId().equals(productId));\n    }\n  }\n\n  /**\n   * Retrieves all items in the user's cart.\n   *\n   * @param userId The ID of the user.\n   * @return A list of {@link Cart} items in the user's cart.\n   */\n  @Override\n  public List<Cart> getItemsInCart(final String userId) {\n    return userCarts.getOrDefault(userId, new ArrayList<>());\n  }\n\n  /**\n   * Calculates the total price of items in the user's cart.\n   *\n   * @param userId The ID of the user.\n   * @return The total price of the cart.\n   */\n  @Override\n  public double calculateTotal(final String userId) {\n    return userCarts.getOrDefault(userId, new ArrayList<>()).stream()\n        .mapToDouble(Cart::getTotalPrice)\n        .sum();\n  }\n\n  /**\n   * Clears all items from the user's cart.\n   *\n   * @param userId The ID of the user.\n   */\n  @Override\n  public void clearCart(final String userId) {\n    userCarts.remove(userId);\n  }\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryOrderRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * An in-memory implementation of the {@link OrderRepository}.\n *\n * <p>This class stores orders in a list, allowing orders to be saved but not persisted beyond the\n * application's runtime.\n */\npublic class InMemoryOrderRepository implements OrderRepository {\n  /** A list to store orders in memory. */\n  private final List<Order> orders = new ArrayList<>();\n\n  /**\n   * Saves an order to the in-memory repository.\n   *\n   * @param order The order to be saved.\n   */\n  @Override\n  public void saveOrder(final Order order) {\n    orders.add(order);\n  }\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/InMemoryProductRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * In-memory implementation of the {@link ProductRepository} interface.\n *\n * <p>This repository stores products in memory allowing retrieval by product ID.\n */\npublic class InMemoryProductRepository implements ProductRepository {\n  /** A map to store products by their unique product ID. */\n  private final Map<String, Product> products = new HashMap<>();\n\n  /**\n   * The price of the Laptop in USD.\n   *\n   * <p>Used in the in-memory product repository to define the cost of a Laptop.\n   */\n  private static final double LAPTOP_PRICE = 1000.0;\n\n  /**\n   * The price of the Smartphone in USD.\n   *\n   * <p>Used in the in-memory product repository to define the cost of a Smartphone.\n   */\n  private static final double SMARTPHONE_PRICE = 500.0;\n\n  /**\n   * Constructs an {@code InMemoryProductRepository} and initializes it with some example products.\n   */\n  public InMemoryProductRepository() {\n    products.put(\"1\", new Product(\"1\", \"Laptop\", LAPTOP_PRICE));\n    products.put(\"2\", new Product(\"2\", \"Smartphone\", SMARTPHONE_PRICE));\n  }\n\n  /**\n   * Retrieves a product by its unique ID.\n   *\n   * @param productId The ID of the product to retrieve.\n   * @return The {@link Product} corresponding to the given ID {@code null} if not found.\n   */\n  @Override\n  public Product getProductById(final String productId) {\n    return products.get(productId);\n  }\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Order.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\nimport java.util.List;\nimport lombok.Getter;\n\n/**\n * Represents an order placed by a user containing the ordered items and total price.\n *\n * <p>An order includes a unique order ID, a list of cart items and the total price of the order.\n */\n@Getter\npublic class Order {\n  /** The unique identifier for this order. */\n  private final String orderId;\n\n  /** The list of items included in this order. */\n  private final List<Cart> items;\n\n  /** The list of items included in this order. */\n  private final double totalPrice;\n\n  /**\n   * Constructs an {@code Order} with the given order ID and list of cart items. The total price is\n   * based on the individual item prices in the cart.\n   *\n   * @param id The unique identifier for the order.\n   * @param item The list of cart items included in the order.\n   */\n  public Order(final String id, final List<Cart> item) {\n    this.orderId = id;\n    this.items = item;\n    this.totalPrice = items.stream().mapToDouble(Cart::getTotalPrice).sum();\n  }\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\n/**\n * Controller for handling order-related operations.\n *\n * <p>This class provides an endpoint for users to checkout their cart and place an order.\n */\npublic class OrderController {\n  /** Service for managing shopping cart operations. */\n  private final ShoppingCartService shoppingCartUseCase;\n\n  /**\n   * Constructs an {@code OrderController} with the given shopping cart service.\n   *\n   * @param shoppingCartUse The shopping cart service used to process orders.\n   */\n  public OrderController(final ShoppingCartService shoppingCartUse) {\n    this.shoppingCartUseCase = shoppingCartUse;\n  }\n\n  /**\n   * Processes the checkout for a given user and creates an order.\n   *\n   * @param userId The ID of the user checking out.\n   * @return The created {@link Order} after checkout.\n   */\n  public Order checkout(final String userId) {\n    return shoppingCartUseCase.checkout(userId);\n  }\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/OrderRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\n/**\n * Repository interface for managing order persistence.\n *\n * <p>This interface defines the contract for storing orders in the system.\n */\npublic interface OrderRepository {\n  /**\n   * Saves an order to the repository.\n   *\n   * @param order The order to be saved.\n   */\n  void saveOrder(Order order);\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/Product.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\nimport lombok.Getter;\n\n/** Represents a product in the system. */\n@Getter\npublic class Product {\n  /** The unique identifier for the product. */\n  private final String id;\n\n  /** The name of the product. */\n  private final String name;\n\n  /** The price of the product. */\n  private final double price;\n\n  /**\n   * Constructs a new Product with the given details.\n   *\n   * @param pdtId The unique identifier of the product.\n   * @param firstName The name of the product.\n   * @param p The price of the product.\n   */\n  public Product(final String pdtId, final String firstName, final double p) {\n    this.id = pdtId;\n    this.name = firstName;\n    this.price = p;\n  }\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ProductRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\n/** Repository interface for handling product-related operations. */\npublic interface ProductRepository {\n  /**\n   * Retrieves a product by its unique identifier.\n   *\n   * @param productId The unique ID of the product.\n   * @return The product corresponding to the given ID.\n   */\n  Product getProductById(String productId);\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/ShoppingCartService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\nimport java.util.List;\n\n/**\n * Service class for managing shopping cart operations.\n *\n * <p>This class provides functionalities to add and remove items from the cart, calculate the total\n * price, and handle checkout operations.\n */\npublic class ShoppingCartService {\n  /** Repository for managing product data. */\n  private final ProductRepository productRepository;\n\n  /** Repository for managing cart data. */\n  private final CartRepository cartRepository;\n\n  /** Repository for managing order data. */\n  private final OrderRepository orderRepository;\n\n  /**\n   * Constructs a ShoppingCartService with the required repositories.\n   *\n   * @param pdtRepository The repository to fetch product details.\n   * @param repository The repository to manage cart operations.\n   * @param ordRepository The repository to handle order persistence.\n   */\n  public ShoppingCartService(\n      final ProductRepository pdtRepository,\n      final CartRepository repository,\n      final OrderRepository ordRepository) {\n    this.productRepository = pdtRepository;\n    this.cartRepository = repository;\n    this.orderRepository = ordRepository;\n  }\n\n  /**\n   * Adds an item to the user's shopping cart.\n   *\n   * @param userId The ID of the user.\n   * @param productId The ID of the product to be added.\n   * @param quantity The quantity of the product.\n   */\n  public void addItemToCart(final String userId, final String productId, final int quantity) {\n    Product product = productRepository.getProductById(productId);\n    if (product != null) {\n      cartRepository.addItemToCart(userId, product, quantity);\n    }\n  }\n\n  /**\n   * Removes an item from the user's shopping cart.\n   *\n   * @param userId The ID of the user.\n   * @param productId The ID of the product to be removed.\n   */\n  public void removeItemFromCart(final String userId, final String productId) {\n    cartRepository.removeItemFromCart(userId, productId);\n  }\n\n  /**\n   * Calculates the total cost of items in the user's shopping cart.\n   *\n   * @param userId The ID of the user.\n   * @return The total price of all items in the cart.\n   */\n  public double calculateTotal(final String userId) {\n    return cartRepository.calculateTotal(userId);\n  }\n\n  /**\n   * Checks out the user's cart and creates an order.\n   *\n   * <p>This method retrieves the cart items, generates an order ID, creates a new order, saves it,\n   * and clears the cart.\n   *\n   * @param userId The ID of the user.\n   * @return The created order containing purchased items.\n   */\n  public Order checkout(final String userId) {\n    List<Cart> items = cartRepository.getItemsInCart(userId);\n    String orderId = \"ORDER-\" + System.currentTimeMillis();\n    Order order = new Order(orderId, items);\n    orderRepository.saveOrder(order);\n    cartRepository.clearCart(userId);\n    return order;\n  }\n}\n"
  },
  {
    "path": "clean-architecture/src/main/java/com/iluwatar/cleanarchitecture/package-info.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/**\n * Provides classes and interfaces for the clean architecture pattern implementation.\n *\n * <p>This package includes classes for managing products, carts, orders, repositories, and services\n * for a shopping cart system, following the clean architecture principles.\n */\npackage com.iluwatar.cleanarchitecture;\n"
  },
  {
    "path": "clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "clean-architecture/src/test/java/com/iluwatar/cleanarchitecture/CartControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cleanarchitecture;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass CartControllerTest {\n\n  private CartController cartController;\n\n  @BeforeEach\n  void setUp() {\n    ProductRepository productRepository = new InMemoryProductRepository();\n    CartRepository cartRepository = new InMemoryCartRepository();\n    OrderRepository orderRepository = new InMemoryOrderRepository();\n    ShoppingCartService shoppingCartUseCase =\n        new ShoppingCartService(productRepository, cartRepository, orderRepository);\n    cartController = new CartController(shoppingCartUseCase);\n  }\n\n  @Test\n  void testRemoveItemFromCart() {\n    cartController.addItemToCart(\"user123\", \"1\", 1);\n    cartController.addItemToCart(\"user123\", \"2\", 2);\n\n    assertEquals(2000.0, cartController.calculateTotal(\"user123\"));\n\n    cartController.removeItemFromCart(\"user123\", \"1\");\n\n    assertEquals(1000.0, cartController.calculateTotal(\"user123\"));\n  }\n\n  @Test\n  void testRemoveNonExistentItem() {\n    cartController.addItemToCart(\"user123\", \"2\", 2);\n    cartController.removeItemFromCart(\"user123\", \"999\");\n\n    assertEquals(1000.0, cartController.calculateTotal(\"user123\"));\n  }\n}\n"
  },
  {
    "path": "client-session/README.md",
    "content": "---\ntitle: \"Client-Session Pattern in Java: Streamlining Client Data Across Sessions\"\nshortTitle: Client Session\ndescription: \"Explore the Client Session design pattern in Java. Learn how to manage user state and data across multiple requests for seamless, personalized web application experiences.\"\ncategory: Behavioral\nlanguage: en\ntags:\n  - Client-server\n  - Session management\n  - State tracking\n  - Web development\n---\n\n## Also known as\n\n* User Session\n\n## Intent of Client Session Design Pattern\n\nThe Client Session design pattern is essential for web development involving client-server interactions. It aims to maintain a user's state and data across multiple requests within a web application, ensuring a continuous and personalized user experience. This pattern helps in creating a seamless user experience by managing user state and data effectively across different sessions, crucial for modern web applications.\n\n## Detailed Explanation of Client Session Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world example of the Client Session pattern is a library membership system. When a member logs in, the system starts a session to track their borrowing activities. This session holds data such as the member's ID, current borrowed books, due dates, and any fines. As the member browses the catalog, borrows books, or returns them, the session maintains this stateful information, ensuring the member's interactions are consistent and personalized until they log out or the session expires. This approach helps the library system manage user-specific data efficiently across multiple interactions, providing a seamless and personalized experience for the members.\n\nIn plain words\n\n> The Client Session pattern manages user-specific data across multiple requests within a web application to maintain continuity and personalization.\n\nWikipedia says\n\n> The client-server model on Wikipedia describes a system where client devices request services and resources from centralized servers. This model is crucial in web applications where client sessions are used to manage user-specific data across multiple requests. For example, when a bank customer accesses online banking services, their login credentials and session state are managed by the web server to maintain continuity of their interactions.\n\nSequence diagram\n\n![Client Session sequence diagram](./etc/client-session-sequence-diagram.png)\n\n## Programmatic Example of Client Session Pattern in Java\n\nThe Client Session design pattern is a behavioral design pattern that maintains a user's state and data across multiple requests within a web application, ensuring a continuous and personalized user experience. This pattern is commonly used in web applications where user-specific data needs to be managed across multiple requests.\n\nIn the given code, we have a `Server` class and a `Session` class. The `Server` class represents the server that processes incoming requests and assigns sessions to clients. The `Session` class represents a session that is assigned to a client.\n\n```java\n// The Server class represents the server that processes incoming requests and assigns sessions to clients.\npublic class Server {\n  private String host;\n  private int port;\n\n  public Server(String host, int port) {\n    this.host = host;\n    this.port = port;\n  }\n\n  // Other methods...\n\n  // This method returns a new session for a client.\n  public Session getSession(String name) {\n    return new Session(name, \"ClientName\");\n  }\n\n  // This method processes a request from a client.\n  public void process(Request request) {\n    // Process the request...\n  }\n}\n\n// The Session class represents a session that is assigned to a client.\npublic class Session {\n  private String id;\n  private String clientName;\n\n  public Session(String id, String clientName) {\n    this.id = id;\n    this.clientName = clientName;\n  }\n\n  // Other methods...\n}\n```\n\nIn the `main` method, we create an instance of `Server`, create two sessions for two different clients, and then pass these sessions to the server in the request along with the data. The server is then able to interpret the client based on the session associated with it.\n\n```java\npublic class App {\n  public static void main(String[] args) {\n    var server = new Server(\"localhost\", 8080);\n    var session1 = server.getSession(\"Session1\");\n    var session2 = server.getSession(\"Session2\");\n    var request1 = new Request(\"Data1\", session1);\n    var request2 = new Request(\"Data2\", session2);\n    server.process(request1);\n    server.process(request2);\n  }\n}\n```\n\nIn this example, the `Server` class is responsible for creating and managing sessions for clients, and the `Session` class represents the client's session. The `Request` class represents a request from a client, which includes the client's session and data. The server processes the request based on the client's session.\n\nRunning the program produces the following console output:\n\n```\n19:28:49.152 [main] INFO com.iluwatar.client.session.Server -- Processing Request with client: Session1 data: Data1\n19:28:49.154 [main] INFO com.iluwatar.client.session.Server -- Processing Request with client: Session2 data: Data2\n```\n\n## When to Use the Client Session Pattern in Java\n\nUse the client state pattern when:\n\n* Web applications requiring user authentication and authorization.\n* Applications needing to track user activities and preferences over multiple requests or visits.\n* Systems where server resources need to be optimized by offloading state management to the client side.\n\n## Real-World Applications of Client Session Pattern in Java\n\n* E-commerce websites to track shopping cart contents across sessions.\n* Online platforms that offer personalized content based on user preferences and history.\n* Web applications requiring user login to access personalized or secured content.\n\n## Benefits and Trade-offs of Client Session Pattern\n\nBenefits:\n\n* Improved server performance by reducing the need to store user state on the server.\n* Enhanced user experience through personalized content and seamless navigation across different parts of the application.\n* Flexibility in managing sessions through various client-side storage mechanisms (e.g., cookies, Web Storage API).\n\nTrade-offs:\n\n* Potential security risks if sensitive information is stored in client sessions without proper encryption and validation.\n* Dependence on client-side capabilities and settings, such as cookie policies, which can vary across browsers and user configurations.\n* Increased complexity in session management logic, especially in handling session expiration, renewal, and synchronization across multiple devices or tabs.\n\n## Related Patterns\n\n* Server Session: Often used in conjunction with the Client Session pattern to provide a balance between client-side efficiency and server-side control.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Ensuring a single instance of a user's session throughout the application.\n* [State](https://java-design-patterns.com/patterns/state/): Managing state transitions in a session, such as authenticated, guest, or expired states.\n\n## References and Credits\n\n* [Professional Java for Web Applications](https://amzn.to/4aazY59)\n* [Securing Web Applications with Spring Security](https://amzn.to/3PCCEA1)\n* [Client Session State Design Pattern: Explained Simply (Ram N Java)](https://www.youtube.com/watch?v=ycOSj9g41pc)\n"
  },
  {
    "path": "client-session/etc/client-session.urm.puml",
    "content": "@startuml\npackage com.iluwatar.client.session {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Request {\n    - data : String\n    - session : Session\n    + Request(data : String, session : Session)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getData() : String\n    + getSession() : Session\n    + hashCode() : int\n    + setData(data : String)\n    + setSession(session : Session)\n    + toString() : String\n  }\n  class Server {\n    - LOGGER : Logger {static}\n    - host : String\n    - port : int\n    + Server(host : String, port : int)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getHost() : String\n    + getPort() : int\n    + getSession(name : String) : Session\n    + hashCode() : int\n    + process(request : Request)\n    + setHost(host : String)\n    + setPort(port : int)\n    + toString() : String\n  }\n  class Session {\n    - clientName : String\n    - id : String\n    + Session(id : String, clientName : String)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getClientName() : String\n    + getId() : String\n    + hashCode() : int\n    + setClientName(clientName : String)\n    + setId(id : String)\n    + toString() : String\n  }\n}\nRequest -->  \"-session\" Session\n@enduml"
  },
  {
    "path": "client-session/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>client-session</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.client.session.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "client-session/src/main/java/com/iluwatar/client/session/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.client.session;\n\n/**\n * The Client-Session pattern allows the session data to be stored on the client side and send this\n * data to the server with each request.\n *\n * <p>In this example, The {@link Server} class represents the server that would process the\n * incoming {@link Request} and also assign {@link Session} to a client. Here one instance of Server\n * is created. The we create two sessions for two different clients. These sessions are then passed\n * on to the server in the request along with the data. The server is then able to interpret the\n * client based on the session associated with it.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args Command line args\n   */\n  public static void main(String[] args) {\n    var server = new Server(\"localhost\", 8080);\n    var session1 = server.getSession(\"Session1\");\n    var session2 = server.getSession(\"Session2\");\n    var request1 = new Request(\"Data1\", session1);\n    var request2 = new Request(\"Data2\", session2);\n    server.process(request1);\n    server.process(request2);\n  }\n}\n"
  },
  {
    "path": "client-session/src/main/java/com/iluwatar/client/session/Request.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.client.session;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\n/** The Request class which contains the Session details and data. */\n@Data\n@AllArgsConstructor\npublic class Request {\n\n  private String data;\n\n  private Session session;\n}\n"
  },
  {
    "path": "client-session/src/main/java/com/iluwatar/client/session/Server.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.client.session;\n\nimport java.util.UUID;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Server class. The client communicates with the server and request processing and getting a\n * new session.\n */\n@Slf4j\n@Data\n@AllArgsConstructor\npublic class Server {\n  private String host;\n\n  private int port;\n\n  /**\n   * Creates a new session.\n   *\n   * @param name name of the client\n   * @return Session Object\n   */\n  public Session getSession(String name) {\n    return new Session(UUID.randomUUID().toString(), name);\n  }\n\n  /**\n   * Processes a request based on the session.\n   *\n   * @param request Request object with data and Session\n   */\n  public void process(Request request) {\n    LOGGER.info(\n        \"Processing Request with client: \"\n            + request.getSession().getClientName()\n            + \" data: \"\n            + request.getData());\n  }\n}\n"
  },
  {
    "path": "client-session/src/main/java/com/iluwatar/client/session/Session.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.client.session;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\n/**\n * The Session class. Each client get assigned a Session which is then used for further\n * communications.\n */\n@Data\n@AllArgsConstructor\npublic class Session {\n\n  /** Session id. */\n  private String id;\n\n  /** Client name. */\n  private String clientName;\n}\n"
  },
  {
    "path": "client-session/src/test/java/com/iluwatar/client/session/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.client.session;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n\n  @Test\n  void appStartsWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "client-session/src/test/java/com/iluwatar/client/session/ServerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.client.session;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\nclass ServerTest {\n\n  @Test\n  void checkGetSession() {\n    Server server = new Server(\"localhost\", 8080);\n    Session session = server.getSession(\"Session\");\n    assertEquals(\"Session\", session.getClientName());\n  }\n}\n"
  },
  {
    "path": "collecting-parameter/README.md",
    "content": "---\ntitle: \"Collecting Parameter Pattern in Java: Mastering Efficient Parameter Handling\"\nshortTitle: Collecting Parameter\ndescription: \"Discover how the Collecting Parameter design pattern simplifies Java method calls by aggregating multiple parameters into a single collection object. Enhance code readability and maintainability with practical examples and real-world applications.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Accumulation\n  - Data processing\n  - Data transfer\n  - Generic\n---\n\n## Also known as\n\n* Collector\n* Accumulator\n\n## Intent of Collecting Parameter Design Pattern\n\nThe Collecting Parameter pattern in Java design patterns aims to simplify method calls by aggregating multiple parameters into a single collection object. This pattern is particularly effective for methods that collect information by passing a single collection object through various method calls. Each method can then add results to this collection, instead of creating its own collection. This approach enhances code readability and maintainability, optimizing the process of information collection in Java programming.\n\n## Detailed Explanation of Collecting Parameter Pattern with Real-World Examples\n\nReal-world example\n\n> In software development, the Collecting Parameter pattern provides significant benefits by optimizing method calls and improving code maintainability.\n> \n> Imagine a scenario in a restaurant where a waiter needs to take an order from a customer. Instead of noting down each item separately (e.g., appetizer, main course, dessert, drink), the waiter uses an order form that collects all the items into a single document. This order form simplifies the communication between the waiter and the kitchen staff by aggregating all the details into one place. Similarly, in software, the Collecting Parameter pattern aggregates multiple parameters into a single object, streamlining method calls and improving code readability and maintainability.\n\nIn plain words\n\n> The Collecting Parameter pattern simplifies method calls by encapsulating multiple parameters into a single object.\n\nWikipedia says\n\n> In the Collecting Parameter idiom a collection (list, map, etc.) is passed repeatedly as a parameter to a method which adds items to the collection.\n\nFlowchart\n\n![Collecting Parameter flowchart](./etc/collecting-parameter-flowchart.png)\n\n## Programmatic Example of Collecting Parameter Pattern in Java\n\nWithin a large corporate building, there exists a global printer queue that is a collection of all the printing jobs that are currently pending. Various floors contain different models of printers, each having a different printing policy. We must construct a program that can continually add appropriate printing jobs to a collection, which is called the collecting parameter.\n\nThe following business rules are implemented:\n\n* If an A4 paper is coloured, it must also be single-sided. All other non-coloured papers are accepted\n* A3 papers must be non-coloured and single-sided\n* A2 papers must be single-page, single-sided, and non-coloured\n\nLet's see the implementation first and explain afterward.\n\n```java\npublic class App {\n  static PrinterQueue printerQueue = PrinterQueue.getInstance();\n\n  public static void main(String[] args) {\n    printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A4, 5, false, false));\n    printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A3, 2, false, false));\n    printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A2, 5, false, false));\n\n    var result = new LinkedList<PrinterItem>();\n\n    addValidA4Papers(result);\n    addValidA3Papers(result);\n    addValidA2Papers(result);\n  }\n\n  public static void addValidA4Papers(Queue<PrinterItem> printerItemsCollection) {\n    for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n      if (nextItem.paperSize.equals(PaperSizes.A4)) {\n        var isColouredAndSingleSided = nextItem.isColour && !nextItem.isDoubleSided;\n        if (isColouredAndSingleSided || !nextItem.isColour) {\n          printerItemsCollection.add(nextItem);\n        }\n      }\n    }\n  }\n\n  public static void addValidA3Papers(Queue<PrinterItem> printerItemsCollection) {\n    for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n      if (nextItem.paperSize.equals(PaperSizes.A3)) {\n        var isNotColouredAndSingleSided = !nextItem.isColour && !nextItem.isDoubleSided;\n        if (isNotColouredAndSingleSided) {\n          printerItemsCollection.add(nextItem);\n        }\n      }\n    }\n  }\n\n  public static void addValidA2Papers(Queue<PrinterItem> printerItemsCollection) {\n    for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n      if (nextItem.paperSize.equals(PaperSizes.A2)) {\n        var isNotColouredSingleSidedAndOnePage = nextItem.pageCount == 1 && !nextItem.isDoubleSided\n                && !nextItem.isColour;\n        if (isNotColouredSingleSidedAndOnePage) {\n          printerItemsCollection.add(nextItem);\n        }\n      }\n    }\n  }\n}\n```\n\nThis `App` class is the main entry point of the application. It uses the Collecting Parameter design pattern to filter print jobs based on certain policies.\n\n1. **Initialization**: The `printerQueue` is initialized with three print jobs of different paper sizes (A4, A3, A2).\n\n2. **Creating the Collecting Parameter**: A `LinkedList` named `result` is created to store the print jobs that meet the policy requirements.\n\n3. **Adding Valid Jobs to the Collecting Parameter**: The `addValidA4Papers`, `addValidA3Papers`, and `addValidA2Papers` methods are called. These methods iterate over the `printerQueue` and add the print jobs that meet the policy requirements to the `result` list.\n\nThe `result` list, which is the collecting parameter, accumulates the valid print jobs as it is passed from method to method. This is the essence of the Collecting Parameter design pattern.\n\nUtilizing the Collecting Parameter pattern in Java design patterns leads to more efficient method calls and improved overall code structure.\n\n## When to Use the Collecting Parameter Pattern in Java\n\nThis pattern is useful for managing parameters in Java coding practices, ensuring efficient code refactoring and enhanced readability.\n\n* Use when a method needs to accept a large number of parameters, making the method signature unwieldy.\n* Use when the same group of parameters is passed to multiple methods, reducing redundancy and potential errors.\n* Use to improve the readability and maintainability of the code.\n\n## Collecting Parameter Pattern Java Tutorials\n\n* [Refactoring To Patterns (Joshua Kerivsky)](http://www.tarrani.net/RefactoringToPatterns.pdf)\n* [Smalltalk Best Practice Patterns (Kent Beck)](https://ptgmedia.pearsoncmg.com/images/9780134769042/samplepages/013476904X.pdf)\n\n## Real-World Applications of Collecting Parameter Pattern in Java\n\n* Use when a method needs to accept a large number of parameters, making the method signature unwieldy.\n* Use when the same group of parameters is passed to multiple methods, reducing redundancy and potential errors.\n* Use to improve the readability and maintainability of the code.\n\n## Benefits and Trade-offs of Collecting Parameter Pattern\n\nBenefits:\n\n* Improves code readability by reducing the number of parameters in method signatures.\n* Facilitates the reuse of parameter sets across different methods.\n* Enhances maintainability by centralizing the parameter structure.\n\nTrade-offs:\n\n* Introduces an additional class, which may increase complexity if not managed properly.\n* Can lead to over-generalization if the parameter object becomes too large or unwieldy.\n\n## Related Java Design Patterns\n\n* [Command](https://java-design-patterns.com/patterns/command/): Commands may utilize Collecting Parameter to aggregate results from multiple operations executed by the command objects.\n* [Composite](https://java-design-patterns.com/patterns/composite/): Can be used in tandem with Collecting Parameter when dealing with hierarchical structures, allowing results to be collected across a composite structure.\n* [Visitor](https://java-design-patterns.com/patterns/visitor/): Often used together, where Visitor handles traversal and operations on a structure, and Collecting Parameter accumulates the results.\n\n## References and Credits\n\n* [Clean Code: A Handbook of Agile Software Craftsmanship](https://amzn.to/4aApLP0)\n* [Refactoring: Improving the Design of Existing Code](https://amzn.to/3TVEgaB)\n* [Collecting Parameter (WikiWikiWeb)](https://wiki.c2.com/?CollectingParameter)\n"
  },
  {
    "path": "collecting-parameter/etc/collecting-parameter.urm.puml",
    "content": "@startuml\npackage com.iluwatar.collectingparameter {\n  class App {\n    ~ printerQueue : PrinterQueue {static}\n    + App()\n    + addValidA2Papers(printerItemsCollection : Queue<PrinterItem>) {static}\n    + addValidA3Papers(printerItemsCollection : Queue<PrinterItem>) {static}\n    + addValidA4Papers(printerItemsCollection : Queue<PrinterItem>) {static}\n    + main(args : String[]) {static}\n  }\n  ~enum PaperSizes {\n    + A2 {static}\n    + A3 {static}\n    + A4 {static}\n    + valueOf(name : String) : PaperSizes {static}\n    + values() : PaperSizes[] {static}\n  }\n  class PrinterItem {\n    ~ isColour : boolean\n    ~ isDoubleSided : boolean\n    ~ pageCount : int\n    ~ paperSize : PaperSizes\n    + PrinterItem(paperSize : PaperSizes, pageCount : int, isDoubleSided : boolean, isColour : boolean)\n  }\n  class PrinterQueue {\n    ~ currentInstance : PrinterQueue {static}\n    - printerItemQueue : Queue<PrinterItem>\n    - PrinterQueue()\n    + addPrinterItem(printerItem : PrinterItem)\n    + emptyQueue()\n    + getInstance() : PrinterQueue {static}\n    + getPrinterQueue() : Queue<PrinterItem>\n  }\n}\nPrinterQueue -->  \"-currentInstance\" PrinterQueue\nPrinterQueue -->  \"-printerItemQueue\" PrinterItem\nApp -->  \"-printerQueue\" PrinterQueue\nPrinterItem -->  \"-paperSize\" PaperSizes\n@enduml"
  },
  {
    "path": "collecting-parameter/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>java-design-patterns</artifactId>\n        <groupId>com.iluwatar</groupId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>collecting-parameter</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.collectingparameter.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "collecting-parameter/src/main/java/com/iluwatar/collectingparameter/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectingparameter;\n\nimport java.util.LinkedList;\nimport java.util.Queue;\n\n/**\n * The Collecting Parameter Design Pattern aims to return a result that is the collaborative result\n * of several methods. This design pattern uses a 'collecting parameter' that is passed to several\n * functions, accumulating results as it travels from method-to-method. This is different to the\n * Composed Method design pattern, where a single collection is modified via several methods.\n *\n * <p>This example is inspired by Kent Beck's example in his book, 'Smalltalk Best Practice\n * Patterns'. The context for this situation is that there is a single printer queue {@link\n * PrinterQueue} that holds numerous print jobs {@link PrinterItem} that must be distributed to\n * various print centers. Each print center has its own requirements and printing limitations. In\n * this example, the following requirements are: If an A4 document is coloured, it must also be\n * single-sided. All other non-coloured A4 documents are accepted. All A3 documents must be\n * non-coloured and single sided. All A2 documents must be a single page, single sided, and\n * non-coloured.\n *\n * <p>A collecting parameter (the result variable) is used to filter the global printer queue so\n * that it meets the requirements for this centre,\n */\npublic class App {\n  static PrinterQueue printerQueue = PrinterQueue.getInstance();\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    /*\n      Initialising the printer queue with jobs\n    */\n    printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A4, 5, false, false));\n    printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A3, 2, false, false));\n    printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A2, 5, false, false));\n\n    /*\n      This variable is the collecting parameter, and will store the policy abiding print jobs.\n    */\n    var result = new LinkedList<PrinterItem>();\n\n    /*\n      Adding A4, A3, and A2 papers that obey the policy\n    */\n    addValidA4Papers(result);\n    addValidA3Papers(result);\n    addValidA2Papers(result);\n  }\n\n  /**\n   * Adds A4 document jobs to the collecting parameter according to some policy that can be whatever\n   * the client (the print center) wants.\n   *\n   * @param printerItemsCollection the collecting parameter\n   */\n  public static void addValidA4Papers(Queue<PrinterItem> printerItemsCollection) {\n    /*\n     Iterate through the printer queue, and add A4 papers according to the correct policy to the collecting parameter,\n     which is 'printerItemsCollection' in this case.\n    */\n    for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n      if (nextItem.paperSize.equals(PaperSizes.A4)) {\n        var isColouredAndSingleSided = nextItem.isColour && !nextItem.isDoubleSided;\n        if (isColouredAndSingleSided || !nextItem.isColour) {\n          printerItemsCollection.add(nextItem);\n        }\n      }\n    }\n  }\n\n  /**\n   * Adds A3 document jobs to the collecting parameter according to some policy that can be whatever\n   * the client (the print center) wants. The code is similar to the 'addA4Papers' method. The code\n   * can be changed to accommodate the wants of the client.\n   *\n   * @param printerItemsCollection the collecting parameter\n   */\n  public static void addValidA3Papers(Queue<PrinterItem> printerItemsCollection) {\n    for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n      if (nextItem.paperSize.equals(PaperSizes.A3)) {\n\n        // Encoding the policy into a Boolean: the A3 paper cannot be coloured and double-sided at\n        // the same time\n        var isNotColouredAndSingleSided = !nextItem.isColour && !nextItem.isDoubleSided;\n        if (isNotColouredAndSingleSided) {\n          printerItemsCollection.add(nextItem);\n        }\n      }\n    }\n  }\n\n  /**\n   * Adds A2 document jobs to the collecting parameter according to some policy that can be whatever\n   * the client (the print center) wants. The code is similar to the 'addA4Papers' method. The code\n   * can be changed to accommodate the wants of the client.\n   *\n   * @param printerItemsCollection the collecting parameter\n   */\n  public static void addValidA2Papers(Queue<PrinterItem> printerItemsCollection) {\n    for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n      if (nextItem.paperSize.equals(PaperSizes.A2)) {\n\n        // Encoding the policy into a Boolean: the A2 paper must be single page, single-sided, and\n        // non-coloured.\n        var isNotColouredSingleSidedAndOnePage =\n            nextItem.pageCount == 1 && !nextItem.isDoubleSided && !nextItem.isColour;\n        if (isNotColouredSingleSidedAndOnePage) {\n          printerItemsCollection.add(nextItem);\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "collecting-parameter/src/main/java/com/iluwatar/collectingparameter/PaperSizes.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectingparameter;\n\nenum PaperSizes {\n  A2,\n  A3,\n  A4\n}\n"
  },
  {
    "path": "collecting-parameter/src/main/java/com/iluwatar/collectingparameter/PrinterItem.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectingparameter;\n\nimport java.util.Objects;\n\n/** This class represents a Print Item, that should be added to the queue. */\npublic class PrinterItem {\n  PaperSizes paperSize;\n  int pageCount;\n  boolean isDoubleSided;\n  boolean isColour;\n\n  /** The {@link PrinterItem} constructor. */\n  public PrinterItem(PaperSizes paperSize, int pageCount, boolean isDoubleSided, boolean isColour) {\n    if (!Objects.isNull(paperSize)) {\n      this.paperSize = paperSize;\n    } else {\n      throw new IllegalArgumentException();\n    }\n\n    if (pageCount > 0) {\n      this.pageCount = pageCount;\n    } else {\n      throw new IllegalArgumentException();\n    }\n\n    this.isColour = isColour;\n    this.isDoubleSided = isDoubleSided;\n  }\n}\n"
  },
  {
    "path": "collecting-parameter/src/main/java/com/iluwatar/collectingparameter/PrinterQueue.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectingparameter;\n\nimport java.util.LinkedList;\nimport java.util.Objects;\nimport java.util.Queue;\n\n/**\n * This class represents a singleton Printer Queue. It contains a queue that can be filled up with\n * {@link PrinterItem}.\n */\npublic class PrinterQueue {\n\n  static PrinterQueue currentInstance = null;\n  private final Queue<PrinterItem> printerItemQueue;\n\n  /**\n   * This class is a singleton. The getInstance method will ensure that only one instance exists at\n   * a time.\n   */\n  public static PrinterQueue getInstance() {\n    if (Objects.isNull(currentInstance)) {\n      currentInstance = new PrinterQueue();\n    }\n    return currentInstance;\n  }\n\n  /** Empty the printer queue. */\n  public void emptyQueue() {\n    currentInstance.getPrinterQueue().clear();\n  }\n\n  /** Private constructor prevents instantiation, unless using the getInstance() method. */\n  private PrinterQueue() {\n    printerItemQueue = new LinkedList<>();\n  }\n\n  public Queue<PrinterItem> getPrinterQueue() {\n    return currentInstance.printerItemQueue;\n  }\n\n  /**\n   * Adds a single print job to the queue.\n   *\n   * @param printerItem The printing job to be added to the queue\n   */\n  public void addPrinterItem(PrinterItem printerItem) {\n    currentInstance.getPrinterQueue().add(printerItem);\n  }\n}\n"
  },
  {
    "path": "collecting-parameter/src/test/java/com/iluwatar/collectingparameter/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectingparameter;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n  /** Checks whether {@link App} executes without throwing exception */\n  @Test\n  void executesWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "collecting-parameter/src/test/java/com/iluwatar/collectingparameter/CollectingParameterTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectingparameter;\n\nimport java.util.LinkedList;\nimport java.util.Queue;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.Timeout;\n\nclass CollectingParameterTest {\n\n  @Test\n  @Timeout(1000)\n  void testCollectingParameter() {\n    PrinterQueue printerQueue = PrinterQueue.getInstance();\n    printerQueue.emptyQueue();\n\n    PrinterItem item1 = new PrinterItem(PaperSizes.A4, 1, false, true);\n    PrinterItem item2 = new PrinterItem(PaperSizes.A4, 10, true, false);\n    PrinterItem item3 = new PrinterItem(PaperSizes.A4, 4, true, true);\n    PrinterItem item4 = new PrinterItem(PaperSizes.A3, 9, false, false);\n    PrinterItem item5 = new PrinterItem(PaperSizes.A3, 3, true, true);\n    PrinterItem item6 = new PrinterItem(PaperSizes.A3, 3, false, true);\n    PrinterItem item7 = new PrinterItem(PaperSizes.A3, 3, true, false);\n    PrinterItem item8 = new PrinterItem(PaperSizes.A2, 1, false, false);\n    PrinterItem item9 = new PrinterItem(PaperSizes.A2, 2, false, false);\n    PrinterItem item10 = new PrinterItem(PaperSizes.A2, 1, true, false);\n    PrinterItem item11 = new PrinterItem(PaperSizes.A2, 1, false, true);\n\n    printerQueue.addPrinterItem(item1);\n    printerQueue.addPrinterItem(item2);\n    printerQueue.addPrinterItem(item3);\n    printerQueue.addPrinterItem(item4);\n    printerQueue.addPrinterItem(item5);\n    printerQueue.addPrinterItem(item6);\n    printerQueue.addPrinterItem(item7);\n    printerQueue.addPrinterItem(item8);\n    printerQueue.addPrinterItem(item9);\n    printerQueue.addPrinterItem(item10);\n    printerQueue.addPrinterItem(item11);\n\n    Queue<PrinterItem> result = new LinkedList<>();\n    App.addValidA4Papers(result);\n    App.addValidA3Papers(result);\n    App.addValidA2Papers(result);\n\n    Queue<PrinterItem> testResult = new LinkedList<>();\n    testResult.add(item1);\n    testResult.add(item2);\n    testResult.add(item4);\n    testResult.add(item8);\n\n    Assertions.assertArrayEquals(testResult.toArray(), result.toArray());\n  }\n}\n"
  },
  {
    "path": "collecting-parameter/src/test/java/com/iluwatar/collectingparameter/PrinterQueueTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectingparameter;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.Timeout;\n\nclass PrinterQueueTest {\n\n  @Test\n  @Timeout(1000)\n  void singletonTest() {\n    PrinterQueue printerQueue1 = PrinterQueue.getInstance();\n    PrinterQueue printerQueue2 = PrinterQueue.getInstance();\n    assertSame(printerQueue1, printerQueue2);\n  }\n\n  @Test()\n  @Timeout(1000)\n  void negativePageCount() throws IllegalArgumentException {\n    Assertions.assertThrows(\n        IllegalArgumentException.class, () -> new PrinterItem(PaperSizes.A4, -1, true, true));\n  }\n\n  @Test()\n  @Timeout(1000)\n  void nullPageSize() throws IllegalArgumentException {\n    Assertions.assertThrows(\n        IllegalArgumentException.class, () -> new PrinterItem(null, 1, true, true));\n  }\n}\n"
  },
  {
    "path": "collection-pipeline/README.md",
    "content": "---\ntitle: \"Collection Pipeline Pattern in Java: Streamlining Data Manipulation\"\nshortTitle: Collection Pipeline\ndescription: \"Learn how the Collection Pipeline design pattern in Java enhances data processing by chaining operations in a sequence. This pattern promotes a declarative approach, improving code readability, maintainability, and performance.\"\ncategory: Functional\nlanguage: en\ntag:\n  - Functional decomposition\n  - Data processing\n  - Data transformation\n  - Reactive\n---\n\n## Intent of Collection Pipeline Design Pattern\n\nThe Collection Pipeline design pattern in Java processes collections of data by chaining operations in a sequence. Utilizing the Java Stream API, it transforms data declaratively, focusing on what should be done rather than how.\n\n## Detailed Explanation of Collection Pipeline Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a real-world example of a factory assembly line for manufacturing cars. In this assembly line, each station performs a specific task on the car chassis, such as installing the engine, painting the body, attaching the wheels, and inspecting the final product. Each station takes the output from the previous station and adds its own processing step. This sequence of operations is analogous to the Collection Pipeline design pattern, where each step in the pipeline transforms the data and passes it on to the next step, ensuring an efficient and organized workflow.\n\nIn plain words\n\n> The Collection Pipeline pattern in Java involves processing data through a series of operations using the Stream API. Each operation transforms the data in sequence, akin to an assembly line in a factory, promoting functional programming principles.\n\nWikipedia says\n\n> In software engineering, a pipeline consists of a chain of processing elements (processes, threads, coroutines, functions, etc.), arranged so that the output of each element is the input of the next; the name is by analogy to a physical pipeline. Usually some amount of buffering is provided between consecutive elements. The information that flows in these pipelines is often a stream of records, bytes, or bits, and the elements of a pipeline may be called filters; this is also called the pipe(s) and filters design pattern. Connecting elements into a pipeline is analogous to function composition.\n\nFlowchart\n\n![Collection Pipeline flowchart](./etc/collection-pipeline-flowchart.png)\n\n## Programmatic Example of Collection Pipeline Pattern in Java\n\nThe Collection Pipeline is a programming pattern where you organize some computation as a sequence of operations which compose by taking a collection as output of one operation and feeding it into the next.\n\nHere's a programmatic example of the Collection Pipeline design pattern:\n\n**Step 1: Filtering**\n\nWe start with a list of `Car` objects and we want to filter out those that were manufactured after the year 2000. This is done using the `stream()` method to create a stream from the list, the `filter()` method to filter out the cars we want, and the `collect()` method to collect the results into a new list.\n\n```java\npublic static List<String> getModelsAfter2000(List<Car> cars){\n    return cars.stream()\n        .filter(car -> car.getYear() > 2000) // Filter cars manufactured after 2000\n        .sorted(comparing(Car::getYear)) // Sort the cars by year\n        .map(Car::getModel) // Get the model of each car\n        .collect(toList()); // Collect the results into a new list\n}\n```\n\n**Step 2: Grouping**\n\nNext, we want to group the cars by their category. This is done using the `groupingBy` collector.\n\n```java\npublic static Map<Category, List<Car>> getGroupingOfCarsByCategory(List<Car> cars){\n    return cars.stream()\n        .collect(groupingBy(Car::getCategory)); // Group cars by category\n}\n```\n\n**Step 3: Filtering, Sorting and Transforming**\n\nFinally, we want to filter the cars owned by a person to only include sedans, sort them by date, and then transform the sorted cars into a list of `Car` objects.\n\n```java\npublic static List<Car> getSedanCarsOwnedSortedByDate(List<Person> persons){\n    return persons.stream()\n        .flatMap(person -> person.getCars().stream()) // Flatten the list of cars owned by each person\n        .filter(car -> Category.SEDAN.equals(car.getCategory())) // Filter to only include sedans\n        .sorted(comparing(Car::getDate)) // Sort the cars by date\n        .collect(toList()); // Collect the results into a new list\n}\n```\n\nIn each of these methods, the Collection Pipeline pattern is used to perform a series of operations on the collection of cars in a declarative manner, which improves readability and maintainability.\n\n## When to Use the Collection Pipeline Pattern in Java\n\nThe Collection Pipeline pattern is ideal for Java developers handling bulk data operations, including filtering, mapping, sorting, and reducing collections, particularly with Java 8+ Stream API.\n\nUse the Collection Pipeline pattern:\n\n* When you need to perform a series of transformations on a collection of data.\n* When you want to improve readability and maintainability of complex data processing code.\n* When working with large datasets where intermediate results should not be stored in memory.\n\n## Real-World Applications of Collection Pipeline Pattern in Java\n\n* LINQ in .NET\n* Stream API in Java 8+\n* Collections in modern functional languages (e.g., Haskell, Scala)\n* Database query builders and ORM frameworks\n\n## Benefits and Trade-offs of Collection Pipeline Pattern\n\nBenefits:\n\n* Readability: The code is more readable and declarative, making it easier to understand the sequence of operations.\n* Maintainability: Easier to modify or extend the pipeline with additional operations.\n* Reusability: Common operations can be abstracted into reusable functions.\n* Lazy Evaluation: Some implementations allow for operations to be lazily evaluated, improving performance.\n\nTrade-offs:\n\n* Performance Overhead: Chaining multiple operations can introduce overhead compared to traditional loops, especially for short pipelines or very large collections.\n* Debugging Difficulty: Debugging a chain of operations might be more challenging due to the lack of intermediate variables.\n* Limited to Collections: Primarily focused on collections, and its utility might be limited outside of collection processing.\n\n## Related Java Design Patterns\n\n* [Builder](https://java-design-patterns.com/patterns/builder/): Similar fluent interface style but used for object construction.\n* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Conceptually similar in chaining handlers, but applied to object requests rather than data collection processing.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Can be used within a pipeline stage to encapsulate different algorithms that can be selected at runtime.\n\n## References and Credits\n\n* [Functional Programming in Scala](https://amzn.to/4cEo6K2)\n* [Java 8 in Action: Lambdas, Streams, and functional-style programming](https://amzn.to/3THp4wy)\n* [Refactoring: Improving the Design of Existing Code](https://amzn.to/3VDMWDO)\n* [Collection Pipeline (Martin Fowler)](https://martinfowler.com/articles/collection-pipeline/)\n"
  },
  {
    "path": "collection-pipeline/etc/collection-pipeline.urm.puml",
    "content": "@startuml\npackage com.iluwatar.collectionpipeline {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Car {\n    - category : Category\n    - make : String\n    - model : String\n    - year : int\n    + Car(make : String, model : String, yearOfMake : int, category : Category)\n    + equals(obj : Object) : boolean\n    + getCategory() : Category\n    + getMake() : String\n    + getModel() : String\n    + getYear() : int\n    + hashCode() : int\n  }\n  class CarFactory {\n    - CarFactory()\n    + createCars() : List<Car> {static}\n  }\n  enum Category {\n    + CONVERTIBLE {static}\n    + JEEP {static}\n    + SEDAN {static}\n    + valueOf(name : String) : Category {static}\n    + values() : Category[] {static}\n  }\n  class FunctionalProgramming {\n    - FunctionalProgramming()\n    + getGroupingOfCarsByCategory(cars : List<Car>) : Map<Category, List<Car>> {static}\n    + getModelsAfter2000(cars : List<Car>) : List<String> {static}\n    + getSedanCarsOwnedSortedByDate(persons : List<Person>) : List<Car> {static}\n  }\n  class ImperativeProgramming {\n    - ImperativeProgramming()\n    + getGroupingOfCarsByCategory(cars : List<Car>) : Map<Category, List<Car>> {static}\n    + getModelsAfter2000(cars : List<Car>) : List<String> {static}\n    + getSedanCarsOwnedSortedByDate(persons : List<Person>) : List<Car> {static}\n  }\n  class Person {\n    - cars : List<Car>\n    + Person(cars : List<Car>)\n    + getCars() : List<Car>\n  }\n}\nPerson -->  \"-cars\" Car\nCar -->  \"-category\" Category\n@enduml"
  },
  {
    "path": "collection-pipeline/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>collection-pipeline</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.collectionpipeline.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectionpipeline;\n\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * In imperative-style programming, it is common to use for and while loops for most kinds of data\n * processing. Function composition is a simple technique that lets you sequence modular functions\n * to create more complex operations. When you run data through the sequence, you have a collection\n * pipeline. Together, the Function Composition and Collection Pipeline patterns enable you to\n * create sophisticated programs where data flow from upstream to downstream and is passed through a\n * series of transformations.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var cars = CarFactory.createCars();\n\n    var modelsImperative = ImperativeProgramming.getModelsAfter2000(cars);\n    LOGGER.info(modelsImperative.toString());\n\n    var modelsFunctional = FunctionalProgramming.getModelsAfter2000(cars);\n    LOGGER.info(modelsFunctional.toString());\n\n    var groupingByCategoryImperative = ImperativeProgramming.getGroupingOfCarsByCategory(cars);\n    LOGGER.info(groupingByCategoryImperative.toString());\n\n    var groupingByCategoryFunctional = FunctionalProgramming.getGroupingOfCarsByCategory(cars);\n    LOGGER.info(groupingByCategoryFunctional.toString());\n\n    var john = new Person(cars);\n\n    var sedansOwnedImperative = ImperativeProgramming.getSedanCarsOwnedSortedByDate(List.of(john));\n    LOGGER.info(sedansOwnedImperative.toString());\n\n    var sedansOwnedFunctional = FunctionalProgramming.getSedanCarsOwnedSortedByDate(List.of(john));\n    LOGGER.info(sedansOwnedFunctional.toString());\n  }\n}\n"
  },
  {
    "path": "collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/Car.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.collectionpipeline;\n\n/** A Car class that has the properties of make, model, year and category. */\npublic record Car(String make, String model, int year, Category category) {}\n"
  },
  {
    "path": "collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/CarFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectionpipeline;\n\nimport java.util.List;\n\n/** A factory class to create a collection of {@link Car} instances. */\npublic class CarFactory {\n  private CarFactory() {}\n\n  /**\n   * Factory method to create a {@link List} of {@link Car} instances.\n   *\n   * @return {@link List} of {@link Car}\n   */\n  public static List<Car> createCars() {\n    return List.of(\n        new Car(\"Jeep\", \"Wrangler\", 2011, Category.JEEP),\n        new Car(\"Jeep\", \"Comanche\", 1990, Category.JEEP),\n        new Car(\"Dodge\", \"Avenger\", 2010, Category.SEDAN),\n        new Car(\"Buick\", \"Cascada\", 2016, Category.CONVERTIBLE),\n        new Car(\"Ford\", \"Focus\", 2012, Category.SEDAN),\n        new Car(\"Chevrolet\", \"Geo Metro\", 1992, Category.CONVERTIBLE));\n  }\n}\n"
  },
  {
    "path": "collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/Category.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectionpipeline;\n\n/** Enum for the category of car. */\npublic enum Category {\n  JEEP,\n  SEDAN,\n  CONVERTIBLE\n}\n"
  },
  {
    "path": "collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/FunctionalProgramming.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.collectionpipeline;\n\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\n/**\n * Iterating and sorting with a collection pipeline\n *\n * <p>In functional programming, it's common to sequence complex operations through a series of\n * smaller modular functions or operations. The series is called a composition of functions, or a\n * function composition. When a collection of data flows through a function composition, it becomes\n * a collection pipeline. Function Composition and Collection Pipeline are two design patterns\n * frequently used in functional-style programming.\n *\n * <p>Instead of passing a lambda expression to the map method, we passed the method reference\n * Car::getModel. Likewise, instead of passing the lambda expression car -> car.getYear() to the\n * comparing method, we passed the method reference Car::getYear. Method references are short,\n * concise, and expressive. It is best to use them wherever possible.\n */\npublic class FunctionalProgramming {\n  private FunctionalProgramming() {}\n\n  /**\n   * Method to get models using for collection pipeline.\n   *\n   * @param cars {@link List} of {@link Car} to be used for filtering\n   * @return {@link List} of {@link String} representing models built after year 2000\n   */\n  public static List<String> getModelsAfter2000(List<Car> cars) {\n    return cars.stream()\n        .filter(car -> car.year() > 2000)\n        .sorted(Comparator.comparing(Car::year))\n        .map(Car::model)\n        .toList();\n  }\n\n  /**\n   * Method to group cars by category using groupingBy.\n   *\n   * @param cars {@link List} of {@link Car} to be used for grouping\n   * @return {@link Map} with category as key and cars belonging to that category as value\n   */\n  public static Map<Category, List<Car>> getGroupingOfCarsByCategory(List<Car> cars) {\n    return cars.stream().collect(Collectors.groupingBy(Car::category));\n  }\n\n  /**\n   * Method to get all Sedan cars belonging to a group of persons sorted by year of manufacture.\n   *\n   * @param persons {@link List} of {@link Person} to be used\n   * @return {@link List} of {@link Car} to belonging to the group\n   */\n  public static List<Car> getSedanCarsOwnedSortedByDate(List<Person> persons) {\n    return persons.stream()\n        .map(Person::cars)\n        .flatMap(List::stream)\n        .filter(car -> Category.SEDAN.equals(car.category()))\n        .sorted(Comparator.comparing(Car::year))\n        .toList();\n  }\n}\n"
  },
  {
    "path": "collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/ImperativeProgramming.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectionpipeline;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Imperative-style programming to iterate over the list and get the names of cars made later than\n * the year 2000. We then sort the models in ascending order by year.\n *\n * <p>As you can see, there's a lot of looping in this code. First, the getModelsAfter2000UsingFor\n * method takes a list of cars as its parameter. It extracts or filters out cars made after the year\n * 2000, putting them into a new list named carsSortedByYear. Next, it sorts that list in ascending\n * order by year-of-make. Finally, it loops through the list carsSortedByYear to get the model names\n * and returns them in a list.\n *\n * <p>This short example demonstrates what I call the effect of statements. While functions and\n * methods in general can be used as expressions, the {@link Collections} sort method doesn't return\n * a result. Because it is used as a statement, it mutates the list given as argument. Both of the\n * for loops also mutate lists as they iterate. Being statements, that's just how these elements\n * work. As a result, the code contains unnecessary garbage variables\n */\npublic class ImperativeProgramming {\n  private ImperativeProgramming() {}\n\n  /**\n   * Method to return the car models built after year 2000 using for loops.\n   *\n   * @param cars {@link List} of {@link Car} to iterate over\n   * @return {@link List} of {@link String} of car models built after year 2000\n   */\n  public static List<String> getModelsAfter2000(List<Car> cars) {\n    List<Car> carsSortedByYear = new ArrayList<>();\n\n    for (Car car : cars) {\n      if (car.year() > 2000) {\n        carsSortedByYear.add(car);\n      }\n    }\n\n    Collections.sort(\n        carsSortedByYear,\n        new Comparator<Car>() {\n          @Override\n          public int compare(Car car1, Car car2) {\n            return car1.year() - car2.year();\n          }\n        });\n\n    List<String> models = new ArrayList<>();\n    for (Car car : carsSortedByYear) {\n      models.add(car.model());\n    }\n\n    return models;\n  }\n\n  /**\n   * Method to group cars by category using for loops.\n   *\n   * @param cars {@link List} of {@link Car} to be used for grouping\n   * @return {@link Map} with category as key and cars belonging to that category as value\n   */\n  public static Map<Category, List<Car>> getGroupingOfCarsByCategory(List<Car> cars) {\n    Map<Category, List<Car>> groupingByCategory = new HashMap<>();\n    for (Car car : cars) {\n      if (groupingByCategory.containsKey(car.category())) {\n        groupingByCategory.get(car.category()).add(car);\n      } else {\n        List<Car> categoryCars = new ArrayList<>();\n        categoryCars.add(car);\n        groupingByCategory.put(car.category(), categoryCars);\n      }\n    }\n    return groupingByCategory;\n  }\n\n  /**\n   * Method to get all Sedan cars belonging to a group of persons sorted by year of manufacture\n   * using for loops.\n   *\n   * @param persons {@link List} of {@link Person} to be used\n   * @return {@link List} of {@link Car} to belonging to the group\n   */\n  public static List<Car> getSedanCarsOwnedSortedByDate(List<Person> persons) {\n    List<Car> cars = new ArrayList<>();\n    for (Person person : persons) {\n      cars.addAll(person.cars());\n    }\n\n    List<Car> sedanCars = new ArrayList<>();\n    for (Car car : cars) {\n      if (Category.SEDAN.equals(car.category())) {\n        sedanCars.add(car);\n      }\n    }\n\n    sedanCars.sort(\n        new Comparator<Car>() {\n          @Override\n          public int compare(Car o1, Car o2) {\n            return o1.year() - o2.year();\n          }\n        });\n\n    return sedanCars;\n  }\n}\n"
  },
  {
    "path": "collection-pipeline/src/main/java/com/iluwatar/collectionpipeline/Person.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectionpipeline;\n\nimport java.util.List;\n\n/** A Person class that has the list of cars that the person owns and use. */\npublic record Person(List<Car> cars) {}\n"
  },
  {
    "path": "collection-pipeline/src/test/java/com/iluwatar/collectionpipeline/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.collectionpipeline;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.List;\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Collection Pipeline methods work as expected. */\n@Slf4j\nclass AppTest {\n\n  private final List<Car> cars = CarFactory.createCars();\n\n  @Test\n  void testGetModelsAfter2000UsingFor() {\n    var models = ImperativeProgramming.getModelsAfter2000(cars);\n    assertEquals(List.of(\"Avenger\", \"Wrangler\", \"Focus\", \"Cascada\"), models);\n  }\n\n  @Test\n  void testGetModelsAfter2000UsingPipeline() {\n    var models = FunctionalProgramming.getModelsAfter2000(cars);\n    assertEquals(List.of(\"Avenger\", \"Wrangler\", \"Focus\", \"Cascada\"), models);\n  }\n\n  @Test\n  void testGetGroupingOfCarsByCategory() {\n    var modelsExpected =\n        Map.of(\n            Category.CONVERTIBLE,\n                List.of(\n                    new Car(\"Buick\", \"Cascada\", 2016, Category.CONVERTIBLE),\n                    new Car(\"Chevrolet\", \"Geo Metro\", 1992, Category.CONVERTIBLE)),\n            Category.SEDAN,\n                List.of(\n                    new Car(\"Dodge\", \"Avenger\", 2010, Category.SEDAN),\n                    new Car(\"Ford\", \"Focus\", 2012, Category.SEDAN)),\n            Category.JEEP,\n                List.of(\n                    new Car(\"Jeep\", \"Wrangler\", 2011, Category.JEEP),\n                    new Car(\"Jeep\", \"Comanche\", 1990, Category.JEEP)));\n    var modelsFunctional = FunctionalProgramming.getGroupingOfCarsByCategory(cars);\n    var modelsImperative = ImperativeProgramming.getGroupingOfCarsByCategory(cars);\n    LOGGER.info(\"Category \" + modelsFunctional);\n    assertEquals(modelsExpected, modelsFunctional);\n    assertEquals(modelsExpected, modelsImperative);\n  }\n\n  @Test\n  void testGetSedanCarsOwnedSortedByDate() {\n    var john = new Person(cars);\n    var modelsExpected =\n        List.of(\n            new Car(\"Dodge\", \"Avenger\", 2010, Category.SEDAN),\n            new Car(\"Ford\", \"Focus\", 2012, Category.SEDAN));\n    var modelsFunctional = FunctionalProgramming.getSedanCarsOwnedSortedByDate(List.of(john));\n    var modelsImperative = ImperativeProgramming.getSedanCarsOwnedSortedByDate(List.of(john));\n    assertEquals(modelsExpected, modelsFunctional);\n    assertEquals(modelsExpected, modelsImperative);\n  }\n}\n"
  },
  {
    "path": "combinator/README.md",
    "content": "---\ntitle: \"Combinator Pattern in Java: Crafting Flexible Code Compositions\"\nshortTitle: Combinator\ndescription: \"Learn how to use the Combinator pattern in Java with real-world examples and comprehensive explanations. Enhance your Java design skills with this detailed guide.\"\ncategory: Functional\nlanguage: en\ntag:\n  - Abstraction\n  - Code simplification\n  - Functional decomposition\n  - Idiom\n  - Reactive\n---\n\n## Also known as\n\n* Function Composition\n* Functional Combinator\n\n## Intent of Combinator Design Pattern\n\nThe Combinator pattern, a functional programming technique widely used in Java, is essential for combining functions to build complex behaviors. This pattern allows developers to combine multiple smaller functions or operations into a single, more complex operation, promoting flexible and reusable code. By leveraging higher-order functions, the Combinator pattern enhances code reuse and maintainability in Java applications, making it a valuable tool in software design. This approach fosters the creation of modular, scalable solutions in Java development.\n\n## Detailed Explanation of Combinator Pattern with Real-World Examples\n\nReal-world example\n\n> In the real world, the combinator design pattern can be likened to a meal preparation process in a kitchen. Imagine a chef who has a set of simple operations: chopping vegetables, boiling water, cooking rice, grilling chicken, and mixing ingredients. Each of these operations is a standalone function. The chef can combine these operations in various sequences to create different dishes. For example, to prepare a chicken rice bowl, the chef can combine the operations of cooking rice, grilling chicken, and mixing them with vegetables. By reusing these basic operations and combining them in different ways, the chef can efficiently prepare a wide variety of meals. Similarly, in software, the combinator pattern allows developers to combine simple, reusable functions to create more complex behaviors.\n\nIn plain words\n\n> The combinator design pattern combines simple, reusable functions to create more complex and flexible operations.\n\nWikipedia says\n\n> A combinator is a higher-order function that uses only function application and earlier defined combinators to define a result from its arguments.\n\nFlowchart\n\n![Combinator flowchart](./etc/combinator-flowchart.png)\n\n## Programmatic Example of Combinator Pattern in Java\n\nIn software design, combinatory logic is pivotal for creating reusable and modular code components. By leveraging higher-order functions, the Combinator pattern promotes code reuse and maintainability in Java applications.\n\nIn this Java example, we demonstrate the implementation of combinators such as `contains`, `not`, `or`, and `and` to create complex finders.\n\n```java\n// Functional interface to find lines in text.\npublic interface Finder {\n\n    // The function to find lines in text.\n    List<String> find(String text);\n\n    // Simple implementation of function {@link #find(String)}.\n    static Finder contains(String word) {\n        return txt -> Stream.of(txt.split(\"\\n\"))\n                .filter(line -> line.toLowerCase().contains(word.toLowerCase()))\n                .collect(Collectors.toList());\n    }\n\n    // combinator not.\n    default Finder not(Finder notFinder) {\n        return txt -> {\n            List<String> res = this.find(txt);\n            res.removeAll(notFinder.find(txt));\n            return res;\n        };\n    }\n\n    // combinator or.\n    default Finder or(Finder orFinder) {\n        return txt -> {\n            List<String> res = this.find(txt);\n            res.addAll(orFinder.find(txt));\n            return res;\n        };\n    }\n\n    // combinator and.\n    default Finder and(Finder andFinder) {\n        return\n                txt -> this\n                        .find(txt)\n                        .stream()\n                        .flatMap(line -> andFinder.find(line).stream())\n                        .collect(Collectors.toList());\n    }\n    // Other properties and methods...\n}\n```\n\nThen we have also another combinator for some complex finders `advancedFinder`, `filteredFinder`, `specializedFinder` and `expandedFinder`.\n\n```java\n// Complex finders consisting of simple finder.\npublic class Finders {\n\n    private Finders() {\n    }\n\n    // Finder to find a complex query.\n    public static Finder advancedFinder(String query, String orQuery, String notQuery) {\n        return\n                Finder.contains(query)\n                        .or(Finder.contains(orQuery))\n                        .not(Finder.contains(notQuery));\n    }\n\n    // Filtered finder looking a query with excluded queries as well.\n    public static Finder filteredFinder(String query, String... excludeQueries) {\n        var finder = Finder.contains(query);\n\n        for (String q : excludeQueries) {\n            finder = finder.not(Finder.contains(q));\n        }\n        return finder;\n    }\n\n    // Specialized query. Every next query is looked in previous result.\n    public static Finder specializedFinder(String... queries) {\n        var finder = identMult();\n\n        for (String query : queries) {\n            finder = finder.and(Finder.contains(query));\n        }\n        return finder;\n    }\n\n    // Expanded query. Looking for alternatives.\n    public static Finder expandedFinder(String... queries) {\n        var finder = identSum();\n\n        for (String query : queries) {\n            finder = finder.or(Finder.contains(query));\n        }\n        return finder;\n    }\n    // Other properties and methods...\n}\n```\n\nNow that we have created the interface and methods for combinators, let's see how an application works with them.\n\n```java\npublic class CombinatorApp {\n\n    private static final String TEXT = \"\"\"\n            It was many and many a year ago,\n            In a kingdom by the sea,\n            That a maiden there lived whom you may know\n            By the name of ANNABEL LEE;\n            And this maiden she lived with no other thought\n            Than to love and be loved by me.\n            I was a child and she was a child,\n            In this kingdom by the sea;\n            But we loved with a love that was more than love-\n            I and my Annabel Lee;\n            With a love that the winged seraphs of heaven\n            Coveted her and me.\"\"\";\n\n    public static void main(String[] args) {\n        var queriesOr = new String[]{\"many\", \"Annabel\"};\n        var finder = Finders.expandedFinder(queriesOr);\n        var res = finder.find(text());\n        LOGGER.info(\"the result of expanded(or) query[{}] is {}\", queriesOr, res);\n\n        var queriesAnd = new String[]{\"Annabel\", \"my\"};\n        finder = Finders.specializedFinder(queriesAnd);\n        res = finder.find(text());\n        LOGGER.info(\"the result of specialized(and) query[{}] is {}\", queriesAnd, res);\n\n        finder = Finders.advancedFinder(\"it was\", \"kingdom\", \"sea\");\n        res = finder.find(text());\n        LOGGER.info(\"the result of advanced query is {}\", res);\n\n        res = Finders.filteredFinder(\" was \", \"many\", \"child\").find(text());\n        LOGGER.info(\"the result of filtered query is {}\", res);\n    }\n\n    private static String text() {\n        return TEXT;\n    }\n}\n```\n\nProgram output:\n\n```\n20:03:52.746 [main] INFO com.iluwatar.combinator.CombinatorApp -- the result of expanded(or) query[[many, Annabel]] is [It was many and many a year ago,, By the name of ANNABEL LEE;, I and my Annabel Lee;]\n20:03:52.749 [main] INFO com.iluwatar.combinator.CombinatorApp -- the result of specialized(and) query[[Annabel, my]] is [I and my Annabel Lee;]\n20:03:52.750 [main] INFO com.iluwatar.combinator.CombinatorApp -- the result of advanced query is [It was many and many a year ago,]\n20:03:52.750 [main] INFO com.iluwatar.combinator.CombinatorApp -- the result of filtered query is [But we loved with a love that was more than love-]\n```\n\nNow we can design our app to with the queries finding feature `expandedFinder`, `specializedFinder`, `advancedFinder`, `filteredFinder` which are all derived from `contains`, `or`, `not`, `and`.\n\n## When to Use the Combinator Pattern in Java\n\nThe Combinator pattern is particularly useful in functional programming where complex values are built from simpler, reusable components.\n\nThe applicable scenarios include:\n\n* The solution to a problem can be constructed from simple, reusable components.\n* There is a need for high modularity and reusability of functions.\n* The programming environment supports first-class functions and higher-order functions.\n\n## Real-World Applications of Combinator Pattern in Java\n\n* Functional programming languages like Haskell and Scala extensively use combinators for tasks ranging from parsing to UI construction.\n* In domain-specific languages, particularly those involved in parsing, such as parsing expression grammars.\n* In libraries for functional programming in languages like JavaScript, Python, and Ruby.\n* java.util.function.Function#compose\n* java.util.function.Function#andThen\n\n## Benefits and Trade-offs of Combinator Pattern\n\nBenefits:\n\n* Enhances developer productivity by using domain-specific terms and facilitates parallel execution in Java applications.\n* Enhances modularity and reusability by breaking down complex tasks into simpler, composable functions.\n* Promotes readability and maintainability by using a declarative style of programming.\n* Facilitates lazy evaluation and potentially more efficient execution through function composition.\n\nTrade-offs:\n\n* Can lead to a steep learning curve for those unfamiliar with functional programming principles.\n* May result in performance overhead due to the creation of intermediate functions.\n* Debugging can be challenging due to the abstract nature of function compositions.\n\n## Related Java Design Patterns\n\n* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Relies on chaining objects, whereas Combinator chains functions.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Similar to Combinator in enhancing functionality, but Decorator focuses on object augmentation.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Both involve selecting an algorithm at runtime, but Combinator uses composition of functions.\n\n## References and Credits\n\n* [Functional Programming in Scala](https://amzn.to/4cEo6K2)\n* [Haskell: The Craft of Functional Programming](https://amzn.to/4axxtcF)\n* [Structure and Interpretation of Computer Programs](https://amzn.to/3PJwVsf)\n* [Combinator Pattern with Java 8 (Gregor Trefs)](https://gtrefs.github.io/code/combinator-pattern/)\n"
  },
  {
    "path": "combinator/etc/combinator.urm.puml",
    "content": "@startuml\npackage com.iluwatar.combinator {\n  class CombinatorApp {\n    - LOGGER : Logger {static}\n    + CombinatorApp()\n    + main(args : String[]) {static}\n    - text() : String {static}\n  }\n  interface Finder {\n    + and(andFinder : Finder) : Finder\n    + contains(word : String) : Finder {static}\n    + find(String) : List<String> {abstract}\n    + not(notFinder : Finder) : Finder\n    + or(orFinder : Finder) : Finder\n  }\n  class Finders {\n    - Finders()\n    + advancedFinder(query : String, orQuery : String, notQuery : String) : Finder {static}\n    + expandedFinder(queries : String[]) : Finder {static}\n    + filteredFinder(query : String, excludeQueries : String[]) : Finder {static}\n    - identMult() : Finder {static}\n    - identSum() : Finder {static}\n    + specializedFinder(queries : String[]) : Finder {static}\n  }\n}\n@enduml"
  },
  {
    "path": "combinator/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n    <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>combinator</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.combinator.CombinatorApp</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "combinator/src/main/java/com/iluwatar/combinator/CombinatorApp.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.combinator;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The functional pattern representing a style of organizing libraries centered around the idea of\n * combining functions. Putting it simply, there is some type T, some functions for constructing\n * \"primitive\" values of type T, and some \"combinators\" which can combine values of type T in\n * various ways to build up more complex values of type T. The class {@link Finder} defines a simple\n * function {@link Finder#find(String)} and connected functions {@link Finder#or(Finder)}, {@link\n * Finder#not(Finder)}, {@link Finder#and(Finder)} Using them the became possible to get more\n * complex functions {@link Finders}\n */\n@Slf4j\npublic class CombinatorApp {\n\n  private static final String TEXT =\n      \"\"\"\n            It was many and many a year ago,\n            In a kingdom by the sea,\n            That a maiden there lived whom you may know\n            By the name of ANNABEL LEE;\n            And this maiden she lived with no other thought\n            Than to love and be loved by me.\n            I was a child and she was a child,\n            In this kingdom by the sea;\n            But we loved with a love that was more than love-\n            I and my Annabel Lee;\n            With a love that the winged seraphs of heaven\n            Coveted her and me.\"\"\";\n\n  /**\n   * main.\n   *\n   * @param args args\n   */\n  public static void main(String[] args) {\n    var queriesOr = new String[] {\"many\", \"Annabel\"};\n    var finder = Finders.expandedFinder(queriesOr);\n    var res = finder.find(text());\n    LOGGER.info(\"the result of expanded(or) query[{}] is {}\", queriesOr, res);\n\n    var queriesAnd = new String[] {\"Annabel\", \"my\"};\n    finder = Finders.specializedFinder(queriesAnd);\n    res = finder.find(text());\n    LOGGER.info(\"the result of specialized(and) query[{}] is {}\", queriesAnd, res);\n\n    finder = Finders.advancedFinder(\"it was\", \"kingdom\", \"sea\");\n    res = finder.find(text());\n    LOGGER.info(\"the result of advanced query is {}\", res);\n\n    res = Finders.filteredFinder(\" was \", \"many\", \"child\").find(text());\n    LOGGER.info(\"the result of filtered query is {}\", res);\n  }\n\n  private static String text() {\n\n    return TEXT;\n  }\n}\n"
  },
  {
    "path": "combinator/src/main/java/com/iluwatar/combinator/Finder.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.combinator;\n\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\n/** Functional interface to find lines in text. */\npublic interface Finder {\n\n  /**\n   * The function to find lines in text.\n   *\n   * @param text full tet\n   * @return result of searching\n   */\n  List<String> find(String text);\n\n  /**\n   * Simple implementation of function {@link #find(String)}.\n   *\n   * @param word for searching\n   * @return this\n   */\n  static Finder contains(String word) {\n    return txt ->\n        Stream.of(txt.split(\"\\n\"))\n            .filter(line -> line.toLowerCase().contains(word.toLowerCase()))\n            .collect(Collectors.toList());\n  }\n\n  /**\n   * combinator not.\n   *\n   * @param notFinder finder to combine\n   * @return new finder including previous finders\n   */\n  default Finder not(Finder notFinder) {\n    return txt -> {\n      List<String> res = this.find(txt);\n      res.removeAll(notFinder.find(txt));\n      return res;\n    };\n  }\n\n  /**\n   * combinator or.\n   *\n   * @param orFinder finder to combine\n   * @return new finder including previous finders\n   */\n  default Finder or(Finder orFinder) {\n    return txt -> {\n      List<String> res = this.find(txt);\n      res.addAll(orFinder.find(txt));\n      return res;\n    };\n  }\n\n  /**\n   * combinator and.\n   *\n   * @param andFinder finder to combine\n   * @return new finder including previous finders\n   */\n  default Finder and(Finder andFinder) {\n    return txt ->\n        this.find(txt).stream()\n            .flatMap(line -> andFinder.find(line).stream())\n            .collect(Collectors.toList());\n  }\n}\n"
  },
  {
    "path": "combinator/src/main/java/com/iluwatar/combinator/Finders.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.combinator;\n\nimport java.util.ArrayList;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\n/** Complex finders consisting of simple finder. */\npublic class Finders {\n  private Finders() {}\n\n  /**\n   * Finder to find a complex query.\n   *\n   * @param query to find\n   * @param orQuery alternative to find\n   * @param notQuery exclude from search\n   * @return new finder\n   */\n  public static Finder advancedFinder(String query, String orQuery, String notQuery) {\n    return Finder.contains(query).or(Finder.contains(orQuery)).not(Finder.contains(notQuery));\n  }\n\n  /**\n   * Filtered finder looking a query with excluded queries as well.\n   *\n   * @param query to find\n   * @param excludeQueries to exclude\n   * @return new finder\n   */\n  public static Finder filteredFinder(String query, String... excludeQueries) {\n    var finder = Finder.contains(query);\n\n    for (String q : excludeQueries) {\n      finder = finder.not(Finder.contains(q));\n    }\n    return finder;\n  }\n\n  /**\n   * Specialized query. Every next query is looked in previous result.\n   *\n   * @param queries array with queries\n   * @return new finder\n   */\n  public static Finder specializedFinder(String... queries) {\n    var finder = identMult();\n\n    for (String query : queries) {\n      finder = finder.and(Finder.contains(query));\n    }\n    return finder;\n  }\n\n  /**\n   * Expanded query. Looking for alternatives.\n   *\n   * @param queries array with queries.\n   * @return new finder\n   */\n  public static Finder expandedFinder(String... queries) {\n    var finder = identSum();\n\n    for (String query : queries) {\n      finder = finder.or(Finder.contains(query));\n    }\n    return finder;\n  }\n\n  private static Finder identMult() {\n    return txt -> Stream.of(txt.split(\"\\n\")).collect(Collectors.toList());\n  }\n\n  private static Finder identSum() {\n    return txt -> new ArrayList<>();\n  }\n}\n"
  },
  {
    "path": "combinator/src/test/java/com/iluwatar/combinator/CombinatorAppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.combinator;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass CombinatorAppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * CombinatorApp#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> CombinatorApp.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "combinator/src/test/java/com/iluwatar/combinator/FinderTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.combinator;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\nclass FinderTest {\n\n  @Test\n  void contains() {\n    var example = \"\"\"\n        the first one\n        the second one\\s\n        \"\"\";\n\n    var result = Finder.contains(\"second\").find(example);\n    assertEquals(1, result.size());\n    assertEquals(\"the second one \", result.get(0));\n  }\n}\n"
  },
  {
    "path": "combinator/src/test/java/com/iluwatar/combinator/FindersTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.combinator;\n\nimport static com.iluwatar.combinator.Finders.advancedFinder;\nimport static com.iluwatar.combinator.Finders.expandedFinder;\nimport static com.iluwatar.combinator.Finders.filteredFinder;\nimport static com.iluwatar.combinator.Finders.specializedFinder;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\nclass FindersTest {\n\n  @Test\n  void advancedFinderTest() {\n    var res = advancedFinder(\"it was\", \"kingdom\", \"sea\").find(text());\n    assertEquals(1, res.size());\n    assertEquals(\"It was many and many a year ago,\", res.get(0));\n  }\n\n  @Test\n  void filteredFinderTest() {\n    var res = filteredFinder(\" was \", \"many\", \"child\").find(text());\n    assertEquals(1, res.size());\n    assertEquals(\"But we loved with a love that was more than love-\", res.get(0));\n  }\n\n  @Test\n  void specializedFinderTest() {\n    var res = specializedFinder(\"love\", \"heaven\").find(text());\n    assertEquals(1, res.size());\n    assertEquals(\"With a love that the winged seraphs of heaven\", res.get(0));\n  }\n\n  @Test\n  void expandedFinderTest() {\n    var res = expandedFinder(\"It was\", \"kingdom\").find(text());\n    assertEquals(3, res.size());\n    assertEquals(\"It was many and many a year ago,\", res.get(0));\n    assertEquals(\"In a kingdom by the sea,\", res.get(1));\n    assertEquals(\"In this kingdom by the sea;\", res.get(2));\n  }\n\n  private String text() {\n    return \"\"\"\n        It was many and many a year ago,\n        In a kingdom by the sea,\n        That a maiden there lived whom you may know\n        By the name of ANNABEL LEE;\n        And this maiden she lived with no other thought\n        Than to love and be loved by me.\n        I was a child and she was a child,\n        In this kingdom by the sea;\n        But we loved with a love that was more than love-\n        I and my Annabel Lee;\n        With a love that the winged seraphs of heaven\n        Coveted her and me.\"\"\";\n  }\n}\n"
  },
  {
    "path": "command/README.md",
    "content": "---\ntitle: \"Command Pattern in Java: Empowering Flexible Command Execution\"\nshortTitle: Command\ndescription: \"Learn about the Command design pattern in Java with real-world examples, detailed explanations, and practical use cases. Understand how this pattern encapsulates requests as objects to support undo operations and more.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Decoupling\n  - Extensibility\n  - Gang of Four\n  - Undo\n---\n\n## Also known as\n\n* Action\n* Transaction\n\n## Intent of Command Design Pattern\n\nThe Command design pattern is a behavioral pattern used in Java programming. It encapsulates a request as an object, allowing for parameterization of clients with queues, requests, and operations. This pattern also supports undoable operations, enhancing flexibility in managing and executing commands.\n\n## Detailed Explanation of Command Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a smart home system where you can control devices such as lights, thermostats, and security cameras through a central application. Each command to operate these devices is encapsulated as an object, enabling the system to queue, execute sequentially, and undo commands if necessary. This approach decouples control logic from device implementation, allowing easy addition of new devices or features without altering the core application. This flexibility and functionality illustrate the practical application of the Command design pattern in Java programming.\n\nIn plain words\n\n> Storing requests as command objects allows performing an action or undoing it at a later time.\n\nWikipedia says\n\n> In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time.\n\nSequence diagram\n\n![Command sequence diagram](./etc/command-sequence-diagram.png)\n\n## Programmatic Example of Command Pattern in Java\n\nIn the Command pattern, objects are used to encapsulate all information needed to perform an action or trigger an event at a later time. This pattern is particularly useful for implementing undo functionality in applications.\n\nIn our example, a `Wizard` casts spells on a `Goblin`. Each spell is a command object that can be executed and undone, demonstrating the core principles of the Command pattern in Java. The spells are executed on the goblin one by one. The first spell shrinks the goblin and the second makes him invisible. Then the wizard reverses the spells one by one. Each spell here is a command object that can be undone.\n\nLet's start from the `Wizard` class.\n\n```java\n\n@Slf4j\npublic class Wizard {\n\n    private final Deque<Runnable> undoStack = new LinkedList<>();\n    private final Deque<Runnable> redoStack = new LinkedList<>();\n\n    public Wizard() {\n    }\n\n    public void castSpell(Runnable runnable) {\n        runnable.run();\n        undoStack.offerLast(runnable);\n    }\n\n    public void undoLastSpell() {\n        if (!undoStack.isEmpty()) {\n            var previousSpell = undoStack.pollLast();\n            redoStack.offerLast(previousSpell);\n            previousSpell.run();\n        }\n    }\n\n    public void redoLastSpell() {\n        if (!redoStack.isEmpty()) {\n            var previousSpell = redoStack.pollLast();\n            undoStack.offerLast(previousSpell);\n            previousSpell.run();\n        }\n    }\n\n    @Override\n    public String toString() {\n        return \"Wizard\";\n    }\n}\n```\n\nNext, we have the `Goblin` who's the `Target` of the spells.\n\n```java\n@Slf4j\n@Getter\n@Setter\npublic abstract class Target {\n\n    private Size size;\n\n    private Visibility visibility;\n\n    public void printStatus() {\n        LOGGER.info(\"{}, [size={}] [visibility={}]\", this, getSize(), getVisibility());\n    }\n\n    public void changeSize() {\n        var oldSize = getSize() == Size.NORMAL ? Size.SMALL : Size.NORMAL;\n        setSize(oldSize);\n    }\n\n    public void changeVisibility() {\n        var visible = getVisibility() == Visibility.INVISIBLE\n                ? Visibility.VISIBLE : Visibility.INVISIBLE;\n        setVisibility(visible);\n    }\n}\n```\n\n```java\npublic class Goblin extends Target {\n\n    public Goblin() {\n        setSize(Size.NORMAL);\n        setVisibility(Visibility.VISIBLE);\n    }\n\n    @Override\n    public String toString() {\n        return \"Goblin\";\n    }\n}\n```\n\nFinally, we can show the full example of `Wizard` casting spells.\n\n```java\npublic static void main(String[] args) {\n    var wizard = new Wizard();\n    var goblin = new Goblin();\n\n    goblin.printStatus();\n\n    wizard.castSpell(goblin::changeSize);\n    goblin.printStatus();\n\n    wizard.castSpell(goblin::changeVisibility);\n    goblin.printStatus();\n\n    wizard.undoLastSpell();\n    goblin.printStatus();\n\n    wizard.undoLastSpell();\n    goblin.printStatus();\n\n    wizard.redoLastSpell();\n    goblin.printStatus();\n\n    wizard.redoLastSpell();\n    goblin.printStatus();\n}\n```\n\nHere's the program output:\n\n```\n20:13:38.406 [main] INFO com.iluwatar.command.Target -- Goblin, [size=normal] [visibility=visible]\n20:13:38.409 [main] INFO com.iluwatar.command.Target -- Goblin, [size=small] [visibility=visible]\n20:13:38.409 [main] INFO com.iluwatar.command.Target -- Goblin, [size=small] [visibility=invisible]\n20:13:38.409 [main] INFO com.iluwatar.command.Target -- Goblin, [size=small] [visibility=visible]\n20:13:38.409 [main] INFO com.iluwatar.command.Target -- Goblin, [size=normal] [visibility=visible]\n20:13:38.409 [main] INFO com.iluwatar.command.Target -- Goblin, [size=small] [visibility=visible]\n20:13:38.409 [main] INFO com.iluwatar.command.Target -- Goblin, [size=small] [visibility=invisible]\n```\n\n## When to Use the Command Pattern in Java\n\nThe Command design pattern is applicable when you need to parameterize objects with actions, support undo operations, or structure a system around high-level operations built on primitive ones. It is commonly used in GUI buttons, database transactions, and macro recording.\n\nUse the Command pattern when you want to:\n\n* Parameterize objects with actions to perform, offering an object-oriented alternative to callbacks found in procedural languages. Commands can be registered and executed later.\n* Specify, queue, and execute requests at different times, allowing commands to exist independently of the original request and even be transferred across processes.\n* Support undo functionality, where the Command’s execute operation stores state and includes an un-execute operation to reverse previous actions. This allows for unlimited undo and redo capabilities by maintaining a history list.\n* Log changes to reapply them after a system crash. By adding load and store operations to the Command interface, you can maintain a persistent log of changes and recover by reloading and re-executing commands from this log.\n* Structure a system around high-level operations built on primitive operations, which is common in transaction-based systems. The Command pattern models transactions by providing a common interface for invoking and extending operations.\n* Keep a history of requests.\n* Implement callback functionality.\n* Implement undo functionality.\n\n## Real-World Applications of Command Pattern in Java\n\n* GUI Buttons and menu items in desktop applications.\n* Operations in database systems and transactional systems that support rollback.\n* Macro recording in applications like text editors and spreadsheets.\n* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)\n* [org.junit.runners.model.Statement](https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/runners/model/Statement.java)\n* [Netflix Hystrix](https://github.com/Netflix/Hystrix/wiki)\n* [javax.swing.Action](http://docs.oracle.com/javase/8/docs/api/javax/swing/Action.html)\n\n## Benefits and Trade-offs of Command Pattern\n\nBenefits:\n\n* Decouples the object that invokes the operation from the one that knows how to perform it.\n* It's easy to add new Commands, because you don't have to change existing classes.\n* You can assemble a set of commands into a composite command.\n\nTrade-offs:\n\n* Increases the number of classes for each individual command.\n* Can complicate the design by adding multiple layers between senders and receivers.\n\n## Related Java Design Patterns\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): Commands can be composed using the Composite pattern to create macro commands.\n* [Memento](https://java-design-patterns.com/patterns/memento/): Can be used for implementing undo mechanisms.\n* [Observer](https://java-design-patterns.com/patterns/observer/): The pattern can be observed for changes that trigger commands.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/3PFUqSY)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "command/etc/command.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\"\n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">\n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.command.Goblin\" project=\"command\"\n    file=\"/command/src/main/java/com/iluwatar/command/Goblin.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"129\" y=\"1223\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.command.Wizard\" project=\"command\"\n    file=\"/command/src/main/java/com/iluwatar/command/Wizard.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"129\" y=\"362\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.command.Target\" project=\"command\"\n    file=\"/command/src/main/java/com/iluwatar/command/Target.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"129\" y=\"1014\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <association id=\"7\">\n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">\n      <attribute id=\"8\" name=\"redoStack\">\n        <position height=\"20\" width=\"67\" x=\"140\" y=\"451\"/>\n      </attribute>\n      <multiplicity id=\"9\" minimum=\"0\" maximum=\"2147483647\">\n        <position height=\"18\" width=\"25\" x=\"221\" y=\"452\"/>\n      </multiplicity>\n    </end>\n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <generalization id=\"10\">\n    <end type=\"SOURCE\" refId=\"2\"/>\n    <end type=\"TARGET\" refId=\"6\"/>\n  </generalization>\n  <association id=\"11\">\n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">\n      <attribute id=\"12\" name=\"target\"/>\n      <multiplicity id=\"13\" minimum=\"0\" maximum=\"1\"/>\n    </end>\n    <end type=\"TARGET\" refId=\"6\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <generalization id=\"14\">\n    <end type=\"SOURCE\" refId=\"1\"/>\n    <end type=\"TARGET\" refId=\"4\"/>\n  </generalization>\n  <association id=\"15\">\n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">\n      <attribute id=\"16\" name=\"undoStack\">\n        <position height=\"20\" width=\"70\" x=\"-17\" y=\"451\"/>\n      </attribute>\n      <multiplicity id=\"17\" minimum=\"0\" maximum=\"2147483647\">\n        <position height=\"18\" width=\"25\" x=\"60\" y=\"452\"/>\n      </multiplicity>\n    </end>\n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <generalization id=\"18\">\n    <end type=\"SOURCE\" refId=\"5\"/>\n    <end type=\"TARGET\" refId=\"4\"/>\n  </generalization>\n  <association id=\"19\">\n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">\n      <attribute id=\"20\" name=\"target\"/>\n      <multiplicity id=\"21\" minimum=\"0\" maximum=\"1\"/>\n    </end>\n    <end type=\"TARGET\" refId=\"6\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n  </classifier-display>\n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>\n"
  },
  {
    "path": "command/etc/command.urm.puml",
    "content": "@startuml\npackage com.iluwatar.command {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Goblin {\n    + Goblin()\n    + toString() : String\n    + changeSize()\n    + changeVisibility()\n  }\n  enum Size {\n    + NORMAL {static}\n    + SMALL {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Size {static}\n    + values() : Size[] {static}\n  }\n  abstract class Target {\n    - LOGGER : Logger {static}\n    - size : Size\n    - visibility : Visibility\n    + Target()\n    + getSize() : Size\n    + getVisibility() : Visibility\n    + printStatus()\n    + setSize(size : Size)\n    + setVisibility(visibility : Visibility)\n    + toString() : String {abstract}\n  }\n  enum Visibility {\n    + INVISIBLE {static}\n    + VISIBLE {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Visibility {static}\n    + values() : Visibility[] {static}\n  }\n  class Wizard {\n    - LOGGER : Logger {static}\n    - redoStack : Deque<Runnable>\n    - undoStack : Deque<Runnable>\n    + Wizard()\n    + castSpell(Runnable : runnable)\n    + redoLastSpell()\n    + toString() : String\n    + undoLastSpell()\n  }\n}\nTarget -->  \"-size\" Size\nWizard -->  \"-changeSize\" Goblin\nWizard -->  \"-changeVisibility\" Goblin\nTarget -->  \"-visibility\" Visibility\nGoblin --|> Target\nApp --> \"castSpell\" Wizard\n@enduml\n"
  },
  {
    "path": "command/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>command</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.command.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "command/src/main/java/com/iluwatar/command/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.command;\n\n/**\n * The Command pattern is a behavioral design pattern in which an object is used to encapsulate all\n * information needed to perform an action or trigger an event at a later time. This information\n * includes the method name, the object that owns the method, and values for the method parameters.\n *\n * <p>Four terms always associated with the command pattern are command, receiver, invoker and\n * client. A command object (spell) knows about the receiver (target) and invokes a method of the\n * receiver. An invoker object (wizard) receives a reference to the command to be executed and\n * optionally does bookkeeping about the command execution. The invoker does not know anything about\n * how the command is executed. The client decides which commands to execute at which points. To\n * execute a command, it passes a reference of the function to the invoker object.\n *\n * <p>In other words, in this example the wizard casts spells on the goblin. The wizard keeps track\n * of the previous spells cast, so it is easy to undo them. In addition, the wizard keeps track of\n * the spells undone, so they can be redone.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var wizard = new Wizard();\n    var goblin = new Goblin();\n\n    goblin.printStatus();\n\n    wizard.castSpell(goblin::changeSize);\n    goblin.printStatus();\n\n    wizard.castSpell(goblin::changeVisibility);\n    goblin.printStatus();\n\n    wizard.undoLastSpell();\n    goblin.printStatus();\n\n    wizard.undoLastSpell();\n    goblin.printStatus();\n\n    wizard.redoLastSpell();\n    goblin.printStatus();\n\n    wizard.redoLastSpell();\n    goblin.printStatus();\n  }\n}\n"
  },
  {
    "path": "command/src/main/java/com/iluwatar/command/Goblin.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.command;\n\n/** Goblin is the target of the spells. */\npublic class Goblin extends Target {\n\n  public Goblin() {\n    setSize(Size.NORMAL);\n    setVisibility(Visibility.VISIBLE);\n  }\n\n  @Override\n  public String toString() {\n    return \"Goblin\";\n  }\n}\n"
  },
  {
    "path": "command/src/main/java/com/iluwatar/command/Size.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.command;\n\nimport lombok.RequiredArgsConstructor;\n\n/** Enumeration for target size. */\n@RequiredArgsConstructor\npublic enum Size {\n  SMALL(\"small\"),\n  NORMAL(\"normal\");\n\n  private final String title;\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "command/src/main/java/com/iluwatar/command/Target.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.command;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Base class for spell targets. */\n@Slf4j\n@Getter\n@Setter\npublic abstract class Target {\n\n  private Size size;\n\n  private Visibility visibility;\n\n  /** Print status. */\n  public void printStatus() {\n    LOGGER.info(\"{}, [size={}] [visibility={}]\", this, getSize(), getVisibility());\n  }\n\n  /** Changes the size of the target. */\n  public void changeSize() {\n    var oldSize = getSize() == Size.NORMAL ? Size.SMALL : Size.NORMAL;\n    setSize(oldSize);\n  }\n\n  /** Changes the visibility of the target. */\n  public void changeVisibility() {\n    var visible =\n        getVisibility() == Visibility.INVISIBLE ? Visibility.VISIBLE : Visibility.INVISIBLE;\n    setVisibility(visible);\n  }\n}\n"
  },
  {
    "path": "command/src/main/java/com/iluwatar/command/Visibility.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.command;\n\nimport lombok.RequiredArgsConstructor;\n\n/** Enumeration for target visibility. */\n@RequiredArgsConstructor\npublic enum Visibility {\n  VISIBLE(\"visible\"),\n  INVISIBLE(\"invisible\");\n\n  private final String title;\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "command/src/main/java/com/iluwatar/command/Wizard.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.command;\n\nimport java.util.Deque;\nimport java.util.LinkedList;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Wizard is the invoker of the commands. */\n@Slf4j\npublic class Wizard {\n\n  private final Deque<Runnable> undoStack = new LinkedList<>();\n  private final Deque<Runnable> redoStack = new LinkedList<>();\n\n  /** Cast spell. */\n  public void castSpell(Runnable runnable) {\n    runnable.run();\n    undoStack.offerLast(runnable);\n  }\n\n  /** Undo last spell. */\n  public void undoLastSpell() {\n    if (!undoStack.isEmpty()) {\n      var previousSpell = undoStack.pollLast();\n      redoStack.offerLast(previousSpell);\n      previousSpell.run();\n    }\n  }\n\n  /** Redo last spell. */\n  public void redoLastSpell() {\n    if (!redoStack.isEmpty()) {\n      var previousSpell = redoStack.pollLast();\n      undoStack.offerLast(previousSpell);\n      previousSpell.run();\n    }\n  }\n\n  @Override\n  public String toString() {\n    return \"Wizard\";\n  }\n}\n"
  },
  {
    "path": "command/src/test/java/com/iluwatar/command/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.command;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Command example runs without errors. */\nclass AppTest {\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "command/src/test/java/com/iluwatar/command/CommandTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.command;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/**\n * The Command pattern is a behavioral design pattern in which an object is used to encapsulate all\n * information needed to perform an action or trigger an event at a later time. This information\n * includes the method name, the object that owns the method and values for the method parameters.\n *\n * <p>Four terms always associated with the command pattern are command, receiver, invoker and\n * client. A command object (spell) knows about the receiver (target) and invokes a method of the\n * receiver.Values for parameters of the receiver method are stored in the command. The receiver\n * then does the work. An invoker object (wizard) knows how to execute a command, and optionally\n * does bookkeeping about the command execution. The invoker does not know anything about a concrete\n * command, it knows only about command interface. Both an invoker object and several command\n * objects are held by a client object (app). The client decides which commands to execute at which\n * points. To execute a command, it passes the command object to the invoker object.\n */\nclass CommandTest {\n\n  private static final String GOBLIN = \"Goblin\";\n\n  /**\n   * This test verifies that when the wizard casts spells on the goblin. The wizard keeps track of\n   * the previous spells cast, so it is easy to undo them. In addition, it also verifies that the\n   * wizard keeps track of the spells undone, so they can be redone.\n   */\n  @Test\n  void testCommand() {\n\n    var wizard = new Wizard();\n    var goblin = new Goblin();\n\n    wizard.castSpell(goblin::changeSize);\n    verifyGoblin(goblin, GOBLIN, Size.SMALL, Visibility.VISIBLE);\n\n    wizard.castSpell(goblin::changeVisibility);\n    verifyGoblin(goblin, GOBLIN, Size.SMALL, Visibility.INVISIBLE);\n\n    wizard.undoLastSpell();\n    verifyGoblin(goblin, GOBLIN, Size.SMALL, Visibility.VISIBLE);\n\n    wizard.undoLastSpell();\n    verifyGoblin(goblin, GOBLIN, Size.NORMAL, Visibility.VISIBLE);\n\n    wizard.redoLastSpell();\n    verifyGoblin(goblin, GOBLIN, Size.SMALL, Visibility.VISIBLE);\n\n    wizard.redoLastSpell();\n    verifyGoblin(goblin, GOBLIN, Size.SMALL, Visibility.INVISIBLE);\n  }\n\n  /**\n   * This method asserts that the passed goblin object has the name as expectedName, size as\n   * expectedSize and visibility as expectedVisibility.\n   *\n   * @param goblin a goblin object whose state is to be verified against other parameters\n   * @param expectedName expectedName of the goblin\n   * @param expectedSize expected size of the goblin\n   * @param expectedVisibility expected visibility of the goblin\n   */\n  private void verifyGoblin(\n      Goblin goblin, String expectedName, Size expectedSize, Visibility expectedVisibility) {\n    assertEquals(expectedName, goblin.toString(), \"Goblin's name must be same as expectedName\");\n    assertEquals(expectedSize, goblin.getSize(), \"Goblin's size must be same as expectedSize\");\n    assertEquals(\n        expectedVisibility,\n        goblin.getVisibility(),\n        \"Goblin's visibility must be same as expectedVisibility\");\n  }\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/README.md",
    "content": "---\ntitle: \"Command Query Responsibility Segregation in Java: Optimizing Data Interaction for Scalability\"\nshortTitle: Command Query Responsibility Segregation (CQRS)\ndescription: \"Learn about the Command Query Responsibility Segregation (CQRS) pattern in Java. Discover how segregating commands and queries can enhance the scalability, performance, and maintainability of your software systems.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - Event-driven\n  - Performance\n  - Scalability\n---\n\n## Also known as\n\n* CQRS\n\n## Intent of Command Query Responsibility Segregation Design Pattern\n\nCommand Query Responsibility Segregation (CQRS) aims to segregate the operations that modify the state of an application (commands) from the operations that read the state (queries). This separation enhances scalability, performance, and maintainability in complex software systems.\n\n## Detailed Explanation of Command Query Responsibility Segregation Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a modern library where the tasks of borrowing and returning books (commands) are handled at the front desk, while the task of searching for books and reading them (queries) happens in the reading area. The front desk optimizes for transaction efficiency and record-keeping, ensuring books are properly checked in and out. Meanwhile, the reading area is optimized for comfort and accessibility, making it easy for readers to find and engage with the books. This separation improves the library's overall efficiency and user experience, much like the CQRS pattern enhances a software system's performance and maintainability.\n\nIn plain words\n\n> The CQRS design pattern separates the actions of modifying data (commands) from the actions of retrieving data (queries) to enhance performance, scalability, and maintainability in software systems. By implementing CQRS, you can optimize your system's read and write operations independently, allowing for more efficient data handling and improved overall system performance.\n\nMicrosoft's documentation says\n\n> CQRS separates reads and writes into different models, using commands to update data, and queries to read data.\n\nArchitecture diagram\n\n![CQRS Architecture Diagram](./etc/cqrs-architecture-diagram.png)\n\n## Programmatic Example of CQRS Pattern in Java\n\nOne way to implement the Command Query Responsibility Segregation (CQRS) pattern is to separate the read and write operations into different services.\n\nLet's see the code implementation first and explain how it works afterward.\n\n```java\npublic static void main(String[] args) {\n\n    // Create Authors and Books using CommandService\n    var commands = new CommandServiceImpl();\n\n    commands.authorCreated(AppConstants.E_EVANS, \"Eric Evans\", \"evans@email.com\");\n    commands.authorCreated(AppConstants.J_BLOCH, \"Joshua Bloch\", \"jBloch@email.com\");\n    commands.authorCreated(AppConstants.M_FOWLER, \"Martin Fowler\", \"mFowler@email.com\");\n\n    commands.bookAddedToAuthor(\"Domain-Driven Design\", 60.08, AppConstants.E_EVANS);\n    commands.bookAddedToAuthor(\"Effective Java\", 40.54, AppConstants.J_BLOCH);\n    commands.bookAddedToAuthor(\"Java Puzzlers\", 39.99, AppConstants.J_BLOCH);\n    commands.bookAddedToAuthor(\"Java Concurrency in Practice\", 29.40, AppConstants.J_BLOCH);\n    commands.bookAddedToAuthor(\"Patterns of Enterprise\"\n            + \" Application Architecture\", 54.01, AppConstants.M_FOWLER);\n    commands.bookAddedToAuthor(\"Domain Specific Languages\", 48.89, AppConstants.M_FOWLER);\n    commands.authorNameUpdated(AppConstants.E_EVANS, \"Eric J. Evans\");\n\n    // Query the database using QueryService\n    var queries = new QueryServiceImpl();\n\n    var nullAuthor = queries.getAuthorByUsername(\"username\");\n    var evans = queries.getAuthorByUsername(AppConstants.E_EVANS);\n    var blochBooksCount = queries.getAuthorBooksCount(AppConstants.J_BLOCH);\n    var authorsCount = queries.getAuthorsCount();\n    var dddBook = queries.getBook(\"Domain-Driven Design\");\n    var blochBooks = queries.getAuthorBooks(AppConstants.J_BLOCH);\n\n    LOGGER.info(\"Author username : {}\", nullAuthor);\n    LOGGER.info(\"Author evans : {}\", evans);\n    LOGGER.info(\"jBloch number of books : {}\", blochBooksCount);\n    LOGGER.info(\"Number of authors : {}\", authorsCount);\n    LOGGER.info(\"DDD book : {}\", dddBook);\n    LOGGER.info(\"jBloch books : {}\", blochBooks);\n\n    HibernateUtil.getSessionFactory().close();\n}\n```\n\n1. Command Service: The `CommandServiceImpl` class is used for write operations. It provides methods to create authors and books, and to add books to authors.\n\n2. Query Service: The `QueryServiceImpl` class is used for read operations. It provides methods to get author and book details.\n\nThis separation of concerns allows for flexibility in how the application handles data access and manipulation, and is a key aspect of the CQRS pattern.\n\nProgram output:\n\n```\n17:37:56.040 [main] INFO  com.iluwatar.cqrs.app.App - Author username : null\n17:37:56.040 [main] INFO  com.iluwatar.cqrs.app.App - Author evans : Author(name=Eric J. Evans, email=evans@email.com, username=eEvans)\n17:37:56.041 [main] INFO  com.iluwatar.cqrs.app.App - jBloch number of books : 3\n17:37:56.041 [main] INFO  com.iluwatar.cqrs.app.App - Number of authors : 3\n17:37:56.041 [main] INFO  com.iluwatar.cqrs.app.App - DDD book : Book(title=Domain-Driven Design, price=60.08)\n17:37:56.042 [main] INFO  com.iluwatar.cqrs.app.App - jBloch books : [Book(title=Effective Java, price=40.54), Book(title=Java Puzzlers, price=39.99), Book(title=Java Concurrency in Practice, price=29.4)]\n```\n\n## When to Use the Command Query Responsibility Segregation Pattern in Java\n\n* Systems requiring distinct models for read and write operations for scalability and maintainability, such as e-commerce platforms and high-traffic websites.\n* Complex domain models, like financial services or healthcare applications, where the task of updating objects differs significantly from the task of reading object data.\n* Scenarios where performance optimization for read operations is crucial, and the system can benefit from different data models or databases for reads and writes, enhancing data retrieval speed and accuracy.\n\n## Real-World Applications of CQRS Pattern in Java\n\n* Distributed Systems and Microservices Architecture, where different services manage read and write responsibilities.\n* Event-Sourced Systems, where changes to the application state are stored as a sequence of events.\n* High-Performance Web Applications, segregating read and write databases to optimize load handling.\n\n## Benefits and Trade-offs of Command Query Responsibility Segregation Pattern\n\nBenefits:\n\n* Scalability: By separating read and write models, each can be scaled independently according to their specific demands.\n* Optimization: Allows for the optimization of read models for query efficiency and write models for transactional integrity.\n* Maintainability: Reduces complexity by separating the concerns, leading to cleaner, more maintainable code.\n* Flexibility: Offers the flexibility to choose different technologies for the read and write sides according to their requirements.\n\nTrade-Offs:\n\n* Complexity: Introduces complexity due to synchronization between read and write models, especially in consistency maintenance.\n* Overhead: Might be an overkill for simple systems where the benefits do not outweigh the additional complexity.\n* Learning Curve: Requires a deeper understanding and careful design to implement effectively, increasing the initial learning curve.\n\n## Related Java Design Patterns\n\n* [Event Sourcing](https://java-design-patterns.com/patterns/event-sourcing/): Often used in conjunction with CQRS, where changes to the application state are stored as a sequence of events.\n* Domain-Driven Design (DDD): CQRS fits well within the DDD context, providing clear boundaries and separation of concerns.\n* [Repository](https://java-design-patterns.com/patterns/repository/): Can be used to abstract the data layer, providing a more seamless integration between the command and query sides.\n\n## References and Credits\n\n* [Implementing Domain-Driven Design](https://amzn.to/3TJN2HH)\n* [Microsoft .NET: Architecting Applications for the Enterprise](https://amzn.to/4aktRes)\n* [Patterns, Principles, and Practices of Domain-Driven Design](https://amzn.to/3vNV4Hm)\n* [CQRS, Task Based UIs, Event Sourcing agh! (Greg Young)](http://codebetter.com/gregyoung/2010/02/16/cqrs-task-based-uis-event-sourcing-agh/)\n* [CQRS (Martin Fowler)](https://martinfowler.com/bliki/CQRS.html)\n* [CQRS for Great Good (Oliver Wolf)](https://www.youtube.com/watch?v=Ge53swja9Dw)\n* [CQRS pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs)\n"
  },
  {
    "path": "command-query-responsibility-segregation/etc/command-query-responsibility-segregation.urm.puml",
    "content": "@startuml\npackage com.iluwatar.cqrs.util {\n  class HibernateUtil {\n    - LOGGER : Logger {static}\n    - SESSIONFACTORY : SessionFactory {static}\n    + HibernateUtil()\n    - buildSessionFactory() : SessionFactory {static}\n    + getSessionFactory() : SessionFactory {static}\n  }\n}\npackage com.iluwatar.cqrs.app {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n}\npackage com.iluwatar.cqrs.dto {\n  class Author {\n    - email : String\n    - name : String\n    - username : String\n    + Author()\n    + Author(name : String, email : String, username : String)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getEmail() : String\n    + getName() : String\n    + getUsername() : String\n    + hashCode() : int\n    + toString() : String\n  }\n  class Book {\n    - price : double\n    - title : String\n    + Book()\n    + Book(title : String, price : double)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getPrice() : double\n    + getTitle() : String\n    + hashCode() : int\n    + toString() : String\n  }\n}\npackage com.iluwatar.cqrs.commandes {\n  interface CommandService {\n    + authorCreated(String, String, String) {abstract}\n    + authorEmailUpdated(String, String) {abstract}\n    + authorNameUpdated(String, String) {abstract}\n    + authorUsernameUpdated(String, String) {abstract}\n    + bookAddedToAuthor(String, double, String) {abstract}\n    + bookPriceUpdated(String, double) {abstract}\n    + bookTitleUpdated(String, String) {abstract}\n  }\n  class CommandServiceImpl {\n    - sessionFactory : SessionFactory\n    + CommandServiceImpl()\n    + authorCreated(username : String, name : String, email : String)\n    + authorEmailUpdated(username : String, email : String)\n    + authorNameUpdated(username : String, name : String)\n    + authorUsernameUpdated(oldUsername : String, newUsername : String)\n    + bookAddedToAuthor(title : String, price : double, username : String)\n    + bookPriceUpdated(title : String, price : double)\n    + bookTitleUpdated(oldTitle : String, newTitle : String)\n    - getAuthorByUsername(username : String) : Author\n    - getBookByTitle(title : String) : Book\n  }\n}\npackage com.iluwatar.cqrs.queries {\n  interface QueryService {\n    + getAuthorBooks(String) : List<Book> {abstract}\n    + getAuthorBooksCount(String) : BigInteger {abstract}\n    + getAuthorByUsername(String) : Author {abstract}\n    + getAuthorsCount() : BigInteger {abstract}\n    + getBook(String) : Book {abstract}\n  }\n  class QueryServiceImpl {\n    - sessionFactory : SessionFactory\n    + QueryServiceImpl()\n    + getAuthorBooks(username : String) : List<Book>\n    + getAuthorBooksCount(username : String) : BigInteger\n    + getAuthorByUsername(username : String) : Author\n    + getAuthorsCount() : BigInteger\n    + getBook(title : String) : Book\n  }\n}\npackage com.iluwatar.cqrs.constants {\n  class AppConstants {\n    + E_EVANS : String {static}\n    + J_BLOCH : String {static}\n    + M_FOWLER : String {static}\n    + USER_NAME : String {static}\n    + AppConstants()\n  }\n}\npackage com.iluwatar.cqrs.domain.model {\n  class Author {\n    - email : String\n    - id : long\n    - name : String\n    - username : String\n    # Author()\n    + Author(username : String, name : String, email : String)\n    + getEmail() : String\n    + getId() : long\n    + getName() : String\n    + getUsername() : String\n    + setEmail(email : String)\n    + setId(id : long)\n    + setName(name : String)\n    + setUsername(username : String)\n    + toString() : String\n  }\n  class Book {\n    - author : Author\n    - id : long\n    - price : double\n    - title : String\n    # Book()\n    + Book(title : String, price : double, author : Author)\n    + getAuthor() : Author\n    + getId() : long\n    + getPrice() : double\n    + getTitle() : String\n    + setAuthor(author : Author)\n    + setId(id : long)\n    + setPrice(price : double)\n    + setTitle(title : String)\n    + toString() : String\n  }\n}\nBook -->  \"-author\" Author\nCommandServiceImpl ..|> CommandService \nQueryServiceImpl ..|> QueryService \n@enduml"
  },
  {
    "path": "command-query-responsibility-segregation/etc/cqrs.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.2.0\" icons=\"true\" always-add-relationships=\"false\" generalizations=\"true\" realizations=\"true\" \n  associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <interface id=\"1\" language=\"java\" name=\"com.iluwatar.cqrs.commandes.ICommandService\" project=\"cqrs\" \n    file=\"/cqrs/src/main/java/com/iluwatar/cqrs/commandes/ICommandService.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"291\" y=\"-49\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.cqrs.commandes.CommandServiceImpl\" project=\"cqrs\" \n    file=\"/cqrs/src/main/java/com/iluwatar/cqrs/commandes/CommandServiceImpl.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"263\" width=\"256\" x=\"170\" y=\"87\"/>    \n    <display autosize=\"false\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"3\" language=\"java\" name=\"com.iluwatar.cqrs.queries.IQueryService\" project=\"cqrs\" \n    file=\"/cqrs/src/main/java/com/iluwatar/cqrs/queries/IQueryService.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"182\" width=\"248\" x=\"176\" y=\"428\"/>    \n    <display autosize=\"false\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.cqrs.queries.QueryServiceImpl\" project=\"cqrs\" \n    file=\"/cqrs/src/main/java/com/iluwatar/cqrs/queries/QueryServiceImpl.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"258\" width=\"253\" x=\"169\" y=\"665\"/>    \n    <display autosize=\"false\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.cqrs.domain.model.Book\" project=\"cqrs\" \n    file=\"/cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Book.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"326\" width=\"158\" x=\"778\" y=\"-93\"/>    \n    <display autosize=\"false\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.cqrs.dto.Book\" project=\"cqrs\" \n    file=\"/cqrs/src/main/java/com/iluwatar/cqrs/dto/Book.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"219\" width=\"150\" x=\"541\" y=\"607\"/>    \n    <display autosize=\"false\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.cqrs.domain.model.Author\" project=\"cqrs\" \n    file=\"/cqrs/src/main/java/com/iluwatar/cqrs/domain/model/Author.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"608\" y=\"70\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.cqrs.dto.Author\" project=\"cqrs\" \n    file=\"/cqrs/src/main/java/com/iluwatar/cqrs/dto/Author.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"834\" y=\"719\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"9\" language=\"java\" name=\"com.iluwatar.cqrs.util.HibernateUtil\" project=\"cqrs\" \n    file=\"/cqrs/src/main/java/com/iluwatar/cqrs/util/HibernateUtil.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"662\" y=\"412\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <dependency id=\"10\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"9\"/>  \n  </dependency>  \n  <dependency id=\"11\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"9\"/>  \n  </dependency>  \n  <realization id=\"12\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </realization>  \n  <association id=\"13\">    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"14\" name=\"author\"/>      \n      <multiplicity id=\"15\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"7\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"16\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "command-query-responsibility-segregation/etc/cqrs.urm.puml",
    "content": "@startuml\npackage com.iluwatar.cqrs.util {\n  class HibernateUtil {\n    - LOGGER : Logger {static}\n    - SESSIONFACTORY : SessionFactory {static}\n    + HibernateUtil()\n    - buildSessionFactory() : SessionFactory {static}\n    + getSessionFactory() : SessionFactory {static}\n  }\n}\npackage com.iluwatar.cqrs.app {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n}\npackage com.iluwatar.cqrs.dto {\n  class Author {\n    - email : String\n    - name : String\n    - username : String\n    + Author()\n    + Author(name : String, email : String, username : String)\n    + equals(obj : Object) : boolean\n    + getEmail() : String\n    + getName() : String\n    + getUsername() : String\n    + hashCode() : int\n    + toString() : String\n  }\n  class Book {\n    - price : double\n    - title : String\n    + Book()\n    + Book(title : String, price : double)\n    + equals(obj : Object) : boolean\n    + getPrice() : double\n    + getTitle() : String\n    + hashCode() : int\n    + toString() : String\n  }\n}\npackage com.iluwatar.cqrs.commandes {\n  class CommandServiceImpl {\n    - sessionFactory : SessionFactory\n    + CommandServiceImpl()\n    + authorCreated(username : String, name : String, email : String)\n    + authorEmailUpdated(username : String, email : String)\n    + authorNameUpdated(username : String, name : String)\n    + authorUsernameUpdated(oldUsername : String, newUsername : String)\n    + bookAddedToAuthor(title : String, price : double, username : String)\n    + bookPriceUpdated(title : String, price : double)\n    + bookTitleUpdated(oldTitle : String, newTitle : String)\n    - getAuthorByUsername(username : String) : Author\n    - getBookByTitle(title : String) : Book\n  }\n  interface ICommandService {\n    + authorCreated(String, String, String) {abstract}\n    + authorEmailUpdated(String, String) {abstract}\n    + authorNameUpdated(String, String) {abstract}\n    + authorUsernameUpdated(String, String) {abstract}\n    + bookAddedToAuthor(String, double, String) {abstract}\n    + bookPriceUpdated(String, double) {abstract}\n    + bookTitleUpdated(String, String) {abstract}\n  }\n}\npackage com.iluwatar.cqrs.queries {\n  interface IQueryService {\n    + getAuthorBooks(String) : List<Book> {abstract}\n    + getAuthorBooksCount(String) : BigInteger {abstract}\n    + getAuthorByUsername(String) : Author {abstract}\n    + getAuthorsCount() : BigInteger {abstract}\n    + getBook(String) : Book {abstract}\n  }\n  class QueryServiceImpl {\n    - sessionFactory : SessionFactory\n    + QueryServiceImpl()\n    + getAuthorBooks(username : String) : List<Book>\n    + getAuthorBooksCount(username : String) : BigInteger\n    + getAuthorByUsername(username : String) : Author\n    + getAuthorsCount() : BigInteger\n    + getBook(title : String) : Book\n  }\n}\npackage com.iluwatar.cqrs.constants {\n  class AppConstants {\n    + E_EVANS : String {static}\n    + J_BLOCH : String {static}\n    + M_FOWLER : String {static}\n    + USER_NAME : String {static}\n    + AppConstants()\n  }\n}\npackage com.iluwatar.cqrs.domain.model {\n  class Author {\n    - email : String\n    - id : long\n    - name : String\n    - username : String\n    # Author()\n    + Author(username : String, name : String, email : String)\n    + getEmail() : String\n    + getId() : long\n    + getName() : String\n    + getUsername() : String\n    + setEmail(email : String)\n    + setId(id : long)\n    + setName(name : String)\n    + setUsername(username : String)\n    + toString() : String\n  }\n  class Book {\n    - author : Author\n    - id : long\n    - price : double\n    - title : String\n    # Book()\n    + Book(title : String, price : double, author : Author)\n    + getAuthor() : Author\n    + getId() : long\n    + getPrice() : double\n    + getTitle() : String\n    + setAuthor(author : Author)\n    + setId(id : long)\n    + setPrice(price : double)\n    + setTitle(title : String)\n    + toString() : String\n  }\n}\nBook -->  \"-author\" Author\nCommandServiceImpl ..|> ICommandService \nQueryServiceImpl ..|> IQueryService \n@enduml"
  },
  {
    "path": "command-query-responsibility-segregation/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>command-query-responsibility-segregation</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.h2database</groupId>\n            <artifactId>h2</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.hibernate</groupId>\n            <artifactId>hibernate-core</artifactId>\n            <version>5.6.15.Final</version>\n        </dependency>\n        <dependency>\n            <groupId>org.glassfish.jaxb</groupId>\n            <artifactId>jaxb-runtime</artifactId>\n            <version>2.3.3</version>\n        </dependency>\n        <dependency>\n            <groupId>javax.xml.bind</groupId>\n            <artifactId>jaxb-api</artifactId>\n            <version>2.3.1</version>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.cqrs.app.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/java/com/iluwatar/cqrs/app/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cqrs.app;\n\nimport com.iluwatar.cqrs.commandes.CommandServiceImpl;\nimport com.iluwatar.cqrs.constants.AppConstants;\nimport com.iluwatar.cqrs.queries.QueryServiceImpl;\nimport com.iluwatar.cqrs.util.HibernateUtil;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * CQRS : Command Query Responsibility Segregation. A pattern used to separate query services from\n * commands or writes services. The pattern is very simple, but it has many consequences. For\n * example, it can be used to tackle down a complex domain, or to use other architectures that were\n * hard to implement with the classical way.\n *\n * <p>This implementation is an example of managing books and authors in a library. The persistence\n * of books and authors is done according to the CQRS architecture. A command side that deals with a\n * data model to persist(insert,update,delete) objects to a database. And a query side that uses\n * native queries to get data from the database and return objects as DTOs (Data transfer Objects).\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    // Create Authors and Books using CommandService\n    var commands = new CommandServiceImpl();\n\n    commands.authorCreated(AppConstants.E_EVANS, \"Eric Evans\", \"evans@email.com\");\n    commands.authorCreated(AppConstants.J_BLOCH, \"Joshua Bloch\", \"jBloch@email.com\");\n    commands.authorCreated(AppConstants.M_FOWLER, \"Martin Fowler\", \"mFowler@email.com\");\n\n    commands.bookAddedToAuthor(\"Domain-Driven Design\", 60.08, AppConstants.E_EVANS);\n    commands.bookAddedToAuthor(\"Effective Java\", 40.54, AppConstants.J_BLOCH);\n    commands.bookAddedToAuthor(\"Java Puzzlers\", 39.99, AppConstants.J_BLOCH);\n    commands.bookAddedToAuthor(\"Java Concurrency in Practice\", 29.40, AppConstants.J_BLOCH);\n    commands.bookAddedToAuthor(\n        \"Patterns of Enterprise\" + \" Application Architecture\", 54.01, AppConstants.M_FOWLER);\n    commands.bookAddedToAuthor(\"Domain Specific Languages\", 48.89, AppConstants.M_FOWLER);\n    commands.authorNameUpdated(AppConstants.E_EVANS, \"Eric J. Evans\");\n\n    // Query the database using QueryService\n    var queries = new QueryServiceImpl();\n\n    var nullAuthor = queries.getAuthorByUsername(\"username\");\n    var evans = queries.getAuthorByUsername(AppConstants.E_EVANS);\n    var blochBooksCount = queries.getAuthorBooksCount(AppConstants.J_BLOCH);\n    var authorsCount = queries.getAuthorsCount();\n    var dddBook = queries.getBook(\"Domain-Driven Design\");\n    var blochBooks = queries.getAuthorBooks(AppConstants.J_BLOCH);\n\n    LOGGER.info(\"Author username : {}\", nullAuthor);\n    LOGGER.info(\"Author evans : {}\", evans);\n    LOGGER.info(\"jBloch number of books : {}\", blochBooksCount);\n    LOGGER.info(\"Number of authors : {}\", authorsCount);\n    LOGGER.info(\"DDD book : {}\", dddBook);\n    LOGGER.info(\"jBloch books : {}\", blochBooks);\n\n    HibernateUtil.getSessionFactory().close();\n  }\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/java/com/iluwatar/cqrs/commandes/CommandService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cqrs.commandes;\n\n/** This interface represents the commands of the CQRS pattern. */\npublic interface CommandService {\n\n  void authorCreated(String username, String name, String email);\n\n  void bookAddedToAuthor(String title, double price, String username);\n\n  void authorNameUpdated(String username, String name);\n\n  void authorUsernameUpdated(String oldUsername, String newUsername);\n\n  void authorEmailUpdated(String username, String email);\n\n  void bookTitleUpdated(String oldTitle, String newTitle);\n\n  void bookPriceUpdated(String title, double price);\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/java/com/iluwatar/cqrs/commandes/CommandServiceImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cqrs.commandes;\n\nimport com.iluwatar.cqrs.domain.model.Author;\nimport com.iluwatar.cqrs.domain.model.Book;\nimport com.iluwatar.cqrs.util.HibernateUtil;\nimport org.hibernate.SessionFactory;\n\n/**\n * This class is an implementation of {@link CommandService} interface. It uses Hibernate as an api\n * for persistence.\n */\npublic class CommandServiceImpl implements CommandService {\n\n  private final SessionFactory sessionFactory = HibernateUtil.getSessionFactory();\n\n  private Author getAuthorByUsername(String username) {\n    Author author;\n    try (var session = sessionFactory.openSession()) {\n      var query = session.createQuery(\"from Author where username=:username\");\n      query.setParameter(\"username\", username);\n      author = (Author) query.uniqueResult();\n    }\n    if (author == null) {\n      HibernateUtil.getSessionFactory().close();\n      throw new NullPointerException(\"Author \" + username + \" doesn't exist!\");\n    }\n    return author;\n  }\n\n  private Book getBookByTitle(String title) {\n    Book book;\n    try (var session = sessionFactory.openSession()) {\n      var query = session.createQuery(\"from Book where title=:title\");\n      query.setParameter(\"title\", title);\n      book = (Book) query.uniqueResult();\n    }\n    if (book == null) {\n      HibernateUtil.getSessionFactory().close();\n      throw new NullPointerException(\"Book \" + title + \" doesn't exist!\");\n    }\n    return book;\n  }\n\n  @Override\n  public void authorCreated(String username, String name, String email) {\n    var author = new Author(username, name, email);\n    try (var session = sessionFactory.openSession()) {\n      session.beginTransaction();\n      session.save(author);\n      session.getTransaction().commit();\n    }\n  }\n\n  @Override\n  public void bookAddedToAuthor(String title, double price, String username) {\n    var author = getAuthorByUsername(username);\n    var book = new Book(title, price, author);\n    try (var session = sessionFactory.openSession()) {\n      session.beginTransaction();\n      session.save(book);\n      session.getTransaction().commit();\n    }\n  }\n\n  @Override\n  public void authorNameUpdated(String username, String name) {\n    var author = getAuthorByUsername(username);\n    author.setName(name);\n    try (var session = sessionFactory.openSession()) {\n      session.beginTransaction();\n      session.update(author);\n      session.getTransaction().commit();\n    }\n  }\n\n  @Override\n  public void authorUsernameUpdated(String oldUsername, String newUsername) {\n    var author = getAuthorByUsername(oldUsername);\n    author.setUsername(newUsername);\n    try (var session = sessionFactory.openSession()) {\n      session.beginTransaction();\n      session.update(author);\n      session.getTransaction().commit();\n    }\n  }\n\n  @Override\n  public void authorEmailUpdated(String username, String email) {\n    var author = getAuthorByUsername(username);\n    author.setEmail(email);\n    try (var session = sessionFactory.openSession()) {\n      session.beginTransaction();\n      session.update(author);\n      session.getTransaction().commit();\n    }\n  }\n\n  @Override\n  public void bookTitleUpdated(String oldTitle, String newTitle) {\n    var book = getBookByTitle(oldTitle);\n    book.setTitle(newTitle);\n    try (var session = sessionFactory.openSession()) {\n      session.beginTransaction();\n      session.update(book);\n      session.getTransaction().commit();\n    }\n  }\n\n  @Override\n  public void bookPriceUpdated(String title, double price) {\n    var book = getBookByTitle(title);\n    book.setPrice(price);\n    try (var session = sessionFactory.openSession()) {\n      session.beginTransaction();\n      session.update(book);\n      session.getTransaction().commit();\n    }\n  }\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/java/com/iluwatar/cqrs/constants/AppConstants.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cqrs.constants;\n\n/** Class to define the constants. */\npublic class AppConstants {\n\n  public static final String E_EVANS = \"eEvans\";\n  public static final String J_BLOCH = \"jBloch\";\n  public static final String M_FOWLER = \"mFowler\";\n  public static final String USER_NAME = \"username\";\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/java/com/iluwatar/cqrs/domain/model/Author.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cqrs.domain.model;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.GenerationType;\nimport javax.persistence.Id;\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\n/** This is an Author entity. It is used by Hibernate for persistence. */\n@ToString\n@Getter\n@Setter\n@Entity\npublic class Author {\n  @Id\n  @GeneratedValue(strategy = GenerationType.IDENTITY)\n  private long id;\n\n  private String username;\n  private String name;\n  private String email;\n\n  /**\n   * Constructor.\n   *\n   * @param username username of the author\n   * @param name name of the author\n   * @param email email of the author\n   */\n  public Author(String username, String name, String email) {\n    this.username = username;\n    this.name = name;\n    this.email = email;\n  }\n\n  protected Author() {}\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/java/com/iluwatar/cqrs/domain/model/Book.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cqrs.domain.model;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.GenerationType;\nimport javax.persistence.Id;\nimport javax.persistence.ManyToOne;\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\n/**\n * This is a Book entity. It is used by Hibernate for persistence. Many books can be written by one\n * {@link Author}\n */\n@ToString\n@Setter\n@Getter\n@Entity\npublic class Book {\n  @Id\n  @GeneratedValue(strategy = GenerationType.IDENTITY)\n  private long id;\n\n  private String title;\n  private double price;\n  @ManyToOne private Author author;\n\n  /**\n   * Constructor.\n   *\n   * @param title title of the book\n   * @param price price of the book\n   * @param author author of the book\n   */\n  public Book(String title, double price, Author author) {\n    this.title = title;\n    this.price = price;\n    this.author = author;\n  }\n\n  protected Book() {}\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/java/com/iluwatar/cqrs/dto/Author.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cqrs.dto;\n\nimport lombok.AllArgsConstructor;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.ToString;\n\n/** This is a DTO (Data Transfer Object) author, contains only useful information to be returned. */\n@ToString\n@EqualsAndHashCode\n@Getter\n@NoArgsConstructor\n@AllArgsConstructor\npublic class Author {\n\n  private String name;\n  private String email;\n  private String username;\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/java/com/iluwatar/cqrs/dto/Book.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cqrs.dto;\n\nimport lombok.AllArgsConstructor;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.ToString;\n\n/** This is a DTO (Data Transfer Object) book, contains only useful information to be returned. */\n@ToString\n@EqualsAndHashCode\n@Getter\n@AllArgsConstructor\n@NoArgsConstructor\npublic class Book {\n\n  private String title;\n  private double price;\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/java/com/iluwatar/cqrs/queries/QueryService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cqrs.queries;\n\nimport com.iluwatar.cqrs.dto.Author;\nimport com.iluwatar.cqrs.dto.Book;\nimport java.math.BigInteger;\nimport java.util.List;\n\n/** This interface represents the query methods of the CQRS pattern. */\npublic interface QueryService {\n\n  Author getAuthorByUsername(String username);\n\n  Book getBook(String title);\n\n  List<Book> getAuthorBooks(String username);\n\n  BigInteger getAuthorBooksCount(String username);\n\n  BigInteger getAuthorsCount();\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/java/com/iluwatar/cqrs/queries/QueryServiceImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cqrs.queries;\n\nimport com.iluwatar.cqrs.constants.AppConstants;\nimport com.iluwatar.cqrs.dto.Author;\nimport com.iluwatar.cqrs.dto.Book;\nimport com.iluwatar.cqrs.util.HibernateUtil;\nimport java.math.BigInteger;\nimport java.util.List;\nimport org.hibernate.SessionFactory;\nimport org.hibernate.query.Query;\n\n/**\n * This class is an implementation of {@link QueryService}. It uses Hibernate native queries to\n * return DTOs from the database.\n */\npublic class QueryServiceImpl implements QueryService {\n\n  private final SessionFactory sessionFactory = HibernateUtil.getSessionFactory();\n\n  @Override\n  public Author getAuthorByUsername(String username) {\n    Author authorDto;\n    try (var session = sessionFactory.openSession()) {\n      Query<Author> sqlQuery =\n          session.createQuery(\n              \"select new com.iluwatar.cqrs.dto.Author(a.name, a.email, a.username)\"\n                  + \" from com.iluwatar.cqrs.domain.model.Author a where a.username=:username\");\n      sqlQuery.setParameter(AppConstants.USER_NAME, username);\n      authorDto = sqlQuery.uniqueResult();\n    }\n    return authorDto;\n  }\n\n  @Override\n  public Book getBook(String title) {\n    Book bookDto;\n    try (var session = sessionFactory.openSession()) {\n      Query<Book> sqlQuery =\n          session.createQuery(\n              \"select new com.iluwatar.cqrs.dto.Book(b.title, b.price)\"\n                  + \" from com.iluwatar.cqrs.domain.model.Book b where b.title=:title\");\n      sqlQuery.setParameter(\"title\", title);\n      bookDto = sqlQuery.uniqueResult();\n    }\n    return bookDto;\n  }\n\n  @Override\n  public List<Book> getAuthorBooks(String username) {\n    List<Book> bookDtos;\n    try (var session = sessionFactory.openSession()) {\n      Query<Book> sqlQuery =\n          session.createQuery(\n              \"select new com.iluwatar.cqrs.dto.Book(b.title, b.price)\"\n                  + \" from com.iluwatar.cqrs.domain.model.Author a, com.iluwatar.cqrs.domain.model.Book b \"\n                  + \"where b.author.id = a.id and a.username=:username\");\n      sqlQuery.setParameter(AppConstants.USER_NAME, username);\n      bookDtos = sqlQuery.list();\n    }\n    return bookDtos;\n  }\n\n  @Override\n  public BigInteger getAuthorBooksCount(String username) {\n    BigInteger bookcount;\n    try (var session = sessionFactory.openSession()) {\n      var sqlQuery =\n          session.createNativeQuery(\n              \"SELECT count(b.title)\"\n                  + \" FROM  Book b, Author a\"\n                  + \" where b.author_id = a.id and a.username=:username\");\n      sqlQuery.setParameter(AppConstants.USER_NAME, username);\n      bookcount = (BigInteger) sqlQuery.uniqueResult();\n    }\n    return bookcount;\n  }\n\n  @Override\n  public BigInteger getAuthorsCount() {\n    BigInteger authorcount;\n    try (var session = sessionFactory.openSession()) {\n      var sqlQuery = session.createNativeQuery(\"SELECT count(id) from Author\");\n      authorcount = (BigInteger) sqlQuery.uniqueResult();\n    }\n    return authorcount;\n  }\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/java/com/iluwatar/cqrs/util/HibernateUtil.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cqrs.util;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.hibernate.SessionFactory;\nimport org.hibernate.boot.MetadataSources;\nimport org.hibernate.boot.registry.StandardServiceRegistryBuilder;\n\n/**\n * This class simply returns one instance of {@link SessionFactory} initialized when the application\n * is started.\n */\n@Slf4j\npublic class HibernateUtil {\n\n  private static final SessionFactory SESSIONFACTORY = buildSessionFactory();\n\n  private static SessionFactory buildSessionFactory() {\n\n    // configures settings from hibernate.cfg.xml\n    final var registry = new StandardServiceRegistryBuilder().configure().build();\n    try {\n      return new MetadataSources(registry).buildMetadata().buildSessionFactory();\n    } catch (Exception ex) {\n      StandardServiceRegistryBuilder.destroy(registry);\n      LOGGER.error(\"Initial SessionFactory creation failed.\", ex);\n      throw new ExceptionInInitializerError(ex);\n    }\n  }\n\n  public static SessionFactory getSessionFactory() {\n    return SESSIONFACTORY;\n  }\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/resources/hibernate.cfg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<!DOCTYPE hibernate-configuration SYSTEM \"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd\">\n<hibernate-configuration>\n  <session-factory>\n    <property name=\"dialect\">org.hibernate.dialect.H2Dialect</property>\n    <property name=\"connection.driver_class\">org.h2.Driver</property>\n    <property name=\"connection.url\">jdbc:h2:mem:test</property>\n    <property name=\"connection.username\">sa</property>\n    <property name=\"hbm2ddl.auto\">create</property>\n    <mapping class=\"com.iluwatar.cqrs.domain.model.Author\" />\n    <mapping class=\"com.iluwatar.cqrs.domain.model.Book\" />\n  </session-factory>\n</hibernate-configuration>\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<configuration>\n  <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n    <encoder>\n      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>\n    </encoder>\n  </appender>\n  <root level=\"info\">\n    <appender-ref ref=\"STDOUT\" />\n  </root>\n</configuration>\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/test/java/com/iluwatar/cqrs/IntegrationTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.cqrs;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.cqrs.commandes.CommandServiceImpl;\nimport com.iluwatar.cqrs.dto.Author;\nimport com.iluwatar.cqrs.dto.Book;\nimport com.iluwatar.cqrs.queries.QueryService;\nimport com.iluwatar.cqrs.queries.QueryServiceImpl;\nimport java.math.BigInteger;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\n/** Integration test of IQueryService and ICommandService with h2 data */\nclass IntegrationTest {\n\n  private static QueryService queryService;\n\n  @BeforeAll\n  static void initializeAndPopulateDatabase() {\n    var commandService = new CommandServiceImpl();\n    queryService = new QueryServiceImpl();\n\n    // create first author1\n    commandService.authorCreated(\"username1\", \"name1\", \"email1\");\n\n    // create author1 and update all its data\n    commandService.authorCreated(\"username2\", \"name2\", \"email2\");\n    commandService.authorEmailUpdated(\"username2\", \"new_email2\");\n    commandService.authorNameUpdated(\"username2\", \"new_name2\");\n    commandService.authorUsernameUpdated(\"username2\", \"new_username2\");\n\n    // add book1 to author1\n    commandService.bookAddedToAuthor(\"title1\", 10, \"username1\");\n\n    // add book2 to author1 and update all its data\n    commandService.bookAddedToAuthor(\"title2\", 20, \"username1\");\n    commandService.bookPriceUpdated(\"title2\", 30);\n    commandService.bookTitleUpdated(\"title2\", \"new_title2\");\n  }\n\n  @Test\n  void testGetAuthorByUsername() {\n    var author = queryService.getAuthorByUsername(\"username1\");\n    assertEquals(\"username1\", author.getUsername());\n    assertEquals(\"name1\", author.getName());\n    assertEquals(\"email1\", author.getEmail());\n  }\n\n  @Test\n  void testGetUpdatedAuthorByUsername() {\n    var author = queryService.getAuthorByUsername(\"new_username2\");\n    var expectedAuthor = new Author(\"new_name2\", \"new_email2\", \"new_username2\");\n    assertEquals(expectedAuthor, author);\n  }\n\n  @Test\n  void testGetBook() {\n    var book = queryService.getBook(\"title1\");\n    assertEquals(\"title1\", book.getTitle());\n    assertEquals(10, book.getPrice(), 0.01);\n  }\n\n  @Test\n  void testGetAuthorBooks() {\n    var books = queryService.getAuthorBooks(\"username1\");\n    assertEquals(2, books.size());\n    assertTrue(books.contains(new Book(\"title1\", 10)));\n    assertTrue(books.contains(new Book(\"new_title2\", 30)));\n  }\n\n  @Test\n  void testGetAuthorBooksCount() {\n    var bookCount = queryService.getAuthorBooksCount(\"username1\");\n    assertEquals(new BigInteger(\"2\"), bookCount);\n  }\n\n  @Test\n  void testGetAuthorsCount() {\n    var authorCount = queryService.getAuthorsCount();\n    assertEquals(new BigInteger(\"2\"), authorCount);\n  }\n}\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/test/resources/hibernate.cfg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<!DOCTYPE hibernate-configuration SYSTEM \"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd\">\n<hibernate-configuration>\n  <session-factory>\n    <property name=\"dialect\">org.hibernate.dialect.H2Dialect</property>\n    <property name=\"connection.driver_class\">org.h2.Driver</property>\n    <property name=\"connection.url\">jdbc:h2:mem:test</property>\n    <property name=\"connection.username\">sa</property>\n    <property name=\"hbm2ddl.auto\">create</property>\n    <mapping class=\"com.iluwatar.cqrs.domain.model.Author\" />\n    <mapping class=\"com.iluwatar.cqrs.domain.model.Book\" />\n  </session-factory>\n</hibernate-configuration>\n"
  },
  {
    "path": "command-query-responsibility-segregation/src/test/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<configuration>\n  <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n    <encoder>\n      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>\n    </encoder>\n  </appender>\n  <root level=\"info\">\n    <appender-ref ref=\"STDOUT\" />\n  </root>\n</configuration>\n"
  },
  {
    "path": "commander/README.md",
    "content": "---\ntitle: \"Commander Pattern in Java: Orchestrating Complex Commands with Ease\"\nshortTitle: Commander\ndescription: \"Learn about the Commander design pattern in Java, a powerful approach for managing distributed transactions across multiple services. Ensure data consistency and reliability in your microservices architecture with practical examples and use cases.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Cloud distributed\n  - Microservices\n  - Transactions\nhead:\n  - - meta\n    - name: keywords\n      content:\n---\n\n## Also known as\n\n* Distributed Transaction Commander\n* Transaction Coordinator\n\n## Intent of Commander Design Pattern\n\nThe intent of the Commander pattern in Java, especially in the context of distributed transactions, is to manage and coordinate complex transactions across multiple distributed components or services. This pattern ensures data consistency and integrity in distributed systems, making it crucial for microservices architecture. It encapsulates transaction commands and coordination logic, facilitating the implementation of distributed transaction protocols like two-phase commit or Saga.\n\n## Detailed Explanation of Commander Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine organizing a large international music festival where various bands from around the world are scheduled to perform. Each band's arrival, soundcheck, and performance are akin to individual transactions in a distributed system. This scenario mirrors the Commander pattern in Java, where the \"Commander\" coordinates distributed transactions to maintain overall consistency and reliability. The festival organizer acts as the \"Commander,\" coordinating these transactions to ensure that if a band's flight is delayed (akin to a transaction failure), there's a backup plan, such as rescheduling or swapping time slots with another band (compensating actions), to keep the overall schedule intact. This setup mirrors the Commander pattern in distributed transactions, where various components must be coordinated to achieve a successful outcome despite individual failures.\n\nIn plain words\n\n> The Commander pattern turns a request into a stand-alone object, allowing for the parameterization of commands, queueing of actions, and the implementation of undo operations.\n\nSequence diagram\n\n![Commander sequence diagram](./etc/commander-sequence-diagram.png)\n\n## Programmatic Example of Commander Pattern in Java\n\nManaging transactions across different services in a distributed system, such as an e-commerce platform with separate `Payment` and `Shipping` microservices, requires careful coordination. Using the Commander pattern in Java for transaction coordination helps ensure data consistency and reliability, even when services experience partial failures.\n\nA strategy to address this involves using a `Commander` component that orchestrates the process. Initially, the order is processed by the available service (`Shipping` in this case). The `Commander` then attempts to synchronize the order with the currently unavailable service (`Payment`) by storing the order details in a database or queueing it for future processing. This queueing system must also account for possible failures in adding requests to the queue.\n\nThe `Commander` repeatedly tries to process the queued orders to ensure both services eventually reflect the same transaction data. This process involves ensuring idempotence, meaning that even if the same order synchronization request is made multiple times, it will only be executed once, preventing duplicate transactions. The goal is to achieve eventual consistency across services, where all systems are synchronized over time despite initial failures or delays.\n\nHere's a simplified example of how the `Commander` class is used in the `AppAllCases` class:\n\n```java\npublic class AppAllCases {\n  // ... other methods ...\n\n  // Shipping Database Fail Cases\n  void itemUnavailableCase() {\n    var ps = new PaymentService(new PaymentDatabase());\n    var ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException());\n    var ms = new MessagingService(new MessagingDatabase());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb = new QueueDatabase();\n    // Create a Commander instance\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    // Use the Commander instance to place an order\n    c.placeOrder(order);\n  }\n\n  // ... other methods ...\n}\n```\n\nIn the `itemUnavailableCase` method, a `Commander` instance is created with the respective services and their databases. Then, a `User` and an `Order` are created, and the `placeOrder` method of the `Commander` instance is called with the order. This triggers the process of placing the order and handling any failures according to the Commander pattern.\n\nThe `Commander` class encapsulates the logic for handling the order placement and any potential failures. This separation of concerns makes the code easier to understand and maintain, and it allows for the reuse of the `Commander` class in different parts of the application.  In a real-world application, the `Commander` class would be more complex and would include additional logic for handling different types of failures, retrying failed operations, and coordinating transactions across multiple services.\n\nHere is the output from executing the `itemUnavailableCase`:\n\n```\n09:10:13.894 [main] DEBUG com.iluwatar.commander.Commander -- Order YN3V8B7IL2PI: Error in creating shipping request..\n09:10:13.896 [main] INFO com.iluwatar.commander.Commander -- This item is currently unavailable. We will inform you as soon as the item becomes available again.\n09:10:13.896 [main] INFO com.iluwatar.commander.Commander -- Order YN3V8B7IL2PI: Item book unavailable, trying to add problem to employee handle..\n09:10:13.897 [Thread-0] INFO com.iluwatar.commander.Commander -- Order YN3V8B7IL2PI: Added order to employee database\n```\n\n## When to Use the Commander Pattern in Java\n\nUse the Commander pattern in Java for distributed transactions when:\n\n* You need to ensure data consistency across distributed services in the event of partial system failures.\n* Transactions span multiple microservices or distributed components requiring coordinated commit or rollback.\n* You are implementing long-lived transactions requiring compensating actions for rollback.\n\n## Real-World Applications of Commander Pattern in Java\n\n* Two-Phase Commit (2PC) Protocols: Coordinating commit or rollback across distributed databases or services.\n* Saga Pattern Implementations: Managing long-lived business processes that span multiple microservices, with each step having a compensating action for rollback.\n* Distributed Transactions in Microservices Architecture: Coordinating complex operations across microservices while maintaining data integrity and consistency.\n\n## Benefits and Trade-offs of Commander Pattern\n\nBenefits:\n\n* Provides a clear mechanism for managing complex distributed transactions, enhancing system reliability.\n* Enables the implementation of compensating transactions, which are crucial for maintaining consistency in long-lived transactions.\n* Facilitates the integration of heterogeneous systems within a transactional context.\n\nTrade-offs:\n\n* Increases complexity, especially in failure scenarios, due to the need for coordinated rollback mechanisms.\n* Potentially impacts performance due to the overhead of coordination and consistency checks.\n* Saga-based implementations can lead to increased complexity in understanding the overall business process flow.\n\n## Related Java Design Patterns\n\n* [Saga Pattern](https://java-design-patterns.com/patterns/saga/): Often discussed in tandem with the Commander pattern for distributed transactions, focusing on long-lived transactions with compensating actions.\n\n## References and Credits\n\n* [Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions](https://amzn.to/4aATcRe)\n* [Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems](https://amzn.to/4axHwOV)\n* [Microservices Patterns: With examples in Java](https://amzn.to/4axjnYW)\n* [Distributed Transactions: The Icebergs of Microservices (Graham Lea)](https://www.grahamlea.com/2016/08/distributed-transactions-microservices-icebergs/)\n"
  },
  {
    "path": "commander/etc/commander.urm.puml",
    "content": "@startuml\npackage com.iluwatar.commander.queue {\n  class Queue<T> {\n    - front : Queue.Node<T>\n    - rear : Queue.Node<T>\n    - size : int\n    ~ Queue<T>()\n    ~ dequeue() : T\n    ~ enqueue(obj : T)\n    ~ isEmpty() : boolean\n    ~ peek() : T\n  }\n  ~class Node<V> {\n    ~ next : Queue.Node<V>\n    ~ value : V\n    ~ Node<V>(obj : V, b : Queue.Node<V>)\n  }\n  class QueueDatabase {\n    - data : Queue<QueueTask>\n    + exceptionsList : List<Exception>\n    + QueueDatabase(exc : Exception[])\n    + add(t : QueueTask) : QueueTask\n    + dequeue() : QueueTask\n    + get(taskId : String) : QueueTask\n    + peek() : QueueTask\n  }\n  class QueueTask {\n    + firstAttemptTime : long\n    + messageType : int\n    + order : Order\n    + taskType : TaskType\n    + QueueTask(o : Order, t : TaskType, messageType : int)\n    + getType() : String\n  }\n  enum TaskType {\n    + EmployeeDb {static}\n    + Messaging {static}\n    + Payment {static}\n    + valueOf(name : String) : TaskType {static}\n    + values() : TaskType[] {static}\n  }\n}\npackage com.iluwatar.commander.messagingservice {\n  class MessagingDatabase {\n    - data : Hashtable<String, MessageRequest>\n    + MessagingDatabase()\n    + add(r : MessageRequest) : MessageRequest\n    + get(requestId : String) : MessageRequest\n  }\n  class MessagingService {\n    - LOGGER : Logger {static}\n    + MessagingService(db : MessagingDatabase, exc : Exception[])\n    + receiveRequest(parameters : Object[]) : String\n    ~ sendMessage(m : MessageToSend) : String\n    # updateDb(parameters : Object[]) : String\n  }\n  ~class MessageRequest {\n    ~ msg : MessageToSend\n    ~ reqId : String\n    ~ MessageRequest(this$0 : String, reqId : MessageToSend)\n  }\n  ~enum MessageToSend {\n    + PaymentFail {static}\n    + PaymentSuccessful {static}\n    + PaymentTrying {static}\n    + valueOf(name : String) : MessageToSend {static}\n    + values() : MessageToSend[] {static}\n  }\n}\npackage com.iluwatar.commander {\n  class AppEmployeeDbFailCases {\n    - employeeTime : long\n    - messageTime : long\n    - numOfRetries : int\n    - paymentTime : long\n    - queueTaskTime : long\n    - queueTime : long\n    - retryDuration : long\n    + AppEmployeeDbFailCases()\n    ~ employeeDatabaseUnavailableCase()\n    ~ employeeDbSuccessCase()\n    + main(args : String[]) {static}\n  }\n  class AppMessagingFailCases {\n    - employeeTime : long\n    - messageTime : long\n    - numOfRetries : int\n    - paymentTime : long\n    - queueTaskTime : long\n    - queueTime : long\n    - retryDuration : long\n    + AppMessagingFailCases()\n    + main(args : String[]) {static}\n    ~ messagingDatabaseUnavailableCasePaymentError()\n    ~ messagingDatabaseUnavailableCasePaymentFailure()\n    ~ messagingDatabaseUnavailableCasePaymentSuccess()\n    ~ messagingSuccessCase()\n  }\n  class AppPaymentFailCases {\n    - employeeTime : long\n    - messageTime : long\n    - numOfRetries : int\n    - paymentTime : long\n    - queueTaskTime : long\n    - queueTime : long\n    - retryDuration : long\n    + AppPaymentFailCases()\n    + main(args : String[]) {static}\n    ~ paymentDatabaseUnavailableCase()\n    ~ paymentNotPossibleCase()\n    ~ paymentSuccessCase()\n  }\n  class AppQueueFailCases {\n    - employeeTime : long\n    - messageTime : long\n    - numOfRetries : int\n    - paymentTime : long\n    - queueTaskTime : long\n    - queueTime : long\n    - retryDuration : long\n    + AppQueueFailCases()\n    + main(args : String[]) {static}\n    ~ queueEmployeeDbTaskDatabaseUnavailableCase()\n    ~ queueMessageTaskDatabaseUnavailableCase()\n    ~ queuePaymentTaskDatabaseUnavailableCase()\n    ~ queueSuccessCase()\n  }\n  class AppShippingFailCases {\n    - employeeTime : long\n    - messageTime : long\n    - numOfRetries : int\n    - paymentTime : long\n    - queueTaskTime : long\n    - queueTime : long\n    - retryDuration : long\n    + AppShippingFailCases()\n    ~ itemUnavailableCase()\n    + main(args : String[]) {static}\n    ~ shippingDatabaseUnavailableCase()\n    ~ shippingNotPossibleCase()\n    ~ shippingSuccessCase()\n  }\n  class Commander {\n    - LOG : Logger {static}\n    - employeeDb : EmployeeHandle\n    - employeeTime : long\n    - finalSiteMsgShown : boolean\n    - messageTime : long\n    - messagingService : MessagingService\n    - numOfRetries : int\n    - paymentService : PaymentService\n    - paymentTime : long\n    - queue : QueueDatabase\n    - queueItems : int\n    - queueTaskTime : long\n    - queueTime : long\n    - retryDuration : long\n    - shippingService : ShippingService\n    ~ Commander(empDb : EmployeeHandle, paymentService : PaymentService, shippingService : ShippingService, messagingService : MessagingService, qdb : QueueDatabase, numOfRetries : int, retryDuration : long, queueTime : long, queueTaskTime : long, paymentTime : long, messageTime : long, employeeTime : long)\n    - doTasksInQueue()\n    - employeeHandleIssue(order : Order)\n    ~ placeOrder(order : Order)\n    - sendPaymentFailureMessage(order : Order)\n    - sendPaymentPossibleErrorMsg(order : Order)\n    - sendPaymentRequest(order : Order)\n    - sendShippingRequest(order : Order)\n    - sendSuccessMessage(order : Order)\n    - tryDequeue()\n    - tryDoingTasksInQueue()\n    - updateQueue(qt : QueueTask)\n  }\n  abstract class Database<T> {\n    + Database<T>()\n    + add(T) : T {abstract}\n    + get(String) : T {abstract}\n  }\n  class Order {\n    - ALL_CHARS : String {static}\n    - RANDOM : Random {static}\n    - USED_IDS : Hashtable<String, Boolean> {static}\n    ~ addedToEmployeeHandle : boolean\n    ~ createdTime : long\n    + id : String\n    ~ item : String\n    ~ messageSent : MessageSent\n    ~ paid : PaymentStatus\n    ~ price : float\n    ~ user : User\n    ~ Order(user : User, item : String, price : float)\n    - createUniqueId() : String\n  }\n  ~enum MessageSent {\n    + NoneSent {static}\n    + PaymentFail {static}\n    + PaymentSuccessful {static}\n    + PaymentTrying {static}\n    + valueOf(name : String) : MessageSent {static}\n    + values() : MessageSent[] {static}\n  }\n  ~enum PaymentStatus {\n    + Done {static}\n    + NotDone {static}\n    + Trying {static}\n    + valueOf(name : String) : PaymentStatus {static}\n    + values() : PaymentStatus[] {static}\n  }\n  class Retry<T> {\n    - RANDOM : Random {static}\n    - attempts : AtomicInteger\n    - errors : List<Exception>\n    - handleError : Retry.HandleErrorIssue<T>\n    - maxAttempts : int\n    - maxDelay : long\n    - op : Operation\n    - test : Predicate<Exception>\n    ~ Retry<T>(op : Operation, handleError : Retry.HandleErrorIssue<T>, maxAttempts : int, maxDelay : long, ignoreTests : Predicate<Exception>[])\n    + perform(list : List<Exception>, obj : T)\n  }\n  interface HandleErrorIssue<T> {\n    + handleIssue(T, Exception) {abstract}\n  }\n  interface Operation {\n    + operation(List<Exception>) {abstract}\n  }\n  abstract class Service {\n    - ALL_CHARS : String {static}\n    - RANDOM : Random {static}\n    - USED_IDS : Hashtable<String, Boolean> {static}\n    # database : Database<T>\n    + exceptionsList : ArrayList<Exception>\n    # Service(db : Database<T>, exc : Exception[])\n    # generateId() : String\n    + receiveRequest(Object[]) : String {abstract}\n    # updateDb(Object[]) : String {abstract}\n  }\n  class User {\n    ~ address : String\n    ~ name : String\n    ~ User(name : String, address : String)\n  }\n}\npackage com.iluwatar.commander.shippingservice {\n  class ShippingDatabase {\n    - data : Hashtable<String, ShippingRequest>\n    + ShippingDatabase()\n    + add(r : ShippingRequest) : ShippingRequest\n    + get(trasnactionId : String) : ShippingRequest\n  }\n  class ShippingService {\n    + ShippingService(db : ShippingDatabase, exc : Exception[])\n    + receiveRequest(parameters : Object[]) : String\n    # updateDb(parameters : Object[]) : String\n  }\n  ~class ShippingRequest {\n    ~ address : String\n    ~ item : String\n    ~ transactionId : String\n    ~ ShippingRequest(transactionId : String, item : String, address : String)\n  }\n}\npackage com.iluwatar.commander.paymentservice {\n  class PaymentDatabase {\n    - data : Hashtable<String, PaymentRequest>\n    + PaymentDatabase()\n    + add(r : PaymentRequest) : PaymentRequest\n    + get(requestId : String) : PaymentRequest\n  }\n  class PaymentService {\n    + PaymentService(db : PaymentDatabase, exc : Exception[])\n    + receiveRequest(parameters : Object[]) : String\n    # updateDb(parameters : Object[]) : String\n  }\n  ~class PaymentRequest {\n    ~ paid : boolean\n    ~ payment : float\n    ~ transactionId : String\n    ~ PaymentRequest(this$0 : String, transactionId : float)\n  }\n}\npackage com.iluwatar.commander.employeehandle {\n  class EmployeeDatabase {\n    - data : Hashtable<String, Order>\n    + EmployeeDatabase()\n    + add(o : Order) : Order\n    + get(orderId : String) : Order\n  }\n  class EmployeeHandle {\n    + EmployeeHandle(db : EmployeeDatabase, exc : Exception[])\n    + receiveRequest(parameters : Object[]) : String\n    # updateDb(parameters : Object[]) : String\n  }\n}\nOrder -->  \"-messageSent\" MessageSent\nMessageSent ..+ Order\nMessageToSend ..+ MessagingService\nRetry -->  \"-op\" Operation\nOperation ..+ Retry\nService -->  \"-database\" Database\nNode -->  \"-next\" Node\nPaymentRequest --+ PaymentService\nCommander -->  \"-messagingService\" MessagingService\nShippingRequest ..+ ShippingService\nCommander -->  \"-shippingService\" ShippingService\nCommander -->  \"-paymentService\" PaymentService\nMessageRequest --+ MessagingService\nCommander -->  \"-employeeDb\" EmployeeHandle\nHandleErrorIssue ..+ Retry\nRetry -->  \"-handleError\" HandleErrorIssue\nQueueTask -->  \"-taskType\" TaskType\nTaskType ..+ QueueTask\nOrder -->  \"-user\" User\nMessageRequest -->  \"-msg\" MessageToSend\nQueueTask -->  \"-order\" Order\nCommander -->  \"-queue\" QueueDatabase\nQueueDatabase -->  \"-data\" Queue\nQueue -->  \"-front\" Node\nNode ..+ Queue\nOrder -->  \"-paid\" PaymentStatus\nPaymentStatus ..+ Order\nEmployeeDatabase --|> Database \nEmployeeHandle --|> Service \nMessagingDatabase --|> Database \nMessagingService --|> Service \nPaymentDatabase --|> Database \nPaymentService --|> Service \nQueueDatabase --|> Database \nShippingDatabase --|> Database \nShippingService --|> Service \n@enduml"
  },
  {
    "path": "commander/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>commander</artifactId>\n  <properties>\n    <slf4j.version>2.0.17</slf4j.version>\n    <logback.version>1.5.6</logback.version>\n  </properties>\n  <dependencies>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n      <dependency>\n          <groupId>org.slf4j</groupId>\n          <artifactId>slf4j-api</artifactId>\n          <version>${slf4j.version}</version>\n      </dependency>\n  </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n                <version>3.14.0</version>\n                <executions>\n                    <execution>\n                        <id>allCases</id>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.commander.AppAllCases</mainClass>\n                                </manifest>\n                            </archive>\n                            <finalName>${project.artifactId}-AllCases</finalName>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/AppAllCases.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander;\n\nimport com.iluwatar.commander.employeehandle.EmployeeDatabase;\nimport com.iluwatar.commander.employeehandle.EmployeeHandle;\nimport com.iluwatar.commander.exceptions.DatabaseUnavailableException;\nimport com.iluwatar.commander.exceptions.ItemUnavailableException;\nimport com.iluwatar.commander.exceptions.PaymentDetailsErrorException;\nimport com.iluwatar.commander.messagingservice.MessagingDatabase;\nimport com.iluwatar.commander.messagingservice.MessagingService;\nimport com.iluwatar.commander.paymentservice.PaymentDatabase;\nimport com.iluwatar.commander.paymentservice.PaymentService;\nimport com.iluwatar.commander.queue.QueueDatabase;\nimport com.iluwatar.commander.shippingservice.ShippingDatabase;\nimport com.iluwatar.commander.shippingservice.ShippingService;\n\n/**\n * The {@code AppAllCases} class tests various scenarios for the microservices involved in the order\n * placement process. This class consolidates previously separated cases into a single class to\n * manage different success and failure scenarios for each service.\n *\n * <p>The application consists of abstract classes {@link Database} and {@link Service} which are\n * extended by all the databases and services. Each service has a corresponding database to be\n * updated and receives requests from an external user through the {@link Commander} class. There\n * are 5 microservices:\n *\n * <ul>\n *   <li>{@link ShippingService}\n *   <li>{@link PaymentService}\n *   <li>{@link MessagingService}\n *   <li>{@link EmployeeHandle}\n *   <li>{@link QueueDatabase}\n * </ul>\n *\n * <p>Retries are managed using the {@link Retry} class, ensuring idempotence by performing checks\n * before making requests to services and updating the {@link Order} class fields upon request\n * success or definitive failure.\n *\n * <p>This class tests the following scenarios:\n *\n * <ul>\n *   <li>Employee database availability and unavailability\n *   <li>Payment service success and failures\n *   <li>Messaging service database availability and unavailability\n *   <li>Queue database availability and unavailability\n *   <li>Shipping service success and failures\n * </ul>\n *\n * <p>Each scenario is encapsulated in a corresponding method that sets up the service conditions\n * and tests the order placement process.\n *\n * <p>The main method executes all success and failure cases to verify the application's behavior\n * under different conditions.\n *\n * <p><strong>Usage:</strong>\n *\n * <pre>{@code\n * public static void main(String[] args) {\n *     AppAllCases app = new AppAllCases();\n *     app.testAllScenarios();\n * }\n * }</pre>\n */\npublic class AppAllCases {\n  private static final RetryParams retryParams = RetryParams.DEFAULT;\n  private static final TimeLimits timeLimits = TimeLimits.DEFAULT;\n\n  // Employee Database Fail Case\n  void employeeDatabaseUnavailableCase() {\n    var ps =\n        new PaymentService(\n            new PaymentDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var ss = new ShippingService(new ShippingDatabase());\n    var ms = new MessagingService(new MessagingDatabase());\n    var eh =\n        new EmployeeHandle(\n            new EmployeeDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var qdb =\n        new QueueDatabase(\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  // Employee Database Success Case\n  void employeeDbSuccessCase() {\n    var ps = new PaymentService(new PaymentDatabase());\n    var ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException());\n    var ms = new MessagingService(new MessagingDatabase());\n    var eh =\n        new EmployeeHandle(\n            new EmployeeDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var qdb = new QueueDatabase();\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  // Messaging Database Fail Cases\n  void messagingDatabaseUnavailableCasePaymentSuccess() {\n    var ps = new PaymentService(new PaymentDatabase());\n    var ss = new ShippingService(new ShippingDatabase());\n    var ms =\n        new MessagingService(\n            new MessagingDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb = new QueueDatabase();\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  void messagingDatabaseUnavailableCasePaymentError() {\n    var ps =\n        new PaymentService(\n            new PaymentDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var ss = new ShippingService(new ShippingDatabase());\n    var ms =\n        new MessagingService(\n            new MessagingDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb = new QueueDatabase();\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  void messagingDatabaseUnavailableCasePaymentFailure() {\n    var ps =\n        new PaymentService(\n            new PaymentDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var ss = new ShippingService(new ShippingDatabase());\n    var ms =\n        new MessagingService(\n            new MessagingDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb =\n        new QueueDatabase(\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  // Messaging Database Success Case\n  void messagingSuccessCase() {\n    var ps =\n        new PaymentService(\n            new PaymentDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var ss = new ShippingService(new ShippingDatabase());\n    var ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb = new QueueDatabase();\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  // Payment Database Fail Cases\n  void paymentNotPossibleCase() {\n    var ps =\n        new PaymentService(\n            new PaymentDatabase(),\n            new DatabaseUnavailableException(),\n            new PaymentDetailsErrorException());\n    var ss = new ShippingService(new ShippingDatabase());\n    var ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb = new QueueDatabase(new DatabaseUnavailableException());\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  void paymentDatabaseUnavailableCase() {\n    var ps =\n        new PaymentService(\n            new PaymentDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var ss = new ShippingService(new ShippingDatabase());\n    var ms = new MessagingService(new MessagingDatabase());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb = new QueueDatabase();\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  // Payment Database Success Case\n  void paymentSuccessCase() {\n    var ps =\n        new PaymentService(\n            new PaymentDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var ss = new ShippingService(new ShippingDatabase());\n    var ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb = new QueueDatabase(new DatabaseUnavailableException());\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  // Queue Database Fail Cases\n  void queuePaymentTaskDatabaseUnavailableCase() {\n    var ps =\n        new PaymentService(\n            new PaymentDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var ss = new ShippingService(new ShippingDatabase());\n    var ms = new MessagingService(new MessagingDatabase());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb =\n        new QueueDatabase(\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  void queueMessageTaskDatabaseUnavailableCase() {\n    var ps = new PaymentService(new PaymentDatabase());\n    var ss = new ShippingService(new ShippingDatabase());\n    var ms =\n        new MessagingService(\n            new MessagingDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb =\n        new QueueDatabase(\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  void queueEmployeeDbTaskDatabaseUnavailableCase() {\n    var ps = new PaymentService(new PaymentDatabase());\n    var ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException());\n    var ms = new MessagingService(new MessagingDatabase());\n    var eh =\n        new EmployeeHandle(\n            new EmployeeDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var qdb =\n        new QueueDatabase(\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  // Queue Database Success Cases\n  void queueSuccessCase() {\n    var ps = new PaymentService(new PaymentDatabase());\n    var ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException());\n    var ms = new MessagingService(new MessagingDatabase());\n    var eh =\n        new EmployeeHandle(\n            new EmployeeDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var qdb = new QueueDatabase();\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  // Shipping Database Fail Cases\n  void itemUnavailableCase() {\n    var ps = new PaymentService(new PaymentDatabase());\n    var ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException());\n    var ms = new MessagingService(new MessagingDatabase());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb = new QueueDatabase();\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  void shippingDatabaseUnavailableCase() {\n    var ps = new PaymentService(new PaymentDatabase());\n    var ss =\n        new ShippingService(\n            new ShippingDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var ms = new MessagingService(new MessagingDatabase());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb = new QueueDatabase();\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  void shippingItemNotPossibleCase() {\n    var ps = new PaymentService(new PaymentDatabase());\n    var ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException());\n    var ms = new MessagingService(new MessagingDatabase());\n    var eh = new EmployeeHandle(new EmployeeDatabase());\n    var qdb = new QueueDatabase();\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  // Shipping Database Success Cases\n  void shippingSuccessCase() {\n    var ps = new PaymentService(new PaymentDatabase());\n    var ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException());\n    var ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());\n    var eh =\n        new EmployeeHandle(\n            new EmployeeDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var qdb = new QueueDatabase();\n    var c = new Commander(eh, ps, ss, ms, qdb, retryParams, timeLimits);\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    c.placeOrder(order);\n  }\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line arguments\n   */\n  public static void main(String[] args) {\n    AppAllCases app = new AppAllCases();\n\n    // Employee Database cases\n    app.employeeDatabaseUnavailableCase();\n    app.employeeDbSuccessCase();\n\n    // Messaging Database cases\n    app.messagingDatabaseUnavailableCasePaymentSuccess();\n    app.messagingDatabaseUnavailableCasePaymentError();\n    app.messagingDatabaseUnavailableCasePaymentFailure();\n    app.messagingSuccessCase();\n\n    // Payment Database cases\n    app.paymentNotPossibleCase();\n    app.paymentDatabaseUnavailableCase();\n    app.paymentSuccessCase();\n\n    // Queue Database cases\n    app.queuePaymentTaskDatabaseUnavailableCase();\n    app.queueMessageTaskDatabaseUnavailableCase();\n    app.queueEmployeeDbTaskDatabaseUnavailableCase();\n    app.queueSuccessCase();\n\n    // Shipping Database cases\n    app.itemUnavailableCase();\n    app.shippingDatabaseUnavailableCase();\n    app.shippingItemNotPossibleCase();\n    app.shippingSuccessCase();\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/Commander.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander;\n\nimport com.iluwatar.commander.Order.MessageSent;\nimport com.iluwatar.commander.Order.PaymentStatus;\nimport com.iluwatar.commander.employeehandle.EmployeeHandle;\nimport com.iluwatar.commander.exceptions.DatabaseUnavailableException;\nimport com.iluwatar.commander.exceptions.IsEmptyException;\nimport com.iluwatar.commander.exceptions.ItemUnavailableException;\nimport com.iluwatar.commander.exceptions.PaymentDetailsErrorException;\nimport com.iluwatar.commander.exceptions.ShippingNotPossibleException;\nimport com.iluwatar.commander.messagingservice.MessagingService;\nimport com.iluwatar.commander.paymentservice.PaymentService;\nimport com.iluwatar.commander.queue.QueueDatabase;\nimport com.iluwatar.commander.queue.QueueTask;\nimport com.iluwatar.commander.queue.QueueTask.TaskType;\nimport com.iluwatar.commander.shippingservice.ShippingService;\nimport java.util.List;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Commander pattern is used to handle all issues that can come up while making a distributed\n * transaction. The idea is to have a commander, which coordinates the execution of all instructions\n * and ensures proper completion using retries and taking care of idempotence. By queueing\n * instructions while they haven't been done, we can ensure a state of 'eventual consistency'.\n *\n * <p>In our example, we have an e-commerce application. When the user places an order, the shipping\n * service is intimated first. If the service does not respond for some reason, the order is not\n * placed. If response is received, the commander then calls for the payment service to be\n * intimated. If this fails, the shipping still takes place (order converted to COD) and the item is\n * queued. If the queue is also found to be unavailable, the payment is noted to be not done and\n * this is added to an employee database. Three types of messages are sent to the user - one, if\n * payment succeeds; two, if payment fails definitively; and three, if payment fails in the first\n * attempt. If the message is not sent, this is also queued and is added to employee db. We also\n * have a time limit for each instruction to be completed, after which, the instruction is not\n * executed, thereby ensuring that resources are not held for too long. In the rare occasion in\n * which everything fails, an individual would have to step in to figure out how to solve the issue.\n *\n * <p>We have abstract classes {@link Database} and {@link Service} which are extended by all the\n * databases and services. Each service has a database to be updated, and receives request from an\n * outside user (the {@link Commander} class here). There are 5 microservices - {@link\n * ShippingService}, {@link PaymentService}, {@link MessagingService}, {@link EmployeeHandle} and a\n * {@link QueueDatabase}. We use retries to execute any instruction using {@link Retry} class, and\n * idempotence is ensured by going through some checks before making requests to services and making\n * change in {@link Order} class fields if request succeeds or definitively fails. There is a single\n * class {@link AppAllCases} that looks at the different scenarios that may be encountered during\n * the placing of an order, including both success and failure cases for each service.\n */\npublic class Commander {\n\n  private final QueueDatabase queue;\n  private final EmployeeHandle employeeDb;\n  private final PaymentService paymentService;\n  private final ShippingService shippingService;\n  private final MessagingService messagingService;\n  private int queueItems =\n      0; // keeping track here only so don't need access to queue db to get this\n  private final int numOfRetries;\n  private final long retryDuration;\n  private final long queueTime;\n  private final long queueTaskTime;\n  private final long paymentTime;\n  private final long messageTime;\n  private final long employeeTime;\n  private boolean finalSiteMsgShown;\n\n  private static final Logger LOG = LoggerFactory.getLogger(Commander.class);\n  // we could also have another db where it stores all orders\n\n  private static final String ORDER_ID = \"Order {}\";\n  private static final String REQUEST_ID = \" request Id: {}\";\n  private static final String ERROR_CONNECTING_MSG_SVC =\n      \": Error in connecting to messaging service \";\n  private static final String TRY_CONNECTING_MSG_SVC = \": Trying to connect to messaging service..\";\n\n  private static final String DEFAULT_EXCEPTION_MESSAGE = \"An exception occurred\";\n\n  Commander(\n      EmployeeHandle empDb,\n      PaymentService paymentService,\n      ShippingService shippingService,\n      MessagingService messagingService,\n      QueueDatabase qdb,\n      RetryParams retryParams,\n      TimeLimits timeLimits) {\n    this.paymentService = paymentService;\n    this.shippingService = shippingService;\n    this.messagingService = messagingService;\n    this.employeeDb = empDb;\n    this.queue = qdb;\n    this.numOfRetries = retryParams.numOfRetries();\n    this.retryDuration = retryParams.retryDuration();\n    this.queueTime = timeLimits.queueTime();\n    this.queueTaskTime = timeLimits.queueTaskTime();\n    this.paymentTime = timeLimits.paymentTime();\n    this.messageTime = timeLimits.messageTime();\n    this.employeeTime = timeLimits.employeeTime();\n    this.finalSiteMsgShown = false;\n  }\n\n  void placeOrder(Order order) {\n    sendShippingRequest(order);\n  }\n\n  private void sendShippingRequest(Order order) {\n    var list = shippingService.exceptionsList;\n    Retry.Operation op =\n        l -> {\n          if (!l.isEmpty()) {\n            if (DatabaseUnavailableException.class.isAssignableFrom(l.get(0).getClass())) {\n              LOG.debug(\n                  ORDER_ID + \": Error in connecting to shipping service, \" + \"trying again..\",\n                  order.id);\n            } else {\n              LOG.debug(ORDER_ID + \": Error in creating shipping request..\", order.id);\n            }\n            throw l.remove(0);\n          }\n          String transactionId = shippingService.receiveRequest(order.item, order.user.address);\n          // could save this transaction id in a db too\n          LOG.info(\n              ORDER_ID + \": Shipping placed successfully, transaction id: {}\",\n              order.id,\n              transactionId);\n          LOG.info(\n              \"Order has been placed and will be shipped to you. Please wait while we make your\"\n                  + \" payment... \");\n          sendPaymentRequest(order);\n        };\n    Retry.HandleErrorIssue<Order> handleError =\n        (o, err) -> {\n          if (ShippingNotPossibleException.class.isAssignableFrom(err.getClass())) {\n            LOG.info(\n                \"Shipping is currently not possible to your address. We are working on the problem\"\n                    + \" and will get back to you asap.\");\n            finalSiteMsgShown = true;\n            LOG.info(\n                ORDER_ID\n                    + \": Shipping not possible to address, trying to add problem \"\n                    + \"to employee db..\",\n                order.id);\n            employeeHandleIssue(o);\n          } else if (ItemUnavailableException.class.isAssignableFrom(err.getClass())) {\n            LOG.info(\n                \"This item is currently unavailable. We will inform you as soon as the item \"\n                    + \"becomes available again.\");\n            finalSiteMsgShown = true;\n            LOG.info(\n                ORDER_ID\n                    + \": Item {}\"\n                    + \" unavailable, trying to add \"\n                    + \"problem to employee handle..\",\n                order.id,\n                order.item);\n            employeeHandleIssue(o);\n          } else {\n            LOG.info(\"Sorry, there was a problem in creating your order. Please try later.\");\n            LOG.error(ORDER_ID + \": Shipping service unavailable, order not placed..\", order.id);\n            finalSiteMsgShown = true;\n          }\n        };\n    var r =\n        new Retry<>(\n            op,\n            handleError,\n            numOfRetries,\n            retryDuration,\n            e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));\n    r.perform(list, order);\n  }\n\n  private void sendPaymentRequest(Order order) {\n    if (System.currentTimeMillis() - order.createdTime >= this.paymentTime) {\n      if (order.paid.equals(PaymentStatus.TRYING)) {\n        order.paid = PaymentStatus.NOT_DONE;\n        sendPaymentFailureMessage(order);\n        LOG.error(ORDER_ID + \": Payment time for order over, failed and returning..\", order.id);\n      } // if succeeded or failed, would have been dequeued, no attempt to make payment\n      return;\n    }\n    var list = paymentService.exceptionsList;\n    var t =\n        new Thread(\n            () -> {\n              Retry.Operation op = getRetryOperation(order);\n\n              Retry.HandleErrorIssue<Order> handleError = getRetryHandleErrorIssue(order);\n\n              var r =\n                  new Retry<>(\n                      op,\n                      handleError,\n                      numOfRetries,\n                      retryDuration,\n                      e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));\n              try {\n                r.perform(list, order);\n              } catch (Exception e1) {\n                LOG.error(DEFAULT_EXCEPTION_MESSAGE, e1);\n              }\n            });\n\n    t.start();\n  }\n\n  private Retry.HandleErrorIssue<Order> getRetryHandleErrorIssue(Order order) {\n    return (o, err) -> {\n      if (PaymentDetailsErrorException.class.isAssignableFrom(err.getClass())) {\n        handlePaymentDetailsError(order.id, o);\n      } else {\n        if (o.messageSent.equals(MessageSent.NONE_SENT)) {\n          handlePaymentError(order.id, o);\n        }\n        if (o.paid.equals(PaymentStatus.TRYING)\n            && System.currentTimeMillis() - o.createdTime < paymentTime) {\n          var qt = new QueueTask(o, TaskType.PAYMENT, -1);\n          updateQueue(qt);\n        }\n      }\n    };\n  }\n\n  private void handlePaymentError(String orderId, Order o) {\n    if (!finalSiteMsgShown) {\n      LOG.info(\n          \"There was an error in payment. We are on it, and will get back to you \"\n              + \"asap. Don't worry, your order has been placed and will be shipped.\");\n      finalSiteMsgShown = true;\n    }\n    LOG.warn(ORDER_ID + \": Payment error, going to queue..\", orderId);\n    sendPaymentPossibleErrorMsg(o);\n  }\n\n  private void handlePaymentDetailsError(String orderId, Order o) {\n    if (!finalSiteMsgShown) {\n      LOG.info(\n          \"There was an error in payment. Your account/card details \"\n              + \"may have been incorrect. \"\n              + \"Meanwhile, your order has been converted to COD and will be shipped.\");\n      finalSiteMsgShown = true;\n    }\n    LOG.error(ORDER_ID + \": Payment details incorrect, failed..\", orderId);\n    o.paid = PaymentStatus.NOT_DONE;\n    sendPaymentFailureMessage(o);\n  }\n\n  private Retry.Operation getRetryOperation(Order order) {\n    return l -> {\n      if (!l.isEmpty()) {\n        if (DatabaseUnavailableException.class.isAssignableFrom(l.get(0).getClass())) {\n          LOG.debug(\n              ORDER_ID + \": Error in connecting to payment service,\" + \" trying again..\", order.id);\n        } else {\n          LOG.debug(ORDER_ID + \": Error in creating payment request..\", order.id);\n        }\n        throw l.remove(0);\n      }\n      if (order.paid.equals(PaymentStatus.TRYING)) {\n        var transactionId = paymentService.receiveRequest(order.price);\n        order.paid = PaymentStatus.DONE;\n        LOG.info(ORDER_ID + \": Payment successful, transaction Id: {}\", order.id, transactionId);\n        if (!finalSiteMsgShown) {\n          LOG.info(\"Payment made successfully, thank you for shopping with us!!\");\n          finalSiteMsgShown = true;\n        }\n        sendSuccessMessage(order);\n      }\n    };\n  }\n\n  private void updateQueue(QueueTask qt) {\n    if (System.currentTimeMillis() - qt.order.createdTime >= this.queueTime) {\n      // since payment time is lesser than queuetime it would have already failed..\n      // additional check not needed\n      LOG.trace(ORDER_ID + \": Queue time for order over, failed..\", qt.order.id);\n      return;\n    } else if (qt.taskType.equals(TaskType.PAYMENT) && !qt.order.paid.equals(PaymentStatus.TRYING)\n        || qt.taskType.equals(TaskType.MESSAGING)\n            && (qt.messageType == 1 && !qt.order.messageSent.equals(MessageSent.NONE_SENT)\n                || qt.order.messageSent.equals(MessageSent.PAYMENT_FAIL)\n                || qt.order.messageSent.equals(MessageSent.PAYMENT_SUCCESSFUL))\n        || qt.taskType.equals(TaskType.EMPLOYEE_DB) && qt.order.addedToEmployeeHandle) {\n      LOG.trace(ORDER_ID + \": Not queueing task since task already done..\", qt.order.id);\n      return;\n    }\n    var list = queue.exceptionsList;\n    Thread t =\n        new Thread(\n            () -> {\n              Retry.Operation op =\n                  list1 -> {\n                    if (!list1.isEmpty()) {\n                      LOG.warn(\n                          ORDER_ID + \": Error in connecting to queue db, trying again..\",\n                          qt.order.id);\n                      throw list1.remove(0);\n                    }\n                    queue.add(qt);\n                    queueItems++;\n                    LOG.info(ORDER_ID + \": {}\" + \" task enqueued..\", qt.order.id, qt.getType());\n                    tryDoingTasksInQueue();\n                  };\n              Retry.HandleErrorIssue<QueueTask> handleError =\n                  (qt1, err) -> {\n                    if (qt1.taskType.equals(TaskType.PAYMENT)) {\n                      qt1.order.paid = PaymentStatus.NOT_DONE;\n                      sendPaymentFailureMessage(qt1.order);\n                      LOG.error(\n                          ORDER_ID + \": Unable to enqueue payment task,\" + \" payment failed..\",\n                          qt1.order.id);\n                    }\n                    LOG.error(\n                        ORDER_ID\n                            + \": Unable to enqueue task of type {}\"\n                            + \", trying to add to employee handle..\",\n                        qt1.order.id,\n                        qt1.getType());\n                    employeeHandleIssue(qt1.order);\n                  };\n              var r =\n                  new Retry<>(\n                      op,\n                      handleError,\n                      numOfRetries,\n                      retryDuration,\n                      e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));\n              try {\n                r.perform(list, qt);\n              } catch (Exception e1) {\n                LOG.error(DEFAULT_EXCEPTION_MESSAGE, e1);\n              }\n            });\n    t.start();\n  }\n\n  private void tryDoingTasksInQueue() { // commander controls operations done to queue\n    var list = queue.exceptionsList;\n    var t2 =\n        new Thread(\n            () -> {\n              Retry.Operation op =\n                  list1 -> {\n                    if (!list1.isEmpty()) {\n                      LOG.warn(\"Error in accessing queue db to do tasks, trying again..\");\n                      throw list1.remove(0);\n                    }\n                    doTasksInQueue();\n                  };\n              Retry.HandleErrorIssue<QueueTask> handleError = (o, err) -> {};\n              var r =\n                  new Retry<>(\n                      op,\n                      handleError,\n                      numOfRetries,\n                      retryDuration,\n                      e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));\n              try {\n                r.perform(list, null);\n              } catch (Exception e1) {\n                LOG.error(DEFAULT_EXCEPTION_MESSAGE, e1);\n              }\n            });\n    t2.start();\n  }\n\n  private void tryDequeue() {\n    var list = queue.exceptionsList;\n    var t3 =\n        new Thread(\n            () -> {\n              Retry.Operation op =\n                  list1 -> {\n                    if (!list1.isEmpty()) {\n                      LOG.warn(\"Error in accessing queue db to dequeue task, trying again..\");\n                      throw list1.remove(0);\n                    }\n                    queue.dequeue();\n                    queueItems--;\n                  };\n              Retry.HandleErrorIssue<QueueTask> handleError = (o, err) -> {};\n              var r =\n                  new Retry<>(\n                      op,\n                      handleError,\n                      numOfRetries,\n                      retryDuration,\n                      e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));\n              try {\n                r.perform(list, null);\n              } catch (Exception e1) {\n                LOG.error(DEFAULT_EXCEPTION_MESSAGE, e1);\n              }\n            });\n    t3.start();\n  }\n\n  private void sendSuccessMessage(Order order) {\n    if (System.currentTimeMillis() - order.createdTime >= this.messageTime) {\n      LOG.trace(ORDER_ID + \": Message time for order over, returning..\", order.id);\n      return;\n    }\n    var list = messagingService.exceptionsList;\n    Thread t =\n        new Thread(\n            () -> {\n              Retry.Operation op = handleSuccessMessageRetryOperation(order);\n              Retry.HandleErrorIssue<Order> handleError =\n                  (o, err) -> handleSuccessMessageErrorIssue(order, o);\n              var r =\n                  new Retry<>(\n                      op,\n                      handleError,\n                      numOfRetries,\n                      retryDuration,\n                      e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));\n              try {\n                r.perform(list, order);\n              } catch (Exception e1) {\n                LOG.error(DEFAULT_EXCEPTION_MESSAGE, e1);\n              }\n            });\n    t.start();\n  }\n\n  private void handleSuccessMessageErrorIssue(Order order, Order o) {\n    if ((o.messageSent.equals(MessageSent.NONE_SENT)\n            || o.messageSent.equals(MessageSent.PAYMENT_TRYING))\n        && System.currentTimeMillis() - o.createdTime < messageTime) {\n      var qt = new QueueTask(order, TaskType.MESSAGING, 2);\n      updateQueue(qt);\n      LOG.info(\n          ORDER_ID\n              + \": Error in sending Payment Success message, trying to\"\n              + \" queue task and add to employee handle..\",\n          order.id);\n      employeeHandleIssue(order);\n    }\n  }\n\n  private Retry.Operation handleSuccessMessageRetryOperation(Order order) {\n    return l -> {\n      if (!l.isEmpty()) {\n        if (DatabaseUnavailableException.class.isAssignableFrom(l.get(0).getClass())) {\n          LOG.debug(\n              ORDER_ID + ERROR_CONNECTING_MSG_SVC + \"(Payment Success msg), trying again..\",\n              order.id);\n        } else {\n          LOG.debug(\n              ORDER_ID + \": Error in creating Payment Success\" + \" messaging request..\", order.id);\n        }\n        throw l.remove(0);\n      }\n      if (!order.messageSent.equals(MessageSent.PAYMENT_FAIL)\n          && !order.messageSent.equals(MessageSent.PAYMENT_SUCCESSFUL)) {\n        var requestId = messagingService.receiveRequest(2);\n        order.messageSent = MessageSent.PAYMENT_SUCCESSFUL;\n        LOG.info(ORDER_ID + \": Payment Success message sent,\" + REQUEST_ID, order.id, requestId);\n      }\n    };\n  }\n\n  private void sendPaymentFailureMessage(Order order) {\n    if (System.currentTimeMillis() - order.createdTime >= this.messageTime) {\n      LOG.trace(ORDER_ID + \": Message time for order over, returning..\", order.id);\n      return;\n    }\n    var list = messagingService.exceptionsList;\n    var t =\n        new Thread(\n            () -> {\n              Retry.Operation op = l -> handlePaymentFailureRetryOperation(order, l);\n              Retry.HandleErrorIssue<Order> handleError =\n                  (o, err) -> handlePaymentErrorIssue(order, o);\n              var r =\n                  new Retry<>(\n                      op,\n                      handleError,\n                      numOfRetries,\n                      retryDuration,\n                      e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));\n              try {\n                r.perform(list, order);\n              } catch (Exception e1) {\n                LOG.error(DEFAULT_EXCEPTION_MESSAGE, e1);\n              }\n            });\n    t.start();\n  }\n\n  private void handlePaymentErrorIssue(Order order, Order o) {\n    if ((o.messageSent.equals(MessageSent.NONE_SENT)\n            || o.messageSent.equals(MessageSent.PAYMENT_TRYING))\n        && System.currentTimeMillis() - o.createdTime < messageTime) {\n      var qt = new QueueTask(order, TaskType.MESSAGING, 0);\n      updateQueue(qt);\n      LOG.warn(\n          ORDER_ID\n              + \": Error in sending Payment Failure message, \"\n              + \"trying to queue task and add to employee handle..\",\n          order.id);\n      employeeHandleIssue(o);\n    }\n  }\n\n  private void handlePaymentFailureRetryOperation(Order order, List<Exception> l)\n      throws IndexOutOfBoundsException, DatabaseUnavailableException {\n    if (!l.isEmpty()) {\n      if (DatabaseUnavailableException.class.isAssignableFrom(l.get(0).getClass())) {\n        LOG.debug(\n            ORDER_ID + ERROR_CONNECTING_MSG_SVC + \"(Payment Failure msg), trying again..\",\n            order.id);\n      } else {\n        LOG.debug(\n            ORDER_ID + \": Error in creating Payment Failure\" + \" message request..\", order.id);\n      }\n      throw new IndexOutOfBoundsException();\n    }\n    if (!order.messageSent.equals(MessageSent.PAYMENT_FAIL)\n        && !order.messageSent.equals(MessageSent.PAYMENT_SUCCESSFUL)) {\n      var requestId = messagingService.receiveRequest(0);\n      order.messageSent = MessageSent.PAYMENT_FAIL;\n      LOG.info(\n          ORDER_ID + \": Payment Failure message sent successfully,\" + REQUEST_ID,\n          order.id,\n          requestId);\n    }\n  }\n\n  private void sendPaymentPossibleErrorMsg(Order order) {\n    if (System.currentTimeMillis() - order.createdTime >= this.messageTime) {\n      LOG.trace(\"Message time for order over, returning..\");\n      return;\n    }\n    var list = messagingService.exceptionsList;\n    var t =\n        new Thread(\n            () -> {\n              Retry.Operation op = l -> handlePaymentPossibleErrorMsgRetryOperation(order, l);\n              Retry.HandleErrorIssue<Order> handleError =\n                  (o, err) -> handlePaymentPossibleErrorMsgErrorIssue(order, o);\n              var r =\n                  new Retry<>(\n                      op,\n                      handleError,\n                      numOfRetries,\n                      retryDuration,\n                      e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));\n              try {\n                r.perform(list, order);\n              } catch (Exception e1) {\n                LOG.error(DEFAULT_EXCEPTION_MESSAGE, e1);\n              }\n            });\n    t.start();\n  }\n\n  private void handlePaymentPossibleErrorMsgErrorIssue(Order order, Order o) {\n    if (o.messageSent.equals(MessageSent.NONE_SENT)\n        && order.paid.equals(PaymentStatus.TRYING)\n        && System.currentTimeMillis() - o.createdTime < messageTime) {\n      var qt = new QueueTask(order, TaskType.MESSAGING, 1);\n      updateQueue(qt);\n      LOG.warn(\n          \"Order {}: Error in sending Payment Error message, trying to queue task and add to employee handle..\",\n          order.id);\n      employeeHandleIssue(o);\n    }\n  }\n\n  private void handlePaymentPossibleErrorMsgRetryOperation(Order order, List<Exception> l)\n      throws IndexOutOfBoundsException, DatabaseUnavailableException {\n    if (!l.isEmpty()) {\n      if (DatabaseUnavailableException.class.isAssignableFrom(l.get(0).getClass())) {\n        LOG.debug(\n            ORDER_ID + ERROR_CONNECTING_MSG_SVC + \"(Payment Error msg), trying again..\", order.id);\n      } else {\n        LOG.debug(\n            ORDER_ID + \": Error in creating Payment Error\" + \" messaging request..\", order.id);\n      }\n      throw new IndexOutOfBoundsException();\n    }\n    if (order.paid.equals(PaymentStatus.TRYING)\n        && order.messageSent.equals(MessageSent.NONE_SENT)) {\n      var requestId = messagingService.receiveRequest(1);\n      order.messageSent = MessageSent.PAYMENT_TRYING;\n      LOG.info(\n          ORDER_ID + \": Payment Error message sent successfully,\" + REQUEST_ID,\n          order.id,\n          requestId);\n    }\n  }\n\n  private void employeeHandleIssue(Order order) {\n    if (System.currentTimeMillis() - order.createdTime >= this.employeeTime) {\n      LOG.trace(ORDER_ID + \": Employee handle time for order over, returning..\", order.id);\n      return;\n    }\n    var list = employeeDb.exceptionsList;\n    var t =\n        new Thread(\n            () -> {\n              Retry.Operation op =\n                  l -> {\n                    if (!l.isEmpty()) {\n                      LOG.warn(\n                          ORDER_ID\n                              + \": Error in connecting to employee handle,\"\n                              + \" trying again..\",\n                          order.id);\n                      throw l.remove(0);\n                    }\n                    if (!order.addedToEmployeeHandle) {\n                      employeeDb.receiveRequest(order);\n                      order.addedToEmployeeHandle = true;\n                      LOG.info(ORDER_ID + \": Added order to employee database\", order.id);\n                    }\n                  };\n              Retry.HandleErrorIssue<Order> handleError =\n                  (o, err) -> {\n                    if (!o.addedToEmployeeHandle\n                        && System.currentTimeMillis() - order.createdTime < employeeTime) {\n                      var qt = new QueueTask(order, TaskType.EMPLOYEE_DB, -1);\n                      updateQueue(qt);\n                      LOG.warn(\n                          ORDER_ID\n                              + \": Error in adding to employee db,\"\n                              + \" trying to queue task..\",\n                          order.id);\n                    }\n                  };\n              var r =\n                  new Retry<>(\n                      op,\n                      handleError,\n                      numOfRetries,\n                      retryDuration,\n                      e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));\n              try {\n                r.perform(list, order);\n              } catch (Exception e1) {\n                LOG.error(DEFAULT_EXCEPTION_MESSAGE, e1);\n              }\n            });\n    t.start();\n  }\n\n  private void doTasksInQueue() throws IsEmptyException, InterruptedException {\n    if (queueItems != 0) {\n      var qt = queue.peek(); // this should probably be cloned here\n      // this is why we have retry for doTasksInQueue\n      LOG.trace(ORDER_ID + \": Started doing task of type {}\", qt.order.id, qt.getType());\n      if (qt.isFirstAttempt()) {\n        qt.setFirstAttemptTime(System.currentTimeMillis());\n      }\n      if (System.currentTimeMillis() - qt.getFirstAttemptTime() >= queueTaskTime) {\n        tryDequeue();\n        LOG.trace(\n            ORDER_ID\n                + \": This queue task of type {}\"\n                + \" does not need to be done anymore (timeout), dequeue..\",\n            qt.order.id,\n            qt.getType());\n      } else {\n        switch (qt.taskType) {\n          case PAYMENT -> doPaymentTask(qt);\n          case MESSAGING -> doMessagingTask(qt);\n          case EMPLOYEE_DB -> doEmployeeDbTask(qt);\n          default -> throw new IllegalArgumentException(\"Unknown task type\");\n        }\n      }\n    }\n    if (queueItems == 0) {\n      LOG.trace(\"Queue is empty, returning..\");\n    } else {\n      Thread.sleep(queueTaskTime / 3);\n      tryDoingTasksInQueue();\n    }\n  }\n\n  private void doEmployeeDbTask(QueueTask qt) {\n    if (qt.order.addedToEmployeeHandle) {\n      tryDequeue();\n      LOG.trace(ORDER_ID + \": This employee handle task already done,\" + \" dequeue..\", qt.order.id);\n    } else {\n      employeeHandleIssue(qt.order);\n      LOG.debug(ORDER_ID + \": Trying to connect to employee handle..\", qt.order.id);\n    }\n  }\n\n  private void doMessagingTask(QueueTask qt) {\n    if (qt.order.messageSent.equals(MessageSent.PAYMENT_FAIL)\n        || qt.order.messageSent.equals(MessageSent.PAYMENT_SUCCESSFUL)) {\n      tryDequeue();\n      LOG.trace(ORDER_ID + \": This messaging task already done, dequeue..\", qt.order.id);\n    } else if (qt.messageType == 1\n        && (!qt.order.messageSent.equals(MessageSent.NONE_SENT)\n            || !qt.order.paid.equals(PaymentStatus.TRYING))) {\n      tryDequeue();\n      LOG.trace(\n          ORDER_ID + \": This messaging task does not need to be done,\" + \" dequeue..\", qt.order.id);\n    } else if (qt.messageType == 0) {\n      sendPaymentFailureMessage(qt.order);\n      LOG.debug(ORDER_ID + TRY_CONNECTING_MSG_SVC, qt.order.id);\n    } else if (qt.messageType == 1) {\n      sendPaymentPossibleErrorMsg(qt.order);\n      LOG.debug(ORDER_ID + TRY_CONNECTING_MSG_SVC, qt.order.id);\n    } else if (qt.messageType == 2) {\n      sendSuccessMessage(qt.order);\n      LOG.debug(ORDER_ID + TRY_CONNECTING_MSG_SVC, qt.order.id);\n    }\n  }\n\n  private void doPaymentTask(QueueTask qt) {\n    if (!qt.order.paid.equals(PaymentStatus.TRYING)) {\n      tryDequeue();\n      LOG.trace(ORDER_ID + \": This payment task already done, dequeueing..\", qt.order.id);\n    } else {\n      sendPaymentRequest(qt.order);\n      LOG.debug(ORDER_ID + \": Trying to connect to payment service..\", qt.order.id);\n    }\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/Database.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander;\n\nimport com.iluwatar.commander.exceptions.DatabaseUnavailableException;\n\n/**\n * Database abstract class is extended by all databases in our example. The add and get methods are\n * used by the respective service to add to database or get from database.\n *\n * @param <T> T is the type of object being held by database.\n */\npublic abstract class Database<T> {\n  public abstract T add(T obj) throws DatabaseUnavailableException;\n\n  public abstract T get(String id) throws DatabaseUnavailableException;\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/Order.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander;\n\nimport java.security.SecureRandom;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/** Order class holds details of the order. */\npublic class Order { // can store all transactions ids also\n\n  enum PaymentStatus {\n    NOT_DONE,\n    TRYING,\n    DONE\n  }\n\n  enum MessageSent {\n    NONE_SENT,\n    PAYMENT_FAIL,\n    PAYMENT_TRYING,\n    PAYMENT_SUCCESSFUL\n  }\n\n  final User user;\n  final String item;\n  public final String id;\n  final float price;\n  final long createdTime;\n  private static final SecureRandom RANDOM = new SecureRandom();\n  private static final String ALL_CHARS = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\";\n  private static final Map<String, Boolean> USED_IDS = new HashMap<>();\n  PaymentStatus paid;\n  MessageSent messageSent; // to avoid sending error msg on page and text more than once\n  boolean addedToEmployeeHandle; // to avoid creating more to enqueue\n\n  Order(User user, String item, float price) {\n    this.createdTime = System.currentTimeMillis();\n    this.user = user;\n    this.item = item;\n    this.price = price;\n    String id = createUniqueId();\n    if (USED_IDS.get(id) != null) {\n      while (USED_IDS.get(id)) {\n        id = createUniqueId();\n      }\n    }\n    this.id = id;\n    USED_IDS.put(this.id, true);\n    this.paid = PaymentStatus.TRYING;\n    this.messageSent = MessageSent.NONE_SENT;\n    this.addedToEmployeeHandle = false;\n  }\n\n  private String createUniqueId() {\n    StringBuilder random = new StringBuilder();\n    while (random.length() < 12) { // length of the random string.\n      int index = (int) (RANDOM.nextFloat() * ALL_CHARS.length());\n      random.append(ALL_CHARS.charAt(index));\n    }\n    return random.toString();\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/Retry.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander;\n\nimport java.security.SecureRandom;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.function.Predicate;\n\n/**\n * Retry pattern.\n *\n * @param <T> is the type of object passed into HandleErrorIssue as a parameter.\n */\npublic class Retry<T> {\n\n  /** Operation Interface will define method to be implemented. */\n  public interface Operation {\n    void operation(List<Exception> list) throws Exception;\n  }\n\n  /**\n   * HandleErrorIssue defines how to handle errors.\n   *\n   * @param <T> is the type of object to be passed into the method as parameter.\n   */\n  public interface HandleErrorIssue<T> {\n    void handleIssue(T obj, Exception e);\n  }\n\n  private static final SecureRandom RANDOM = new SecureRandom();\n\n  private final Operation op;\n  private final HandleErrorIssue<T> handleError;\n  private final int maxAttempts;\n  private final long maxDelay;\n  private final AtomicInteger attempts;\n  private final Predicate<Exception> test;\n  private final List<Exception> errors;\n\n  Retry(\n      Operation op,\n      HandleErrorIssue<T> handleError,\n      int maxAttempts,\n      long maxDelay,\n      Predicate<Exception>... ignoreTests) {\n    this.op = op;\n    this.handleError = handleError;\n    this.maxAttempts = maxAttempts;\n    this.maxDelay = maxDelay;\n    this.attempts = new AtomicInteger();\n    this.test = Arrays.stream(ignoreTests).reduce(Predicate::or).orElse(e -> false);\n    this.errors = new ArrayList<>();\n  }\n\n  /**\n   * Performing the operation with retries.\n   *\n   * @param list is the exception list\n   * @param obj is the parameter to be passed into handleIsuue method\n   */\n  public void perform(List<Exception> list, T obj) {\n    do {\n      try {\n        op.operation(list);\n        return;\n      } catch (Exception e) {\n        this.errors.add(e);\n        if (this.attempts.incrementAndGet() >= this.maxAttempts || !this.test.test(e)) {\n          this.handleError.handleIssue(obj, e);\n          return; // return here... don't go further\n        }\n        try {\n          long testDelay =\n              (long) Math.pow(2, this.attempts.intValue()) * 1000 + RANDOM.nextInt(1000);\n          long delay = Math.min(testDelay, this.maxDelay);\n          Thread.sleep(delay);\n        } catch (InterruptedException f) {\n          // ignore\n        }\n      }\n    } while (true);\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/RetryParams.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander;\n\n/**\n * Record to hold the parameters related to retries.\n *\n * @param numOfRetries number of retries\n * @param retryDuration retry duration\n */\npublic record RetryParams(int numOfRetries, long retryDuration) {\n  public static final RetryParams DEFAULT = new RetryParams(3, 30000L);\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/Service.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander;\n\nimport com.iluwatar.commander.exceptions.DatabaseUnavailableException;\nimport java.security.SecureRandom;\nimport java.util.ArrayList;\nimport java.util.Hashtable;\nimport java.util.List;\n\n/**\n * Service class is an abstract class extended by all services in this example. They all have a\n * public receiveRequest method to receive requests, which could also contain details of the user\n * other than the implementation details (though we are not doing that here) and updateDb method\n * which adds to their respective databases. There is a method to generate transaction/request id\n * for the transactions/requests, which are then sent back. These could be stored by the {@link\n * Commander} class in a separate database for reference (though we are not doing that here).\n */\npublic abstract class Service {\n\n  protected final Database database;\n  public ArrayList<Exception> exceptionsList;\n  private static final SecureRandom RANDOM = new SecureRandom();\n  private static final String ALL_CHARS = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\";\n  private static final Hashtable<String, Boolean> USED_IDS = new Hashtable<>();\n\n  protected Service(Database db, Exception... exc) {\n    this.database = db;\n    this.exceptionsList = new ArrayList<>(List.of(exc));\n  }\n\n  public abstract String receiveRequest(Object... parameters) throws DatabaseUnavailableException;\n\n  protected abstract String updateDb(Object... parameters) throws DatabaseUnavailableException;\n\n  protected String generateId() {\n    StringBuilder random = new StringBuilder();\n    while (random.length() < 12) { // length of the random string.\n      int index = (int) (RANDOM.nextFloat() * ALL_CHARS.length());\n      random.append(ALL_CHARS.charAt(index));\n    }\n    String id = random.toString();\n    if (USED_IDS.get(id) != null) {\n      while (USED_IDS.get(id)) {\n        id = generateId();\n      }\n    }\n    return id;\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/TimeLimits.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander;\n\n/**\n * Record to hold parameters related to time limit for various tasks.\n *\n * @param queueTime time limit for queue\n * @param queueTaskTime time limit for queuing task\n * @param paymentTime time limit for payment error message\n * @param messageTime time limit for message time order\n * @param employeeTime time limit for employee handle time\n */\npublic record TimeLimits(\n    long queueTime, long queueTaskTime, long paymentTime, long messageTime, long employeeTime) {\n\n  public static final TimeLimits DEFAULT =\n      new TimeLimits(240000L, 60000L, 120000L, 150000L, 240000L);\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/User.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander;\n\nimport lombok.AllArgsConstructor;\n\n/** User class contains details of user who places order. */\n@AllArgsConstructor\npublic class User {\n  String name;\n  String address;\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/employeehandle/EmployeeDatabase.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.employeehandle;\n\nimport com.iluwatar.commander.Database;\nimport com.iluwatar.commander.Order;\nimport com.iluwatar.commander.exceptions.DatabaseUnavailableException;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/** The Employee Database is where orders which have encountered some issue(s) are added. */\npublic class EmployeeDatabase extends Database<Order> {\n  private final Map<String, Order> data = new HashMap<>();\n\n  @Override\n  public Order add(Order o) throws DatabaseUnavailableException {\n    return data.put(o.id, o);\n  }\n\n  @Override\n  public Order get(String orderId) throws DatabaseUnavailableException {\n    return data.get(orderId);\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/employeehandle/EmployeeHandle.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.employeehandle;\n\nimport com.iluwatar.commander.Order;\nimport com.iluwatar.commander.Service;\nimport com.iluwatar.commander.exceptions.DatabaseUnavailableException;\n\n/**\n * The EmployeeHandle class is the middle-man between {@link com.iluwatar.commander.Commander} and\n * {@link EmployeeDatabase}.\n */\npublic class EmployeeHandle extends Service {\n\n  public EmployeeHandle(EmployeeDatabase db, Exception... exc) {\n    super(db, exc);\n  }\n\n  public String receiveRequest(Object... parameters) throws DatabaseUnavailableException {\n    return updateDb(parameters[0]);\n  }\n\n  protected String updateDb(Object... parameters) throws DatabaseUnavailableException {\n    var o = (Order) parameters[0];\n    if (database.get(o.id) == null) {\n      database.add(o);\n      return o.id; // true rcvd - change addedToEmployeeHandle to true else don't do anything\n    }\n    return null;\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/exceptions/DatabaseUnavailableException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.exceptions;\n\n/**\n * DatabaseUnavailableException is thrown when database is unavailable and nothing can be added or\n * retrieved.\n */\npublic class DatabaseUnavailableException extends Exception {\n  private static final long serialVersionUID = 2459603L;\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/exceptions/IsEmptyException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.exceptions;\n\n/** IsEmptyException is thrown when it is attempted to dequeue from an empty queue. */\npublic class IsEmptyException extends Exception {\n  private static final long serialVersionUID = 123546L;\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/exceptions/ItemUnavailableException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.exceptions;\n\n/** ItemUnavailableException is thrown when item is not available for shipping. */\npublic class ItemUnavailableException extends Exception {\n  private static final long serialVersionUID = 575940L;\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/exceptions/PaymentDetailsErrorException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.exceptions;\n\n/**\n * PaymentDetailsErrorException is thrown when the details entered are incorrect or payment cannot\n * be made with the details given.\n */\npublic class PaymentDetailsErrorException extends Exception {\n  private static final long serialVersionUID = 867203L;\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/exceptions/ShippingNotPossibleException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.exceptions;\n\n/**\n * ShippingNotPossibleException is thrown when the address entered cannot be shipped to by service\n * currently for some reason.\n */\npublic class ShippingNotPossibleException extends Exception {\n  private static final long serialVersionUID = 342055L;\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/messagingservice/MessagingDatabase.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.messagingservice;\n\nimport com.iluwatar.commander.Database;\nimport com.iluwatar.commander.messagingservice.MessagingService.MessageRequest;\nimport java.util.Hashtable;\nimport java.util.Map;\n\n/** The MessagingDatabase is where the MessageRequest is added. */\npublic class MessagingDatabase extends Database<MessageRequest> {\n  private final Map<String, MessageRequest> data = new Hashtable<>();\n\n  @Override\n  public MessageRequest add(MessageRequest r) {\n    return data.put(r.reqId(), r);\n  }\n\n  @Override\n  public MessageRequest get(String requestId) {\n    return data.get(requestId);\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/messagingservice/MessagingService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.messagingservice;\n\nimport com.iluwatar.commander.Service;\nimport com.iluwatar.commander.exceptions.DatabaseUnavailableException;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The MessagingService is used to send messages to user regarding their order and payment status.\n * In case an error is encountered in payment and this service is found to be unavailable, the order\n * is added to the {@link com.iluwatar.commander.employeehandle.EmployeeDatabase}.\n */\n@Slf4j\npublic class MessagingService extends Service {\n\n  enum MessageToSend {\n    PAYMENT_FAIL,\n    PAYMENT_TRYING,\n    PAYMENT_SUCCESSFUL\n  }\n\n  record MessageRequest(String reqId, MessageToSend msg) {}\n\n  public MessagingService(MessagingDatabase db, Exception... exc) {\n    super(db, exc);\n  }\n\n  /** Public method which will receive request from {@link com.iluwatar.commander.Commander}. */\n  public String receiveRequest(Object... parameters) throws DatabaseUnavailableException {\n    var messageToSend = (int) parameters[0];\n    var id = generateId();\n    MessageToSend msg;\n    if (messageToSend == 0) {\n      msg = MessageToSend.PAYMENT_FAIL;\n    } else if (messageToSend == 1) {\n      msg = MessageToSend.PAYMENT_TRYING;\n    } else { // messageToSend == 2\n      msg = MessageToSend.PAYMENT_SUCCESSFUL;\n    }\n    var req = new MessageRequest(id, msg);\n    return updateDb(req);\n  }\n\n  protected String updateDb(Object... parameters) throws DatabaseUnavailableException {\n    var req = (MessageRequest) parameters[0];\n    if (this.database.get(req.reqId) == null) { // idempotence, in case db fails here\n      database.add(req); // if successful:\n      LOGGER.info(sendMessage(req.msg));\n      return req.reqId;\n    }\n    return null;\n  }\n\n  String sendMessage(MessageToSend m) {\n    if (m.equals(MessageToSend.PAYMENT_SUCCESSFUL)) {\n      return \"Msg: Your order has been placed and paid for successfully!\"\n          + \" Thank you for shopping with us!\";\n    } else if (m.equals(MessageToSend.PAYMENT_TRYING)) {\n      return \"Msg: There was an error in your payment process,\"\n          + \" we are working on it and will return back to you shortly.\"\n          + \" Meanwhile, your order has been placed and will be shipped.\";\n    } else {\n      return \"Msg: There was an error in your payment process.\"\n          + \" Your order is placed and has been converted to COD.\"\n          + \" Please reach us on CUSTOMER-CARE-NUBER in case of any queries.\"\n          + \" Thank you for shopping with us!\";\n    }\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/paymentservice/PaymentDatabase.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.paymentservice;\n\nimport com.iluwatar.commander.Database;\nimport com.iluwatar.commander.paymentservice.PaymentService.PaymentRequest;\nimport java.util.Hashtable;\nimport java.util.Map;\n\n/** PaymentDatabase is where the PaymentRequest is added, along with details. */\npublic class PaymentDatabase extends Database<PaymentRequest> {\n\n  // 0-fail, 1-error, 2-success\n  private final Map<String, PaymentRequest> data = new Hashtable<>();\n\n  @Override\n  public PaymentRequest add(PaymentRequest r) {\n    return data.put(r.transactionId, r);\n  }\n\n  @Override\n  public PaymentRequest get(String requestId) {\n    return data.get(requestId);\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/paymentservice/PaymentService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.paymentservice;\n\nimport com.iluwatar.commander.Service;\nimport com.iluwatar.commander.exceptions.DatabaseUnavailableException;\nimport lombok.RequiredArgsConstructor;\n\n/**\n * The PaymentService class receives request from the {@link com.iluwatar.commander.Commander} and\n * adds to the {@link PaymentDatabase}.\n */\npublic class PaymentService extends Service {\n\n  @RequiredArgsConstructor\n  static class PaymentRequest {\n    final String transactionId;\n    final float payment;\n    boolean paid;\n  }\n\n  public PaymentService(PaymentDatabase db, Exception... exc) {\n    super(db, exc);\n  }\n\n  /** Public method which will receive request from {@link com.iluwatar.commander.Commander}. */\n  public String receiveRequest(Object... parameters) throws DatabaseUnavailableException {\n    // it could also be sending an userid, payment details here or something, not added here\n    var id = generateId();\n    var req = new PaymentRequest(id, (float) parameters[0]);\n    return updateDb(req);\n  }\n\n  protected String updateDb(Object... parameters) throws DatabaseUnavailableException {\n    var req = (PaymentRequest) parameters[0];\n    if (database.get(req.transactionId) == null || !req.paid) {\n      database.add(req);\n      req.paid = true;\n      return req.transactionId;\n    }\n    return null;\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/queue/Queue.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.queue;\n\nimport com.iluwatar.commander.exceptions.IsEmptyException;\n\n/**\n * Queue data structure implementation.\n *\n * @param <T> is the type of object the queue will hold.\n */\npublic class Queue<T> {\n\n  private Node<T> front;\n  private Node<T> rear;\n  private int size;\n\n  static class Node<V> {\n    V value;\n    Node<V> next;\n\n    Node(V obj, Node<V> b) {\n      value = obj;\n      next = b;\n    }\n  }\n\n  boolean isEmpty() {\n    return size == 0;\n  }\n\n  void enqueue(T obj) {\n    if (front == null) {\n      front = new Node<>(obj, null);\n      rear = front;\n    } else {\n      var temp = new Node<>(obj, null);\n      rear.next = temp;\n      rear = temp;\n    }\n    size++;\n  }\n\n  T dequeue() throws IsEmptyException {\n    if (isEmpty()) {\n      throw new IsEmptyException();\n    } else {\n      var temp = front;\n      front = front.next;\n      size = size - 1;\n      return temp.value;\n    }\n  }\n\n  T peek() throws IsEmptyException {\n    if (isEmpty()) {\n      throw new IsEmptyException();\n    } else {\n      return front.value;\n    }\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/queue/QueueDatabase.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.queue;\n\nimport com.iluwatar.commander.Database;\nimport com.iluwatar.commander.exceptions.IsEmptyException;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** QueueDatabase id where the instructions to be implemented are queued. */\npublic class QueueDatabase extends Database<QueueTask> {\n\n  private final Queue<QueueTask> data;\n  public List<Exception> exceptionsList;\n\n  public QueueDatabase(Exception... exc) {\n    this.data = new Queue<>();\n    this.exceptionsList = new ArrayList<>(List.of(exc));\n  }\n\n  @Override\n  public QueueTask add(QueueTask t) {\n    data.enqueue(t);\n    return t;\n    // even if same thing queued twice, it is taken care of in other dbs\n  }\n\n  /**\n   * peek method returns object at front without removing it from queue.\n   *\n   * @return object at front of queue\n   * @throws IsEmptyException if queue is empty\n   */\n  public QueueTask peek() throws IsEmptyException {\n    return this.data.peek();\n  }\n\n  /**\n   * dequeue method removes the object at front and returns it.\n   *\n   * @return object at front of queue\n   * @throws IsEmptyException if queue is empty\n   */\n  public QueueTask dequeue() throws IsEmptyException {\n    return this.data.dequeue();\n  }\n\n  @Override\n  public QueueTask get(String taskId) {\n    return null;\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/queue/QueueTask.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.queue;\n\nimport com.iluwatar.commander.Order;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\nimport lombok.Setter;\n\n/** QueueTask object is the object enqueued in queue. */\n@RequiredArgsConstructor\npublic class QueueTask {\n\n  /** TaskType is the type of task to be done. */\n  public enum TaskType {\n    MESSAGING,\n    PAYMENT,\n    EMPLOYEE_DB\n  }\n\n  public final Order order;\n  public final TaskType taskType;\n  public final int messageType; // 0-fail, 1-error, 2-success\n\n  /*we could have varargs Object instead to pass in any parameter instead of just message type\n  but keeping it simple here*/\n  @Getter @Setter private long firstAttemptTime = -1L; // when first time attempt made to do task\n\n  /**\n   * getType method.\n   *\n   * @return String representing type of task\n   */\n  public String getType() {\n    if (!this.taskType.equals(TaskType.MESSAGING)) {\n      return this.taskType.toString();\n    } else {\n      if (this.messageType == 0) {\n        return \"Payment Failure Message\";\n      } else if (this.messageType == 1) {\n        return \"Payment Error Message\";\n      } else {\n        return \"Payment Success Message\";\n      }\n    }\n  }\n\n  public boolean isFirstAttempt() {\n    return this.firstAttemptTime == -1L;\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/shippingservice/ShippingDatabase.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.shippingservice;\n\nimport com.iluwatar.commander.Database;\nimport com.iluwatar.commander.shippingservice.ShippingService.ShippingRequest;\nimport java.util.Hashtable;\nimport java.util.Map;\n\n/** ShippingDatabase is where the ShippingRequest objects are added. */\npublic class ShippingDatabase extends Database<ShippingRequest> {\n\n  private final Map<String, ShippingRequest> data = new Hashtable<>();\n\n  @Override\n  public ShippingRequest add(ShippingRequest r) {\n    return data.put(r.transactionId, r);\n  }\n\n  public ShippingRequest get(String trasnactionId) {\n    return data.get(trasnactionId);\n  }\n}\n"
  },
  {
    "path": "commander/src/main/java/com/iluwatar/commander/shippingservice/ShippingService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander.shippingservice;\n\nimport com.iluwatar.commander.Service;\nimport com.iluwatar.commander.exceptions.DatabaseUnavailableException;\nimport lombok.AllArgsConstructor;\n\n/**\n * ShippingService class receives request from {@link com.iluwatar.commander.Commander} class and\n * adds it to the {@link ShippingDatabase}.\n */\npublic class ShippingService extends Service {\n\n  @AllArgsConstructor\n  static class ShippingRequest {\n    String transactionId;\n    String item;\n    String address;\n  }\n\n  public ShippingService(ShippingDatabase db, Exception... exc) {\n    super(db, exc);\n  }\n\n  /** Public method which will receive request from {@link com.iluwatar.commander.Commander}. */\n  public String receiveRequest(Object... parameters) throws DatabaseUnavailableException {\n    var id = generateId();\n    var item = (String) parameters[0];\n    var address = (String) parameters[1];\n    var req = new ShippingRequest(id, item, address);\n    return updateDb(req);\n  }\n\n  protected String updateDb(Object... parameters) throws DatabaseUnavailableException {\n    var req = (ShippingRequest) parameters[0];\n    if (this.database.get(req.transactionId) == null) {\n      database.add(req);\n      return req.transactionId;\n    }\n    return null;\n  }\n}\n"
  },
  {
    "path": "commander/src/test/java/com/iluwatar/commander/CommanderTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\nimport com.iluwatar.commander.employeehandle.EmployeeDatabase;\nimport com.iluwatar.commander.employeehandle.EmployeeHandle;\nimport com.iluwatar.commander.exceptions.DatabaseUnavailableException;\nimport com.iluwatar.commander.exceptions.ItemUnavailableException;\nimport com.iluwatar.commander.exceptions.PaymentDetailsErrorException;\nimport com.iluwatar.commander.exceptions.ShippingNotPossibleException;\nimport com.iluwatar.commander.messagingservice.MessagingDatabase;\nimport com.iluwatar.commander.messagingservice.MessagingService;\nimport com.iluwatar.commander.paymentservice.PaymentDatabase;\nimport com.iluwatar.commander.paymentservice.PaymentService;\nimport com.iluwatar.commander.queue.QueueDatabase;\nimport com.iluwatar.commander.shippingservice.ShippingDatabase;\nimport com.iluwatar.commander.shippingservice.ShippingService;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\nimport org.junit.platform.commons.util.StringUtils;\n\nclass CommanderTest {\n\n  private final RetryParams retryParams = new RetryParams(1, 1_000L);\n\n  private final TimeLimits timeLimits = new TimeLimits(1L, 1000L, 6000L, 5000L, 2000L);\n\n  private static final List<Exception> exceptionList = new ArrayList<>();\n\n  private static final AppAllCases appAllCases = new AppAllCases();\n\n  static {\n    exceptionList.add(new DatabaseUnavailableException());\n    exceptionList.add(new ShippingNotPossibleException());\n    exceptionList.add(new ItemUnavailableException());\n    exceptionList.add(new PaymentDetailsErrorException());\n    exceptionList.add(new IllegalStateException());\n  }\n\n  private Commander buildCommanderObject() {\n    return buildCommanderObject(false);\n  }\n\n  private Commander buildCommanderObject(boolean nonPaymentException) {\n    PaymentService paymentService =\n        new PaymentService(\n            new PaymentDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n\n    ShippingService shippingService;\n    MessagingService messagingService;\n    if (nonPaymentException) {\n      shippingService =\n          new ShippingService(new ShippingDatabase(), new DatabaseUnavailableException());\n      messagingService =\n          new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());\n\n    } else {\n      shippingService =\n          new ShippingService(new ShippingDatabase(), new DatabaseUnavailableException());\n      messagingService =\n          new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());\n    }\n    var employeeHandle =\n        new EmployeeHandle(\n            new EmployeeDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var qdb =\n        new QueueDatabase(\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    return new Commander(\n        employeeHandle,\n        paymentService,\n        shippingService,\n        messagingService,\n        qdb,\n        retryParams,\n        timeLimits);\n  }\n\n  private Commander buildCommanderObjectVanilla() {\n    PaymentService paymentService =\n        new PaymentService(\n            new PaymentDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var shippingService = new ShippingService(new ShippingDatabase());\n    var messagingService = new MessagingService(new MessagingDatabase());\n    var employeeHandle =\n        new EmployeeHandle(\n            new EmployeeDatabase(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    var qdb =\n        new QueueDatabase(\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException(),\n            new DatabaseUnavailableException());\n    return new Commander(\n        employeeHandle,\n        paymentService,\n        shippingService,\n        messagingService,\n        qdb,\n        retryParams,\n        timeLimits);\n  }\n\n  private Commander buildCommanderObjectUnknownException() {\n    PaymentService paymentService =\n        new PaymentService(new PaymentDatabase(), new IllegalStateException());\n    var shippingService = new ShippingService(new ShippingDatabase());\n    var messagingService = new MessagingService(new MessagingDatabase());\n    var employeeHandle = new EmployeeHandle(new EmployeeDatabase(), new IllegalStateException());\n    var qdb = new QueueDatabase(new DatabaseUnavailableException(), new IllegalStateException());\n    return new Commander(\n        employeeHandle,\n        paymentService,\n        shippingService,\n        messagingService,\n        qdb,\n        retryParams,\n        timeLimits);\n  }\n\n  private Commander buildCommanderObjectNoPaymentException1() {\n    PaymentService paymentService = new PaymentService(new PaymentDatabase());\n    var shippingService = new ShippingService(new ShippingDatabase());\n    var messagingService = new MessagingService(new MessagingDatabase());\n    var employeeHandle = new EmployeeHandle(new EmployeeDatabase(), new IllegalStateException());\n    var qdb = new QueueDatabase(new DatabaseUnavailableException(), new IllegalStateException());\n    return new Commander(\n        employeeHandle,\n        paymentService,\n        shippingService,\n        messagingService,\n        qdb,\n        retryParams,\n        timeLimits);\n  }\n\n  private Commander buildCommanderObjectNoPaymentException2() {\n    PaymentService paymentService = new PaymentService(new PaymentDatabase());\n    var shippingService = new ShippingService(new ShippingDatabase());\n    var messagingService =\n        new MessagingService(new MessagingDatabase(), new IllegalStateException());\n    var employeeHandle = new EmployeeHandle(new EmployeeDatabase(), new IllegalStateException());\n    var qdb = new QueueDatabase(new DatabaseUnavailableException(), new IllegalStateException());\n    return new Commander(\n        employeeHandle,\n        paymentService,\n        shippingService,\n        messagingService,\n        qdb,\n        retryParams,\n        timeLimits);\n  }\n\n  private Commander buildCommanderObjectNoPaymentException3() {\n    PaymentService paymentService = new PaymentService(new PaymentDatabase());\n    var shippingService = new ShippingService(new ShippingDatabase());\n    var messagingService =\n        new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());\n    var employeeHandle = new EmployeeHandle(new EmployeeDatabase(), new IllegalStateException());\n    var qdb = new QueueDatabase(new DatabaseUnavailableException(), new IllegalStateException());\n    return new Commander(\n        employeeHandle,\n        paymentService,\n        shippingService,\n        messagingService,\n        qdb,\n        retryParams,\n        timeLimits);\n  }\n\n  private Commander buildCommanderObjectWithDB() {\n    return buildCommanderObjectWithoutDB(false, false, new IllegalStateException());\n  }\n\n  private Commander buildCommanderObjectWithDB(\n      boolean includeException, boolean includeDBException, Exception e) {\n    var l = includeDBException ? new DatabaseUnavailableException() : e;\n    PaymentService paymentService;\n    ShippingService shippingService;\n    MessagingService messagingService;\n    EmployeeHandle employeeHandle;\n    if (includeException) {\n      paymentService = new PaymentService(new PaymentDatabase(), l);\n      shippingService = new ShippingService(new ShippingDatabase(), l);\n      messagingService = new MessagingService(new MessagingDatabase(), l);\n      employeeHandle = new EmployeeHandle(new EmployeeDatabase(), l);\n    } else {\n      paymentService = new PaymentService(null);\n      shippingService = new ShippingService(null);\n      messagingService = new MessagingService(null);\n      employeeHandle = new EmployeeHandle(null);\n    }\n\n    return new Commander(\n        employeeHandle,\n        paymentService,\n        shippingService,\n        messagingService,\n        null,\n        retryParams,\n        timeLimits);\n  }\n\n  private Commander buildCommanderObjectWithoutDB() {\n    return buildCommanderObjectWithoutDB(false, false, new IllegalStateException());\n  }\n\n  private Commander buildCommanderObjectWithoutDB(\n      boolean includeException, boolean includeDBException, Exception e) {\n    var l = includeDBException ? new DatabaseUnavailableException() : e;\n    PaymentService paymentService;\n    ShippingService shippingService;\n    MessagingService messagingService;\n    EmployeeHandle employeeHandle;\n    if (includeException) {\n      paymentService = new PaymentService(null, l);\n      shippingService = new ShippingService(null, l);\n      messagingService = new MessagingService(null, l);\n      employeeHandle = new EmployeeHandle(null, l);\n    } else {\n      paymentService = new PaymentService(null);\n      shippingService = new ShippingService(null);\n      messagingService = new MessagingService(null);\n      employeeHandle = new EmployeeHandle(null);\n    }\n\n    return new Commander(\n        employeeHandle,\n        paymentService,\n        shippingService,\n        messagingService,\n        null,\n        retryParams,\n        timeLimits);\n  }\n\n  @Test\n  void testPlaceOrderVanilla() {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      Commander c = buildCommanderObjectVanilla();\n      var order = new Order(new User(\"K\", \"J\"), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrder() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      Commander c = buildCommanderObject(true);\n      var order = new Order(new User(\"K\", \"J\"), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrder2() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      Commander c = buildCommanderObject(false);\n      var order = new Order(new User(\"K\", \"J\"), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderNoException1() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      Commander c = buildCommanderObjectNoPaymentException1();\n      var order = new Order(new User(\"K\", \"J\"), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderNoException2() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      Commander c = buildCommanderObjectNoPaymentException2();\n      var order = new Order(new User(\"K\", \"J\"), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderNoException3() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      Commander c = buildCommanderObjectNoPaymentException3();\n      var order = new Order(new User(\"K\", \"J\"), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderNoException4() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      Commander c = buildCommanderObjectNoPaymentException3();\n      var order = new Order(new User(\"K\", \"J\"), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        c.placeOrder(order);\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderUnknownException() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    long messageTime = timeLimits.messageTime();\n    long employeeTime = timeLimits.employeeTime();\n    long queueTime = timeLimits.queueTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      messageTime *= d;\n      employeeTime *= d;\n      queueTime *= d;\n      Commander c = buildCommanderObjectUnknownException();\n      var order = new Order(new User(\"K\", \"J\"), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderShortDuration() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    long messageTime = timeLimits.messageTime();\n    long employeeTime = timeLimits.employeeTime();\n    long queueTime = timeLimits.queueTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      messageTime *= d;\n      employeeTime *= d;\n      queueTime *= d;\n      Commander c = buildCommanderObject(true);\n      var order = new Order(new User(\"K\", \"J\"), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderShortDuration2() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    long messageTime = timeLimits.messageTime();\n    long employeeTime = timeLimits.employeeTime();\n    long queueTime = timeLimits.queueTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      messageTime *= d;\n      employeeTime *= d;\n      queueTime *= d;\n      Commander c = buildCommanderObject(false);\n      var order = new Order(new User(\"K\", \"J\"), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderNoExceptionShortMsgDuration() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    long messageTime = timeLimits.messageTime();\n    long employeeTime = timeLimits.employeeTime();\n    long queueTime = timeLimits.queueTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      messageTime *= d;\n      employeeTime *= d;\n      queueTime *= d;\n      Commander c = buildCommanderObjectNoPaymentException1();\n      var order = new Order(new User(\"K\", \"J\"), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderNoExceptionShortQueueDuration() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    long messageTime = timeLimits.messageTime();\n    long employeeTime = timeLimits.employeeTime();\n    long queueTime = timeLimits.queueTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      messageTime *= d;\n      employeeTime *= d;\n      queueTime *= d;\n      Commander c = buildCommanderObjectUnknownException();\n      var order = new Order(new User(\"K\", \"J\"), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderWithDatabase() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    long messageTime = timeLimits.messageTime();\n    long employeeTime = timeLimits.employeeTime();\n    long queueTime = timeLimits.queueTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      messageTime *= d;\n      employeeTime *= d;\n      queueTime *= d;\n      Commander c = buildCommanderObjectWithDB();\n      var order = new Order(new User(\"K\", null), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderWithDatabaseAndExceptions() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    long messageTime = timeLimits.messageTime();\n    long employeeTime = timeLimits.employeeTime();\n    long queueTime = timeLimits.queueTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      messageTime *= d;\n      employeeTime *= d;\n      queueTime *= d;\n\n      for (Exception e : exceptionList) {\n\n        Commander c = buildCommanderObjectWithDB(true, true, e);\n        var order = new Order(new User(\"K\", null), \"pen\", 1f);\n        for (Order.MessageSent ms : Order.MessageSent.values()) {\n          c.placeOrder(order);\n          assertFalse(StringUtils.isBlank(order.id));\n        }\n\n        c = buildCommanderObjectWithDB(true, false, e);\n        order = new Order(new User(\"K\", null), \"pen\", 1f);\n        for (Order.MessageSent ms : Order.MessageSent.values()) {\n          c.placeOrder(order);\n          assertFalse(StringUtils.isBlank(order.id));\n        }\n\n        c = buildCommanderObjectWithDB(false, false, e);\n        order = new Order(new User(\"K\", null), \"pen\", 1f);\n        for (Order.MessageSent ms : Order.MessageSent.values()) {\n          c.placeOrder(order);\n          assertFalse(StringUtils.isBlank(order.id));\n        }\n\n        c = buildCommanderObjectWithDB(false, true, e);\n        order = new Order(new User(\"K\", null), \"pen\", 1f);\n        for (Order.MessageSent ms : Order.MessageSent.values()) {\n          c.placeOrder(order);\n          assertFalse(StringUtils.isBlank(order.id));\n        }\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderWithoutDatabase() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    long messageTime = timeLimits.messageTime();\n    long employeeTime = timeLimits.employeeTime();\n    long queueTime = timeLimits.queueTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      messageTime *= d;\n      employeeTime *= d;\n      queueTime *= d;\n      Commander c = buildCommanderObjectWithoutDB();\n      var order = new Order(new User(\"K\", null), \"pen\", 1f);\n      for (Order.MessageSent ms : Order.MessageSent.values()) {\n        c.placeOrder(order);\n        assertFalse(StringUtils.isBlank(order.id));\n      }\n    }\n  }\n\n  @Test\n  void testPlaceOrderWithoutDatabaseAndExceptions() throws Exception {\n    long paymentTime = timeLimits.paymentTime();\n    long queueTaskTime = timeLimits.queueTaskTime();\n    long messageTime = timeLimits.messageTime();\n    long employeeTime = timeLimits.employeeTime();\n    long queueTime = timeLimits.queueTime();\n    for (double d = 0.1; d < 2; d = d + 0.1) {\n      paymentTime *= d;\n      queueTaskTime *= d;\n      messageTime *= d;\n      employeeTime *= d;\n      queueTime *= d;\n\n      for (Exception e : exceptionList) {\n\n        Commander c = buildCommanderObjectWithoutDB(true, true, e);\n        var order = new Order(new User(\"K\", null), \"pen\", 1f);\n        for (Order.MessageSent ms : Order.MessageSent.values()) {\n          c.placeOrder(order);\n          assertFalse(StringUtils.isBlank(order.id));\n        }\n\n        c = buildCommanderObjectWithoutDB(true, false, e);\n        order = new Order(new User(\"K\", null), \"pen\", 1f);\n        for (Order.MessageSent ms : Order.MessageSent.values()) {\n          c.placeOrder(order);\n          assertFalse(StringUtils.isBlank(order.id));\n        }\n\n        c = buildCommanderObjectWithoutDB(false, false, e);\n        order = new Order(new User(\"K\", null), \"pen\", 1f);\n        for (Order.MessageSent ms : Order.MessageSent.values()) {\n          c.placeOrder(order);\n          assertFalse(StringUtils.isBlank(order.id));\n        }\n\n        c = buildCommanderObjectWithoutDB(false, true, e);\n        order = new Order(new User(\"K\", null), \"pen\", 1f);\n        for (Order.MessageSent ms : Order.MessageSent.values()) {\n          c.placeOrder(order);\n          assertFalse(StringUtils.isBlank(order.id));\n        }\n      }\n    }\n  }\n\n  @Test\n  void testAllSuccessCases() throws Exception {\n    appAllCases.employeeDbSuccessCase();\n    appAllCases.messagingSuccessCase();\n    appAllCases.paymentSuccessCase();\n    appAllCases.queueSuccessCase();\n    appAllCases.shippingSuccessCase();\n  }\n\n  @Test\n  void testAllUnavailableCase() throws Exception {\n    appAllCases.employeeDatabaseUnavailableCase();\n    appAllCases.messagingDatabaseUnavailableCasePaymentSuccess();\n    appAllCases.messagingDatabaseUnavailableCasePaymentError();\n    appAllCases.messagingDatabaseUnavailableCasePaymentFailure();\n    appAllCases.paymentDatabaseUnavailableCase();\n    appAllCases.queuePaymentTaskDatabaseUnavailableCase();\n    appAllCases.queueMessageTaskDatabaseUnavailableCase();\n    appAllCases.queueEmployeeDbTaskDatabaseUnavailableCase();\n    appAllCases.itemUnavailableCase();\n    appAllCases.shippingDatabaseUnavailableCase();\n  }\n\n  @Test\n  void testAllNotPossibleCase() throws Exception {\n    appAllCases.paymentNotPossibleCase();\n    appAllCases.shippingItemNotPossibleCase();\n  }\n}\n"
  },
  {
    "path": "commander/src/test/java/com/iluwatar/commander/RetryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.commander;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.commander.exceptions.DatabaseUnavailableException;\nimport com.iluwatar.commander.exceptions.ItemUnavailableException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nclass RetryTest {\n\n  private static final Logger LOG = LoggerFactory.getLogger(RetryTest.class);\n\n  @Test\n  void performTest() {\n    Retry.Operation op =\n        (l) -> {\n          if (!l.isEmpty()) {\n            throw l.remove(0);\n          }\n        };\n    Retry.HandleErrorIssue<Order> handleError = (o, e) -> {};\n    var r1 =\n        new Retry<>(\n            op,\n            handleError,\n            3,\n            30000,\n            e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));\n    var r2 =\n        new Retry<>(\n            op,\n            handleError,\n            3,\n            30000,\n            e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));\n    var user = new User(\"Jim\", \"ABCD\");\n    var order = new Order(user, \"book\", 10f);\n    var arr1 =\n        new ArrayList<>(\n            List.of(new ItemUnavailableException(), new DatabaseUnavailableException()));\n    try {\n      r1.perform(arr1, order);\n    } catch (Exception e1) {\n      LOG.error(\"An exception occurred\", e1);\n    }\n    var arr2 =\n        new ArrayList<>(\n            List.of(new DatabaseUnavailableException(), new ItemUnavailableException()));\n    try {\n      r2.perform(arr2, order);\n    } catch (Exception e1) {\n      LOG.error(\"An exception occurred\", e1);\n    }\n    // r1 stops at ItemUnavailableException, r2 retries because it encounters\n    // DatabaseUnavailableException\n    assertTrue(arr1.size() == 1 && arr2.isEmpty());\n  }\n}\n"
  },
  {
    "path": "component/README.md",
    "content": "---\ntitle: \"Component Pattern in Java: Simplifying Complex Systems with Reusable Components\"\nshortTitle: Component\ndescription: \"Learn about the Component Design Pattern in Java, including ECS architecture, modularity, and decoupling. Explore examples, class diagrams, and real-world applications in game development for flexible and maintainable code.\"\ncategories: Structural\nlanguage: en\ntag:\n  - Game programming\n  - Decoupling\n  - Modularity\n---\n\n## Also known as\n\n* Entity-Component-System (ECS)\n* Component-Entity-System (CES)\n* Component-Based Architecture (CBA)\n\n## Intent of Component Design Pattern\n\nThe Component design pattern organizes code into reusable, interchangeable components, promoting flexibility, modularity, and ease of maintenance. This pattern is especially useful in game development, enabling entities to be configured with diverse behaviors dynamically.\n\n## Detailed Explanation of Component Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a video game with a graphics component and a sound component. Including both in a single Java class can create maintenance challenges due to lengthy code and potential conflicts from different teams working on the same class. The Component design pattern resolves this by creating individual component classes for graphics and sound, allowing flexible and independent development. This modular approach enhances maintainability and scalability.\n\nIn plain words\n\n> The component design pattern provides a single attribute to be accessible by numerous objects without requiring the existence of a relationship between the objects themselves.\n\nArchitecture diagram\n\n![Component architecture diagram](./etc/component-architecture-diagram.png)\n\n## Programmatic Example of Component Pattern in Java\n\nThe `App` class creates a demonstration of the use of the component pattern by creating two different objects which inherit a small collection of individual components that are modifiable.\n\n```java\npublic final class App {\n\n    public static void main(String[] args) {\n        final var player = GameObject.createPlayer();\n        final var npc = GameObject.createNpc();\n\n        LOGGER.info(\"Player Update:\");\n        player.update(KeyEvent.KEY_LOCATION_LEFT);\n        LOGGER.info(\"NPC Update:\");\n        npc.demoUpdate();\n    }\n}\n```\n\nMuch of the program exists within the `GameObject` class, within this class, the player and NPC object create methods are set up. Additionally, this class also consists of the method calls used to update/alter information of the object's components.\n\n```java\npublic class GameObject {\n    private final InputComponent inputComponent;\n    private final PhysicComponent physicComponent;\n    private final GraphicComponent graphicComponent;\n\n    public String name;\n    public int velocity = 0;\n    public int coordinate = 0;\n\n    public static GameObject createPlayer() {\n        return new GameObject(new PlayerInputComponent(),\n                new ObjectPhysicComponent(),\n                new ObjectGraphicComponent(),\n                \"player\");\n    }\n\n    public static GameObject createNpc() {\n        return new GameObject(\n                new DemoInputComponent(),\n                new ObjectPhysicComponent(),\n                new ObjectGraphicComponent(),\n                \"npc\");\n    }\n\n    public void demoUpdate() {\n        inputComponent.update(this);\n        physicComponent.update(this);\n        graphicComponent.update(this);\n    }\n\n    public void update(int e) {\n        inputComponent.update(this, e);\n        physicComponent.update(this);\n        graphicComponent.update(this);\n    }\n\n    public void updateVelocity(int acceleration) {\n        this.velocity += acceleration;\n    }\n\n    public void updateCoordinate() {\n        this.coordinate += this.velocity;\n    }\n}\n```\n\nUpon opening the component package, the collection of components are revealed. These components provide the interface for objects to inherit these domains. The `PlayerInputComponent` class shown below updates the object's velocity characteristic based on user's key event input.\n\n```java\npublic class PlayerInputComponent implements InputComponent {\n    private static final int walkAcceleration = 1;\n\n    @Override\n    public void update(GameObject gameObject, int e) {\n        switch (e) {\n            case KeyEvent.KEY_LOCATION_LEFT -> {\n                gameObject.updateVelocity(-WALK_ACCELERATION);\n                LOGGER.info(gameObject.getName() + \" has moved left.\");\n            }\n            case KeyEvent.KEY_LOCATION_RIGHT -> {\n                gameObject.updateVelocity(WALK_ACCELERATION);\n                LOGGER.info(gameObject.getName() + \" has moved right.\");\n            }\n            default -> {\n                LOGGER.info(gameObject.getName() + \"'s velocity is unchanged due to the invalid input\");\n                gameObject.updateVelocity(0);\n            } // incorrect input\n        }\n    }\n}\n```\n\n## When to Use the Component Pattern in Java\n\n* Used in game development and simulations where game entities (e.g., characters, items) can have a dynamic set of abilities or states.\n* Suitable for systems requiring high modularity and systems where entities might need to change behavior at runtime without inheritance hierarchies.\n\n## Real-World Applications of Component Pattern in Java\n\nThe Component pattern is ideal for game development and simulations where entities like characters and items have dynamic abilities or states. It suits systems requiring high modularity and scenarios where entities need to change behavior at runtime without relying on inheritance hierarchies, enhancing flexibility and maintainability.\n\n## Benefits and Trade-offs of Component Pattern\n\nBenefits:\n\n* Flexibility and Reusability: Components can be reused across different entities, making it easier to add new features or modify existing ones.\n* Decoupling: Reduces dependencies between game entity states and behaviors, facilitating easier changes and maintenance.\n* Dynamic Composition: Entities can alter their behavior at runtime by adding or removing components, providing significant flexibility in game design.\n\nTrade-offs:\n\n* Complexity: Can introduce additional complexity in system architecture, particularly in managing dependencies and communications between components.\n* Performance Considerations: Depending on implementation, may incur a performance overhead due to indirection and dynamic behavior, especially critical in high-performance game loops.\n\n## Related Java Design Patterns\n\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Similar concept of adding responsibilities dynamically, but without the focus on game entities.\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Can be used in conjunction with the Component pattern to share component instances among many entities to save memory.\n* [Observer](https://java-design-patterns.com/patterns/observer/): Often used in Component systems to communicate state changes between components.\n\n## References and Credits\n\n* [Game Programming Patterns](https://amzn.to/4cDRWhV)\n* [Procedural Content Generation for Unity Game Development](https://amzn.to/3vBKCTp)\n* [Unity in Action: Multiplatform Game Development in C#](https://amzn.to/3THO6vw)\n* [Component (Game Programming Patterns)](https://gameprogrammingpatterns.com/component.html)\n* [Component pattern - game programming series (Tutemic)](https://www.youtube.com/watch?v=n92GBp2WMkg&ab_channel=Tutemic)\n"
  },
  {
    "path": "component/etc/component.uml.puml",
    "content": "@startuml\nclass App\nclass GameObject\n\ninterface GraphicComponent\ninterface InputComponent\ninterface PhysicComponent\n\nclass ObjectGraphicComponent\nclass DemoInputComponent\nclass PlayerInputComponent\nclass ObjectPhysicComponent\n\nGraphicComponent <|.. ObjectGraphicComponent\nInputComponent <|.. DemoInputComponent\nInputComponent <|.. PlayerInputComponent\nPhysicComponent <|.. ObjectPhysicComponent\n\nGameObject *-- ObjectGraphicComponent\nGameObject *.. DemoInputComponent\nGameObject *.. PlayerInputComponent\nGameObject *-- ObjectPhysicComponent\nclass App {\n+main(String[] args)\n}\n\nclass GameObject{\n  - inputComponent;\n  - physicComponent;\n  - graphicComponent;\n  - name;\n  - velocity\n  - coordinate\n\n  +GameObject()\n  +createPlayer()\n  +createNpc()\n  +demoUpdate()\n  +update(e:int)\n  +getName()\n  +getVelocity()\n  +setVelocity(acceleration:int)\n  +getCoordinate()\n  +setCoordinate()\n}\n\ninterface GraphicComponent{\n    +update()\n}\n\ninterface InputComponent{\n    +update()\n}\n\ninterface PhysicComponent{\n    +update()\n}\n\nclass ObjectGraphicComponent{\n    +update(gameObject:GameObject)\n}\n\nclass DemoInputComponent{\n    -walkAcceleration\n    +update(gameObject:GameObject,e:int)\n}\n\nclass PlayerInputComponent{\n    -walkAcceleration\n    +update(gameObject:GameObject,e:int)\n}\n\nclass ObjectPhysicComponent{\n    +update(gameObject:GameObject)\n}\n\n@enduml"
  },
  {
    "path": "component/etc/component.urm.puml",
    "content": "@startuml\npackage com.iluwatar.component.component.physiccomponent {\n  class ObjectPhysicComponent {\n    - LOGGER : Logger {static}\n    + ObjectPhysicComponent()\n    + update(gameObject : GameObject)\n  }\n  interface PhysicComponent {\n    + update(GameObject) {abstract}\n  }\n}\npackage com.iluwatar.component.component.inputcomponent {\n  class DemoInputComponent {\n    - LOGGER : Logger {static}\n    - WALK_ACCELERATION : int {static}\n    + DemoInputComponent()\n    + update(gameObject : GameObject, e : int)\n  }\n  interface InputComponent {\n    + update(GameObject, int) {abstract}\n  }\n  class PlayerInputComponent {\n    - LOGGER : Logger {static}\n    - WALK_ACCELERATION : int {static}\n    + PlayerInputComponent()\n    + update(gameObject : GameObject, e : int)\n  }\n}\npackage com.iluwatar.component.component.graphiccomponent {\n  interface GraphicComponent {\n    + update(GameObject) {abstract}\n  }\n  class ObjectGraphicComponent {\n    - LOGGER : Logger {static}\n    + ObjectGraphicComponent()\n    + update(gameObject : GameObject)\n  }\n}\npackage com.iluwatar.component {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class GameObject {\n    - coordinate : int\n    - graphicComponent : GraphicComponent\n    - inputComponent : InputComponent\n    - name : String\n    - physicComponent : PhysicComponent\n    - velocity : int\n    + GameObject(inputComponent : InputComponent, physicComponent : PhysicComponent, graphicComponent : GraphicComponent, name : String)\n    + createNpc() : GameObject {static}\n    + createPlayer() : GameObject {static}\n    + demoUpdate()\n    + getCoordinate() : int\n    + getGraphicComponent() : GraphicComponent\n    + getInputComponent() : InputComponent\n    + getName() : String\n    + getPhysicComponent() : PhysicComponent\n    + getVelocity() : int\n    + update(e : int)\n    + updateCoordinate()\n    + updateVelocity(acceleration : int)\n  }\n}\nGameObject -->  \"-inputComponent\" InputComponent\nGameObject -->  \"-graphicComponent\" GraphicComponent\nGameObject -->  \"-physicComponent\" PhysicComponent\nObjectGraphicComponent ..|> GraphicComponent \nDemoInputComponent ..|> InputComponent \nPlayerInputComponent ..|> InputComponent \nObjectPhysicComponent ..|> PhysicComponent \n@enduml"
  },
  {
    "path": "component/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>java-design-patterns</artifactId>\n        <groupId>com.iluwatar</groupId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n\n    <artifactId>component</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.component.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>"
  },
  {
    "path": "component/src/main/java/com/iluwatar/component/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.component;\n\nimport java.awt.event.KeyEvent;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The component design pattern is a common game design structure. This pattern is often used to\n * reduce duplication of code as well as to improve maintainability. In this implementation,\n * component design pattern has been used to provide two game objects with varying component\n * interfaces (features). As opposed to copying and pasting same code for the two game objects, the\n * component interfaces allow game objects to inherit these components from the component classes.\n *\n * <p>The implementation has decoupled graphic, physics and input components from the player and NPC\n * objects. As a result, it avoids the creation of monolithic java classes.\n *\n * <p>The below example in this App class demonstrates the use of the component interfaces for\n * separate objects (player & NPC) and updating of these components as per the implementations in\n * GameObject class and the component classes.\n */\n@Slf4j\npublic final class App {\n  /**\n   * Program entry point.\n   *\n   * @param args args command line args.\n   */\n  public static void main(String[] args) {\n    final var player = GameObject.createPlayer();\n    final var npc = GameObject.createNpc();\n\n    LOGGER.info(\"Player Update:\");\n    player.update(KeyEvent.KEY_LOCATION_LEFT);\n    LOGGER.info(\"NPC Update:\");\n    npc.demoUpdate();\n  }\n}\n"
  },
  {
    "path": "component/src/main/java/com/iluwatar/component/GameObject.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.component;\n\nimport com.iluwatar.component.component.graphiccomponent.GraphicComponent;\nimport com.iluwatar.component.component.graphiccomponent.ObjectGraphicComponent;\nimport com.iluwatar.component.component.inputcomponent.DemoInputComponent;\nimport com.iluwatar.component.component.inputcomponent.InputComponent;\nimport com.iluwatar.component.component.inputcomponent.PlayerInputComponent;\nimport com.iluwatar.component.component.physiccomponent.ObjectPhysicComponent;\nimport com.iluwatar.component.component.physiccomponent.PhysicComponent;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/**\n * The GameObject class has three component class instances that allow the creation of different\n * game objects based on the game design requirements.\n */\n@Getter\n@RequiredArgsConstructor\npublic class GameObject {\n  private final InputComponent inputComponent;\n  private final PhysicComponent physicComponent;\n  private final GraphicComponent graphicComponent;\n\n  private final String name;\n  private int velocity = 0;\n  private int coordinate = 0;\n\n  /**\n   * Creates a player game object.\n   *\n   * @return player object\n   */\n  public static GameObject createPlayer() {\n    return new GameObject(\n        new PlayerInputComponent(),\n        new ObjectPhysicComponent(),\n        new ObjectGraphicComponent(),\n        \"player\");\n  }\n\n  /**\n   * Creates a NPC game object.\n   *\n   * @return npc object\n   */\n  public static GameObject createNpc() {\n    return new GameObject(\n        new DemoInputComponent(), new ObjectPhysicComponent(), new ObjectGraphicComponent(), \"npc\");\n  }\n\n  /**\n   * Updates the three components of the NPC object used in the demo in App.java note that this is\n   * simply a duplicate of update() without the key event for demonstration purposes.\n   *\n   * <p>This method is usually used in games if the player becomes inactive.\n   */\n  public void demoUpdate() {\n    inputComponent.update(this, 0);\n    physicComponent.update(this);\n    graphicComponent.update(this);\n  }\n\n  /**\n   * Updates the three components for objects based on key events.\n   *\n   * @param e key event from the player.\n   */\n  public void update(int e) {\n    inputComponent.update(this, e);\n    physicComponent.update(this);\n    graphicComponent.update(this);\n  }\n\n  /**\n   * Update the velocity based on the acceleration of the GameObject.\n   *\n   * @param acceleration the acceleration of the GameObject\n   */\n  public void updateVelocity(int acceleration) {\n    this.velocity += acceleration;\n  }\n\n  /** Set the c based on the current velocity. */\n  public void updateCoordinate() {\n    this.coordinate += this.velocity;\n  }\n}\n"
  },
  {
    "path": "component/src/main/java/com/iluwatar/component/component/graphiccomponent/GraphicComponent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.component.component.graphiccomponent;\n\nimport com.iluwatar.component.GameObject;\n\n/** Generic GraphicComponent interface. */\npublic interface GraphicComponent {\n  void update(GameObject gameObject);\n}\n"
  },
  {
    "path": "component/src/main/java/com/iluwatar/component/component/graphiccomponent/ObjectGraphicComponent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.component.component.graphiccomponent;\n\nimport com.iluwatar.component.GameObject;\nimport lombok.extern.slf4j.Slf4j;\n\n/** ObjectGraphicComponent class mimics the graphic component of the Game Object. */\n@Slf4j\npublic class ObjectGraphicComponent implements GraphicComponent {\n\n  /**\n   * The method updates the graphics based on the velocity of gameObject.\n   *\n   * @param gameObject the gameObject instance\n   */\n  @Override\n  public void update(GameObject gameObject) {\n    LOGGER.info(gameObject.getName() + \"'s current velocity: \" + gameObject.getVelocity());\n  }\n}\n"
  },
  {
    "path": "component/src/main/java/com/iluwatar/component/component/inputcomponent/DemoInputComponent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.component.component.inputcomponent;\n\nimport com.iluwatar.component.GameObject;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Take this component class to control player or the NPC for demo mode. and implemented the\n * InputComponent interface.\n *\n * <p>Essentially, the demo mode is utilised during a game if the user become inactive. Please see:\n * http://gameprogrammingpatterns.com/component.html\n */\n@Slf4j\npublic class DemoInputComponent implements InputComponent {\n  private static final int WALK_ACCELERATION = 2;\n\n  /**\n   * Redundant method in the demo mode.\n   *\n   * @param gameObject the gameObject instance\n   * @param e key event instance\n   */\n  @Override\n  public void update(GameObject gameObject, int e) {\n    gameObject.updateVelocity(WALK_ACCELERATION);\n    LOGGER.info(gameObject.getName() + \" has moved right.\");\n  }\n}\n"
  },
  {
    "path": "component/src/main/java/com/iluwatar/component/component/inputcomponent/InputComponent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.component.component.inputcomponent;\n\nimport com.iluwatar.component.GameObject;\n\n/** Generic InputComponent interface. */\npublic interface InputComponent {\n  void update(GameObject gameObject, int e);\n}\n"
  },
  {
    "path": "component/src/main/java/com/iluwatar/component/component/inputcomponent/PlayerInputComponent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.component.component.inputcomponent;\n\nimport com.iluwatar.component.GameObject;\nimport java.awt.event.KeyEvent;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * PlayerInputComponent is used to handle user key event inputs, and thus it implements the\n * InputComponent interface.\n */\n@Slf4j\npublic class PlayerInputComponent implements InputComponent {\n  private static final int WALK_ACCELERATION = 1;\n\n  /**\n   * The update method to change the velocity based on the input key event.\n   *\n   * @param gameObject the gameObject instance\n   * @param e key event instance\n   */\n  @Override\n  public void update(GameObject gameObject, int e) {\n    switch (e) {\n      case KeyEvent.KEY_LOCATION_LEFT -> {\n        gameObject.updateVelocity(-WALK_ACCELERATION);\n        LOGGER.info(gameObject.getName() + \" has moved left.\");\n      }\n      case KeyEvent.KEY_LOCATION_RIGHT -> {\n        gameObject.updateVelocity(WALK_ACCELERATION);\n        LOGGER.info(gameObject.getName() + \" has moved right.\");\n      }\n      default -> {\n        LOGGER.info(gameObject.getName() + \"'s velocity is unchanged due to the invalid input\");\n        gameObject.updateVelocity(0);\n      } // incorrect input\n    }\n  }\n}\n"
  },
  {
    "path": "component/src/main/java/com/iluwatar/component/component/physiccomponent/ObjectPhysicComponent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.component.component.physiccomponent;\n\nimport com.iluwatar.component.GameObject;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Take this component class to update the x coordinate for the Game Object instance. */\n@Slf4j\npublic class ObjectPhysicComponent implements PhysicComponent {\n\n  /**\n   * The method update the horizontal (X-axis) coordinate based on the velocity of gameObject.\n   *\n   * @param gameObject the gameObject instance\n   */\n  @Override\n  public void update(GameObject gameObject) {\n    gameObject.updateCoordinate();\n    LOGGER.info(gameObject.getName() + \"'s coordinate has been changed.\");\n  }\n}\n"
  },
  {
    "path": "component/src/main/java/com/iluwatar/component/component/physiccomponent/PhysicComponent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.component.component.physiccomponent;\n\nimport com.iluwatar.component.GameObject;\n\n/** Generic PhysicComponent interface. */\npublic interface PhysicComponent {\n  void update(GameObject gameObject);\n}\n"
  },
  {
    "path": "component/src/test/java/com/iluwatar/component/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.component;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/**\n * Tests App class : src/main/java/com/iluwatar/component/App.java General execution test of the\n * application.\n */\nclass AppTest {\n\n  @Test\n  void shouldExecuteComponentWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "component/src/test/java/com/iluwatar/component/GameObjectTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.component;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.awt.event.KeyEvent;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests GameObject class. src/main/java/com/iluwatar/component/GameObject.java */\n@Slf4j\nclass GameObjectTest {\n  GameObject playerTest;\n  GameObject npcTest;\n\n  @BeforeEach\n  public void initEach() {\n    // creates player & npc objects for testing\n    // note that velocity and coordinates are initialised to 0 in GameObject.java\n    playerTest = GameObject.createPlayer();\n    npcTest = GameObject.createNpc();\n  }\n\n  /** Tests the create methods - createPlayer() and createNPC(). */\n  @Test\n  void objectTest() {\n    LOGGER.info(\"objectTest:\");\n    assertEquals(\"player\", playerTest.getName());\n    assertEquals(\"npc\", npcTest.getName());\n  }\n\n  /** Tests the input component with varying key event inputs. Targets the player game object. */\n  @Test\n  void eventInputTest() {\n    LOGGER.info(\"eventInputTest:\");\n    playerTest.update(KeyEvent.KEY_LOCATION_LEFT);\n    assertEquals(-1, playerTest.getVelocity());\n    assertEquals(-1, playerTest.getCoordinate());\n\n    playerTest.update(KeyEvent.KEY_LOCATION_RIGHT);\n    playerTest.update(KeyEvent.KEY_LOCATION_RIGHT);\n    assertEquals(1, playerTest.getVelocity());\n    assertEquals(0, playerTest.getCoordinate());\n\n    LOGGER.info(Integer.toString(playerTest.getCoordinate()));\n    LOGGER.info(Integer.toString(playerTest.getVelocity()));\n\n    GameObject p2 = GameObject.createPlayer();\n    p2.update(KeyEvent.KEY_LOCATION_LEFT);\n    // in the case of an unknown, object stats are set to default\n    p2.update(KeyEvent.KEY_LOCATION_UNKNOWN);\n    assertEquals(-1, p2.getVelocity());\n  }\n\n  /** Tests the demo component interface. */\n  @Test\n  void npcDemoTest() {\n    LOGGER.info(\"npcDemoTest:\");\n    npcTest.demoUpdate();\n    assertEquals(2, npcTest.getVelocity());\n    assertEquals(2, npcTest.getCoordinate());\n  }\n}\n"
  },
  {
    "path": "composite/README.md",
    "content": "---\ntitle: \"Composite Pattern in Java: Building Flexible Tree Structures\"\nshortTitle: Composite\ndescription: \"Explore the Composite Design Pattern in Java. Learn how to compose objects into tree structures to represent part-whole hierarchies, making it easier to treat individual objects and compositions uniformly. Ideal for graphical user interfaces, file systems, and organizational structures.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Decoupling\n  - Gang of Four\n  - Object composition\n  - Recursion\n---\n\n## Also known as\n\n* Object Tree\n* Composite Structure\n\n## Intent of Composite Design Pattern\n\nCompose objects into tree structures to represent part-whole hierarchies. The Composite Design Pattern lets clients treat individual objects and compositions of objects uniformly.\n\n## Detailed Explanation of Composite Pattern with Real-World Examples\n\nReal-world example\n\n> In a real-world example, consider a company with a complex organizational structure. The company consists of various departments, each of which can contain sub-departments, and ultimately individual employees. The Composite Design Pattern can be used to represent this structure. Each department and employee are treated as a node in a tree structure, where departments can contain other departments or employees, but employees are leaf nodes with no children. This allows the company to perform operations uniformly, such as calculating total salaries or printing the organizational chart, by treating individual employees and entire departments in the same way.\n\nIn plain words\n\n> The Composite Design Pattern lets clients uniformly treat individual objects and compositions of objects.\n\nWikipedia says\n\n> In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes that a group of objects is to be treated in the same way as a single instance of an object. The intent of a composite is to \"compose\" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.\n\nFlowchart\n\n![Composite flowchart](./etc/composite-flowchart.png)\n\n## Programmatic Example of Composite Pattern in Java\n\nEvery sentence is composed of words which are in turn composed of characters. Each of these objects are printable, and they can have something printed before or after them like sentence always ends with full stop and word always has space before it.\n\nHere we have the base class `LetterComposite` and the different printable types `Letter`, `Word` and `Sentence`.\n\n```java\npublic abstract class LetterComposite {\n\n    private final List<LetterComposite> children = new ArrayList<>();\n\n    public void add(LetterComposite letter) {\n        children.add(letter);\n    }\n\n    public int count() {\n        return children.size();\n    }\n\n    protected void printThisBefore() {\n    }\n\n    protected void printThisAfter() {\n    }\n\n    public void print() {\n        printThisBefore();\n        children.forEach(LetterComposite::print);\n        printThisAfter();\n    }\n}\n\npublic class Letter extends LetterComposite {\n\n    private final char character;\n\n    public Letter(char c) {\n        this.character = c;\n    }\n\n    @Override\n    protected void printThisBefore() {\n        System.out.print(character);\n    }\n}\n\npublic class Word extends LetterComposite {\n\n    public Word(List<Letter> letters) {\n        letters.forEach(this::add);\n    }\n\n    public Word(char... letters) {\n        for (char letter : letters) {\n            this.add(new Letter(letter));\n        }\n    }\n\n    @Override\n    protected void printThisBefore() {\n        System.out.print(\" \");\n    }\n}\n\npublic class Sentence extends LetterComposite {\n\n    public Sentence(List<Word> words) {\n        words.forEach(this::add);\n    }\n\n    @Override\n    protected void printThisAfter() {\n        System.out.print(\".\");\n    }\n}\n```\n\nThen we have a messenger to carry messages:\n\n```java\npublic class Messenger {\n\n    LetterComposite messageFromOrcs() {\n\n        var words = List.of(\n                new Word('W', 'h', 'e', 'r', 'e'),\n                new Word('t', 'h', 'e', 'r', 'e'),\n                new Word('i', 's'),\n                new Word('a'),\n                new Word('w', 'h', 'i', 'p'),\n                new Word('t', 'h', 'e', 'r', 'e'),\n                new Word('i', 's'),\n                new Word('a'),\n                new Word('w', 'a', 'y')\n        );\n\n        return new Sentence(words);\n\n    }\n\n    LetterComposite messageFromElves() {\n\n        var words = List.of(\n                new Word('M', 'u', 'c', 'h'),\n                new Word('w', 'i', 'n', 'd'),\n                new Word('p', 'o', 'u', 'r', 's'),\n                new Word('f', 'r', 'o', 'm'),\n                new Word('y', 'o', 'u', 'r'),\n                new Word('m', 'o', 'u', 't', 'h')\n        );\n\n        return new Sentence(words);\n\n    }\n\n}\n```\n\nAnd then it can be used as:\n\n```java\n  public static void main(String[] args) {\n\n    var messenger = new Messenger();\n\n    LOGGER.info(\"Message from the orcs: \");\n    messenger.messageFromOrcs().print();\n\n    LOGGER.info(\"Message from the elves: \");\n    messenger.messageFromElves().print();\n}\n```\n\nThe console output:\n\n```\n20:43:54.801 [main] INFO com.iluwatar.composite.App -- Message from the orcs: \n Where there is a whip there is a way.\n20:43:54.803 [main] INFO com.iluwatar.composite.App -- Message from the elves: \n Much wind pours from your mouth.\n```\n\n## When to Use the Composite Pattern in Java\n\nUse the Composite pattern when\n\n* You want to represent part-whole hierarchies of objects.\n* You want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly.\n\n## Real-World Applications of Composite Pattern in Java\n\n* Graphical user interfaces where components can contain other components (e.g., panels containing buttons, labels, other panels).\n* File system representations where directories can contain files and other directories.\n* Organizational structures where a department can contain sub-departments and employees.\n* [java.awt.Container](http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html) and [java.awt.Component](http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html)\n* [Apache Wicket](https://github.com/apache/wicket) component tree, see [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java) and [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)\n\n## Benefits and Trade-offs of Composite Pattern\n\nBenefits:\n\n* Simplifies client code, as it can treat composite structures and individual objects uniformly.\n* Makes it easier to add new kinds of components, as existing code doesn't need to be changed.\n\nTrade-offs:\n\n* Can make the design overly general. It might be difficult to restrict the components of a composite.\n* Can make it harder to restrict the types of components in a composite.\n\n## Related Java Design Patterns\n\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Composite can use Flyweight to share component instances among several composites.\n* [Iterator](https://java-design-patterns.com/patterns/iterator/): Can be used to traverse Composite structures.\n* [Visitor](https://java-design-patterns.com/patterns/visitor/): Can apply an operation over a Composite structure.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n* [Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/3xoLAmi)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3vBKXWb)\n"
  },
  {
    "path": "composite/etc/composite.urm.puml",
    "content": "@startuml\npackage com.iluwatar.composite {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Letter {\n    - character : char\n    + Letter(c : char)\n    # printThisBefore()\n  }\n  abstract class LetterComposite {\n    - children : List<LetterComposite>\n    + LetterComposite()\n    + add(letter : LetterComposite)\n    + count() : int\n    + print()\n    # printThisAfter()\n    # printThisBefore()\n  }\n  class Messenger {\n    + Messenger()\n    ~ messageFromElves() : LetterComposite\n    ~ messageFromOrcs() : LetterComposite\n  }\n  class Sentence {\n    + Sentence(words : List<Word>)\n    # printThisAfter()\n  }\n  class Word {\n    + Word(letters : List<Letter>)\n    + Word(letters : char[])\n    # printThisBefore()\n  }\n}\nLetterComposite -->  \"-children\" LetterComposite\nLetter --|> LetterComposite \nSentence --|> LetterComposite \nWord --|> LetterComposite \n@enduml"
  },
  {
    "path": "composite/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>composite</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.composite.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "composite/src/main/java/com/iluwatar/composite/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.composite;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Composite pattern is a partitioning design pattern. The Composite pattern describes that a\n * group of objects is to be treated in the same way as a single instance of an object. The intent\n * of a composite is to \"compose\" objects into tree structures to represent part-whole hierarchies.\n * Implementing the Composite pattern lets clients treat individual objects and compositions\n * uniformly.\n *\n * <p>In this example we have sentences composed of words composed of letters. All of the objects\n * can be treated through the same interface ({@link LetterComposite}).\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var messenger = new Messenger();\n\n    LOGGER.info(\"Message from the orcs: \");\n    messenger.messageFromOrcs().print();\n\n    LOGGER.info(\"Message from the elves: \");\n    messenger.messageFromElves().print();\n  }\n}\n"
  },
  {
    "path": "composite/src/main/java/com/iluwatar/composite/Letter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.composite;\n\nimport lombok.RequiredArgsConstructor;\n\n/** Letter. */\n@RequiredArgsConstructor\npublic class Letter extends LetterComposite {\n\n  private final char character;\n\n  @Override\n  protected void printThisBefore() {\n    System.out.print(character);\n  }\n}\n"
  },
  {
    "path": "composite/src/main/java/com/iluwatar/composite/LetterComposite.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.composite;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** Composite interface. */\npublic abstract class LetterComposite {\n\n  private final List<LetterComposite> children = new ArrayList<>();\n\n  public void add(LetterComposite letter) {\n    children.add(letter);\n  }\n\n  public int count() {\n    return children.size();\n  }\n\n  protected void printThisBefore() {}\n\n  protected void printThisAfter() {}\n\n  /** Print. */\n  public void print() {\n    printThisBefore();\n    children.forEach(LetterComposite::print);\n    printThisAfter();\n  }\n}\n"
  },
  {
    "path": "composite/src/main/java/com/iluwatar/composite/Messenger.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.composite;\n\nimport java.util.List;\n\n/** Messenger. */\npublic class Messenger {\n\n  LetterComposite messageFromOrcs() {\n\n    var words =\n        List.of(\n            new Word('W', 'h', 'e', 'r', 'e'),\n            new Word('t', 'h', 'e', 'r', 'e'),\n            new Word('i', 's'),\n            new Word('a'),\n            new Word('w', 'h', 'i', 'p'),\n            new Word('t', 'h', 'e', 'r', 'e'),\n            new Word('i', 's'),\n            new Word('a'),\n            new Word('w', 'a', 'y'));\n\n    return new Sentence(words);\n  }\n\n  LetterComposite messageFromElves() {\n\n    var words =\n        List.of(\n            new Word('M', 'u', 'c', 'h'),\n            new Word('w', 'i', 'n', 'd'),\n            new Word('p', 'o', 'u', 'r', 's'),\n            new Word('f', 'r', 'o', 'm'),\n            new Word('y', 'o', 'u', 'r'),\n            new Word('m', 'o', 'u', 't', 'h'));\n\n    return new Sentence(words);\n  }\n}\n"
  },
  {
    "path": "composite/src/main/java/com/iluwatar/composite/Sentence.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.composite;\n\nimport java.util.List;\n\n/** Sentence. */\npublic class Sentence extends LetterComposite {\n\n  /** Constructor. */\n  public Sentence(List<Word> words) {\n    words.forEach(this::add);\n  }\n\n  @Override\n  protected void printThisAfter() {\n    System.out.print(\".\\n\");\n  }\n}\n"
  },
  {
    "path": "composite/src/main/java/com/iluwatar/composite/Word.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.composite;\n\nimport java.util.List;\n\n/** Word. */\npublic class Word extends LetterComposite {\n\n  /** Constructor. */\n  public Word(List<Letter> letters) {\n    letters.forEach(this::add);\n  }\n\n  /**\n   * Constructor.\n   *\n   * @param letters to include\n   */\n  public Word(char... letters) {\n    for (char letter : letters) {\n      this.add(new Letter(letter));\n    }\n  }\n\n  @Override\n  protected void printThisBefore() {\n    System.out.print(\" \");\n  }\n}\n"
  },
  {
    "path": "composite/src/test/java/com/iluwatar/composite/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.composite;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    Assertions.assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "composite/src/test/java/com/iluwatar/composite/MessengerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.composite;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.PrintStream;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** MessengerTest */\nclass MessengerTest {\n\n  /** The buffer used to capture every write to {@link System#out} */\n  private ByteArrayOutputStream stdOutBuffer = new ByteArrayOutputStream();\n\n  /** Keep the original std-out so it can be restored after the test */\n  private final PrintStream realStdOut = System.out;\n\n  /**\n   * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test\n   */\n  @BeforeEach\n  void setUp() {\n    this.stdOutBuffer = new ByteArrayOutputStream();\n    System.setOut(new PrintStream(stdOutBuffer));\n  }\n\n  /** Removed the mocked std-out {@link PrintStream} again from the {@link System} class */\n  @AfterEach\n  void tearDown() {\n    System.setOut(realStdOut);\n  }\n\n  /** Test the message from the orcs */\n  @Test\n  void testMessageFromOrcs() {\n    final var messenger = new Messenger();\n    testMessage(messenger.messageFromOrcs(), \"Where there is a whip there is a way.\");\n  }\n\n  /** Test the message from the elves */\n  @Test\n  void testMessageFromElves() {\n    final var messenger = new Messenger();\n    testMessage(messenger.messageFromElves(), \"Much wind pours from your mouth.\");\n  }\n\n  /**\n   * Test if the given composed message matches the expected message\n   *\n   * @param composedMessage The composed message, received from the messenger\n   * @param message The expected message\n   */\n  private void testMessage(final LetterComposite composedMessage, final String message) {\n    // Test is the composed message has the correct number of words\n    final var words = message.split(\" \");\n    assertNotNull(composedMessage);\n    assertEquals(words.length, composedMessage.count());\n\n    // Print the message to the mocked stdOut ...\n    composedMessage.print();\n\n    // ... and verify if the message matches with the expected one\n    assertEquals(message, new String(this.stdOutBuffer.toByteArray()).trim());\n  }\n}\n"
  },
  {
    "path": "composite-entity/README.md",
    "content": "---\ntitle: \"Composite Entity Pattern in Java: Streamlining Persistent Object Management\"\nshortTitle: Composite Entity\ndescription: \"Learn about the Composite Entity design pattern in Java, a structural pattern used to manage interrelated persistent objects as a single entity. Ideal for enterprise applications and EJB, this pattern simplifies complex data structures and client interactions.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Client-server\n  - Data access\n  - Decoupling\n  - Enterprise patterns\n  - Object composition\n  - Persistence\n  - Resource management\n---\n\n## Also known as\n\n* Coarse-Grained Entity\n\n## Intent of Composite Entity Design Pattern\n\nThe Composite Entity design pattern in Java is aimed at managing a set of interrelated persistent objects as if they were a single entity. It is commonly used in enterprise applications, particularly within the context of Enterprise JavaBeans (EJB) and similar enterprise frameworks, to represent graph-based data structures within business models. This pattern enables clients to treat these complex structures as a single unit, simplifying operations and interactions.\n\n## Detailed Explanation of Composite Entity Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a university registration system where a \"Student\" entity is a composite entity. Each \"Student\" object includes several dependent objects: personal details, course enrollments, grades, and payment information. Instead of managing each of these aspects separately, the Composite Entity design pattern allows the university system to treat the \"Student\" as a single entity. This simplifies operations such as enrolling a student in a new course, updating grades, and processing payments, since all related actions can be managed through the composite \"Student\" object.\n\nIn plain words\n\n> The Composite Entity pattern in Java allows a set of related persistent objects to be represented and managed by a unified object, simplifying enterprise application design.\n\nWikipedia says\n\n> Composite entity is a Java EE Software design pattern and it is used to model, represent, and manage a set of interrelated persistent objects rather than representing them as individual fine-grained entity beans, and also a composite entity bean represents a graph of objects.\n\nFlowchart\n\n![Composite Entity flowchart](./etc/composite-entity-flowchart.png)\n\n## Programmatic Example of Composite Entity in Java\n\nFor a console, there may be many interfaces that need to be managed and controlled. Using the composite entity pattern, dependent objects such as messages and signals can be combined and controlled using a single object.\n\nWe need a generic solution for the problem. To achieve this, let's introduce a generic Composite Entity Pattern.\n\n```java\npublic abstract class DependentObject<T> {\n\n    T data;\n\n    public void setData(T message) {\n        this.data = message;\n    }\n\n    public T getData() {\n        return data;\n    }\n}\n\npublic abstract class CoarseGrainedObject<T> {\n\n    DependentObject<T>[] dependentObjects;\n\n    public void setData(T... data) {\n        IntStream.range(0, data.length).forEach(i -> dependentObjects[i].setData(data[i]));\n    }\n\n    public T[] getData() {\n        return (T[]) Arrays.stream(dependentObjects).map(DependentObject::getData).toArray();\n    }\n}\n\n```\n\nThe specialized composite entity `console` inherit from this base class as follows.\n\n```java\npublic class MessageDependentObject extends DependentObject<String> {\n\n}\n\npublic class SignalDependentObject extends DependentObject<String> {\n\n}\n\npublic class ConsoleCoarseGrainedObject extends CoarseGrainedObject<String> {\n\n    @Override\n    public String[] getData() {\n        super.getData();\n        return new String[] {\n                dependentObjects[0].getData(), dependentObjects[1].getData()\n        };\n    }\n\n    public void init() {\n        dependentObjects = new DependentObject[] {\n                new MessageDependentObject(), new SignalDependentObject()};\n    }\n}\n\npublic class CompositeEntity {\n\n    private final ConsoleCoarseGrainedObject console = new ConsoleCoarseGrainedObject();\n\n    public void setData(String message, String signal) {\n        console.setData(message, signal);\n    }\n\n    public String[] getData() {\n        return console.getData();\n    }\n}\n```\n\nNow managing the assignment of message and signal objects with the composite entity `console`.\n\n```java\npublic App(String message, String signal) {\n    var console = new CompositeEntity();\n    console.init();\n    console.setData(message, signal);\n    Arrays.stream(console.getData()).forEach(LOGGER::info);\n    console.setData(\"Danger\", \"Red Light\");\n    Arrays.stream(console.getData()).forEach(LOGGER::info);\n}\n```\n\n## When to Use the Composite Entity Pattern in Java\n\n* Useful in Java enterprise applications where business objects are complex and involve various interdependent persistent objects.\n* Ideal for scenarios where clients need to work with a unified interface to a set of objects rather than individual entities.\n* Applicable in systems that require a simplified view of a complex data model for external clients or services.\n\n\n## Real-World Applications of Composite Entity Pattern in Java\n\n* Enterprise applications with complex business models, particularly those using EJB or similar enterprise frameworks.\n* Systems requiring abstraction over complex database schemas to simplify client interactions.\n* Applications that need to enforce consistency or transactions across multiple persistent objects in a business entity.\n\n## Benefits and Trade-offs of Composite Entity Pattern\n\nBenefits:\n\n* Simplifies client interactions with complex entity models by providing a unified interface.\n* Enhances reusability and maintainability of the business layer by decoupling client code from the complex internals of business entities.\n* Facilitates easier transaction management and consistency enforcement across a set of related persistent objects.\n\nTrade-offs:\n\n* May introduce a level of indirection that could impact performance.\n* Can lead to overly coarse-grained interfaces that might not be as flexible for all client needs.\n* Requires careful design to avoid bloated composite entities that are difficult to manage.\n\n## Related Java Design Patterns\n\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): For dynamically adding behavior to individual objects within the composite entity without affecting the structure.\n* [Facade](https://java-design-patterns.com/patterns/facade/): Provides a simplified interface to a complex subsystem, similar to how a composite entity simplifies access to a set of objects.\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Useful for managing shared objects within a composite entity to reduce memory footprint.\n\n## References and Credits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap)\n* [Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML](https://amzn.to/49mslqS)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3xjKdpe)\n* [Composite Entity Pattern (Wikipedia)](https://en.wikipedia.org/wiki/Composite_entity_pattern)\n"
  },
  {
    "path": "composite-entity/etc/composite-entity.urm.puml",
    "content": "@startuml\npackage com.iluwatar.compositeentity {\n  class App {\n     + App(message: String, signal: String)\n     + main(args : String[]) {static}\n  }\n  class CompositeEntity{\n      - console : ConsoleCoarseGrainedObject\n      + CompositeEntity()\n      + setData(message: String, signal: String)\n      + getData()\n      + init()\n    }\n  abstract CoarseGrainedObject{\n    - dependentObjects : DependentObject[]\n    + CoarseGrainedObject()\n    + setData(data: T[])\n    + getData()\n  }\n  abstract DependentObject{\n      - data : T\n      + DependentObject()\n      + setData(data: T)\n      + getData()\n  }\n  class ConsoleCoarseGrainedObject{\n      + ConsoleCoarseGrainedObject()\n      + getData()\n      + init()\n  }\n  class MessageDependentObject{\n          + MessageDependentObject()\n  }\n  class SignalDependentObject{\n            + SignalDependentObject()\n  }\n\n  MessageDependentObject --|> DependentObject\n  SignalDependentObject  --|> DependentObject\n  ConsoleCoarseGrainedObject --|> CoarseGrainedObject\n  CompositeEntity -right-> ConsoleCoarseGrainedObject\n  CoarseGrainedObject \"1\" o--> \"0..\" DependentObject\n  App .right.> CompositeEntity\n}\n@enduml\n"
  },
  {
    "path": "composite-entity/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>composite-entity</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.composite-entity.com.iluwatar.compositeentity.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "composite-entity/src/main/java/com/iluwatar/compositeentity/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeentity;\n\nimport java.util.Arrays;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Composite entity is a Java EE Software design pattern and it is used to model, represent, and\n * manage a set of interrelated persistent objects rather than representing them as individual\n * fine-grained entity beans, and also a composite entity bean represents a graph of objects.\n */\n@Slf4j\npublic class App {\n\n  /** An instance that a console manages two related objects. */\n  public App(String message, String signal) {\n    var console = new CompositeEntity();\n    console.init();\n    console.setData(message, signal);\n    Arrays.stream(console.getData()).forEach(LOGGER::info);\n    console.setData(\"Danger\", \"Red Light\");\n    Arrays.stream(console.getData()).forEach(LOGGER::info);\n  }\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    new App(\"No Danger\", \"Green Light\");\n  }\n}\n"
  },
  {
    "path": "composite-entity/src/main/java/com/iluwatar/compositeentity/CoarseGrainedObject.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeentity;\n\nimport java.util.Arrays;\nimport java.util.stream.IntStream;\n\n/**\n * A coarse-grained object is an object with its own life cycle manages its own relationships to\n * other objects. It can be an object contained in the composite entity, or, composite entity itself\n * can be the coarse-grained object which holds dependent objects.\n */\npublic abstract class CoarseGrainedObject<T> {\n\n  DependentObject<T>[] dependentObjects;\n\n  public void setData(T... data) {\n    IntStream.range(0, data.length).forEach(i -> dependentObjects[i].setData(data[i]));\n  }\n\n  public T[] getData() {\n    return (T[]) Arrays.stream(dependentObjects).map(DependentObject::getData).toArray();\n  }\n}\n"
  },
  {
    "path": "composite-entity/src/main/java/com/iluwatar/compositeentity/CompositeEntity.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeentity;\n\n/**\n * Composite entity is the coarse-grained entity bean which may be the coarse-grained object, or may\n * contain a reference to the coarse-grained object.\n */\npublic class CompositeEntity {\n\n  private final ConsoleCoarseGrainedObject console = new ConsoleCoarseGrainedObject();\n\n  public void setData(String message, String signal) {\n    console.setData(message, signal);\n  }\n\n  public String[] getData() {\n    return console.getData();\n  }\n\n  public void init() {\n    console.init();\n  }\n}\n"
  },
  {
    "path": "composite-entity/src/main/java/com/iluwatar/compositeentity/ConsoleCoarseGrainedObject.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeentity;\n\n/** A specific CoarseGrainedObject to implement a console. */\npublic class ConsoleCoarseGrainedObject extends CoarseGrainedObject<String> {\n\n  @Override\n  public String[] getData() {\n    return new String[] {dependentObjects[0].getData(), dependentObjects[1].getData()};\n  }\n\n  public void init() {\n    dependentObjects =\n        new DependentObject[] {new MessageDependentObject(), new SignalDependentObject()};\n  }\n}\n"
  },
  {
    "path": "composite-entity/src/main/java/com/iluwatar/compositeentity/DependentObject.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeentity;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/**\n * It is an object, which can contain other dependent objects (there may be a tree of objects within\n * the composite entity), that depends on the coarse-grained object and has its life cycle managed\n * by the coarse-grained object.\n */\n@Setter\n@Getter\npublic abstract class DependentObject<T> {\n\n  T data;\n}\n"
  },
  {
    "path": "composite-entity/src/main/java/com/iluwatar/compositeentity/MessageDependentObject.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeentity;\n\n/** The first DependentObject to show message. */\npublic class MessageDependentObject extends DependentObject<String> {}\n"
  },
  {
    "path": "composite-entity/src/main/java/com/iluwatar/compositeentity/SignalDependentObject.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeentity;\n\n/** The second DependentObject to show message. */\npublic class SignalDependentObject extends DependentObject<String> {}\n"
  },
  {
    "path": "composite-entity/src/test/java/com/iluwatar/compositeentity/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeentity;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** com.iluwatar.compositeentity.App running test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "composite-entity/src/test/java/com/iluwatar/compositeentity/PersistenceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeentity;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass PersistenceTest {\n\n  static final ConsoleCoarseGrainedObject console = new ConsoleCoarseGrainedObject();\n\n  @Test\n  void dependentObjectChangedForPersistenceTest() {\n    MessageDependentObject dependentObject = new MessageDependentObject();\n    console.init();\n    console.dependentObjects[0] = dependentObject;\n    String message = \"Danger\";\n    assertNull(console.dependentObjects[0].getData());\n    dependentObject.setData(message);\n    assertEquals(message, console.dependentObjects[0].getData());\n  }\n\n  @Test\n  void coarseGrainedObjectChangedForPersistenceTest() {\n    MessageDependentObject dependentObject = new MessageDependentObject();\n    console.init();\n    console.dependentObjects[0] = dependentObject;\n    String message = \"Danger\";\n    assertNull(console.dependentObjects[0].getData());\n    console.setData(message);\n    assertEquals(message, dependentObject.getData());\n  }\n}\n"
  },
  {
    "path": "composite-view/README.md",
    "content": "---\ntitle: \"Composite View Pattern in Java: Enhancing UI Consistency Across Applications\"\nshortTitle: Composite View\ndescription: \"Learn about the Composite View design pattern in Java, which helps in managing complex hierarchical views. This guide includes examples, applications, and benefits of using the Composite View pattern.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Abstraction\n  - Enterprise patterns\n  - Object composition\n  - Presentation\n---\n\n## Intent of Composite View Design Pattern\n\nThe primary goal of the Composite View design pattern is to compose objects into tree structures to represent part-whole hierarchies. This allows clients to treat individual objects and compositions of objects uniformly, simplifying the management of complex hierarchical views.\n\n## Detailed Explanation of Composite View Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world example of the Composite View design pattern is the layout of a dashboard in a web application. Consider a financial dashboard that displays various widgets such as stock charts, recent transactions, account balances, and news feeds. Each of these widgets is a separate view component that can be independently updated and managed. By using the Composite View pattern, these individual widgets are composed into a single unified dashboard view. This approach allows for easy reorganization of the dashboard, the addition of new widgets without disrupting existing ones, and consistent management of the overall layout. This hierarchical composition of views mirrors how different sections of the dashboard are treated both as individual entities and as part of a larger whole.\n\nIn plain words\n\n> Composite View Pattern is having a main view being composed of smaller subviews. The layout of this composite view is based on a template. A View-manager then decides which subviews to include in this template.\n\nWikipedia says\n\n> Composite views that are composed of multiple atomic subviews. Each component of the template may be included dynamically into the whole and the layout of the page may be managed independently of the content. This solution provides for the creation of a composite view based on the inclusion and substitution of modular dynamic and static template fragments. It promotes the reuse of atomic portions of the view by encouraging modular design.\n\nFlowchart\n\n![Composite View flowchart](./etc/composite-view-flowchart.png)\n\n## Programmatic Example of Composite View Pattern in Java\n\nA news site wants to display the current date and news to different users based on that user's preferences. The news site will substitute in different news feed components depending on the user's interest, defaulting to local news.\n\nSince this is a web development pattern, a server is required to demonstrate it. This example uses Tomcat 10.0.13 to run the servlet, and this programmatic example will only work with Tomcat 10+.\n\nFirstly, there is `AppServlet` which is an `HttpServlet` that runs on Tomcat 10+.\n\n```java\npublic class AppServlet extends HttpServlet {\n    private String msgPartOne = \"<h1>This Server Doesn't Support\";\n    private String msgPartTwo = \"Requests</h1>\\n\"\n            + \"<h2>Use a GET request with boolean values for the following parameters<h2>\\n\"\n            + \"<h3>'name'</h3>\\n<h3>'bus'</h3>\\n<h3>'sports'</h3>\\n<h3>'sci'</h3>\\n<h3>'world'</h3>\";\n\n    private String destination = \"newsDisplay.jsp\";\n\n    public AppServlet() {\n\n    }\n\n    @Override\n    public void doGet(HttpServletRequest req, HttpServletResponse resp)\n            throws ServletException, IOException {\n        RequestDispatcher requestDispatcher = req.getRequestDispatcher(destination);\n        ClientPropertiesBean reqParams = new ClientPropertiesBean(req);\n        req.setAttribute(\"properties\", reqParams);\n        requestDispatcher.forward(req, resp);\n    }\n\n    @Override\n    public void doPost(HttpServletRequest req, HttpServletResponse resp)\n            throws ServletException, IOException {\n        resp.setContentType(\"text/html\");\n        PrintWriter out = resp.getWriter();\n        out.println(msgPartOne + \" Post \" + msgPartTwo);\n\n    }\n\n    @Override\n    public void doDelete(HttpServletRequest req, HttpServletResponse resp)\n            throws ServletException, IOException {\n        resp.setContentType(\"text/html\");\n        PrintWriter out = resp.getWriter();\n        out.println(msgPartOne + \" Delete \" + msgPartTwo);\n\n    }\n\n    @Override\n    public void doPut(HttpServletRequest req, HttpServletResponse resp)\n            throws ServletException, IOException {\n        resp.setContentType(\"text/html\");\n        PrintWriter out = resp.getWriter();\n        out.println(msgPartOne + \" Put \" + msgPartTwo);\n\n    }\n}\n\n```\n\nThis servlet is not part of the pattern, and simply forwards GET requests to the correct JSP. PUT, POST, and DELETE requests are not supported and will simply show an error message.\n\nThe view management in this example is done via a javabean class: `ClientPropertiesBean`, which stores user preferences.\n\n```java\npublic class ClientPropertiesBean implements Serializable {\n\n    private static final String WORLD_PARAM = \"world\";\n    private static final String SCIENCE_PARAM = \"sci\";\n    private static final String SPORTS_PARAM = \"sport\";\n    private static final String BUSINESS_PARAM = \"bus\";\n    private static final String NAME_PARAM = \"name\";\n\n    private static final String DEFAULT_NAME = \"DEFAULT_NAME\";\n    private boolean worldNewsInterest;\n    private boolean sportsInterest;\n    private boolean businessInterest;\n    private boolean scienceNewsInterest;\n    private String name;\n\n    public ClientPropertiesBean() {\n        worldNewsInterest = true;\n        sportsInterest = true;\n        businessInterest = true;\n        scienceNewsInterest = true;\n        name = DEFAULT_NAME;\n\n    }\n\n    public ClientPropertiesBean(HttpServletRequest req) {\n        worldNewsInterest = Boolean.parseBoolean(req.getParameter(WORLD_PARAM));\n        sportsInterest = Boolean.parseBoolean(req.getParameter(SPORTS_PARAM));\n        businessInterest = Boolean.parseBoolean(req.getParameter(BUSINESS_PARAM));\n        scienceNewsInterest = Boolean.parseBoolean(req.getParameter(SCIENCE_PARAM));\n        String tempName = req.getParameter(NAME_PARAM);\n        if (tempName == null || tempName == \"\") {\n            tempName = DEFAULT_NAME;\n        }\n        name = tempName;\n    }\n    // getters and setters generated by Lombok \n}\n```\n\nThis javabean has a default constructor, and another that takes an `HttpServletRequest`.\n\nThis second constructor takes the request object, parses out the request parameters which contain the user preferences for different types of news.\n\nThe template for the news page is in `newsDisplay.jsp`\n\n```html\n\n<html>\n<head>\n    <style>\n        h1 {\n            text-align: center;\n        }\n\n        h2 {\n            text-align: center;\n        }\n\n        h3 {\n            text-align: center;\n        }\n\n        .centerTable {\n            margin-left: auto;\n            margin-right: auto;\n        }\n\n        table {\n            border: 1px solid black;\n        }\n\n        tr {\n            text-align: center;\n        }\n\n        td {\n            text-align: center;\n        }\n    </style>\n</head>\n<body>\n<%ClientPropertiesBean propertiesBean = (ClientPropertiesBean) request.getAttribute(\"properties\");%>\n<h1>Welcome <%= propertiesBean.getName()%></h1>\n<jsp:include page=\"header.jsp\"></jsp:include>\n<table class=\"centerTable\">\n\n    <tr>\n        <td></td>\n        <% if(propertiesBean.isWorldNewsInterest()) { %>\n        <td><%@include file=\"worldNews.jsp\"%></td>\n        <% } else { %>\n        <td><%@include file=\"localNews.jsp\"%></td>\n        <% } %>\n        <td></td>\n    </tr>\n    <tr>\n        <% if(propertiesBean.isBusinessInterest()) { %>\n        <td><%@include file=\"businessNews.jsp\"%></td>\n        <% } else { %>\n        <td><%@include file=\"localNews.jsp\"%></td>\n        <% } %>\n        <td></td>\n        <% if(propertiesBean.isSportsInterest()) { %>\n        <td><%@include file=\"sportsNews.jsp\"%></td>\n        <% } else { %>\n        <td><%@include file=\"localNews.jsp\"%></td>\n        <% } %>\n    </tr>\n    <tr>\n        <td></td>\n        <% if(propertiesBean.isScienceNewsInterest()) { %>\n        <td><%@include file=\"scienceNews.jsp\"%></td>\n        <% } else { %>\n        <td><%@include file=\"localNews.jsp\"%></td>\n        <% } %>\n        <td></td>\n    </tr>\n</table>\n</body>\n</html>\n```\n\nThis JSP page is the template. It declares a table with three rows, with one component in the first row, two components in the second row, and one component in the third row.\n\nThe scriplets in the file are part of the view management strategy that include different atomic subviews based on the user preferences in the Javabean.\n\nHere are two examples of the mock atomic subviews used in the composite: `businessNews.jsp`\n\n```html\n\n<html>\n<head>\n    <style>\n        h2 {\n            text-align: center;\n        }\n\n        table {\n            border: 1px solid black;\n        }\n\n        tr {\n            text-align: center;\n        }\n\n        td {\n            text-align: center;\n        }\n    </style>\n</head>\n<body>\n<h2>\n    Generic Business News\n</h2>\n<table style=\"margin-right: auto; margin-left: auto\">\n    <tr>\n        <td>Stock prices up across the world</td>\n        <td>New tech companies to invest in</td>\n    </tr>\n    <tr>\n        <td>Industry leaders unveil new project</td>\n        <td>Price fluctuations and what they mean</td>\n    </tr>\n</table>\n</body>\n</html>\n```\n\n`localNews.jsp`\n\n```html\n\n<html>\n<body>\n<div style=\"text-align: center\">\n    <h3>\n        Generic Local News\n    </h3>\n    <ul style=\"list-style-type: none\">\n        <li>\n            Mayoral elections coming up in 2 weeks\n        </li>\n        <li>\n            New parking meter rates downtown coming tomorrow\n        </li>\n        <li>\n            Park renovations to finish by the next year\n        </li>\n        <li>\n            Annual marathon sign ups available online\n        </li>\n    </ul>\n</div>\n</body>\n</html>\n```\n\nThe different subviews such as `worldNews.jsp`, `businessNews.jsp`, etc. are included conditionally based on the request parameters.\n\n**How To Use**\n\nTo try this example, make sure you have Tomcat 10+ installed. Set up your IDE to build a WAR file from the module and deploy that file to the server\n\nIntelliJ:\n\nUnder `Run` and `edit configurations` Make sure Tomcat server is one of the run configurations. Go to the deployment tab, and make sure there is one artifact being built called `composite-view:war exploded`. If not present, add one.\n\nEnsure that the artifact is being built from the content of the `web` directory and the compilation results of the module. Point the output of the artifact to a convenient place. Run the configuration and view the landing page, follow instructions on that page to continue.\n\n## When to Use the Composite View Pattern in Java\n\nUse the Composite View design pattern when:\n\n* You want to represent part-whole hierarchies of objects.\n* You expect that the composite structures might include any new components in the future.\n* You want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly.\n\n## Composite View Pattern Java Tutorials\n\n* [Composite View Design Pattern – Core J2EE Patterns (Dinesh on Java)](https://www.dineshonjava.com/composite-view-design-pattern/)\n\n## Real-World Applications of Composite View Pattern in Java\n\n* Graphical User Interfaces (GUIs) where widgets can contain other widgets (e.g., a window containing panels, buttons, and text fields).\n* Document structures, such as the representation of tables containing rows, which in turn contain cells, all of which can be treated as elements in a unified hierarchy.\n\n## Benefits and Trade-offs of Composite View Pattern\n\nBenefits:\n\n* High flexibility in adding new components: Since composites and leaf nodes are treated uniformly, it's easier to add new kinds of components.\n* Simplified client code: Clients can treat composite structures and individual elements uniformly, reducing the complexity in client code.\n\nTrade-offs:\n\n* Overgeneralization: Designing the system might become more complex if you make everything composite, especially if your application doesn't require it.\n* Difficulty in constraint enforcement: It can be harder to restrict the components of a composite to only certain types.\n\n## Related Java Design Patterns\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): General structural pattern that is the foundation for Composite View, used for treating individual objects and compositions uniformly.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Enhances the behavior of individual views without modifying the underlying view.\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Can be used to manage memory consumption of large numbers of similar view objects.\n* View Helper: Separates the view logic from business logic, aiding in the clean organization and management of view components.\n\n## References and Credits\n\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/3xfntGJ)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/49jpQG3)\n* [Core J2EE Patterns - Composite View (Oracle)](https://www.oracle.com/java/technologies/composite-view.html)\n"
  },
  {
    "path": "composite-view/etc/composite-view.urm.puml",
    "content": "@startuml\npackage com.iluwatar.compositeview {\n  class ClientPropertiesBean {\n    - BUSINESS_PARAM : String {static}\n    - DEFAULT_NAME : String {static}\n    - NAME_PARAM : String {static}\n    - SCIENCE_PARAM : String {static}\n    - SPORTS_PARAM : String {static}\n    - WORLD_PARAM : String {static}\n    - businessInterest : boolean\n    - name : String\n    - scienceNewsInterest : boolean\n    - sportsInterest : boolean\n    - worldNewsInterest : boolean\n    + ClientPropertiesBean()\n    + ClientPropertiesBean(req : HttpServletRequest)\n    + getName() : String\n    + isBusinessInterest() : boolean\n    + isScienceNewsInterest() : boolean\n    + isSportsInterest() : boolean\n    + isWorldNewsInterest() : boolean\n    + setBusinessInterest(businessInterest : boolean)\n    + setName(name : String)\n    + setScienceNewsInterest(scienceNewsInterest : boolean)\n    + setSportsInterest(sportsInterest : boolean)\n    + setWorldNewsInterest(worldNewsInterest : boolean)\n  }\n}\n@enduml"
  },
  {
    "path": "composite-view/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>java-design-patterns</artifactId>\n        <groupId>com.iluwatar</groupId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>composite-view</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>jakarta.servlet</groupId>\n            <artifactId>jakarta.servlet-api</artifactId>\n            <version>6.1.0</version>\n            <scope>compile</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.compositeview.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "composite-view/src/main/java/com/iluwatar/compositeview/AppServlet.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeview;\n\nimport jakarta.servlet.RequestDispatcher;\nimport jakarta.servlet.http.HttpServlet;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport java.io.PrintWriter;\nimport lombok.NoArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/** A servlet object that extends HttpServlet. Runs on Tomcat 10 and handles Http requests */\n@Slf4j\n@NoArgsConstructor\npublic final class AppServlet extends HttpServlet {\n  private static final String CONTENT_TYPE = \"text/html\";\n  private String msgPartOne = \"<h1>This Server Doesn't Support\";\n  private String msgPartTwo =\n      \"\"\"\n          Requests</h1>\n          <h2>Use a GET request with boolean values for the following parameters<h2>\n          <h3>'name'</h3>\n          <h3>'bus'</h3>\n          <h3>'sports'</h3>\n          <h3>'sci'</h3>\n          <h3>'world'</h3>\"\"\";\n\n  private String destination = \"newsDisplay.jsp\";\n\n  @Override\n  public void doGet(HttpServletRequest req, HttpServletResponse resp) {\n    try {\n      RequestDispatcher requestDispatcher = req.getRequestDispatcher(destination);\n      ClientPropertiesBean reqParams = new ClientPropertiesBean(req);\n      req.setAttribute(\"properties\", reqParams);\n      requestDispatcher.forward(req, resp);\n    } catch (Exception e) {\n      LOGGER.error(\"Exception occurred GET request processing \", e);\n    }\n  }\n\n  @Override\n  public void doPost(HttpServletRequest req, HttpServletResponse resp) {\n    resp.setContentType(CONTENT_TYPE);\n    try (PrintWriter out = resp.getWriter()) {\n      out.println(msgPartOne + \" Post \" + msgPartTwo);\n    } catch (Exception e) {\n      LOGGER.error(\"Exception occurred POST request processing \", e);\n    }\n  }\n\n  @Override\n  public void doDelete(HttpServletRequest req, HttpServletResponse resp) {\n    resp.setContentType(CONTENT_TYPE);\n    try (PrintWriter out = resp.getWriter()) {\n      out.println(msgPartOne + \" Delete \" + msgPartTwo);\n    } catch (Exception e) {\n      LOGGER.error(\"Exception occurred DELETE request processing \", e);\n    }\n  }\n\n  @Override\n  public void doPut(HttpServletRequest req, HttpServletResponse resp) {\n    resp.setContentType(CONTENT_TYPE);\n    try (PrintWriter out = resp.getWriter()) {\n      out.println(msgPartOne + \" Put \" + msgPartTwo);\n    } catch (Exception e) {\n      LOGGER.error(\"Exception occurred PUT request processing \", e);\n    }\n  }\n}\n"
  },
  {
    "path": "composite-view/src/main/java/com/iluwatar/compositeview/ClientPropertiesBean.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeview;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.io.Serializable;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n/**\n * A Java beans class that parses a http request and stores parameters. Java beans used in JSP's to\n * dynamically include elements in view. DEFAULT_NAME = a constant, default name to be used for the\n * default constructor worldNewsInterest = whether current request has world news interest\n * sportsInterest = whether current request has a sportsInterest businessInterest = whether current\n * request has a businessInterest scienceNewsInterest = whether current request has a\n * scienceNewsInterest\n */\n@Getter\n@Setter\n@NoArgsConstructor\npublic class ClientPropertiesBean implements Serializable {\n\n  private static final String WORLD_PARAM = \"world\";\n  private static final String SCIENCE_PARAM = \"sci\";\n  private static final String SPORTS_PARAM = \"sport\";\n  private static final String BUSINESS_PARAM = \"bus\";\n  private static final String NAME_PARAM = \"name\";\n\n  private static final String DEFAULT_NAME = \"DEFAULT_NAME\";\n  private boolean worldNewsInterest = true;\n  private boolean sportsInterest = true;\n  private boolean businessInterest = true;\n  private boolean scienceNewsInterest = true;\n  private String name = DEFAULT_NAME;\n\n  /**\n   * Constructor that parses an HttpServletRequest and stores all the request parameters.\n   *\n   * @param req the HttpServletRequest object that is passed in\n   */\n  public ClientPropertiesBean(HttpServletRequest req) {\n    worldNewsInterest = Boolean.parseBoolean(req.getParameter(WORLD_PARAM));\n    sportsInterest = Boolean.parseBoolean(req.getParameter(SPORTS_PARAM));\n    businessInterest = Boolean.parseBoolean(req.getParameter(BUSINESS_PARAM));\n    scienceNewsInterest = Boolean.parseBoolean(req.getParameter(SCIENCE_PARAM));\n    String tempName = req.getParameter(NAME_PARAM);\n    if (tempName == null || tempName.equals(\"\")) {\n      tempName = DEFAULT_NAME;\n    }\n    name = tempName;\n  }\n}\n"
  },
  {
    "path": "composite-view/src/test/java/com/iluwatar/compositeview/AppServletTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeview;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.*;\n\nimport jakarta.servlet.RequestDispatcher;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport org.junit.jupiter.api.Test;\n\nclass AppServletTest {\n\n  private final String msgPartOne = \"<h1>This Server Doesn't Support\";\n  private final String msgPartTwo =\n      \"\"\"\n            Requests</h1>\n            <h2>Use a GET request with boolean values for the following parameters<h2>\n            <h3>'name'</h3>\n            <h3>'bus'</h3>\n            <h3>'sports'</h3>\n            <h3>'sci'</h3>\n            <h3>'world'</h3>\"\"\";\n  private final String destination = \"newsDisplay.jsp\";\n\n  @Test\n  void testDoGet() throws Exception {\n    HttpServletRequest mockReq = mock(HttpServletRequest.class);\n    HttpServletResponse mockResp = mock(HttpServletResponse.class);\n    RequestDispatcher mockDispatcher = mock(RequestDispatcher.class);\n    StringWriter stringWriter = new StringWriter();\n    PrintWriter printWriter = new PrintWriter(stringWriter);\n\n    when(mockResp.getWriter()).thenReturn(printWriter);\n    when(mockReq.getRequestDispatcher(destination)).thenReturn(mockDispatcher);\n\n    AppServlet curServlet = new AppServlet();\n    curServlet.doGet(mockReq, mockResp);\n\n    verify(mockReq, times(1)).getRequestDispatcher(destination);\n    verify(mockDispatcher).forward(mockReq, mockResp);\n  }\n\n  @Test\n  void testDoPost() throws Exception {\n    HttpServletRequest mockReq = mock(HttpServletRequest.class);\n    HttpServletResponse mockResp = mock(HttpServletResponse.class);\n    StringWriter stringWriter = new StringWriter();\n    PrintWriter printWriter = new PrintWriter(stringWriter);\n\n    when(mockResp.getWriter()).thenReturn(printWriter);\n\n    AppServlet curServlet = new AppServlet();\n    curServlet.doPost(mockReq, mockResp);\n    printWriter.flush();\n\n    assertTrue(stringWriter.toString().contains(msgPartOne + \" Post \" + msgPartTwo));\n  }\n\n  @Test\n  void testDoPut() throws Exception {\n    HttpServletRequest mockReq = mock(HttpServletRequest.class);\n    HttpServletResponse mockResp = mock(HttpServletResponse.class);\n    StringWriter stringWriter = new StringWriter();\n    PrintWriter printWriter = new PrintWriter(stringWriter);\n\n    when(mockResp.getWriter()).thenReturn(printWriter);\n\n    AppServlet curServlet = new AppServlet();\n    curServlet.doPut(mockReq, mockResp);\n    printWriter.flush();\n\n    assertTrue(stringWriter.toString().contains(msgPartOne + \" Put \" + msgPartTwo));\n  }\n\n  @Test\n  void testDoDelete() throws Exception {\n    HttpServletRequest mockReq = mock(HttpServletRequest.class);\n    HttpServletResponse mockResp = mock(HttpServletResponse.class);\n    StringWriter stringWriter = new StringWriter();\n    PrintWriter printWriter = new PrintWriter(stringWriter);\n\n    when(mockResp.getWriter()).thenReturn(printWriter);\n\n    AppServlet curServlet = new AppServlet();\n    curServlet.doDelete(mockReq, mockResp);\n    printWriter.flush();\n\n    assertTrue(stringWriter.toString().contains(msgPartOne + \" Delete \" + msgPartTwo));\n  }\n}\n"
  },
  {
    "path": "composite-view/src/test/java/com/iluwatar/compositeview/JavaBeansTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.compositeview;\n\nimport static org.junit.jupiter.api.Assertions.*;\nimport static org.mockito.Mockito.*;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport org.junit.jupiter.api.Test;\n\nclass JavaBeansTest {\n\n  @Test\n  void testDefaultConstructor() {\n    ClientPropertiesBean newBean = new ClientPropertiesBean();\n    assertEquals(\"DEFAULT_NAME\", newBean.getName());\n    assertTrue(newBean.isBusinessInterest());\n    assertTrue(newBean.isScienceNewsInterest());\n    assertTrue(newBean.isSportsInterest());\n    assertTrue(newBean.isWorldNewsInterest());\n  }\n\n  @Test\n  void testNameGetterSetter() {\n    ClientPropertiesBean newBean = new ClientPropertiesBean();\n    assertEquals(\"DEFAULT_NAME\", newBean.getName());\n\n    newBean.setName(\"TEST_NAME_ONE\");\n    assertEquals(\"TEST_NAME_ONE\", newBean.getName());\n  }\n\n  @Test\n  void testBusinessSetterGetter() {\n    ClientPropertiesBean newBean = new ClientPropertiesBean();\n    assertTrue(newBean.isBusinessInterest());\n\n    newBean.setBusinessInterest(false);\n    assertFalse(newBean.isBusinessInterest());\n  }\n\n  @Test\n  void testScienceSetterGetter() {\n    ClientPropertiesBean newBean = new ClientPropertiesBean();\n    assertTrue(newBean.isScienceNewsInterest());\n\n    newBean.setScienceNewsInterest(false);\n    assertFalse(newBean.isScienceNewsInterest());\n  }\n\n  @Test\n  void testSportsSetterGetter() {\n    ClientPropertiesBean newBean = new ClientPropertiesBean();\n    assertTrue(newBean.isSportsInterest());\n\n    newBean.setSportsInterest(false);\n    assertFalse(newBean.isSportsInterest());\n  }\n\n  @Test\n  void testWorldSetterGetter() {\n    ClientPropertiesBean newBean = new ClientPropertiesBean();\n    assertTrue(newBean.isWorldNewsInterest());\n\n    newBean.setWorldNewsInterest(false);\n    assertFalse(newBean.isWorldNewsInterest());\n  }\n\n  @Test\n  void testRequestConstructor() {\n    HttpServletRequest mockReq = mock(HttpServletRequest.class);\n    ClientPropertiesBean newBean = new ClientPropertiesBean(mockReq);\n\n    assertEquals(\"DEFAULT_NAME\", newBean.getName());\n    assertFalse(newBean.isWorldNewsInterest());\n    assertFalse(newBean.isBusinessInterest());\n    assertFalse(newBean.isScienceNewsInterest());\n    assertFalse(newBean.isSportsInterest());\n  }\n}\n"
  },
  {
    "path": "composite-view/web/WEB-INF/web.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd\"\n         version=\"4.0\">\n    <servlet>\n        <servlet-name>appServlet</servlet-name>\n        <servlet-class>com.iluwatar.compositeview.AppServlet</servlet-class>\n    </servlet>\n    <servlet-mapping>\n        <servlet-name>appServlet</servlet-name>\n        <url-pattern>/news</url-pattern>\n    </servlet-mapping>\n</web-app>"
  },
  {
    "path": "composite-view/web/businessNews.jsp",
    "content": "<%--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n--%>\n<%--\n  Created by IntelliJ IDEA.\n  User: Kevin\n  Date: 11/29/2021\n  Time: 2:51 PM\n  To change this template use File | Settings | File Templates.\n--%>\n<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<html>\n    <head>\n        <style>\n            h2 { text-align: center;}\n            table {border: 1px solid black;}\n            tr {text-align: center;}\n            td {text-align: center;}\n        </style>\n    </head>\n    <body>\n        <h2>\n            Generic Business News\n        </h2>\n        <table style=\"margin-right: auto; margin-left: auto\">\n            <tr>\n                <td>Stock prices up across the world</td>\n                <td>New tech companies to invest in</td>\n            </tr>\n            <tr>\n                <td>Industry leaders unveil new project</td>\n                <td>Price fluctuations and what they mean</td>\n            </tr>\n        </table>\n    </body>\n</html>\n"
  },
  {
    "path": "composite-view/web/header.jsp",
    "content": "<%--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n--%>\n<%--\n  Created by IntelliJ IDEA.\n  User: Kevin\n  Date: 11/29/2021\n  Time: 1:28 PM\n  To change this template use File | Settings | File Templates.\n--%>\n<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ page import=\"java.util.Date\"%>\n<html>\n<head>\n    <style>\n        h1 { text-align: center;}\n        h2 { text-align: center;}\n        h3 { text-align: center;}\n        nav {\n            text-align: center;\n            margin-bottom: 20px;\n        }\n        .home-link {\n            padding: 10px 20px;\n            background-color: #007bff;\n            color: white;\n            text-decoration: none;\n            border-radius: 5px;\n        }\n        .home-link:hover {\n            background-color: #0056b3;\n        }\n    </style>\n</head>\n<body>\n    <nav>\n        <!-- Add a Home button that links back to the homepage -->\n        <a href=\"/\" class=\"home-link\">Home</a>\n    </nav>\n\n    <% String todayDateStr = (new Date().toString()); %>\n    <h1>Today's Personalized Frontpage</h1>\n    <h2><%= todayDateStr %></h2>\n</body>\n</html>\n"
  },
  {
    "path": "composite-view/web/index.jsp",
    "content": "<%--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n--%>\n<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<html>\n<head>\n    <title>Composite Patterns Mock News Site</title>\n    <style>\n        body {\n            font-family: Arial, sans-serif;\n            background-color: #f4f4f4;\n            margin: 0;\n            padding: 20px;\n        }\n        h1, h2, h3 {\n            text-align: center;\n            color: #333;\n        }\n        h1 {\n            font-size: 2.5em;\n        }\n        h2 {\n            font-size: 2em;\n            margin-top: 20px;\n        }\n        h3 {\n            font-size: 1.5em;\n            margin-top: 10px;\n        }\n        .parameters {\n            max-width: 600px;\n            margin: 0 auto;\n            background: #fff;\n            padding: 20px;\n            border-radius: 8px;\n            box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n        }\n    </style>\n</head>\n<body>\n    <h1>Welcome To The Composite Patterns Mock News Site</h1>\n    <div class=\"parameters\">\n        <h2>Send a GET request to the \"/news\" path to see the composite view with mock news</h2>\n        <h2>Use the following parameters:</h2>\n        <h3>name: <em>string</em> - Your name to be dynamically displayed</h3>\n        <h3>bus: <em>boolean</em> - Set to true to see mock business news</h3>\n        <h3>world: <em>boolean</em> - Set to true to see mock world news</h3>\n        <h3>sci: <em>boolean</em> - Set to true to see mock science news</h3>\n        <h3>sport: <em>boolean</em> - Set to true to see mock sports news</h3>\n        <h2>Example Request:</h2>\n        <h3>/news?name=John&bus=true&world=false&sci=true&sport=false</h3>\n        <h3>If the request fails, ensure you have the correct parameters and try again.</h3>\n    </div>\n</body>\n</html>\n"
  },
  {
    "path": "composite-view/web/localNews.jsp",
    "content": "<%--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n--%>\n<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<html>\n    <body>\n        <div style=\"text-align: center\">\n            <h3>\n                Generic Local News\n            </h3>\n            <ul style=\"list-style-type: none\">\n                <li>\n                    Mayoral elections coming up in 2 weeks\n                </li>\n                <li>\n                    New parking meter rates downtown coming tomorrow\n                </li>\n                <li>\n                    Park renovations to finish by the next year\n                </li>\n                <li>\n                    Annual marathon sign ups available online\n                </li>\n            </ul>\n        </div>\n    </body>\n</html>\n"
  },
  {
    "path": "composite-view/web/newsDisplay.jsp",
    "content": "<%--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n--%>\n<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%@ page import=\"com.iluwatar.compositeview.ClientPropertiesBean\"%>\n<html>\n<head>\n    <style>\n        h1 { text-align: center;}\n        h2 { text-align: center;}\n        h3 { text-align: center;}\n        .centerTable {\n            margin-left: auto;\n            margin-right: auto;\n        }\n        table {border: 1px solid black;}\n        tr {text-align: center;}\n        td {text-align: center;}\n    </style>\n</head>\n<body>\n    <%ClientPropertiesBean propertiesBean = (ClientPropertiesBean) request.getAttribute(\"properties\");%>\n    <h1>Welcome <%= propertiesBean.getName()%></h1>\n    <jsp:include page=\"header.jsp\"></jsp:include>\n    <table class=\"centerTable\">\n\n        <tr>\n            <td></td>\n            <% if(propertiesBean.isWorldNewsInterest()) { %>\n                <td><%@include file=\"worldNews.jsp\"%></td>\n            <% } else { %>\n                <td><%@include file=\"localNews.jsp\"%></td>\n            <% } %>\n            <td></td>\n        </tr>\n        <tr>\n            <% if(propertiesBean.isBusinessInterest()) { %>\n                <td><%@include file=\"businessNews.jsp\"%></td>\n            <% } else { %>\n                <td><%@include file=\"localNews.jsp\"%></td>\n            <% } %>\n            <td></td>\n            <% if(propertiesBean.isSportsInterest()) { %>\n                <td><%@include file=\"sportsNews.jsp\"%></td>\n            <% } else { %>\n                <td><%@include file=\"localNews.jsp\"%></td>\n            <% } %>\n        </tr>\n        <tr>\n            <td></td>\n            <% if(propertiesBean.isScienceNewsInterest()) { %>\n                <td><%@include file=\"scienceNews.jsp\"%></td>\n            <% } else { %>\n                <td><%@include file=\"localNews.jsp\"%></td>\n            <% } %>\n            <td></td>\n        </tr>\n    </table>\n</body>\n</html>\n"
  },
  {
    "path": "composite-view/web/scienceNews.jsp",
    "content": "<%--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n--%>\n<%--\n  Created by IntelliJ IDEA.\n  User: Kevin\n  Date: 11/29/2021\n  Time: 4:18 PM\n  To change this template use File | Settings | File Templates.\n--%>\n<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<html>\n    <body>\n        <div style=\"text-align: center\">\n            <h3>\n                Generic Science News\n            </h3>\n            <ul>\n                <li>\n                    New model of gravity proposed for dark matter\n                </li>\n                <li>\n                    Genetic modifying technique proved on bacteria\n                </li>\n                <li>\n                    Neurology study maps brain with new precision\n                </li>\n                <li>\n                    Survey of rainforest discovers 15 new species\n                </li>\n                <li>\n                    New signalling pathway for immune system discovered\n                </li>\n            </ul>\n        </div>\n    </body>\n</html>\n"
  },
  {
    "path": "composite-view/web/sportsNews.jsp",
    "content": "<%--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n--%>\n<%--\n  Created by IntelliJ IDEA.\n  User: Kevin\n  Date: 11/29/2021\n  Time: 3:53 PM\n  To change this template use File | Settings | File Templates.\n--%>\n<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<html>\n  <head>\n    <style>\n      h2 { text-align: center;}\n      table {border: 1px solid black;}\n      tr {text-align: center;}\n      td {text-align: center;}\n    </style>\n  </head>\n  <body>\n    <h2>\n      Generic Sports News\n    </h2>\n    <div style=\"margin-left: auto; margin-right: auto; padding: 20px\">\n      International football match delayed due to weather, will be held next week\n    </div>\n    <div style=\"margin-left: auto; margin-right: auto; padding: 20px\">\n      New rising stars in winter sports, ten new athletes that will shake up the scene\n    </div>\n    <div style=\"margin-left: auto; margin-right: auto; padding: 20px\">\n      Biggest upset in basketball history, upstart team sweeps competition\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "composite-view/web/worldNews.jsp",
    "content": "<%--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n--%>\n<%--\n  Created by IntelliJ IDEA.\n  User: Kevin\n  Date: 11/29/2021\n  Time: 2:51 PM\n  To change this template use File | Settings | File Templates.\n--%>\n<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<html>\n<head>\n    <style>\n        h2 { text-align: center;}\n        table {border: 1px solid black;}\n        tr {text-align: center;}\n        td {text-align: center;}\n    </style>\n</head>\n<body>\n    <h2>\n        Generic World News\n    </h2>\n    <table style=\"margin-right: auto; margin-left: auto\">\n        <tr>\n            <td>New trade talks happening at UN on Thursday</td>\n        </tr>\n        <tr>\n            <td>European Union to announce new resolution next week</td>\n        </tr>\n        <tr>\n            <td>UN delivers report on world economic status</td>\n        </tr>\n    </table>\n</body>\n</html>\n"
  },
  {
    "path": "context-object/README.md",
    "content": "---\ntitle: \"Context Object Pattern in Java: Simplifying Access to Contextual Data\"\nshortTitle: Context Object\ndescription: \"Learn about the Context Object pattern in Java Design Patterns. Encapsulate state and behaviors relevant to users or requests to decouple application components from environmental complexities. Explore real-world examples, benefits, and implementation tips.\"\ncategory: Behavioral\nlanguage: en\ntags:\n  - Context\n  - Decoupling\n  - Encapsulation\n  - Session management \n---\n\n## Also known as\n\n* Context\n* Context Encapsulation\n* Context Holder\n* Encapsulate Context\n\n## Intent of Context Object Design Pattern\n\nEncapsulate the context (state and behaviors) relevant to the user or the request being processed to decouple Java application components from the complexities of the environment. This design pattern helps in managing the application's context efficiently.\n\n## Detailed Explanation of Context Object Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a busy airport where multiple services need to access and share passenger information throughout their journey. Instead of each service requesting and passing passenger details separately, the airport uses a \"Passenger Context Object.\" This context object holds all relevant passenger information, such as identity, flight details, and preferences. Various services like check-in, security, boarding, and customer service access this context object to get or update passenger data as needed. This approach ensures consistent and efficient information handling without tightly coupling the services, similar to how the Context Object design pattern works in software.\n\nIn plain words\n\n> Create an object to store and manage context data, and pass this context object wherever needed in the Java application, ensuring decoupled and cleaner code.\n\n[Core J2EE Patterns](http://corej2eepatterns.com/ContextObject.htm) says\n\n> Use a Context Object to encapsulate state in a protocol-independent way to be shared throughout your application.\n\nSequence diagram\n\n![Context Object sequence diagram](./etc/context-object-sequence-diagram.png)\n\n## Programmatic Example of Context Object in Java\n\nIn a multi-layered Java application, different layers such as A, B, and C extract specific information from a shared context. Passing each piece of information individually is inefficient. The Context Object pattern efficiently stores and passes this information, improving the overall performance and maintainability of the Java application.\n\nDefine the data that the `ServiceContext` object contains.\n\n```Java\n@Getter\n@Setter\npublic class ServiceContext {\n\n    String accountService;\n    String sessionService;\n    String searchService;\n}\n```\n\nCreate interface `ServiceContextFactory` to be used in parts of the application for context objects to be created.\n\n```Java\npublic class ServiceContextFactory {\n\n    public static ServiceContext createContext() {\n        return new ServiceContext();\n    }\n}\n```\n\nInstantiate the context object in the first layer. The adjoining layer calls the context in the current layer, which then further structures the object.\n\n```Java\n@Getter\npublic class LayerA {\n\n    private static ServiceContext context;\n\n    public LayerA() {\n        context = ServiceContextFactory.createContext();\n    }\n\n    public void addAccountInfo(String accountService) {\n        context.setACCOUNT_SERVICE(accountService);\n    }\n}\n```\n\n```Java\n@Getter\npublic class LayerB {\n\n    private static ServiceContext context;\n\n    public LayerB(LayerA layerA) {\n        this.context = layerA.getContext();\n    }\n\n    public void addSessionInfo(String sessionService) {\n        context.setSESSION_SERVICE(sessionService);\n    }\n}\n```\n\n```Java\n@Getter\npublic class LayerC {\n\n    public static ServiceContext context;\n\n    public LayerC(LayerB layerB) {\n        this.context = layerB.getContext();\n    }\n\n    public void addSearchInfo(String searchService) {\n        context.setSEARCH_SERVICE(searchService);\n    }\n}\n```\n\nHere is the context object and layers in action.\n\n```Java\n@Slf4j\npublic class App {\n\n    private static final String SERVICE = \"SERVICE\";\n\n    public static void main(String[] args) {\n        //Initiate first layer and add service information into context\n        var layerA = new LayerA();\n        layerA.addAccountInfo(SERVICE);\n\n        logContext(layerA.getContext());\n\n        //Initiate second layer and preserving information retrieved in first layer through passing context object\n        var layerB = new LayerB(layerA);\n        layerB.addSessionInfo(SERVICE);\n\n        logContext(layerB.getContext());\n\n        //Initiate third layer and preserving information retrieved in first and second layer through passing context object\n        var layerC = new LayerC(layerB);\n        layerC.addSearchInfo(SERVICE);\n\n        logContext(layerC.getContext());\n    }\n\n    private static void logContext(ServiceContext context) {\n        LOGGER.info(\"Context = {}\", context);\n    }\n}\n```\n\nProgram output:\n\n```\n08:15:32.134 [main] INFO com.iluwatar.context.object.App -- Context = com.iluwatar.context.object.ServiceContext@5577140b\n08:15:32.136 [main] INFO com.iluwatar.context.object.App -- Context = com.iluwatar.context.object.ServiceContext@5577140b\n08:15:32.137 [main] INFO com.iluwatar.context.object.App -- Context = com.iluwatar.context.object.ServiceContext@5577140b\n```\n\n## When to Use the Context Object Pattern in Java\n\n* When there is a need to abstract and encapsulate context information in a Java application to avoid cluttering the business logic with environment-specific code. This is especially useful in web applications for encapsulating request-specific information and in distributed systems for managing user preferences and security credentials.\n* In web applications, to encapsulate request-specific information and make it easily accessible throughout the application without passing it explicitly between functions or components.\n* In distributed systems, to encapsulate contextual information about the task being performed, user preferences, or security credentials, facilitating their propagation across different components and services.\n\n## Real-World Applications of Context Object Pattern in Java\n\n* Web application frameworks often use the Context Object pattern to encapsulate HTTP request and response objects, session information, and other request-specific data. Enterprise Java applications leverage this pattern to manage and propagate transactional information, security credentials, and user-specific settings across different layers and services.\n* Enterprise applications use Context Objects to manage and propagate transactional information, security credentials, and user-specific settings across different layers and services.\n* [Spring: ApplicationContext](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html)\n* [Oracle: SecurityContext](https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/SecurityContext.html)\n* [Oracle: ServletContext](https://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html)\n\n## Benefits and Trade-offs of Context Object Pattern\n\nBenefits:\n\n* Decoupling: Components and services are decoupled from the specificities of the execution environment, enhancing modularity and maintainability.\n* Centralization: Contextual information is centralized in one place, making it easier to manage, access, and debug.\n* Flexibility: The pattern allows for flexible and dynamic context management, which can adapt to changes in the environment or requirements.\n\nTrade-offs:\n\n* Overhead: Introducing a Context Object can add overhead in terms of performance, especially if not implemented efficiently.\n* Complexity: If the Context Object is not well-designed, it can become a bloated and complex monolith, difficult to manage and understand.\n\n## Related Java Design Patterns\n\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): The Context Object is often implemented as a Singleton to ensure a global point of access.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Context Objects can use Strategies to adapt their behavior based on the context they encapsulate.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Can be used to dynamically add responsibilities to the Context Object.\n\n## References and Credits\n\n* [Core J2EE Design Patterns](https://amzn.to/3IhcY9w)\n* [Context Object (Core J2EE Patterns)](http://corej2eepatterns.com/ContextObject.htm)\n* [The Encapsulate Context Pattern (Accu)](https://accu.org/journals/overload/12/63/kelly_246/)\n* [Context Object - A Design Pattern for Efficient Information Sharing across Multiple System Layers (Arvid S. Krishna et al.)](https://www.dre.vanderbilt.edu/~schmidt/PDF/Context-Object-Pattern.pdf)\n"
  },
  {
    "path": "context-object/etc/context-object.urm.puml",
    "content": "@startuml\npackage com.iluwatar.context.object {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class ServiceContext {\n    - ACCOUNT_SERVICE : String\n    - SESSION_SERVICE : String\n    - SEARCH_SERVICE : String\n    + ServiceContext()\n    + getACCOUNT_SERVICE() : String\n    + getSESSION_SERVICE() : String\n    + getSEARCH_SERVICE() : String\n    + setACCOUNT_SERVICE(service : String)\n    + setSESSION_SERVICE(service : String)\n    + setSEARCH_SERVICE(service : String)\n  }\n  class ServiceContextFactory {\n    + ServiceContextFactory()\n    + createContext() : ServiceContext\n  }\n  class LayerA {\n    - context : ServiceContext\n    + LayerA()\n    + getContext() : ServiceContext\n    + addAccountInfo()\n  }\n  class LayerB {\n    - context : ServiceContext\n    + LayerB(layerA : LayerA)\n    + getContext() : ServiceContext\n    + addAccountInfo()\n  }\n  class LayerC {\n    - context : ServiceContext\n    + LayerC(layerB : LayerB)\n    + getContext() : ServiceContext\n    + addAccountInfo()\n  }\n}\n\nLayerC ..|> LayerB\nServiceContext --> LayerC\nServiceContext --> LayerB\nServiceContext --> LayerA\nServiceContextFactory ..|>  \"<<creates>>\" ServiceContext\nLayerB ..|> LayerA\n@enduml"
  },
  {
    "path": "context-object/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>context-object</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.compositeview.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>"
  },
  {
    "path": "context-object/src/main/java/com/iluwatar/context/object/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.context.object;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * In the context object pattern, information and data from underlying protocol-specific\n * classes/systems is decoupled and stored into a protocol-independent object in an organised\n * format. The pattern ensures the data contained within the context object can be shared and\n * further structured between different layers of a software system.\n *\n * <p>In this example we show how a context object {@link ServiceContext} can be initiated, edited\n * and passed/retrieved in different layers of the program ({@link LayerA}, {@link LayerB}, {@link\n * LayerC}) through use of static methods.\n */\n@Slf4j\npublic class App {\n\n  private static final String SERVICE = \"SERVICE\";\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    // Initiate first layer and add service information into context\n    var layerA = new LayerA();\n    layerA.addAccountInfo(SERVICE);\n\n    logContext(layerA.getContext());\n\n    // Initiate second layer and preserving information retrieved in first layer through passing\n    // context object\n    var layerB = new LayerB(layerA);\n    layerB.addSessionInfo(SERVICE);\n\n    logContext(layerB.getContext());\n\n    // Initiate third layer and preserving information retrieved in first and second layer through\n    // passing context object\n    var layerC = new LayerC(layerB);\n    layerC.addSearchInfo(SERVICE);\n\n    logContext(layerC.getContext());\n  }\n\n  private static void logContext(ServiceContext context) {\n    LOGGER.info(\"Context = {}\", context);\n  }\n}\n"
  },
  {
    "path": "context-object/src/main/java/com/iluwatar/context/object/LayerA.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.context.object;\n\nimport lombok.Getter;\n\n/** Layer A in the context object pattern. */\n@Getter\npublic class LayerA {\n\n  private ServiceContext context;\n\n  public LayerA() {\n    context = ServiceContextFactory.createContext();\n  }\n\n  public void addAccountInfo(String accountService) {\n    context.setAccountService(accountService);\n  }\n}\n"
  },
  {
    "path": "context-object/src/main/java/com/iluwatar/context/object/LayerB.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.context.object;\n\nimport lombok.Getter;\n\n/** Layer B in the context object pattern. */\n@Getter\npublic class LayerB {\n\n  private ServiceContext context;\n\n  public LayerB(LayerA layerA) {\n    this.context = layerA.getContext();\n  }\n\n  public void addSessionInfo(String sessionService) {\n    context.setSessionService(sessionService);\n  }\n}\n"
  },
  {
    "path": "context-object/src/main/java/com/iluwatar/context/object/LayerC.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.context.object;\n\nimport lombok.Getter;\n\n/** Layer C in the context object pattern. */\n@Getter\npublic class LayerC {\n\n  public ServiceContext context;\n\n  public LayerC(LayerB layerB) {\n    this.context = layerB.getContext();\n  }\n\n  public void addSearchInfo(String searchService) {\n    context.setSearchService(searchService);\n  }\n}\n"
  },
  {
    "path": "context-object/src/main/java/com/iluwatar/context/object/ServiceContext.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.context.object;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Where context objects are defined. */\n@Getter\n@Setter\npublic class ServiceContext {\n\n  String accountService;\n  String sessionService;\n  String searchService;\n}\n"
  },
  {
    "path": "context-object/src/main/java/com/iluwatar/context/object/ServiceContextFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.context.object;\n\n/** An interface to create context objects passed through layers. */\npublic class ServiceContextFactory {\n\n  public static ServiceContext createContext() {\n    return new ServiceContext();\n  }\n}\n"
  },
  {
    "path": "context-object/src/test/java/com/iluwatar/contect/object/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.contect.object;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport com.iluwatar.context.object.App;\nimport org.junit.jupiter.api.Test;\n\npublic class AppTest {\n\n  /** Test example app runs without error. */\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "context-object/src/test/java/com/iluwatar/contect/object/ServiceContextTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.contect.object;\n\nimport static org.junit.jupiter.api.Assertions.assertAll;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertSame;\n\nimport com.iluwatar.context.object.LayerA;\nimport com.iluwatar.context.object.LayerB;\nimport com.iluwatar.context.object.LayerC;\nimport com.iluwatar.context.object.ServiceContext;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** ServiceContextTest */\npublic class ServiceContextTest {\n\n  private static final String SERVICE = \"SERVICE\";\n\n  private LayerA layerA;\n\n  @BeforeEach\n  void initiateLayerA() {\n    this.layerA = new LayerA();\n  }\n\n  @Test\n  void testSameContextPassedBetweenLayers() {\n    ServiceContext context1 = layerA.getContext();\n    var layerB = new LayerB(layerA);\n    ServiceContext context2 = layerB.getContext();\n    var layerC = new LayerC(layerB);\n    ServiceContext context3 = layerC.getContext();\n\n    assertSame(context1, context2);\n    assertSame(context2, context3);\n    assertSame(context3, context1);\n  }\n\n  @Test\n  void testScopedDataPassedBetweenLayers() {\n    layerA.addAccountInfo(SERVICE);\n    var layerB = new LayerB(layerA);\n    var layerC = new LayerC(layerB);\n    layerC.addSearchInfo(SERVICE);\n    ServiceContext context = layerC.getContext();\n\n    assertEquals(SERVICE, context.getAccountService());\n    assertNull(context.getSessionService());\n    assertEquals(SERVICE, context.getSearchService());\n  }\n\n  @Test\n  void testLayerContexts() {\n    assertAll(\n        () -> assertNull(layerA.getContext().getAccountService()),\n        () -> assertNull(layerA.getContext().getSearchService()),\n        () -> assertNull(layerA.getContext().getSessionService()));\n    layerA.addAccountInfo(SERVICE);\n    assertAll(\n        () -> assertEquals(SERVICE, layerA.getContext().getAccountService()),\n        () -> assertNull(layerA.getContext().getSearchService()),\n        () -> assertNull(layerA.getContext().getSessionService()));\n    var layerB = new LayerB(layerA);\n    layerB.addSessionInfo(SERVICE);\n    assertAll(\n        () -> assertEquals(SERVICE, layerB.getContext().getAccountService()),\n        () -> assertEquals(SERVICE, layerB.getContext().getSessionService()),\n        () -> assertNull(layerB.getContext().getSearchService()));\n    var layerC = new LayerC(layerB);\n    layerC.addSearchInfo(SERVICE);\n    assertAll(\n        () -> assertEquals(SERVICE, layerC.getContext().getAccountService()),\n        () -> assertEquals(SERVICE, layerC.getContext().getSearchService()),\n        () -> assertEquals(SERVICE, layerC.getContext().getSessionService()));\n  }\n}\n"
  },
  {
    "path": "converter/README.md",
    "content": "---\ntitle: \"Converter Pattern in Java: Streamlining Data Conversion Across Layers\"\nshortTitle: Converter\ndescription: \"Discover the benefits and implementation of the Converter Pattern in Java. Learn how to achieve seamless bidirectional conversion between different data formats, promoting clean code and flexibility in your applications.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Compatibility\n  - Data transformation\n  - Decoupling\n  - Interface\n  - Object mapping\n  - Wrapping\n---\n\n## Also known as\n\n* Mapper\n* Translator\n\n## Intent of Converter Design Pattern\n\nThe purpose of the Converter Pattern is to provide a generic, systematic way of bidirectional conversion between corresponding data types. This allows for a clean, decoupled implementation where types are unaware of each other. Additionally, the Converter pattern supports bidirectional collection mapping, minimizing boilerplate code.\n\n## Detailed Explanation of Converter Pattern with Real-World Examples\n\nReal-world example\n\n> In a real-world scenario, consider a library system that interacts with a third-party book database. The library uses an internal book format, while the third-party database uses a different format. By employing the Converter Pattern, a converter class can transform the third-party book data into the library's format and vice versa. This ensures seamless integration without altering the internal structures of either system.\n\nIn plain words\n\n> The Converter Pattern simplifies mapping instances of one class to instances of another class, ensuring consistent and clean data transformation.\n\nSequence diagram\n\n![Converter sequence diagram](./etc/converter-sequence-diagram.png)\n\n## Programmatic Example of Converter Pattern in Java\n\nIn applications, it's common for the database layer to have entities that need mapping to DTOs (Data Transfer Objects) for business logic. This mapping often involves many classes, necessitating a generic solution.\n\nWe introduce a generic `Converter` class:\n\n```java\npublic class Converter<T, U> {\n\n    private final Function<T, U> fromDto;\n    private final Function<U, T> fromEntity;\n\n    public Converter(final Function<T, U> fromDto, final Function<U, T> fromEntity) {\n        this.fromDto = fromDto;\n        this.fromEntity = fromEntity;\n    }\n\n    public final U convertFromDto(final T dto) {\n        return fromDto.apply(dto);\n    }\n\n    public final T convertFromEntity(final U entity) {\n        return fromEntity.apply(entity);\n    }\n\n    public final List<U> createFromDtos(final Collection<T> dtos) {\n        return dtos.stream().map(this::convertFromDto).collect(Collectors.toList());\n    }\n\n    public final List<T> createFromEntities(final Collection<U> entities) {\n        return entities.stream().map(this::convertFromEntity).collect(Collectors.toList());\n    }\n}\n```\n\nSpecialized converters inherit from this base class:\n\n```java\npublic class UserConverter extends Converter<UserDto, User> {\n\n    public UserConverter() {\n        super(UserConverter::convertToEntity, UserConverter::convertToDto);\n    }\n\n    private static UserDto convertToDto(User user) {\n        return new UserDto(user.firstName(), user.lastName(), user.active(), user.userId());\n    }\n\n    private static User convertToEntity(UserDto dto) {\n        return new User(dto.firstName(), dto.lastName(), dto.active(), dto.email());\n    }\n}\n```\n\nMapping between `User` and `UserDto` becomes straightforward:\n\n```java\n  public static void main(String[] args) {\n    Converter<UserDto, User> userConverter = new UserConverter();\n\n    UserDto dtoUser = new UserDto(\"John\", \"Doe\", true, \"whatever[at]wherever.com\");\n    User user = userConverter.convertFromDto(dtoUser);\n    LOGGER.info(\"Entity converted from DTO: {}\", user);\n\n    var users = List.of(\n            new User(\"Camile\", \"Tough\", false, \"124sad\"),\n            new User(\"Marti\", \"Luther\", true, \"42309fd\"),\n            new User(\"Kate\", \"Smith\", true, \"if0243\")\n    );\n    LOGGER.info(\"Domain entities:\");\n    users.stream().map(User::toString).forEach(LOGGER::info);\n\n    LOGGER.info(\"DTO entities converted from domain:\");\n    List<UserDto> dtoEntities = userConverter.createFromEntities(users);\n    dtoEntities.stream().map(UserDto::toString).forEach(LOGGER::info);\n}\n```\n\nProgram output:\n\n```\n08:28:27.019 [main] INFO com.iluwatar.converter.App -- Entity converted from DTO: User[firstName=John, lastName=Doe, active=true, userId=whatever[at]wherever.com]\n08:28:27.035 [main] INFO com.iluwatar.converter.App -- Domain entities:\n08:28:27.035 [main] INFO com.iluwatar.converter.App -- User[firstName=Camile, lastName=Tough, active=false, userId=124sad]\n08:28:27.035 [main] INFO com.iluwatar.converter.App -- User[firstName=Marti, lastName=Luther, active=true, userId=42309fd]\n08:28:27.035 [main] INFO com.iluwatar.converter.App -- User[firstName=Kate, lastName=Smith, active=true, userId=if0243]\n08:28:27.036 [main] INFO com.iluwatar.converter.App -- DTO entities converted from domain:\n08:28:27.037 [main] INFO com.iluwatar.converter.App -- UserDto[firstName=Camile, lastName=Tough, active=false, email=124sad]\n08:28:27.037 [main] INFO com.iluwatar.converter.App -- UserDto[firstName=Marti, lastName=Luther, active=true, email=42309fd]\n08:28:27.037 [main] INFO com.iluwatar.converter.App -- UserDto[firstName=Kate, lastName=Smith, active=true, email=if0243]\n```\n\n## When to Use the Converter Pattern in Java\n\nUse the Converter Pattern in the following situations:\n\n* When there are types that logically correspond with each other, and there is a need to convert between them.\n* In applications that interact with external systems or services that require data in a specific format.\n* For legacy systems integration where data models differ significantly from newer systems.\n* When aiming to encapsulate conversion logic to promote single responsibility and cleaner code.\n\n## Converter Pattern Java Tutorials\n\n* [Converter Pattern in Java 8 (Boldare)](http://www.xsolve.pl/blog/converter-pattern-in-java-8/)\n\n## Real-World Applications of Converter Pattern in Java\n\n* Data Transfer Objects (DTOs) conversions in multi-layered applications.\n* Adapting third-party data structures or API responses to internal models.\n* ORM (Object-Relational Mapping) frameworks for mapping between database records and domain objects.\n* Microservices architecture for data exchange between different services.\n\n## Benefits and Trade-offs of Converter Pattern\n\nBenefits:\n\n* Separation of Concerns: Encapsulates conversion logic in a single component, keeping the rest of the application unaware of the conversion details.\n* Reusability: Converter components can be reused across the application or even in different applications.\n* Flexibility: Makes it easy to add new conversions without impacting existing code, adhering to the [Open/Closed Principle](https://java-design-patterns.com/principles/#open-closed-principle).\n* Interoperability: Facilitates communication between different systems or application layers by translating data formats.\n\nTrade-offs:\n\n* Overhead: Introducing converters can add complexity and potential performance overhead, especially in systems with numerous data formats.\n* Duplication: There's a risk of duplicating model definitions if not carefully managed, leading to increased maintenance.\n\n## Related Java Design Patterns\n\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): Similar in intent to adapting interfaces, but Converter focuses on data models.\n* [Facade](https://java-design-patterns.com/patterns/facade/): Provides a simplified interface to a complex system, which might involve data conversion.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Converters can use different strategies for conversion, especially when multiple formats are involved.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n"
  },
  {
    "path": "converter/etc/Converter.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.14\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" \n  generalizations=\"true\" realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" \n  router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.converter.Converter\" project=\"converter\" \n    file=\"/converter/src/main/java/com/iluwatar/converter/Converter.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"189\" width=\"226\" x=\"41\" y=\"37\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.converter.UserConverter\" project=\"converter\" \n    file=\"/converter/src/main/java/com/iluwatar/converter/UserConverter.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"81\" width=\"107\" x=\"41\" y=\"356\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.converter.User\" project=\"converter\" \n    file=\"/converter/src/main/java/com/iluwatar/converter/User.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"279\" width=\"188\" x=\"307\" y=\"37\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.converter.UserDto\" project=\"converter\" \n    file=\"/converter/src/main/java/com/iluwatar/converter/UserDto.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"279\" width=\"204\" x=\"535\" y=\"37\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <generalization id=\"5\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "converter/etc/converter.urm.puml",
    "content": "@startuml\npackage com.iluwatar.converter {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Converter<T, U> {\n    - fromDto : Function<T, U>\n    - fromEntity : Function<U, T>\n    + Converter<T, U>(fromDto : Function<T, U>, fromEntity : Function<U, T>)\n    + convertFromDto(dto : T) : U\n    + convertFromEntity(entity : U) : T\n    + createFromDtos(dtos : Collection<T>) : List<U>\n    + createFromEntities(entities : Collection<U>) : List<T>\n  }\n  class User {\n    - firstName : String\n    - isActive : boolean\n    - lastName : String\n    - userId : String\n    + User(firstName : String, lastName : String, isActive : boolean, userId : String)\n    + equals(o : Object) : boolean\n    + getFirstName() : String\n    + getLastName() : String\n    + getUserId() : String\n    + hashCode() : int\n    + isActive() : boolean\n    + toString() : String\n  }\n  class UserConverter {\n    + UserConverter()\n  }\n  class UserDto {\n    - email : String\n    - firstName : String\n    - isActive : boolean\n    - lastName : String\n    + UserDto(firstName : String, lastName : String, isActive : boolean, email : String)\n    + equals(o : Object) : boolean\n    + getEmail() : String\n    + getFirstName() : String\n    + getLastName() : String\n    + hashCode() : int\n    + isActive() : boolean\n    + toString() : String\n  }\n}\nUserConverter --|> Converter \n@enduml"
  },
  {
    "path": "converter/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>converter</artifactId>\n  <modelVersion>4.0.0</modelVersion>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.converter.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "converter/src/main/java/com/iluwatar/converter/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.converter;\n\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Converter pattern is a behavioral design pattern which allows a common way of bidirectional\n * conversion between corresponding types (e.g. DTO and domain representations of the logically\n * isomorphic types). Moreover, the pattern introduces a common way of converting a collection of\n * objects between types.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    Converter<UserDto, User> userConverter = new UserConverter();\n\n    UserDto dtoUser = new UserDto(\"John\", \"Doe\", true, \"whatever[at]wherever.com\");\n    User user = userConverter.convertFromDto(dtoUser);\n    LOGGER.info(\"Entity converted from DTO: {}\", user);\n\n    var users =\n        List.of(\n            new User(\"Camile\", \"Tough\", false, \"124sad\"),\n            new User(\"Marti\", \"Luther\", true, \"42309fd\"),\n            new User(\"Kate\", \"Smith\", true, \"if0243\"));\n    LOGGER.info(\"Domain entities:\");\n    users.stream().map(User::toString).forEach(LOGGER::info);\n\n    LOGGER.info(\"DTO entities converted from domain:\");\n    List<UserDto> dtoEntities = userConverter.createFromEntities(users);\n    dtoEntities.stream().map(UserDto::toString).forEach(LOGGER::info);\n  }\n}\n"
  },
  {
    "path": "converter/src/main/java/com/iluwatar/converter/Converter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.converter;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.function.Function;\nimport lombok.RequiredArgsConstructor;\n\n/**\n * Generic converter, thanks to Java8 features not only provides a way of generic bidirectional\n * conversion between corresponding types, but also a common way of converting a collection of\n * objects of the same type, reducing boilerplate code to the absolute minimum.\n *\n * @param <T> DTO representation's type\n * @param <U> Domain representation's type\n */\n@RequiredArgsConstructor\npublic class Converter<T, U> {\n\n  private final Function<T, U> fromDto;\n  private final Function<U, T> fromEntity;\n\n  /**\n   * Converts DTO to Entity.\n   *\n   * @param dto DTO entity\n   * @return The domain representation - the result of the converting function application on dto\n   *     entity.\n   */\n  public final U convertFromDto(final T dto) {\n    return fromDto.apply(dto);\n  }\n\n  /**\n   * Converts Entity to DTO.\n   *\n   * @param entity domain entity\n   * @return The DTO representation - the result of the converting function application on domain\n   *     entity.\n   */\n  public final T convertFromEntity(final U entity) {\n    return fromEntity.apply(entity);\n  }\n\n  /**\n   * Converts list of DTOs to list of Entities.\n   *\n   * @param dtos collection of DTO entities\n   * @return List of domain representation of provided entities retrieved by mapping each of them\n   *     with the conversion function\n   */\n  public final List<U> createFromDtos(final Collection<T> dtos) {\n    return dtos.stream().map(this::convertFromDto).toList();\n  }\n\n  /**\n   * Converts list of Entities to list of DTOs.\n   *\n   * @param entities collection of domain entities\n   * @return List of domain representation of provided entities retrieved by mapping each of them\n   *     with the conversion function\n   */\n  public final List<T> createFromEntities(final Collection<U> entities) {\n    return entities.stream().map(this::convertFromEntity).toList();\n  }\n}\n"
  },
  {
    "path": "converter/src/main/java/com/iluwatar/converter/User.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.converter;\n\n/** User record. */\npublic record User(String firstName, String lastName, boolean active, String userId) {}\n"
  },
  {
    "path": "converter/src/main/java/com/iluwatar/converter/UserConverter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.converter;\n\n/** Example implementation of the simple User converter. */\npublic class UserConverter extends Converter<UserDto, User> {\n\n  public UserConverter() {\n    super(UserConverter::convertToEntity, UserConverter::convertToDto);\n  }\n\n  private static UserDto convertToDto(User user) {\n    return new UserDto(user.firstName(), user.lastName(), user.active(), user.userId());\n  }\n\n  private static User convertToEntity(UserDto dto) {\n    return new User(dto.firstName(), dto.lastName(), dto.active(), dto.email());\n  }\n}\n"
  },
  {
    "path": "converter/src/main/java/com/iluwatar/converter/UserDto.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.converter;\n\n/** UserDto record. */\npublic record UserDto(String firstName, String lastName, boolean active, String email) {}\n"
  },
  {
    "path": "converter/src/test/java/com/iluwatar/converter/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.converter;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** App running test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "converter/src/test/java/com/iluwatar/converter/ConverterTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.converter;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.List;\nimport java.util.Random;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for {@link Converter} */\nclass ConverterTest {\n\n  private final UserConverter userConverter = new UserConverter();\n\n  /** Tests whether a converter created of opposite functions holds equality as a bijection. */\n  @Test\n  void testConversionsStartingFromDomain() {\n    var u1 = new User(\"Tom\", \"Hanks\", true, \"tom@hanks.com\");\n    var u2 = userConverter.convertFromDto(userConverter.convertFromEntity(u1));\n    assertEquals(u1, u2);\n  }\n\n  /** Tests whether a converter created of opposite functions holds equality as a bijection. */\n  @Test\n  void testConversionsStartingFromDto() {\n    var u1 = new UserDto(\"Tom\", \"Hanks\", true, \"tom@hanks.com\");\n    var u2 = userConverter.convertFromEntity(userConverter.convertFromDto(u1));\n    assertEquals(u1, u2);\n  }\n\n  /**\n   * Tests the custom users converter. Thanks to Java8 lambdas, converter can be easily and cleanly\n   * instantiated allowing various different conversion strategies to be implemented.\n   */\n  @Test\n  void testCustomConverter() {\n    var converter =\n        new Converter<UserDto, User>(\n            userDto ->\n                new User(\n                    userDto.firstName(),\n                    userDto.lastName(),\n                    userDto.active(),\n                    String.valueOf(new Random().nextInt())),\n            user ->\n                new UserDto(\n                    user.firstName(),\n                    user.lastName(),\n                    user.active(),\n                    user.firstName().toLowerCase()\n                        + user.lastName().toLowerCase()\n                        + \"@whatever.com\"));\n    var u1 = new User(\"John\", \"Doe\", false, \"12324\");\n    var userDto = converter.convertFromEntity(u1);\n    assertEquals(\"johndoe@whatever.com\", userDto.email());\n  }\n\n  /**\n   * Test whether converting a collection of Users to DTO Users and then converting them back to\n   * domain users returns an equal collection.\n   */\n  @Test\n  void testCollectionConversion() {\n    var users =\n        List.of(\n            new User(\"Camile\", \"Tough\", false, \"124sad\"),\n            new User(\"Marti\", \"Luther\", true, \"42309fd\"),\n            new User(\"Kate\", \"Smith\", true, \"if0243\"));\n    var fromDtos = userConverter.createFromDtos(userConverter.createFromEntities(users));\n    assertEquals(users, fromDtos);\n  }\n}\n"
  },
  {
    "path": "curiously-recurring-template-pattern/README.md",
    "content": "---\ntitle: \"Curiously Recurring Template Pattern in Java: Leveraging Polymorphism Uniquely\"\nshortTitle: Curiously Recurring Template Pattern (CRTP)\ndescription: \"Discover the Curiously Recurring Template Pattern (CRTP) in Java. Learn how to achieve static polymorphism for efficient method overriding and compile-time polymorphic behavior. Perfect for performance-critical applications.\"\nlanguage: en\ncategory: Structural\ntag:\n  - Code simplification\n  - Extensibility\n  - Generic\n  - Idiom\n  - Instantiation\n  - Polymorphism\n  - Recursion\n---\n\n## Also known as\n\n* CRTP\n* Mixin Inheritance\n* Recursive Type Bound\n* Recursive Generic\n* Static Polymorphism\n\n## Intent of Curiously Recurring Template Pattern\n\nThe Curiously Recurring Template Pattern (CRTP) is a powerful design pattern in Java used to achieve static polymorphism. By having a class template derive from a template instantiation of its own class, CRTP enables method overriding and compile-time polymorphic behavior, enhancing efficiency and performance in your Java applications.\n\n## Detailed Explanation of Curiously Recurring Template Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a scenario where a library system manages various types of media: books, DVDs, and magazines. Each media type has specific attributes and behaviors, but they all share common functionality like borrowing and returning. By applying the Curiously Recurring Template Pattern (CRTP) in Java, you can create a base template class `MediaItem` encompassing these common methods. Each specific media type (e.g., `Book`, `DVD`, `Magazine`) would inherit from `MediaItem` using itself as a template parameter. This approach allows each media type to customize shared functionality efficiently, avoiding the overhead of virtual methods.\n\nIn plain words\n\n> The CRTP in Java ensures that certain methods within a type can accept arguments specific to its subtypes, enabling more efficient and type-safe polymorphic behavior at compile time.\n\nWikipedia says\n\n> The curiously recurring template pattern (CRTP) is an idiom, originally in C++, in which a class X derives from a class template instantiation using X itself as a template argument.\n\nFlowchart\n\n![Curiously Recurring Template Pattern flowchart](./etc/crtp-flowchart.png)\n\n## Programmatic example of CRTP in Java\n\nFor a mixed martial arts promotion that is planning an event, ensuring that the fights are organized between athletes of the same weight class is crucial. This prevents mismatches between fighters of significantly different sizes, such as a heavyweight facing off against a bantamweight.\n\nLet's define the generic interface `Fighter`.\n\n```java\npublic interface Fighter<T> {\n\n    void fight(T t);\n\n}\n```\n\nThe `MMAFighter` class is used to instantiate fighters distinguished by their weight class.\n\n```java\n@Slf4j\n@Data\npublic class MmaFighter<T extends MmaFighter<T>> implements Fighter<T> {\n\n    private final String name;\n    private final String surname;\n    private final String nickName;\n    private final String speciality;\n\n    @Override\n    public void fight(T opponent) {\n        LOGGER.info(\"{} is going to fight against {}\", this, opponent);\n    }\n}\n```\n\nThe followings are some subtypes of `MmaFighter`.\n\n```java\nclass MmaBantamweightFighter extends MmaFighter<MmaBantamweightFighter> {\n\n    public MmaBantamweightFighter(String name, String surname, String nickName, String speciality) {\n        super(name, surname, nickName, speciality);\n    }\n}\n\npublic class MmaHeavyweightFighter extends MmaFighter<MmaHeavyweightFighter> {\n\n    public MmaHeavyweightFighter(String name, String surname, String nickName, String speciality) {\n        super(name, surname, nickName, speciality);\n    }\n}\n```\n\nA fighter is allowed to fight an opponent of the same weight classes. If the opponent is of a different weight class, an error is raised.\n\n```java\npublic static void main(String[] args) {\n\n    MmaBantamweightFighter fighter1 = new MmaBantamweightFighter(\"Joe\", \"Johnson\", \"The Geek\", \"Muay Thai\");\n    MmaBantamweightFighter fighter2 = new MmaBantamweightFighter(\"Ed\", \"Edwards\", \"The Problem Solver\", \"Judo\");\n    fighter1.fight(fighter2);\n\n    MmaHeavyweightFighter fighter3 = new MmaHeavyweightFighter(\"Dave\", \"Davidson\", \"The Bug Smasher\", \"Kickboxing\");\n    MmaHeavyweightFighter fighter4 = new MmaHeavyweightFighter(\"Jack\", \"Jackson\", \"The Pragmatic\", \"Brazilian Jiu-Jitsu\");\n    fighter3.fight(fighter4);\n}\n```\n\nProgram output:\n\n```\n08:42:34.048 [main] INFO crtp.MmaFighter -- MmaFighter(name=Joe, surname=Johnson, nickName=The Geek, speciality=Muay Thai) is going to fight against MmaFighter(name=Ed, surname=Edwards, nickName=The Problem Solver, speciality=Judo)\n08:42:34.054 [main] INFO crtp.MmaFighter -- MmaFighter(name=Dave, surname=Davidson, nickName=The Bug Smasher, speciality=Kickboxing) is going to fight against MmaFighter(name=Jack, surname=Jackson, nickName=The Pragmatic, speciality=Brazilian Jiu-Jitsu)\n```\n\n## When to Use the Curiously Recurring Template Pattern in Java\n\n* When you need to extend the functionality of a class through inheritance but prefer compile-time polymorphism to runtime polymorphism for efficiency reasons.\n* When you want to avoid the overhead of virtual functions but still achieve polymorphic behavior.\n* In template metaprogramming to provide implementations of functions or policies that can be selected at compile time.\n* You have type conflicts when chaining methods in an object hierarchy.\n* You want to use a parameterized class method that can accept subclasses of the class as arguments, allowing it to be applied to objects that inherit from the class.\n* You want certain methods to work only with instances of the same type, such as for achieving mutual comparability.\n\n## Curiously Recurring Template Pattern Java Tutorials\n\n* [Curiously Recurring Template Pattern in Java (The NuaH Blog)](https://nuah.livejournal.com/328187.html)\n\n## Real-World Applications of Curiously Recurring Template Pattern in Java\n\n* Implementing compile-time polymorphic interfaces in template libraries.\n* Enhancing code reuse in libraries where performance is critical, like in mathematical computations, embedded systems, and real-time processing applications.\n* Implementation of the `Cloneable` interface in various Java libraries.\n\n## Benefits and Trade-offs of Curiously Recurring Template Pattern\n\nBenefits:\n\n* Elimination of virtual function call overhead, enhancing performance.\n* Safe reuse of the base class code without the risks associated with multiple inheritances.\n* Greater flexibility and extensibility in compile-time polymorphism scenarios.\n\nTrade-offs:\n\n* Increased complexity in understanding and debugging due to the interplay of templates and inheritance.\n* Can lead to code bloat because each instantiation of a template results in a new class.\n* Less flexibility compared to runtime polymorphism as the behavior must be determined entirely at compile time.\n\n## Related Java Design Patterns\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Can be used in conjunction with CRTP to instantiate derived classes without knowing their specific types.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): CRTP can implement compile-time strategy selection.\n* [Template Method](https://java-design-patterns.com/patterns/template-method/): Similar in structure but differs in that CRTP achieves behavior variation through compile-time polymorphism.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n"
  },
  {
    "path": "curiously-recurring-template-pattern/etc/curiously-recurring-template-pattern.urm.puml",
    "content": "@startuml\n@enduml"
  },
  {
    "path": "curiously-recurring-template-pattern/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>curiously-recurring-template-pattern</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.crtp.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "curiously-recurring-template-pattern/src/main/java/crtp/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage crtp;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Shows the {@link Fighter} fight method call on some implementations of {@link MmaFighter}. Note\n * that fighters can only fight against opponents of their same weight class.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    MmaBantamweightFighter fighter1 =\n        new MmaBantamweightFighter(\"Joe\", \"Johnson\", \"The Geek\", \"Muay Thai\");\n    MmaBantamweightFighter fighter2 =\n        new MmaBantamweightFighter(\"Ed\", \"Edwards\", \"The Problem Solver\", \"Judo\");\n    fighter1.fight(fighter2);\n\n    MmaHeavyweightFighter fighter3 =\n        new MmaHeavyweightFighter(\"Dave\", \"Davidson\", \"The Bug Smasher\", \"Kickboxing\");\n    MmaHeavyweightFighter fighter4 =\n        new MmaHeavyweightFighter(\"Jack\", \"Jackson\", \"The Pragmatic\", \"Brazilian Jiu-Jitsu\");\n    fighter3.fight(fighter4);\n  }\n}\n"
  },
  {
    "path": "curiously-recurring-template-pattern/src/main/java/crtp/Fighter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage crtp;\n\n/**\n * Fighter interface.\n *\n * @param <T> The type of fighter.\n */\npublic interface Fighter<T> {\n\n  void fight(T t);\n}\n"
  },
  {
    "path": "curiously-recurring-template-pattern/src/main/java/crtp/MmaBantamweightFighter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage crtp;\n\n/** MmaBantamweightFighter class. */\nclass MmaBantamweightFighter extends MmaFighter<MmaBantamweightFighter> {\n\n  public MmaBantamweightFighter(String name, String surname, String nickName, String speciality) {\n    super(name, surname, nickName, speciality);\n  }\n}\n"
  },
  {
    "path": "curiously-recurring-template-pattern/src/main/java/crtp/MmaFighter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage crtp;\n\nimport lombok.Data;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * MmaFighter class.\n *\n * @param <T> MmaFighter derived class that uses itself as type parameter.\n */\n@Slf4j\n@Data\npublic class MmaFighter<T extends MmaFighter<T>> implements Fighter<T> {\n\n  private final String name;\n  private final String surname;\n  private final String nickName;\n  private final String speciality;\n\n  @Override\n  public void fight(T opponent) {\n    LOGGER.info(\"{} is going to fight against {}\", this, opponent);\n  }\n}\n"
  },
  {
    "path": "curiously-recurring-template-pattern/src/main/java/crtp/MmaHeavyweightFighter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage crtp;\n\n/** MmaHeavyweightFighter. */\npublic class MmaHeavyweightFighter extends MmaFighter<MmaHeavyweightFighter> {\n\n  public MmaHeavyweightFighter(String name, String surname, String nickName, String speciality) {\n    super(name, surname, nickName, speciality);\n  }\n}\n"
  },
  {
    "path": "curiously-recurring-template-pattern/src/main/java/crtp/MmaLightweightFighter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage crtp;\n\n/** MmaLightweightFighter class. */\nclass MmaLightweightFighter extends MmaFighter<MmaLightweightFighter> {\n\n  public MmaLightweightFighter(String name, String surname, String nickName, String speciality) {\n    super(name, surname, nickName, speciality);\n  }\n}\n"
  },
  {
    "path": "curiously-recurring-template-pattern/src/test/java/crtp/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage crtp;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "curiously-recurring-template-pattern/src/test/java/crtp/FightTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage crtp;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\n\n@Slf4j\npublic class FightTest {\n\n  /**\n   * A fighter has signed a contract with a promotion, and he will face some other fighters. A list\n   * of opponents is ready but for some reason not all of them belong to the same weight class.\n   * Let's ensure that the fighter will only face opponents in the same weight class.\n   */\n  @Test\n  void testFighterCanFightOnlyAgainstSameWeightOpponents() {\n    MmaBantamweightFighter fighter =\n        new MmaBantamweightFighter(\"Joe\", \"Johnson\", \"The Geek\", \"Muay Thai\");\n    List<MmaFighter<?>> opponents = getOpponents();\n    List<MmaFighter<?>> challenged = new ArrayList<>();\n\n    opponents.forEach(\n        challenger -> {\n          try {\n            ((MmaBantamweightFighter) challenger).fight(fighter);\n            challenged.add(challenger);\n          } catch (ClassCastException e) {\n            LOGGER.error(e.getMessage());\n          }\n        });\n\n    assertFalse(challenged.isEmpty());\n    assertTrue(challenged.stream().allMatch(c -> c instanceof MmaBantamweightFighter));\n  }\n\n  private static List<MmaFighter<?>> getOpponents() {\n    return List.of(\n        new MmaBantamweightFighter(\"Ed\", \"Edwards\", \"The Problem Solver\", \"Judo\"),\n        new MmaLightweightFighter(\"Evan\", \"Evans\", \"Clean Coder\", \"Sambo\"),\n        new MmaHeavyweightFighter(\"Dave\", \"Davidson\", \"The Bug Smasher\", \"Kickboxing\"),\n        new MmaBantamweightFighter(\"Ray\", \"Raymond\", \"Scrum Master\", \"Karate\"),\n        new MmaHeavyweightFighter(\"Jack\", \"Jackson\", \"The Pragmatic\", \"Brazilian Jiu-Jitsu\"));\n  }\n}\n"
  },
  {
    "path": "currying/README.md",
    "content": "---\ntitle: \"Currying Pattern in Java: Enhancing Function Flexibility and Reusability\"\nshortTitle: Currying\ndescription: \"Learn about currying in Java, a technique to simplify functions by breaking them into a sequence of single-argument functions. Discover its applications, benefits, and examples in this comprehensive guide.\"\ncategory: Functional\nlanguage: en\ntag:\n  - Code simplification\n  - Functional decomposition\n  - Generic\n  - Immutable\n---\n\n## Also known as\n\n* Partial Function Application\n\n## Intent of Currying Design Pattern\n\nCurrying decomposes a function that takes multiple arguments into a sequence of functions that each take a single argument. This technique is integral in functional programming, enabling the creation of higher-order functions through partial application of its arguments. Using currying in Java can lead to more modular, reusable, and maintainable code.\n\n## Detailed Explanation of Currying Pattern with Real-World Examples\n\nReal-world example\n\n> Currying in programming can be compared to an assembly line in a factory. Imagine a car manufacturing process where each station on the assembly line performs a specific task, such as installing the engine, painting the car, and adding the wheels. Each station takes a partially completed car and performs a single operation before passing it to the next station. Similarly, in currying, a function that requires multiple arguments is broken down into a series of functions, each taking a single argument and returning another function until all arguments are provided. This step-by-step processing simplifies complex tasks by dividing them into manageable, sequential operations, which is especially useful in Java functional programming.\n\nIn plain words\n\n> Decompose a function that take multiple arguments into multiple functions that take a single argument.\n\nWikipedia says\n\n> In mathematics and computer science, currying is the technique of translating a function that takes multiple arguments into a sequence of families of functions, each taking a single argument.\n\nSequence diagram\n\n![Currying sequence diagram](./etc/currying-sequence-diagram.png)\n\n## Programmatic example of Currying Pattern in Java\n\nConsider a librarian who wants to populate their library with books. The librarian wants functions which can create books corresponding to specific genres and authors. Currying makes this possible by writing a curried book builder function and utilising partial application.\n\nWe have a `Book` class and `Genre` enum.\n\n```java\npublic class Book {\n    private final Genre genre;\n    private final String author;\n    private final String title;\n    private final LocalDate publicationDate;\n\n    Book(Genre genre, String author, String title, LocalDate publicationDate) {\n        this.genre = genre;\n        this.author = author;\n        this.title = title;\n        this.publicationDate = publicationDate;\n    }\n}\n```\n\n```java\npublic enum Genre {\n    FANTASY,\n    HORROR,\n    SCI_FI\n}\n```\n\nWe could easily create a `Book` object with the following method:\n\n```java\nBook createBook(Genre genre, String author, String title, LocalDate publicationDate) {\n    return new Book(genre, author, title, publicationDate);\n}\n```\n\nHowever, what if we only wanted to create books from the `FANTASY` genre? Passing the `FANTASY` parameter with each method call would be repetitive. Alternatively, we could define a new method specifically for creating `FANTASY` books, but it would be impractical to create a separate method for each genre. The solution is to use a curried function.\n\n```java\nstatic Function<Genre, Function<String, Function<String, Function<LocalDate, Book>>>> book_creator\n        = bookGenre\n        -> bookAuthor\n        -> bookTitle\n        -> bookPublicationDate\n        -> new Book(bookGenre, bookAuthor, bookTitle, bookPublicationDate);\n```\n\nNote that the order of the parameters is important. `genre` must come before `author`, `author` must come before `title` and so on. We must be considerate of this when writing curried functions to take full advantage of partial application. Using the above function, we can define a new function `fantasyBookFunc`, to generate `FANTASY` books as follows:\n\n```java\nFunction<String, Function<String, Function<LocalDate, Book>>> fantasyBookFunc = Book.book_creator.apply(Genre.FANTASY);\n```\n\nUnfortunately, the type signature of `BOOK_CREATOR` and `fantasyBookFunc` are difficult to read and understand. We can improve this by using the [builder pattern](https://java-design-patterns.com/patterns/builder/) and functional interfaces.\n\n```java\npublic static AddGenre builder() {\n    return genre\n            -> author\n            -> title\n            -> publicationDate\n            -> new Book(genre, author, title, publicationDate);\n}\n\npublic interface AddGenre {\n    Book.AddAuthor withGenre(Genre genre);\n}\n\npublic interface AddAuthor {\n    Book.AddTitle withAuthor(String author);\n}\n\npublic interface AddTitle {\n    Book.AddPublicationDate withTitle(String title);\n}\n\npublic interface AddPublicationDate {\n    Book withPublicationDate(LocalDate publicationDate);\n}\n```\n\nThe semantics of the `builder` function can easily be understood. The `builder` function returns a function `AddGenre`, which adds the genre to the book. Similarity, the `AddGenre` function returns another function `AddTitle`, which adds the title to the book and so on, until the `AddPublicationDate` function returns a `Book`. For example, we could create a `Book` as follows:\n\n```java\nBook book = Book.builder().withGenre(Genre.FANTASY)\n    .withAuthor(\"Author\")\n    .withTitle(\"Title\")\n    .withPublicationDate(LocalDate.of(2000, 7, 2));\n```\n\nThe below example demonstrates how partial application can be used with the `builder` function to create specialised book builder functions.\n\n```java\npublic static void main(String[] args) {\n    LOGGER.info(\"Librarian begins their work.\");\n\n    // Defining genre book functions\n    Book.AddAuthor fantasyBookFunc = Book.builder().withGenre(Genre.FANTASY);\n    Book.AddAuthor horrorBookFunc = Book.builder().withGenre(Genre.HORROR);\n    Book.AddAuthor scifiBookFunc = Book.builder().withGenre(Genre.SCIFI);\n\n    // Defining author book functions\n    Book.AddTitle kingFantasyBooksFunc = fantasyBookFunc.withAuthor(\"Stephen King\");\n    Book.AddTitle kingHorrorBooksFunc = horrorBookFunc.withAuthor(\"Stephen King\");\n    Book.AddTitle rowlingFantasyBooksFunc = fantasyBookFunc.withAuthor(\"J.K. Rowling\");\n\n    // Creates books by Stephen King (horror and fantasy genres)\n    Book shining = kingHorrorBooksFunc.withTitle(\"The Shining\")\n            .withPublicationDate(LocalDate.of(1977, 1, 28));\n    Book darkTower = kingFantasyBooksFunc.withTitle(\"The Dark Tower: Gunslinger\")\n            .withPublicationDate(LocalDate.of(1982, 6, 10));\n\n    // Creates fantasy books by J.K. Rowling\n    Book chamberOfSecrets = rowlingFantasyBooksFunc.withTitle(\"Harry Potter and the Chamber of Secrets\")\n            .withPublicationDate(LocalDate.of(1998, 7, 2));\n\n    // Create sci-fi books\n    Book dune = scifiBookFunc.withAuthor(\"Frank Herbert\")\n            .withTitle(\"Dune\")\n            .withPublicationDate(LocalDate.of(1965, 8, 1));\n    Book foundation = scifiBookFunc.withAuthor(\"Isaac Asimov\")\n            .withTitle(\"Foundation\")\n            .withPublicationDate(LocalDate.of(1942, 5, 1));\n\n    LOGGER.info(\"Stephen King Books:\");\n    LOGGER.info(shining.toString());\n    LOGGER.info(darkTower.toString());\n\n    LOGGER.info(\"J.K. Rowling Books:\");\n    LOGGER.info(chamberOfSecrets.toString());\n\n    LOGGER.info(\"Sci-fi Books:\");\n    LOGGER.info(dune.toString());\n    LOGGER.info(foundation.toString());\n}\n```\n\nProgram output:\n\n```\n09:04:52.499 [main] INFO com.iluwatar.currying.App -- Librarian begins their work.\n09:04:52.502 [main] INFO com.iluwatar.currying.App -- Stephen King Books:\n09:04:52.506 [main] INFO com.iluwatar.currying.App -- Book{genre=HORROR, author='Stephen King', title='The Shining', publicationDate=1977-01-28}\n09:04:52.506 [main] INFO com.iluwatar.currying.App -- Book{genre=FANTASY, author='Stephen King', title='The Dark Tower: Gunslinger', publicationDate=1982-06-10}\n09:04:52.506 [main] INFO com.iluwatar.currying.App -- J.K. Rowling Books:\n09:04:52.506 [main] INFO com.iluwatar.currying.App -- Book{genre=FANTASY, author='J.K. Rowling', title='Harry Potter and the Chamber of Secrets', publicationDate=1998-07-02}\n09:04:52.506 [main] INFO com.iluwatar.currying.App -- Sci-fi Books:\n09:04:52.506 [main] INFO com.iluwatar.currying.App -- Book{genre=SCIFI, author='Frank Herbert', title='Dune', publicationDate=1965-08-01}\n09:04:52.506 [main] INFO com.iluwatar.currying.App -- Book{genre=SCIFI, author='Isaac Asimov', title='Foundation', publicationDate=1942-05-01}\n```\n\n## When to Use the Currying Pattern in Java\n\n* When functions need to be called with some arguments preset in Java.\n* In functional programming languages or paradigms to simplify functions that take multiple arguments.\n* To improve code reusability and composability by breaking down functions into simpler, unary functions, enhancing the modularity of Java applications.\n\n## Currying Pattern Java Tutorials\n\n* [Currying in Java (Baeldung)](https://www.baeldung.com/java-currying)\n* [What Is Currying in Programming (Towards Data Science)](https://towardsdatascience.com/what-is-currying-in-programming-56fd57103431#:~:text=Currying%20is%20helpful%20when%20you,concise%2C%20and%20more%20readable%20solution.)\n* [Why the fudge should I use currying? (DailyJS)](https://medium.com/dailyjs/why-the-fudge-should-i-use-currying-84e4000c8743)\n\n## Real-World Applications of Currying Pattern in Java\n\n* Functional programming languages like Haskell, Scala, and JavaScript.\n* Java programming, especially with lambda expressions and streams introduced in Java 8.\n* Event handling in UIs where a function with specific parameters needs to be triggered upon an event.\n* APIs that require configuration with multiple parameters.\n\n## Benefits and Trade-offs of Currying Pattern\n\nBenefits:\n\n* Increases function reusability by allowing the creation of specialized functions from more generic ones.\n* Enhances code readability and maintainability by breaking complex functions into simpler, single-argument functions.\n* Facilitates function composition, leading to more declarative and concise code.\n\nTrade-offs:\n\n* Can lead to performance overhead due to the creation of additional closures.\n* May make debugging more challenging, as it introduces additional layers of function calls.\n* Can be less intuitive for developers unfamiliar with functional programming concepts.\n* As shown in the programmatic example above, curried functions with several parameters have a cumbersome type signature in Java.\n\n## Related Java Design Patterns\n\n* Function Composition: Currying is often used in conjunction with function composition to enable more readable and concise code.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): While not the same, currying shares the decorator pattern's concept of wrapping functionality.\n* [Factory](https://java-design-patterns.com/patterns/factory/): Currying can be used to create factory functions that produce variations of a function with certain arguments preset.\n\n## References and Credits\n\n* [Functional Programming in Java: Harnessing the Power Of Java 8 Lambda Expressions](https://amzn.to/3TKeZPD)\n* [Java 8 in Action: Lambdas, Streams, and functional-style programming](https://amzn.to/3J6vEaW)\n* [Modern Java in Action: Lambdas, streams, functional and reactive programming](https://amzn.to/3J6vJLM)\n"
  },
  {
    "path": "currying/etc/currying.urm.puml",
    "content": "@startuml\npackage com.iluwatar.currying {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Book {\n    ~ BOOK_CREATOR : Function<Genre, Function<String, Function<String, Function<LocalDate, Book>>>> {static}\n    - author : String\n    - genre : Genre\n    - publicationDate : LocalDate\n    - title : String\n    ~ Book(genre : Genre, author : String, title : String, publicationDate : LocalDate)\n    + builder() : AddGenre {static}\n  }\n  interface AddAuthor {\n    + withAuthor(String) : AddTitle {abstract}\n  }\n  interface AddGenre {\n    + withGenre(Genre) : AddAuthor {abstract}\n  }\n  interface AddPublicationDate {\n    + withPublicationDate(LocalDate) : Book {abstract}\n  }\n  interface AddTitle {\n    + withTitle(String) : AddPublicationDate {abstract}\n  }\n  enum Genre {\n    + FANTASY {static}\n    + HORROR {static}\n    + SCI_FI {static}\n  }\n}\nBook -->  \"-genre\" Genre\nAddPublicationDate ..+ Book\nAddAuthor ..+ Book\nAddTitle ..+ Book\nAddGenre ..+ Book\n@enduml"
  },
  {
    "path": "currying/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>currying</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <!-- Maven assembly plugin is invoked with default setting which we have\n        in parent pom and specifying the class having main method -->\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.currying.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>"
  },
  {
    "path": "currying/src/main/java/com/iluwatar/currying/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.currying;\n\nimport java.time.LocalDate;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Currying decomposes a function with multiple arguments in multiple functions that take a single\n * argument. A curried function which has only been passed some of its arguments is called a partial\n * application. Partial application is useful since it can be used to create specialised functions\n * in a concise way.\n *\n * <p>In this example, a librarian uses a curried book builder function create books belonging to\n * desired genres and written by specific authors.\n */\n@Slf4j\npublic class App {\n  /** Main entry point of the program. */\n  public static void main(String[] args) {\n    LOGGER.info(\"Librarian begins their work.\");\n\n    // Defining genre book functions\n    Book.AddAuthor fantasyBookFunc = Book.builder().withGenre(Genre.FANTASY);\n    Book.AddAuthor horrorBookFunc = Book.builder().withGenre(Genre.HORROR);\n    Book.AddAuthor scifiBookFunc = Book.builder().withGenre(Genre.SCIFI);\n\n    // Defining author book functions\n    Book.AddTitle kingFantasyBooksFunc = fantasyBookFunc.withAuthor(\"Stephen King\");\n    Book.AddTitle kingHorrorBooksFunc = horrorBookFunc.withAuthor(\"Stephen King\");\n    Book.AddTitle rowlingFantasyBooksFunc = fantasyBookFunc.withAuthor(\"J.K. Rowling\");\n\n    // Creates books by Stephen King (horror and fantasy genres)\n    Book shining =\n        kingHorrorBooksFunc.withTitle(\"The Shining\").withPublicationDate(LocalDate.of(1977, 1, 28));\n    Book darkTower =\n        kingFantasyBooksFunc\n            .withTitle(\"The Dark Tower: Gunslinger\")\n            .withPublicationDate(LocalDate.of(1982, 6, 10));\n\n    // Creates fantasy books by J.K. Rowling\n    Book chamberOfSecrets =\n        rowlingFantasyBooksFunc\n            .withTitle(\"Harry Potter and the Chamber of Secrets\")\n            .withPublicationDate(LocalDate.of(1998, 7, 2));\n\n    // Create sci-fi books\n    Book dune =\n        scifiBookFunc\n            .withAuthor(\"Frank Herbert\")\n            .withTitle(\"Dune\")\n            .withPublicationDate(LocalDate.of(1965, 8, 1));\n    Book foundation =\n        scifiBookFunc\n            .withAuthor(\"Isaac Asimov\")\n            .withTitle(\"Foundation\")\n            .withPublicationDate(LocalDate.of(1942, 5, 1));\n\n    LOGGER.info(\"Stephen King Books:\");\n    LOGGER.info(shining.toString());\n    LOGGER.info(darkTower.toString());\n\n    LOGGER.info(\"J.K. Rowling Books:\");\n    LOGGER.info(chamberOfSecrets.toString());\n\n    LOGGER.info(\"Sci-fi Books:\");\n    LOGGER.info(dune.toString());\n    LOGGER.info(foundation.toString());\n  }\n}\n"
  },
  {
    "path": "currying/src/main/java/com/iluwatar/currying/Book.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.currying;\n\nimport java.time.LocalDate;\nimport java.util.Objects;\nimport java.util.function.Function;\nimport lombok.AllArgsConstructor;\n\n/** Book class. */\n@AllArgsConstructor\npublic class Book {\n  private final Genre genre;\n  private final String author;\n  private final String title;\n  private final LocalDate publicationDate;\n\n  @Override\n  public boolean equals(Object o) {\n    if (this == o) {\n      return true;\n    }\n    if (o == null || getClass() != o.getClass()) {\n      return false;\n    }\n    Book book = (Book) o;\n    return Objects.equals(author, book.author)\n        && Objects.equals(genre, book.genre)\n        && Objects.equals(title, book.title)\n        && Objects.equals(publicationDate, book.publicationDate);\n  }\n\n  @Override\n  public int hashCode() {\n    return Objects.hash(author, genre, title, publicationDate);\n  }\n\n  @Override\n  public String toString() {\n    return \"Book{\"\n        + \"genre=\"\n        + genre\n        + \", author='\"\n        + author\n        + '\\''\n        + \", title='\"\n        + title\n        + '\\''\n        + \", publicationDate=\"\n        + publicationDate\n        + '}';\n  }\n\n  /** Curried book builder/creator function. */\n  static Function<Genre, Function<String, Function<String, Function<LocalDate, Book>>>>\n      book_creator =\n          bookGenre ->\n              bookAuthor ->\n                  bookTitle ->\n                      bookPublicationDate ->\n                          new Book(bookGenre, bookAuthor, bookTitle, bookPublicationDate);\n\n  /**\n   * Implements the builder pattern using functional interfaces to create a more readable book\n   * creator function. This function is equivalent to the BOOK_CREATOR function.\n   */\n  public static AddGenre builder() {\n    return genre ->\n        author -> title -> publicationDate -> new Book(genre, author, title, publicationDate);\n  }\n\n  /** Functional interface which adds the genre to a book. */\n  public interface AddGenre {\n    Book.AddAuthor withGenre(Genre genre);\n  }\n\n  /** Functional interface which adds the author to a book. */\n  public interface AddAuthor {\n    Book.AddTitle withAuthor(String author);\n  }\n\n  /** Functional interface which adds the title to a book. */\n  public interface AddTitle {\n    Book.AddPublicationDate withTitle(String title);\n  }\n\n  /** Functional interface which adds the publication date to a book. */\n  public interface AddPublicationDate {\n    Book withPublicationDate(LocalDate publicationDate);\n  }\n}\n"
  },
  {
    "path": "currying/src/main/java/com/iluwatar/currying/Genre.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.currying;\n\n/** Enum representing different book genres. */\npublic enum Genre {\n  FANTASY,\n  HORROR,\n  SCIFI\n}\n"
  },
  {
    "path": "currying/src/test/java/com/iluwatar/currying/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.currying;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that the App can be run without throwing any exceptions. */\nclass AppTest {\n  @Test\n  void executesWithoutExceptions() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "currying/src/test/java/com/iluwatar/currying/BookCurryingTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.currying;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.time.LocalDate;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for the Book class */\nclass BookCurryingTest {\n  private static Book expectedBook;\n\n  @BeforeAll\n  public static void initialiseBook() {\n    expectedBook = new Book(Genre.FANTASY, \"Dave\", \"Into the Night\", LocalDate.of(2002, 4, 7));\n  }\n\n  /** Tests that the expected book can be created via curried functions */\n  @Test\n  void createsExpectedBook() {\n    Book builderCurriedBook =\n        Book.builder()\n            .withGenre(Genre.FANTASY)\n            .withAuthor(\"Dave\")\n            .withTitle(\"Into the Night\")\n            .withPublicationDate(LocalDate.of(2002, 4, 7));\n\n    Book funcCurriedBook =\n        Book.book_creator\n            .apply(Genre.FANTASY)\n            .apply(\"Dave\")\n            .apply(\"Into the Night\")\n            .apply(LocalDate.of(2002, 4, 7));\n\n    assertEquals(expectedBook, builderCurriedBook);\n    assertEquals(expectedBook, funcCurriedBook);\n  }\n\n  /** Tests that an intermediate curried function can be used to create the expected book */\n  @Test\n  void functionCreatesExpectedBook() {\n    Book.AddTitle daveFantasyBookFunc = Book.builder().withGenre(Genre.FANTASY).withAuthor(\"Dave\");\n\n    Book curriedBook =\n        daveFantasyBookFunc\n            .withTitle(\"Into the Night\")\n            .withPublicationDate(LocalDate.of(2002, 4, 7));\n\n    assertEquals(expectedBook, curriedBook);\n  }\n}\n"
  },
  {
    "path": "dao-factory/README.md",
    "content": "---\ntitle: \"DAO Factory Pattern: Flexible Data Access Layer for Seamless Data Source Switching\"\nshortTitle: DAO Factory\ndescription: \"Learn the Data Access Object Pattern combine with Abstract Factory Pattern in Java with real-world examples, class diagrams, and tutorials. Understand its intent, applicability, benefits, and known uses to enhance your design pattern knowledge.\"\ncategory: Structural\nlanguage: en\ntag:\n    - Abstraction\n    - Data access\n    - Layer architecture\n    - Persistence\n---\n\n## Also known as\n\n* DAO Factory\n* Factory for Data Access Object strategy using Abstract Factory\n\n\n## Intent of Data Access Object Factory Design Pattern\n\nThe DAO Factory combines the Data Access Object and Abstract Factory patterns to seperate business logic from data access logic, while increasing flexibility when switching between different data sources.\n\n## Detailed Explanation of Data Access Object Factory Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy for the DAO Factory pattern is a multilingual customer service center. Imagine a bank that serves customers speaking different languages—English, French, and Spanish. When a customer calls, an automated system first detects the customer's preferred language, then routes the call to the appropriate support team that speaks that language. Each team follows the same company policies (standard procedures), but handles interactions in a language-specific way.\n> \n> In the same way, the DAO Factory pattern uses a factory to determine the correct set of DAO implementations based on the data source (e.g., MySQL, MongoDB). Each DAO factory returns a group of DAOs tailored to a specific data source, all conforming to the same interfaces. This allows the application to interact with any supported database in a consistent manner, without changing the business logic—just like how the customer service system handles multiple languages while following the same support protocols.\n\nIn plain words\n\n> The DAO Factory pattern abstracts the creation of Data Access Objects (DAOs), allowing you to request a specific DAO from a central factory without worrying about its underlying implementation. This makes the code easier to maintain and flexible to change, especially when switching between databases or storage mechanisms.\n\nWikipedia says\n\n> The Data Access Object (DAO) design pattern is a structural pattern that provides an abstract interface to some type of database or other persistence mechanism. By mapping application calls to the persistence layer, the DAO provides some specific data operations without exposing details of the database. The DAO Factory is an extension of this concept, responsible for generating the required DAO implementations.\n\nClass diagram\n\n![Data Access Object Factory class diagram](./etc/dao-factory.png \"Data Access Object Factory class diagram\")\n\n## Programmatic Example of Data Access Object Factory in Java\n\nIn this example, the persistence object represents a Customer. \n\nWe are considering a flexible storage strategy where the application should be able to work with three different types of data sources: an H2 in-memory relational database (RDBMS), a MongoDB (object-oriented database), and a JSON flat file (flat file storage).\n\n``` java\npublic enum DataSourceType {\nH2,\nMongo,\nFlatFile\n}\n```\n\nFirst, we define a Customer class that will be persisted in different storage systems. The ID field is generic to maintain compatibility with both relational and object-oriented databases.\n\n``` java\n@Getter\n@Setter\n@NoArgsConstructor\n@AllArgsConstructor\n@ToString\npublic class Customer<T> implements Serializable {\nprivate T id;\nprivate String name;\n}\n```\n\nNext, we define a CustomerDAO interface that outlines the standard CRUD operations on the Customer model. This interface will have three concrete implementations, each corresponding to a specific data source: H2 in-memory database, MongoDB, and JSON file.\n\n``` java\npublic interface CustomerDAO<T> {\n\n  void save(Customer<T> customer);\n  \n  void update(Customer<T> customer);\n  \n  void delete(T id);\n  \n  List<Customer<T>> findAll();\n  \n  Optional<Customer<T>> findById(T id);\n}\n```\n\nHere is the implementations\n\n``` java\n@Slf4j\n@RequiredArgsConstructor\npublic class H2CustomerDAO implements CustomerDAO<Long> {\nprivate final DataSource dataSource;\nprivate final String INSERT_CUSTOMER = \"INSERT INTO customer(id, name) VALUES (?, ?)\";\nprivate final String UPDATE_CUSTOMER = \"UPDATE customer SET name = ? WHERE id = ?\";\nprivate final String DELETE_CUSTOMER = \"DELETE FROM customer WHERE id = ?\";\nprivate final String SELECT_CUSTOMER_BY_ID = \"SELECT * FROM customer WHERE id= ?\";\nprivate final String SELECT_ALL_CUSTOMERS = \"SELECT * FROM customer\";\nprivate final String CREATE_SCHEMA =\n\"CREATE TABLE IF NOT EXISTS customer (id BIGINT PRIMARY KEY, name VARCHAR(255))\";\nprivate final String DROP_SCHEMA = \"DROP TABLE IF EXISTS customer\";\n\n  @Override\n  public void save(Customer<Long> customer) {\n    // Implement operation save for H2\n  }\n\n  @Override\n  public void update(Customer<Long> customer) {\n    // Implement operation save for H2\n  }\n\n  @Override\n  public void delete(Long id) {\n    // Implement operation delete for H2\n  }\n\n  @Override\n  public List<Customer<Long>> findAll() {\n    // Implement operation find all for H2\n  }\n\n  @Override\n  public Optional<Customer<Long>> findById(Long id) {\n    // Implement operation find by id for H2\n  }\n}\n```\n\n``` java\n@Slf4j\n@RequiredArgsConstructor\npublic class MongoCustomerDAO implements CustomerDAO<ObjectId> {\nprivate final MongoCollection<Document> customerCollection;\n\n  // Implement CRUD operation with MongoDB data source\n}\n```\n\n``` java\n@Slf4j\n@RequiredArgsConstructor\npublic class FlatFileCustomerDAO implements CustomerDAO<Long> {\n  private final Path filePath;\n  private final Gson gson;\n  Type customerListType = new TypeToken<List<Customer<Long>>>() {\n  }.getType();\n\n  // Implement CRUD operation with Flat file data source\n}\n```\n\nAfter that, we create an abstract class DAOFactory that defines two key methods: a static method getDataSource() and an abstract method createCustomerDAO().\n\n- The getDataSource() method is a factory selector—it returns a concrete DAOFactory instance based on the type of data source requested.\n\n- Each subclass of DAOFactory will implement the createCustomerDAO() method to provide the corresponding CustomerDAO implementation.\n\n``` java\npublic abstract class DAOFactory {\n  public static DAOFactory getDataSource(DataSourceType dataSourceType) {\n    return switch (dataSourceType) {\n      case H2 -> new H2DataSourceFactory();\n      case Mongo -> new MongoDataSourceFactory();\n      case FlatFile -> new FlatFileDataSourceFactory();\n    };\n  }\n\n  public abstract CustomerDAO createCustomerDAO();\n}\n```\n\nWe then implement three specific factory classes:\n\nH2DataSourceFactory for H2 in-memory RDBMS\n``` java\npublic class H2DataSourceFactory extends DAOFactory {\n  private final String DB_URL = \"jdbc:h2:~/test\";\n  private final String USER = \"sa\";\n  private final String PASS = \"\";\n\n  @Override\n  public CustomerDAO createCustomerDAO() {\n    return new H2CustomerDAO(createDataSource());\n  }\n\n  private DataSource createDataSource() {\n    var dataSource = new JdbcDataSource();\n    dataSource.setURL(DB_URL);\n    dataSource.setUser(USER);\n    dataSource.setPassword(PASS);\n    return dataSource;\n  }\n}\n```\n\nMongoDataSourceFactory for MongoDB\n``` java\npublic class MongoDataSourceFactory extends DAOFactory {\n  private final String CONN_STR = \"mongodb://localhost:27017/\";\n  private final String DB_NAME = \"dao_factory\";\n  private final String COLLECTION_NAME = \"customer\";\n\n  @Override\n  public CustomerDAO createCustomerDAO() {\n    try {\n      MongoClient mongoClient = MongoClients.create(CONN_STR);\n      MongoDatabase database = mongoClient.getDatabase(DB_NAME);\n      MongoCollection<Document> customerCollection = database.getCollection(COLLECTION_NAME);\n      return new MongoCustomerDAO(customerCollection);\n    } catch (RuntimeException e) {\n      throw new RuntimeException(\"Error: \" + e);\n    }\n  }\n}\n```\n\nFlatFileDataSourceFactory for flat file storage using JSON\n``` java\npublic class FlatFileDataSourceFactory extends DAOFactory {\n  private final String FILE_PATH = System.getProperty(\"user.home\") + \"/Desktop/customer.json\";\n  @Override\n  public CustomerDAO createCustomerDAO() {\n    Path filePath = Paths.get(FILE_PATH);\n    Gson gson = new GsonBuilder()\n        .setPrettyPrinting()\n        .serializeNulls()\n        .create();\n    return new FlatFileCustomerDAO(filePath, gson);\n  }\n}\n```\n\nFinally, in the main function of client code, we will demonstrate CRUD operations on the Customer using three data source type.\n``` java\n    // Perform CRUD H2 Database\n    LOGGER.debug(\"H2 - Create customer\");\n    performCreateCustomer(customerDAO,\n        List.of(customerInmemory1, customerInmemory2, customerInmemory3));\n    LOGGER.debug(\"H2 - Update customer\");\n    performUpdateCustomer(customerDAO, customerUpdateInmemory);\n    LOGGER.debug(\"H2 - Delete customer\");\n    performDeleteCustomer(customerDAO, 3L);\n    deleteSchema(customerDAO);\n\n    // Perform CRUD MongoDb\n    daoFactory = DAOFactory.getDataSource(DataSourceType.Mongo);\n    customerDAO = daoFactory.createCustomerDAO();\n    LOGGER.debug(\"Mongo - Create customer\");\n    performCreateCustomer(customerDAO, List.of(customer4, customer5));\n    LOGGER.debug(\"Mongo - Update customer\");\n    performUpdateCustomer(customerDAO, customerUpdateMongo);\n    LOGGER.debug(\"Mongo - Delete customer\");\n    performDeleteCustomer(customerDAO, idCustomerMongo2);\n    deleteSchema(customerDAO);\n\n    // Perform CRUD Flat file\n    daoFactory = DAOFactory.getDataSource(DataSourceType.FlatFile);\n    customerDAO = daoFactory.createCustomerDAO();\n    LOGGER.debug(\"Flat file - Create customer\");\n    performCreateCustomer(customerDAO,\n        List.of(customerFlatFile1, customerFlatFile2, customerFlatFile3));\n    LOGGER.debug(\"Flat file - Update customer\");\n    performUpdateCustomer(customerDAO, customerUpdateFlatFile);\n    LOGGER.debug(\"Flat file - Delete customer\");\n    performDeleteCustomer(customerDAO, 3L);\n    deleteSchema(customerDAO);\n```\n\nThe program output\n``` java\n17:17:24.368 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - H2 - Create customer\n17:17:24.514 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=1, name=Green)\n17:17:24.514 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=2, name=Red)\n17:17:24.514 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=3, name=Blue)\n17:17:24.514 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - H2 - Update customer\n17:17:24.573 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=1, name=Yellow)\n17:17:24.573 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=2, name=Red)\n17:17:24.573 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=3, name=Blue)\n17:17:24.573 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - H2 - Delete customer\n17:17:24.632 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=1, name=Yellow)\n17:17:24.632 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=2, name=Red)\n17:17:24.747 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Mongo - Create customer\n17:17:24.834 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=68173eb4c840286dbc2bc5c1, name=Masca)\n17:17:24.834 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=68173eb4c840286dbc2bc5c2, name=Elliot)\n17:17:24.834 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Mongo - Update customer\n17:17:24.845 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=68173eb4c840286dbc2bc5c1, name=Masca)\n17:17:24.845 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=68173eb4c840286dbc2bc5c2, name=Henry)\n17:17:24.845 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Mongo - Delete customer\n17:17:24.850 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=68173eb4c840286dbc2bc5c1, name=Masca)\n17:17:24.876 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Flat file - Create customer\n17:17:24.895 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=1, name=Duc)\n17:17:24.895 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=2, name=Quang)\n17:17:24.895 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=3, name=Nhat)\n17:17:24.895 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Flat file - Update customer\n17:17:24.897 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=1, name=Thanh)\n17:17:24.897 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=2, name=Quang)\n17:17:24.897 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=3, name=Nhat)\n17:17:24.897 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Flat file - Delete customer\n17:17:24.898 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=1, name=Thanh)\n17:17:24.898 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=2, name=Quang)\n```\n## When to Use the Data Access Object Factory Pattern in Java\n\nUse the DAO Factory Pattern when:\n\n* The application needs to support multiple types of storage (RDBMS, NoSQL, file system, etc.) with minimal changes to business logic.\n* You want to abstract and isolate persistence logic from the core application logic.\n* You aim to make your data access layer pluggable and easy to extend with new storage technologies.\n* You want to enable easier unit testing and dependency injection by providing mock implementations of DAOs.\n* Runtime configuration (e.g., via environment variables or application settings) determines which data source to use.\n\n## Data Access Object Factory Pattern Java Tutorials\n\n* [Core J2EE Patterns - Data Access Object (Oracle)](https://www.oracle.com/java/technologies/dataaccessobject.html)\n* [DAO Factories: Java Design Patterns (Youtube)](https://www.youtube.com/watch?v=5HGe9s9qM-o)\n* [Java Design Patterns and Architecture (CaveofProgramming)](https://caveofprogramming.teachable.com/courses/2084/lectures/39549)\n\n## Real-World Applications of Data Access Object Factory Pattern in Java\n\n* Enterprise Java Applications: Where switching between test, dev, and production databases is common (e.g., MySQL ↔ MongoDB ↔ In-Memory).\n* Spring Data JPA & Repository Abstraction: Though Spring provides its own abstraction, the concept is similar to DAO factory for modular and pluggable persistence.\n* Microservices with Varying Storage Backends: Different microservices might store data in SQL, NoSQL, or even flat files; using a DAO Factory per service ensures consistency.\n* Data Integration Tools: Tools that support importing/exporting from various formats (CSV, JSON, databases) often use DAO factories behind the scenes.\n* Framework-Level Implementations: Custom internal frameworks where persistence layers need to support multiple database types.\n\n## Benefits and Trade-offs of Data Access Object Factory Pattern\n\nBenefits:\n\n* Abstraction of Data Source Logic: Client code interacts only with DAO interfaces, completely decoupled from how and where the data is stored.\n* Flexibility in Persistence Strategy: Easily switch between databases (e.g., H2, MongoDB, flat files) by changing the factory configuration.\n* Improved Maintainability: Storage logic for each data source is encapsulated within its own DAO implementation and factory, making it easier to update or extend.\n* Code Reusability: Common data access logic (e.g., CRUD operations) can be reused across different implementations and projects.\n* Testability: DAOs and factories can be mocked or stubbed easily, which supports unit testing and dependency injection.\n\nTrade-offs:\n* Increased Complexity: Introducing abstract DAOs and multiple factory classes adds structural complexity to the codebase.\n* Boilerplate Code: Requires defining many interfaces and implementations, even for simple data access needs.\n* Less Transparent Behavior: Since clients access DAOs indirectly via factories, understanding the concrete data source behavior may require deeper inspection.\n\n## Related Java Design Patterns\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): DAO Factory is a concrete application of the Factory Pattern, used to create DAO objects in a flexible way.\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): When supporting multiple data sources (e.g., MySQLDAO, OracleDAO), DAO Factory can act as an Abstract Factory.\n* [Data Access Object (DAO)](https://java-design-patterns.com/patterns/data-access-object/): The core pattern managed by DAO Factory, it separates data access logic from business logic.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): DAO Factory is often implemented as a Singleton to ensure only one instance manages DAO creation.\n* [Service Locator](https://java-design-patterns.com/patterns/service-locator/): Can be used alongside DAO Factory to retrieve DAO services efficiently.\n* [Dependency Injection](https://java-design-patterns.com/patterns/dependency-injection/): In frameworks like Spring, DAOs are typically injected into the service layer instead of being retrieved from a factory.\n\n\n## References and Credits\n\n* [DAO Factory - J2EE Design Patterns Book](https://www.oreilly.com/library/view/j2ee-design-patterns/0596004273/re15.html)\n* [DAO Factory patterns with Hibernate](http://www.giuseppeurso.eu/en/dao-factory-patterns-with-hibernate/)\n* [Design Patterns - Java Means DURGA SOFT](https://www.scribd.com/document/407219980/2-DAO-Factory-Design-Pattern)\n* [Generic DAO pattern - Hibernate](https://in.relation.to/2005/09/09/generic-dao-pattern-with-jdk-50/)\n  "
  },
  {
    "path": "dao-factory/etc/dao-factory.puml",
    "content": "@startuml\npackage com.iluwatar.daofactory {\n    class App {\n        {static} void main(String[] args)\n    }\n\n    class Customer<T> {\n        T id\n        String name\n    }\n\n    interface CustomerDAO<ID> {\n        void save(Customer<ID> customer)\n        void update(Customer<ID> customer)\n        void delete(ID id)\n        List<Customer<ID>> findAll()\n        Optional<Customer<ID>> findById(ID id)\n        void deleteSchema()\n    }\n\n    abstract class DAOFactory {\n    {static} DAOFactory getDataSource(DataSourceType dataType)\n    {abstract} CustomerDAO createCustomerDAO()\n    }\n\n    enum DataSourceType {\n        H2\n        Mongo\n        FlatFile\n    }\n\n    class FlatFileCustomerDAO implements CustomerDAO<Long> {\n            void save(Customer<Long> customer)\n            void update(Customer<Long> customer)\n            void delete(Long id)\n            List<Customer<Long>> findAll()\n            Optional<Customer<Long>> findById(Long id)\n            void deleteSchema()\n    }\n\n    class H2CustomerDAO implements CustomerDAO<Long> {\n                    void save(Customer<Long> customer)\n                    void update(Customer<Long> customer)\n                    void delete(Long id)\n                    List<Customer<Long>> findAll()\n                    Optional<Customer<Long>> findById(Long id)\n                    void deleteSchema()\n    }\n\n    class FlatFileDataSourceFactory extends DAOFactory {\n        CustomerDAO createCustomerDAO()\n    }\n\n    class H2DataSourceFactory extends DAOFactory {\n        CustomerDAO createCustomerDAO()\n    }\n\n    class MongoCustomerDAO implements CustomerDAO<ObjectId> {\n                    void save(Customer<ObjectId> customer)\n                    void update(Customer<ObjectId> customer)\n                    void delete(ObjectId id)\n                    List<Customer<ObjectId>> findAll()\n                    Optional<Customer<ObjectId>> findById(ObjectId id)\n                    void deleteSchema()\n    }\n    class MongoDataSourceFactory extends DAOFactory {\n        CustomerDAO createCustomerDAO()\n    }\n\n    DataSourceType ..+ DAOFactory\n    DAOFactory ..+ App\n    App --> Customer\n }\n@enduml"
  },
  {
    "path": "dao-factory/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>dao-factory</artifactId>\n\n    <properties>\n        <maven.compiler.source>21</maven.compiler.source>\n        <maven.compiler.target>21</maven.compiler.target>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n    </properties>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.h2database</groupId>\n            <artifactId>h2</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.mongodb</groupId>\n            <artifactId>mongodb-driver-legacy</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.google.code.gson</groupId>\n            <artifactId>gson</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n</project>"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport java.io.Serializable;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\nimport org.bson.types.ObjectId;\n\n@Slf4j\npublic class App {\n\n  public static void main(String[] args) {\n    var daoFactory = DAOFactoryProvider.getDataSource(DataSourceType.H2);\n    CustomerDAO customerDAO = daoFactory.createCustomerDAO();\n\n    // Perform CRUD H2 Database\n    if (customerDAO instanceof H2CustomerDAO h2CustomerDAO) {\n      h2CustomerDAO.deleteSchema();\n      h2CustomerDAO.createSchema();\n    }\n    Customer<Long> customerInmemory1 = new Customer<>(1L, \"Green\");\n    Customer<Long> customerInmemory2 = new Customer<>(2L, \"Red\");\n    Customer<Long> customerInmemory3 = new Customer<>(3L, \"Blue\");\n    Customer<Long> customerUpdateInmemory = new Customer<>(1L, \"Yellow\");\n\n    LOGGER.debug(\"H2 - Create customer\");\n    performCreateCustomer(\n        customerDAO, List.of(customerInmemory1, customerInmemory2, customerInmemory3));\n    LOGGER.debug(\"H2 - Update customer\");\n    performUpdateCustomer(customerDAO, customerUpdateInmemory);\n    LOGGER.debug(\"H2 - Delete customer\");\n    performDeleteCustomer(customerDAO, 3L);\n    deleteSchema(customerDAO);\n\n    // Perform CRUD MongoDb\n    daoFactory = DAOFactoryProvider.getDataSource(DataSourceType.MONGO);\n    customerDAO = daoFactory.createCustomerDAO();\n    ObjectId idCustomerMongo1 = new ObjectId();\n    ObjectId idCustomerMongo2 = new ObjectId();\n    Customer<ObjectId> customer4 = new Customer<>(idCustomerMongo1, \"Masca\");\n    Customer<ObjectId> customer5 = new Customer<>(idCustomerMongo2, \"Elliot\");\n    Customer<ObjectId> customerUpdateMongo = new Customer<>(idCustomerMongo2, \"Henry\");\n\n    LOGGER.debug(\"Mongo - Create customer\");\n    performCreateCustomer(customerDAO, List.of(customer4, customer5));\n    LOGGER.debug(\"Mongo - Update customer\");\n    performUpdateCustomer(customerDAO, customerUpdateMongo);\n    LOGGER.debug(\"Mongo - Delete customer\");\n    performDeleteCustomer(customerDAO, idCustomerMongo2);\n    deleteSchema(customerDAO);\n\n    // Perform CRUD Flat file\n    daoFactory = DAOFactoryProvider.getDataSource(DataSourceType.FLAT_FILE);\n    customerDAO = daoFactory.createCustomerDAO();\n    Customer<Long> customerFlatFile1 = new Customer<>(1L, \"Duc\");\n    Customer<Long> customerFlatFile2 = new Customer<>(2L, \"Quang\");\n    Customer<Long> customerFlatFile3 = new Customer<>(3L, \"Nhat\");\n    Customer<Long> customerUpdateFlatFile = new Customer<>(1L, \"Thanh\");\n    LOGGER.debug(\"Flat file - Create customer\");\n    performCreateCustomer(\n        customerDAO, List.of(customerFlatFile1, customerFlatFile2, customerFlatFile3));\n    LOGGER.debug(\"Flat file - Update customer\");\n    performUpdateCustomer(customerDAO, customerUpdateFlatFile);\n    LOGGER.debug(\"Flat file - Delete customer\");\n    performDeleteCustomer(customerDAO, 3L);\n    deleteSchema(customerDAO);\n  }\n\n  public static void deleteSchema(CustomerDAO customerDAO) {\n    customerDAO.deleteSchema();\n  }\n\n  public static <T extends Serializable> void performCreateCustomer(\n      CustomerDAO<T> customerDAO, List<Customer<T>> customerList) {\n    for (Customer<T> customer : customerList) {\n      customerDAO.save(customer);\n    }\n    List<Customer<T>> customers = customerDAO.findAll();\n    for (Customer<T> customer : customers) {\n      LOGGER.debug(customer.toString());\n    }\n  }\n\n  public static <T extends Serializable> void performUpdateCustomer(\n      CustomerDAO<T> customerDAO, Customer<T> customerUpdate) {\n    customerDAO.update(customerUpdate);\n    List<Customer<T>> customers = customerDAO.findAll();\n    for (Customer<T> customer : customers) {\n      LOGGER.debug(customer.toString());\n    }\n  }\n\n  public static <T extends Serializable> void performDeleteCustomer(\n      CustomerDAO<T> customerDAO, T customerId) {\n    customerDAO.delete(customerId);\n    List<Customer<T>> customers = customerDAO.findAll();\n    for (Customer<T> customer : customers) {\n      LOGGER.debug(customer.toString());\n    }\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/CustomException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\n/** Customer exception */\npublic class CustomException extends RuntimeException {\n  public CustomException(String message) {\n    super(message);\n  }\n\n  public CustomException(String message, Throwable cause) {\n    super(message, cause);\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/Customer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport java.io.Serializable;\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\nimport lombok.ToString;\n\n/**\n * A customer generic POJO that represents the data that can be stored in any supported data source.\n * This class is designed t work with various ID types (e.g., Long, String, or ObjectId) through\n * generic, making it adaptable to different persistence system.\n */\n@Getter\n@Setter\n@NoArgsConstructor\n@AllArgsConstructor\n@ToString\npublic class Customer<T extends Serializable> implements Serializable {\n  private T id;\n  private String name;\n}\n"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/CustomerDAO.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport java.io.Serializable;\nimport java.util.List;\nimport java.util.Optional;\n\n/**\n * The Data Access Object (DAO) pattern provides an abstraction layer between the application and\n * the database. It encapsulates data access logic, allowing the application to work with domain\n * objects instead of direct database operations.\n *\n * <p>Implementations handle specific storage mechanisms (e.g., in-memory, databases) while keeping\n * client code unchanged.\n *\n * @see H2CustomerDAO\n * @see MongoCustomerDAO\n * @see FlatFileCustomerDAO\n */\npublic interface CustomerDAO<T extends Serializable> {\n  /**\n   * Persist the given customer\n   *\n   * @param customer the customer to persist\n   */\n  void save(Customer<T> customer);\n\n  /**\n   * Update the given customer\n   *\n   * @param customer the customer to update\n   */\n  void update(Customer<T> customer);\n\n  /**\n   * Delete the customer with the given id\n   *\n   * @param id the id of the customer to delete\n   */\n  void delete(T id);\n\n  /**\n   * Find all customers\n   *\n   * @return a list of customers\n   */\n  List<Customer<T>> findAll();\n\n  /**\n   * Find the customer with the given id\n   *\n   * @param id the id of the customer to find\n   * @return the customer with the given id\n   */\n  Optional<Customer<T>> findById(T id);\n\n  /**\n   * Delete the customer schema. After executing the statements, this function will be called to\n   * clean up the data and delete the records.\n   */\n  void deleteSchema();\n}\n"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/DAOFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\n/**\n * An abstract factory class that provides a way to create concrete DAO (Data Access Object)\n * factories for different data sources types (e.g., H2, Mongo, FlatFile).\n *\n * <p>This class follows the Abstract Factory design pattern, allowing applications to retrieve the\n * approriate DAO implementation without being tightly coupled to a specific data source.\n *\n * @see H2DataSourceFactory\n * @see MongoDataSourceFactory\n * @see FlatFileDataSourceFactory\n */\npublic abstract class DAOFactory {\n  /**\n   * Retrieves a {@link CustomerDAO} implementation specific to the underlying data source..\n   *\n   * @return A data source-specific implementation of {@link CustomerDAO}\n   */\n  public abstract CustomerDAO createCustomerDAO();\n}\n"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/DAOFactoryProvider.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\n/**\n * {@code DAOFactoryProvider} is a utility class responsible for providing concrete implementations\n * of the {@link DAOFactory} interface based on the specified data source type.\n *\n * <p>This class acts as an entry point to obtain DAO factories for different storage mechanisms\n * such as relational databases (e.g., H2), document stores (e.g., MongoDB), or file-based systems.\n * It uses the {@link DataSourceType} enumeration to determine which concrete factory to\n * instantiate.\n *\n * <p>Example usage:\n *\n * <pre>{@code\n * DAOFactory factory = DAOFactoryProvider.getDataSource(DataSourceType.H2);\n * }</pre>\n */\npublic class DAOFactoryProvider {\n\n  private DAOFactoryProvider() {}\n\n  /**\n   * Returns a concrete {@link DAOFactory} intance based on the specified data source type.\n   *\n   * @param dataSourceType The type of data source for which a factory is needed. Supported values:\n   *     {@code H2}, {@code Mongo}, {@code FlatFile}\n   * @return A {@link DAOFactory} implementation corresponding to the given data source type.\n   * @throws IllegalArgumentException if the given data source type is not supported.\n   */\n  public static DAOFactory getDataSource(DataSourceType dataSourceType) {\n    return switch (dataSourceType) {\n      case H2 -> new H2DataSourceFactory();\n      case MONGO -> new MongoDataSourceFactory();\n      case FLAT_FILE -> new FlatFileDataSourceFactory();\n      default -> throw new IllegalArgumentException(\"Unsupported data source type\");\n    };\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/DataSourceType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\n/** Enumerates the types of data sources supported by the application. */\npublic enum DataSourceType {\n  H2,\n  MONGO,\n  FLAT_FILE\n}\n"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/FlatFileCustomerDAO.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\nimport java.io.FileReader;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.lang.reflect.Type;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Optional;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * A Flat File implementation of {@link CustomerDAO}, which store the customer data in a JSON file\n * at path {@code ~/Desktop/customer.json}.\n */\n@Slf4j\n@RequiredArgsConstructor\npublic class FlatFileCustomerDAO implements CustomerDAO<Long> {\n  private final Path filePath;\n  private final Gson gson;\n  Type customerListType = new TypeToken<List<Customer<Long>>>() {}.getType();\n\n  protected Reader createReader(Path filePath) throws IOException {\n    return new FileReader(filePath.toFile());\n  }\n\n  protected Writer createWriter(Path filePath) throws IOException {\n    return new FileWriter(filePath.toFile());\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public void save(Customer<Long> customer) {\n    List<Customer<Long>> customers = new LinkedList<>();\n    if (filePath.toFile().exists()) {\n      try (Reader reader = createReader(filePath)) {\n        customers = gson.fromJson(reader, customerListType);\n      } catch (IOException ex) {\n        throw new CustomException(\"Failed to read customer data\", ex);\n      }\n    }\n    customers.add(customer);\n    try (Writer writer = createWriter(filePath)) {\n      gson.toJson(customers, writer);\n    } catch (IOException ex) {\n      throw new CustomException(\"Failed to write customer data\", ex);\n    }\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public void update(Customer<Long> customer) {\n    if (!filePath.toFile().exists()) {\n      throw new CustomException(\"File not found\");\n    }\n    List<Customer<Long>> customers;\n    try (Reader reader = createReader(filePath)) {\n      customers = gson.fromJson(reader, customerListType);\n    } catch (IOException ex) {\n      throw new CustomException(\"Failed to read customer data\", ex);\n    }\n    customers.stream()\n        .filter(c -> c.getId().equals(customer.getId()))\n        .findFirst()\n        .ifPresentOrElse(\n            c -> c.setName(customer.getName()),\n            () -> {\n              throw new CustomException(\"Customer not found with id: \" + customer.getId());\n            });\n    try (Writer writer = createWriter(filePath)) {\n      gson.toJson(customers, writer);\n    } catch (IOException ex) {\n      throw new CustomException(\"Failed to write customer data\", ex);\n    }\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public void delete(Long id) {\n    if (!filePath.toFile().exists()) {\n      throw new CustomException(\"File not found\");\n    }\n    List<Customer<Long>> customers;\n    try (Reader reader = createReader(filePath)) {\n      customers = gson.fromJson(reader, customerListType);\n    } catch (IOException ex) {\n      throw new CustomException(\"Failed to read customer data\", ex);\n    }\n    Customer<Long> customerToRemove =\n        customers.stream()\n            .filter(c -> c.getId().equals(id))\n            .findFirst()\n            .orElseThrow(() -> new CustomException(\"Customer not found with id: \" + id));\n    customers.remove(customerToRemove);\n    try (Writer writer = createWriter(filePath)) {\n      gson.toJson(customers, writer);\n    } catch (IOException ex) {\n      throw new CustomException(\"Failed to write customer data\", ex);\n    }\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public List<Customer<Long>> findAll() {\n    if (!filePath.toFile().exists()) {\n      throw new CustomException(\"File not found\");\n    }\n    List<Customer<Long>> customers;\n    try (Reader reader = createReader(filePath)) {\n      customers = gson.fromJson(reader, customerListType);\n    } catch (IOException ex) {\n      throw new CustomException(\"Failed to read customer data\", ex);\n    }\n    return customers;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public Optional<Customer<Long>> findById(Long id) {\n    if (!filePath.toFile().exists()) {\n      throw new CustomException(\"File not found\");\n    }\n    List<Customer<Long>> customers = null;\n    try (Reader reader = createReader(filePath)) {\n      customers = gson.fromJson(reader, customerListType);\n    } catch (IOException ex) {\n      throw new CustomException(\"Failed to read customer data\", ex);\n    }\n    return customers.stream().filter(c -> c.getId().equals(id)).findFirst();\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public void deleteSchema() {\n    if (!filePath.toFile().exists()) {\n      throw new CustomException(\"File not found\");\n    }\n    try {\n      Files.delete(filePath);\n    } catch (IOException ex) {\n      throw new CustomException(\"Failed to delete customer data\");\n    }\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/FlatFileDataSourceFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport com.google.gson.Gson;\nimport com.google.gson.GsonBuilder;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\n\n/** FlatFileDataSourceFactory concrete factory. */\npublic class FlatFileDataSourceFactory extends DAOFactory {\n  private static final String FILE_PATH =\n      System.getProperty(\"user.home\") + \"/Desktop/customer.json\";\n\n  @Override\n  public CustomerDAO<Long> createCustomerDAO() {\n    Path filePath = Paths.get(FILE_PATH);\n    Gson gson = new GsonBuilder().setPrettyPrinting().serializeNulls().create();\n    return new FlatFileCustomerDAO(filePath, gson);\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/H2CustomerDAO.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Statement;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Optional;\nimport javax.sql.DataSource;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * An implementation of {@link CustomerDAO} that uses H2 database (http://www.h2database.com/) which\n * is an in-memory database and data will lost after application exits.\n */\n@Slf4j\n@RequiredArgsConstructor\npublic class H2CustomerDAO implements CustomerDAO<Long> {\n  private final DataSource dataSource;\n  private static final String INSERT_CUSTOMER = \"INSERT INTO customer(id, name) VALUES (?, ?)\";\n  private static final String UPDATE_CUSTOMER = \"UPDATE customer SET name = ? WHERE id = ?\";\n  private static final String DELETE_CUSTOMER = \"DELETE FROM customer WHERE id = ?\";\n  private static final String SELECT_CUSTOMER_BY_ID =\n      \"SELECT customer.id, customer.name FROM customer WHERE id= ?\";\n  private static final String SELECT_ALL_CUSTOMERS = \"SELECT customer.* FROM customer\";\n  private static final String CREATE_SCHEMA =\n      \"CREATE TABLE IF NOT EXISTS customer (id BIGINT PRIMARY KEY, name VARCHAR(255))\";\n  private static final String DROP_SCHEMA = \"DROP TABLE IF EXISTS customer\";\n\n  /** {@inheritDoc} */\n  @Override\n  public void save(Customer<Long> customer) {\n    try (Connection connection = dataSource.getConnection();\n        PreparedStatement saveStatement = connection.prepareStatement(INSERT_CUSTOMER)) {\n      saveStatement.setLong(1, customer.getId());\n      saveStatement.setString(2, customer.getName());\n      saveStatement.execute();\n    } catch (SQLException e) {\n      throw new CustomException(e.getMessage(), e);\n    }\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public void update(Customer<Long> customer) {\n    if (Objects.isNull(customer) || Objects.isNull(customer.getId())) {\n      throw new CustomException(\"Custome null or customer id null\");\n    }\n    try (Connection connection = dataSource.getConnection();\n        PreparedStatement selectStatement = connection.prepareStatement(SELECT_CUSTOMER_BY_ID);\n        PreparedStatement updateStatement = connection.prepareStatement(UPDATE_CUSTOMER)) {\n      selectStatement.setLong(1, customer.getId());\n      try (ResultSet resultSet = selectStatement.executeQuery()) {\n        if (!resultSet.next()) {\n          throw new CustomException(\"Customer not found with id: \" + customer.getId());\n        }\n      }\n      updateStatement.setString(1, customer.getName());\n      updateStatement.setLong(2, customer.getId());\n      updateStatement.executeUpdate();\n    } catch (SQLException e) {\n      throw new CustomException(e.getMessage(), e);\n    }\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public void delete(Long id) {\n    if (Objects.isNull(id)) {\n      throw new CustomException(\"Customer id null\");\n    }\n    try (Connection connection = dataSource.getConnection();\n        PreparedStatement selectStatement = connection.prepareStatement(SELECT_CUSTOMER_BY_ID);\n        PreparedStatement deleteStatement = connection.prepareStatement(DELETE_CUSTOMER)) {\n      selectStatement.setLong(1, id);\n      try (ResultSet resultSet = selectStatement.executeQuery()) {\n        if (!resultSet.next()) {\n          throw new CustomException(\"Customer not found with id: \" + id);\n        }\n      }\n      deleteStatement.setLong(1, id);\n      deleteStatement.execute();\n    } catch (SQLException e) {\n      throw new CustomException(e.getMessage(), e);\n    }\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public List<Customer<Long>> findAll() {\n    List<Customer<Long>> customers = new LinkedList<>();\n    try (Connection connection = dataSource.getConnection();\n        PreparedStatement selectStatement = connection.prepareStatement(SELECT_ALL_CUSTOMERS)) {\n      try (ResultSet resultSet = selectStatement.executeQuery()) {\n        while (resultSet.next()) {\n          Long idCustomer = resultSet.getLong(\"id\");\n          String nameCustomer = resultSet.getString(\"name\");\n          customers.add(new Customer<>(idCustomer, nameCustomer));\n        }\n      }\n    } catch (SQLException e) {\n      throw new CustomException(e.getMessage(), e);\n    }\n    return customers;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public Optional<Customer<Long>> findById(Long id) {\n    if (Objects.isNull(id)) {\n      throw new CustomException(\"Customer id null\");\n    }\n    Customer<Long> customer = null;\n    try (Connection connection = dataSource.getConnection();\n        PreparedStatement selectByIdStatement =\n            connection.prepareStatement(SELECT_CUSTOMER_BY_ID)) {\n      selectByIdStatement.setLong(1, id);\n      try (ResultSet resultSet = selectByIdStatement.executeQuery()) {\n        while (resultSet.next()) {\n          Long idCustomer = resultSet.getLong(\"id\");\n          String nameCustomer = resultSet.getString(\"name\");\n          customer = new Customer<>(idCustomer, nameCustomer);\n        }\n      }\n    } catch (SQLException e) {\n      throw new CustomException(e.getMessage(), e);\n    }\n    return Optional.ofNullable(customer);\n  }\n\n  /** Create customer schema. */\n  public void createSchema() {\n    try (Connection connection = dataSource.getConnection();\n        Statement statement = connection.createStatement()) {\n      statement.execute(CREATE_SCHEMA);\n    } catch (SQLException e) {\n      throw new CustomException(e.getMessage(), e);\n    }\n  }\n\n  /** {@inheritDoc}} */\n  @Override\n  public void deleteSchema() {\n    try (Connection connection = dataSource.getConnection();\n        Statement statement = connection.createStatement(); ) {\n      statement.execute(DROP_SCHEMA);\n    } catch (SQLException e) {\n      throw new CustomException(e.getMessage(), e);\n    }\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/H2DataSourceFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport javax.sql.DataSource;\nimport org.h2.jdbcx.JdbcDataSource;\n\n/** H2DataSourceFactory concrete factory. */\npublic class H2DataSourceFactory extends DAOFactory {\n  private static final String DB_URL = \"jdbc:h2:mem:test;DB_CLOSE_DELAY=-1\";\n  private static final String USER = \"sa\";\n  private static final String PASS = \"\";\n\n  @Override\n  public CustomerDAO createCustomerDAO() {\n    return new H2CustomerDAO(createDataSource());\n  }\n\n  private DataSource createDataSource() {\n    var dataSource = new JdbcDataSource();\n    dataSource.setURL(DB_URL);\n    dataSource.setUser(USER);\n    dataSource.setPassword(PASS);\n    return dataSource;\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/MongoCustomerDAO.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport com.mongodb.client.FindIterable;\nimport com.mongodb.client.MongoCollection;\nimport com.mongodb.client.model.Filters;\nimport com.mongodb.client.model.Updates;\nimport com.mongodb.client.result.DeleteResult;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Optional;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\nimport org.bson.Document;\nimport org.bson.conversions.Bson;\nimport org.bson.types.ObjectId;\n\n/** An implementation of {@link CustomerDAO} that uses MongoDB (https://www.mongodb.com/) */\n@Slf4j\n@RequiredArgsConstructor\npublic class MongoCustomerDAO implements CustomerDAO<ObjectId> {\n  private final MongoCollection<Document> customerCollection;\n\n  /** {@inheritDoc} */\n  @Override\n  public void save(Customer<ObjectId> customer) {\n    Document customerDocument = new Document(\"_id\", customer.getId());\n    customerDocument.append(\"name\", customer.getName());\n    customerCollection.insertOne(customerDocument);\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public void update(Customer<ObjectId> customer) {\n    Document updateQuery = new Document(\"_id\", customer.getId());\n    Bson update = Updates.set(\"name\", customer.getName());\n    customerCollection.updateOne(updateQuery, update);\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public void delete(ObjectId objectId) {\n    Bson deleteQuery = Filters.eq(\"_id\", objectId);\n    DeleteResult deleteResult = customerCollection.deleteOne(deleteQuery);\n    if (deleteResult.getDeletedCount() == 0) {\n      throw new CustomException(\"Delete failed: No document found with id: \" + objectId);\n    }\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public List<Customer<ObjectId>> findAll() {\n    List<Customer<ObjectId>> customers = new LinkedList<>();\n    FindIterable<Document> customerDocuments = customerCollection.find();\n    for (Document customerDocument : customerDocuments) {\n      Customer<ObjectId> customer =\n          new Customer<>(\n              (ObjectId) customerDocument.get(\"_id\"), customerDocument.getString(\"name\"));\n      customers.add(customer);\n    }\n    return customers;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public Optional<Customer<ObjectId>> findById(ObjectId objectId) {\n    Bson filter = Filters.eq(\"_id\", objectId);\n    Document customerDocument = customerCollection.find(filter).first();\n    Customer<ObjectId> customerResult = null;\n    if (customerDocument != null) {\n      customerResult =\n          new Customer<>(\n              (ObjectId) customerDocument.get(\"_id\"), customerDocument.getString(\"name\"));\n    }\n    return Optional.ofNullable(customerResult);\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public void deleteSchema() {\n    customerCollection.drop();\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/main/java/com/iluwatar/daofactory/MongoDataSourceFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport com.mongodb.client.MongoClient;\nimport com.mongodb.client.MongoClients;\nimport com.mongodb.client.MongoCollection;\nimport com.mongodb.client.MongoDatabase;\nimport org.bson.Document;\nimport org.bson.types.ObjectId;\n\n/** MongoDataSourceFactory concrete factory. */\npublic class MongoDataSourceFactory extends DAOFactory {\n  private static final String CONN_STR = \"mongodb://localhost:27017/\";\n  private static final String DB_NAME = \"dao_factory\";\n  private static final String COLLECTION_NAME = \"customer\";\n\n  @Override\n  public CustomerDAO<ObjectId> createCustomerDAO() {\n    try {\n      MongoClient mongoClient = MongoClients.create(CONN_STR);\n      MongoDatabase database = mongoClient.getDatabase(DB_NAME);\n      MongoCollection<Document> customerCollection = database.getCollection(COLLECTION_NAME);\n      return new MongoCustomerDAO(customerCollection);\n    } catch (CustomException e) {\n      throw new CustomException(\"Error: \" + e);\n    }\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/main/resources/logback.xml",
    "content": "<configuration>\n    <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n        <encoder>\n            <pattern>%d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{15}) %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <logger name=\"com.iluwatar.daofactory\" level=\"DEBUG\"/>\n    <root level=\"ERROR\">\n        <appender-ref ref=\"STDOUT\" />\n    </root>\n</configuration>"
  },
  {
    "path": "dao-factory/src/test/java/com/iluwatar/daofactory/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport java.util.List;\nimport org.bson.types.ObjectId;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** {@link App} */\nclass AppTest {\n  /** Test perform CRUD in main class */\n  private CustomerDAO<Long> mockLongCustomerDAO;\n\n  private CustomerDAO<ObjectId> mockObjectIdCustomerDAO;\n\n  @BeforeEach\n  void setUp() {\n    mockLongCustomerDAO = mock(CustomerDAO.class);\n    mockObjectIdCustomerDAO = mock(CustomerDAO.class);\n  }\n\n  @Test\n  void testPerformCreateCustomerWithLongId() {\n    Customer<Long> c1 = new Customer<>(1L, \"Test1\");\n    Customer<Long> c2 = new Customer<>(2L, \"Test2\");\n\n    when(mockLongCustomerDAO.findAll()).thenReturn(List.of(c1, c2));\n\n    App.performCreateCustomer(mockLongCustomerDAO, List.of(c1, c2));\n\n    verify(mockLongCustomerDAO).save(c1);\n    verify(mockLongCustomerDAO).save(c2);\n    verify(mockLongCustomerDAO).findAll();\n  }\n\n  @Test\n  void testPerformUpdateCustomerWithObjectId() {\n    ObjectId id = new ObjectId();\n    Customer<ObjectId> updatedCustomer = new Customer<>(id, \"Updated\");\n\n    when(mockObjectIdCustomerDAO.findAll()).thenReturn(List.of(updatedCustomer));\n\n    App.performUpdateCustomer(mockObjectIdCustomerDAO, updatedCustomer);\n\n    verify(mockObjectIdCustomerDAO).update(updatedCustomer);\n    verify(mockObjectIdCustomerDAO).findAll();\n  }\n\n  @Test\n  void testPerformDeleteCustomerWithLongId() {\n    Long id = 100L;\n    Customer<Long> remainingCustomer = new Customer<>(1L, \"Remaining\");\n\n    when(mockLongCustomerDAO.findAll()).thenReturn(List.of(remainingCustomer));\n\n    App.performDeleteCustomer(mockLongCustomerDAO, id);\n\n    verify(mockLongCustomerDAO).delete(id);\n    verify(mockLongCustomerDAO).findAll();\n  }\n\n  @Test\n  void testDeleteSchema() {\n    App.deleteSchema(mockLongCustomerDAO);\n    verify(mockLongCustomerDAO).deleteSchema();\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/test/java/com/iluwatar/daofactory/DAOFactoryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport static org.junit.jupiter.api.Assertions.assertInstanceOf;\n\nimport org.junit.jupiter.api.Test;\n\n/** {@link DAOFactory} */\nclass DAOFactoryTest {\n\n  @Test\n  void verifyH2CustomerDAOCreation() {\n    var daoFactory = DAOFactoryProvider.getDataSource(DataSourceType.H2);\n    var customerDAO = daoFactory.createCustomerDAO();\n    assertInstanceOf(H2CustomerDAO.class, customerDAO);\n  }\n\n  @Test\n  void verifyMongoCustomerDAOCreation() {\n    var daoFactory = DAOFactoryProvider.getDataSource(DataSourceType.MONGO);\n    var customerDAO = daoFactory.createCustomerDAO();\n    assertInstanceOf(MongoCustomerDAO.class, customerDAO);\n  }\n\n  @Test\n  void verifyFlatFileCustomerDAOCreation() {\n    var daoFactory = DAOFactoryProvider.getDataSource(DataSourceType.FLAT_FILE);\n    var customerDAO = daoFactory.createCustomerDAO();\n    assertInstanceOf(FlatFileCustomerDAO.class, customerDAO);\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/test/java/com/iluwatar/daofactory/FlatFileCustomerDAOTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.argThat;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.mockStatic;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport com.google.gson.Gson;\nimport com.google.gson.reflect.TypeToken;\nimport java.io.File;\nimport java.io.FileReader;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.lang.reflect.Type;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Optional;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.MockedStatic;\n\n/** {@link FlatFileCustomerDAO} */\nclass FlatFileCustomerDAOTest {\n  private Path filePath;\n  private File file;\n  private Gson gson;\n\n  private final Type customerListType = new TypeToken<List<Customer<Long>>>() {}.getType();\n  private final Customer<Long> existingCustomer = new Customer<>(1L, \"Thanh\");\n  private FlatFileCustomerDAO flatFileCustomerDAO;\n  private FileReader fileReader;\n  private FileWriter fileWriter;\n\n  @BeforeEach\n  void setUp() {\n    filePath = mock(Path.class);\n    file = mock(File.class);\n    gson = mock(Gson.class);\n    fileReader = mock(FileReader.class);\n    fileWriter = mock(FileWriter.class);\n    flatFileCustomerDAO =\n        new FlatFileCustomerDAO(filePath, gson) {\n          @Override\n          protected Reader createReader(Path filePath) throws IOException {\n            return fileReader;\n          }\n\n          @Override\n          protected Writer createWriter(Path filePath) throws IOException {\n            return fileWriter;\n          }\n        };\n    when(filePath.toFile()).thenReturn(file);\n  }\n\n  /** Class test with scenario Save Customer */\n  @Nested\n  class Save {\n    @Test\n    void giveFilePathNotExist_whenSaveCustomer_thenCreateNewFileWithCustomer() {\n      when(file.exists()).thenReturn(false);\n      flatFileCustomerDAO.save(existingCustomer);\n\n      verify(gson)\n          .toJson(\n              argThat(\n                  (List<Customer<Long>> list) ->\n                      list.size() == 1 && list.getFirst().equals(existingCustomer)),\n              eq(fileWriter));\n    }\n\n    @Test\n    void givenEmptyFileExist_whenSaveCustomer_thenAddCustomer() {\n      when(file.exists()).thenReturn(true);\n      when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(new LinkedList<>());\n      flatFileCustomerDAO.save(existingCustomer);\n\n      verify(gson).fromJson(fileReader, customerListType);\n      verify(gson)\n          .toJson(\n              argThat(\n                  (List<Customer<Long>> list) ->\n                      list.size() == 1 && list.getFirst().equals(existingCustomer)),\n              eq(fileWriter));\n    }\n\n    @Test\n    void givenFileWithCustomerExist_whenSaveCustomer_thenShouldAppendCustomer() {\n      List<Customer<Long>> customers = new LinkedList<>();\n      customers.add(new Customer<>(2L, \"Duc\"));\n      customers.add(new Customer<>(3L, \"Nguyen\"));\n      when(file.exists()).thenReturn(true);\n      when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(customers);\n\n      flatFileCustomerDAO.save(existingCustomer);\n\n      verify(gson).fromJson(fileReader, customerListType);\n      verify(gson).toJson(argThat((List<Customer<Long>> list) -> list.size() == 3), eq(fileWriter));\n    }\n\n    @Test\n    void whenReadFails_thenThrowException() {\n      flatFileCustomerDAO =\n          new FlatFileCustomerDAO(filePath, gson) {\n            @Override\n            protected Reader createReader(Path filePath) throws IOException {\n              throw new IOException(\"Failed to read file\");\n            }\n\n            @Override\n            protected Writer createWriter(Path filePath) {\n              return fileWriter;\n            }\n          };\n      when(file.exists()).thenReturn(true);\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.save(existingCustomer));\n    }\n\n    @Test\n    void whenWriteFails_thenThrowException() {\n      when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(new LinkedList<>());\n      flatFileCustomerDAO =\n          new FlatFileCustomerDAO(filePath, gson) {\n            @Override\n            protected Reader createReader(Path filePath) {\n              return fileReader;\n            }\n\n            @Override\n            protected Writer createWriter(Path filePath) throws IOException {\n              throw new IOException(\"Failed to write file\");\n            }\n          };\n      when(file.exists()).thenReturn(true);\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.save(existingCustomer));\n    }\n  }\n\n  /** Class test with scenario Update Customer */\n  @Nested\n  class Update {\n    @Test\n    void givenFilePathNotExist_whenUpdateCustomer_thenThrowException() {\n      when(file.exists()).thenReturn(false);\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.update(existingCustomer));\n    }\n\n    @Test\n    void whenReadFails_thenThrowException() {\n      when(file.exists()).thenReturn(true);\n      flatFileCustomerDAO =\n          new FlatFileCustomerDAO(filePath, gson) {\n            @Override\n            protected Reader createReader(Path filePath) throws IOException {\n              throw new IOException(\"Failed to read file\");\n            }\n\n            @Override\n            protected Writer createWriter(Path filePath) throws IOException {\n              return fileWriter;\n            }\n          };\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.update(existingCustomer));\n    }\n\n    @Test\n    void whenWriteFails_thenThrowException() {\n      when(file.exists()).thenReturn(true);\n      when(gson.fromJson(any(Reader.class), eq(customerListType)))\n          .thenReturn(\n              new LinkedList<>() {\n                {\n                  add(new Customer<>(1L, \"Quang\"));\n                }\n              });\n      flatFileCustomerDAO =\n          new FlatFileCustomerDAO(filePath, gson) {\n            @Override\n            protected Reader createReader(Path filePath) {\n              return fileReader;\n            }\n\n            @Override\n            protected Writer createWriter(Path filePath) throws IOException {\n              throw new IOException(\"Failed to write file\");\n            }\n          };\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.update(existingCustomer));\n    }\n\n    @Test\n    void givenValidCustomer_whenUpdateCustomer_thenUpdateSucceed() {\n      when(file.exists()).thenReturn(true);\n      List<Customer<Long>> existingListCustomer = new LinkedList<>();\n      existingListCustomer.add(new Customer<>(1L, \"Quang\"));\n      when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer);\n      flatFileCustomerDAO =\n          new FlatFileCustomerDAO(filePath, gson) {\n            @Override\n            protected Reader createReader(Path filePath) {\n              return fileReader;\n            }\n\n            @Override\n            protected Writer createWriter(Path filePath) throws IOException {\n              return fileWriter;\n            }\n          };\n      flatFileCustomerDAO.update(existingCustomer);\n      verify(gson)\n          .toJson(\n              argThat(\n                  (List<Customer<Long>> customers) ->\n                      customers.size() == 1\n                          && customers.stream()\n                              .anyMatch(c -> c.getId().equals(1L) && c.getName().equals(\"Thanh\"))),\n              eq(fileWriter));\n    }\n\n    @Test\n    void givenIdCustomerNotExist_whenUpdateCustomer_thenThrowException() {\n      when(file.exists()).thenReturn(true);\n      List<Customer<Long>> existingListCustomer = new LinkedList<>();\n      existingListCustomer.add(new Customer<>(2L, \"Quang\"));\n      when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer);\n      flatFileCustomerDAO =\n          new FlatFileCustomerDAO(filePath, gson) {\n            @Override\n            protected Reader createReader(Path filePath) {\n              return fileReader;\n            }\n\n            @Override\n            protected Writer createWriter(Path filePath) {\n              return fileWriter;\n            }\n          };\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.update(existingCustomer));\n    }\n  }\n\n  /** Class test with scenario Delete Customer */\n  @Nested\n  class Delete {\n    @Test\n    void givenFilePathNotExist_whenDeleteCustomer_thenThrowException() {\n      when(file.exists()).thenReturn(false);\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.delete(1L));\n    }\n\n    @Test\n    void whenReadFails_thenThrowException() {\n      when(file.exists()).thenReturn(true);\n      flatFileCustomerDAO =\n          new FlatFileCustomerDAO(filePath, gson) {\n            @Override\n            protected Reader createReader(Path filePath) throws IOException {\n              throw new IOException(\"Failed to read file\");\n            }\n\n            @Override\n            protected Writer createWriter(Path filePath) {\n              return fileWriter;\n            }\n          };\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.delete(1L));\n    }\n\n    @Test\n    void whenWriteFails_thenThrowException() {\n      when(file.exists()).thenReturn(true);\n      List<Customer<Long>> existingListCustomer = new LinkedList<>();\n      existingListCustomer.add(new Customer<>(1L, \"Quang\"));\n      when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer);\n      flatFileCustomerDAO =\n          new FlatFileCustomerDAO(filePath, gson) {\n            @Override\n            protected Reader createReader(Path filePath) {\n              return fileReader;\n            }\n\n            @Override\n            protected Writer createWriter(Path filePath) throws IOException {\n              throw new IOException(\"Failed to write file\");\n            }\n          };\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.delete(1L));\n    }\n\n    @Test\n    void givenValidId_whenDeleteCustomer_thenDeleteSucceed() {\n      when(file.exists()).thenReturn(true);\n      List<Customer<Long>> existingListCustomer = new LinkedList<>();\n      existingListCustomer.add(new Customer<>(1L, \"Quang\"));\n      existingListCustomer.add(new Customer<>(2L, \"Thanh\"));\n      when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer);\n      flatFileCustomerDAO =\n          new FlatFileCustomerDAO(filePath, gson) {\n            @Override\n            protected Reader createReader(Path filePath) {\n              return fileReader;\n            }\n\n            @Override\n            protected Writer createWriter(Path filePath) {\n              return fileWriter;\n            }\n          };\n\n      flatFileCustomerDAO.delete(1L);\n      assertEquals(1, existingListCustomer.size());\n      verify(gson)\n          .toJson(\n              argThat(\n                  (List<Customer<Long>> customers) ->\n                      customers.stream()\n                          .noneMatch(c -> c.getId().equals(1L) && c.getName().equals(\"Quang\"))),\n              eq(fileWriter));\n    }\n\n    @Test\n    void givenIdNotExist_whenDeleteCustomer_thenThrowException() {\n      when(file.exists()).thenReturn(true);\n      List<Customer<Long>> existingListCustomer = new LinkedList<>();\n      existingListCustomer.add(new Customer<>(1L, \"Quang\"));\n      existingListCustomer.add(new Customer<>(2L, \"Thanh\"));\n      when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer);\n      flatFileCustomerDAO =\n          new FlatFileCustomerDAO(filePath, gson) {\n            @Override\n            protected Reader createReader(Path filePath) {\n              return fileReader;\n            }\n\n            @Override\n            protected Writer createWriter(Path filePath) {\n              return fileWriter;\n            }\n          };\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.delete(3L));\n    }\n  }\n\n  /** Class test with scenario Find All Customer */\n  @Nested\n  class FindAll {\n    @Test\n    void givenFileNotExist_thenThrowException() {\n      when(file.exists()).thenReturn(false);\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.findAll());\n    }\n\n    @Test\n    void whenReadFails_thenThrowException() {\n      when(file.exists()).thenReturn(true);\n      flatFileCustomerDAO =\n          new FlatFileCustomerDAO(filePath, gson) {\n            @Override\n            protected Reader createReader(Path filePath) throws IOException {\n              throw new IOException(\"Failed to read file\");\n            }\n\n            @Override\n            protected Writer createWriter(Path filePath) {\n              return fileWriter;\n            }\n          };\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.findAll());\n    }\n\n    @Test\n    void givenEmptyCustomer_thenReturnEmptyList() {\n      when(file.exists()).thenReturn(true);\n      when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(new LinkedList<>());\n      List<Customer<Long>> customers = flatFileCustomerDAO.findAll();\n      assertEquals(0, customers.size());\n      verify(gson).fromJson(fileReader, customerListType);\n    }\n\n    @Test\n    void givenCustomerExist_thenReturnCustomerList() {\n      when(file.exists()).thenReturn(true);\n      List<Customer<Long>> existingListCustomer = new LinkedList<>();\n      existingListCustomer.add(new Customer<>(1L, \"Quang\"));\n      existingListCustomer.add(new Customer<>(2L, \"Thanh\"));\n      when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer);\n      List<Customer<Long>> customers = flatFileCustomerDAO.findAll();\n      assertEquals(2, customers.size());\n    }\n  }\n\n  /** Class test with scenario Find By Id Customer */\n  @Nested\n  class FindById {\n\n    @Test\n    void givenFilePathNotExist_whenFindById_thenThrowException() {\n      when(file.exists()).thenReturn(false);\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.findById(1L));\n    }\n\n    @Test\n    void whenReadFails_thenThrowException() {\n      when(file.exists()).thenReturn(true);\n      flatFileCustomerDAO =\n          new FlatFileCustomerDAO(filePath, gson) {\n            @Override\n            protected Reader createReader(Path filePath) throws IOException {\n              throw new IOException(\"Failed to read file\");\n            }\n\n            @Override\n            protected Writer createWriter(Path filePath) {\n              return fileWriter;\n            }\n          };\n      assertThrows(CustomException.class, () -> flatFileCustomerDAO.findById(1L));\n    }\n\n    @Test\n    void givenIdCustomerExist_whenFindById_thenReturnCustomer() {\n      when(file.exists()).thenReturn(true);\n      List<Customer<Long>> existingListCustomer = new LinkedList<>();\n      existingListCustomer.add(new Customer<>(1L, \"Quang\"));\n      existingListCustomer.add(new Customer<>(2L, \"Thanh\"));\n      when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer);\n      Optional<Customer<Long>> customer = flatFileCustomerDAO.findById(1L);\n      assertTrue(customer.isPresent());\n      assertEquals(\"Quang\", customer.get().getName());\n    }\n\n    @Test\n    void givenIdCustomerNotExist_whenFindById_thenReturnEmpty() {\n      when(file.exists()).thenReturn(true);\n      when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(new LinkedList<>());\n      Optional<Customer<Long>> customers = flatFileCustomerDAO.findById(1L);\n      assertTrue(customers.isEmpty());\n    }\n  }\n\n  /** Clas test with scenario Delete schema */\n  @Nested\n  class DeleteSchema {\n    @Test\n    void givenFilePathExist_thenDeleteFile() {\n      when(file.exists()).thenReturn(true);\n\n      try (MockedStatic<Files> mockedFiles = mockStatic(Files.class)) {\n        flatFileCustomerDAO.deleteSchema();\n        mockedFiles.verify(() -> Files.delete(filePath), times(1));\n      }\n    }\n\n    @Test\n    void givenFilePathNotExist_thenThrowException() {\n      when(file.exists()).thenReturn(false);\n\n      try (MockedStatic<Files> mockedFiles = mockStatic(Files.class)) {\n        assertThrows(CustomException.class, () -> flatFileCustomerDAO.deleteSchema());\n        mockedFiles.verify(() -> Files.delete(filePath), times(0));\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/test/java/com/iluwatar/daofactory/H2CustomerDAOTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.SQLException;\nimport java.util.List;\nimport javax.sql.DataSource;\nimport org.h2.jdbcx.JdbcDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\n/** Tests {@link H2CustomerDAO} */\nclass H2CustomerDAOTest {\n  private static final String DB_URL = \"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1\";\n  private static final String USER = \"sa\";\n  private static final String PASS = \"\";\n  private static final String CREATE_SCHEMA =\n      \"CREATE TABLE IF NOT EXISTS customer (id BIGINT PRIMARY KEY, name VARCHAR(255))\";\n  private static final String DROP_SCHEMA = \"DROP TABLE IF EXISTS customer\";\n  private final Customer<Long> existingCustomer = new Customer<>(1L, \"Nguyen\");\n  private H2CustomerDAO h2CustomerDAO;\n\n  @BeforeEach\n  void createSchema() throws SQLException {\n    try (var connection = DriverManager.getConnection(DB_URL, USER, PASS);\n        var statement = connection.createStatement()) {\n      statement.execute(CREATE_SCHEMA);\n    }\n  }\n\n  @AfterEach\n  void deleteSchema() throws SQLException {\n    try (var connection = DriverManager.getConnection(DB_URL, USER, PASS);\n        var statement = connection.createStatement()) {\n      statement.execute(DROP_SCHEMA);\n    }\n  }\n\n  /** Class test for scenario connect with datasource succeed */\n  @Nested\n  class ConnectionSucceed {\n\n    @BeforeEach\n    void setUp() {\n      var dataSource = new JdbcDataSource();\n      dataSource.setURL(DB_URL);\n      dataSource.setUser(USER);\n      dataSource.setPassword(PASS);\n      h2CustomerDAO = new H2CustomerDAO(dataSource);\n      assertDoesNotThrow(() -> h2CustomerDAO.save(existingCustomer));\n      var customer = h2CustomerDAO.findById(existingCustomer.getId());\n      assertTrue(customer.isPresent());\n      assertEquals(customer.get().getName(), existingCustomer.getName());\n      assertEquals(customer.get().getId(), existingCustomer.getId());\n    }\n\n    @Nested\n    class SaveCustomer {\n      @Test\n      void givenValidCustomer_whenSaveCustomer_thenAddSucceed() {\n        var customer = new Customer<>(2L, \"Duc\");\n        assertDoesNotThrow(() -> h2CustomerDAO.save(customer));\n        var customerInDb = h2CustomerDAO.findById(customer.getId());\n        assertTrue(customerInDb.isPresent());\n        assertEquals(customerInDb.get().getName(), customer.getName());\n        assertEquals(customerInDb.get().getId(), customer.getId());\n        List<Customer<Long>> customers = h2CustomerDAO.findAll();\n        assertEquals(2, customers.size());\n      }\n\n      @Test\n      void givenIdCustomerDuplicated_whenSaveCustomer_thenThrowException() {\n        var customer = new Customer<>(existingCustomer.getId(), \"Duc\");\n        assertThrows(CustomException.class, () -> h2CustomerDAO.save(customer));\n        List<Customer<Long>> customers = h2CustomerDAO.findAll();\n        assertEquals(1, customers.size());\n      }\n    }\n\n    @Nested\n    class UpdateCustomer {\n      @Test\n      void givenValidCustomer_whenUpdateCustomer_thenUpdateSucceed() {\n        var customerUpdate = new Customer<>(existingCustomer.getId(), \"Duc\");\n        assertDoesNotThrow(() -> h2CustomerDAO.update(customerUpdate));\n        var customerInDb = h2CustomerDAO.findById(customerUpdate.getId());\n        assertTrue(customerInDb.isPresent());\n        assertEquals(customerInDb.get().getName(), customerUpdate.getName());\n      }\n\n      @Test\n      void givenIdCustomerNotExist_whenUpdateCustomer_thenThrowException() {\n        var customerUpdate = new Customer<>(100L, \"Duc\");\n        var customerInDb = h2CustomerDAO.findById(customerUpdate.getId());\n        assertTrue(customerInDb.isEmpty());\n        assertThrows(CustomException.class, () -> h2CustomerDAO.update(customerUpdate));\n      }\n\n      @Test\n      void givenNull_whenUpdateCustomer_thenThrowException() {\n        assertThrows(CustomException.class, () -> h2CustomerDAO.update(null));\n        List<Customer<Long>> customers = h2CustomerDAO.findAll();\n        assertEquals(1, customers.size());\n      }\n    }\n\n    @Nested\n    class DeleteCustomer {\n      @Test\n      void givenValidId_whenDeleteCustomer_thenDeleteSucceed() {\n        assertDoesNotThrow(() -> h2CustomerDAO.delete(existingCustomer.getId()));\n        var customerInDb = h2CustomerDAO.findById(existingCustomer.getId());\n        assertTrue(customerInDb.isEmpty());\n        List<Customer<Long>> customers = h2CustomerDAO.findAll();\n        assertEquals(0, customers.size());\n      }\n\n      @Test\n      void givenIdCustomerNotExist_whenDeleteCustomer_thenThrowException() {\n        var customerInDb = h2CustomerDAO.findById(100L);\n        assertTrue(customerInDb.isEmpty());\n        assertThrows(CustomException.class, () -> h2CustomerDAO.delete(100L));\n        List<Customer<Long>> customers = h2CustomerDAO.findAll();\n        assertEquals(1, customers.size());\n        assertEquals(existingCustomer.getName(), customers.get(0).getName());\n        assertEquals(existingCustomer.getId(), customers.get(0).getId());\n      }\n\n      @Test\n      void givenNull_whenDeleteCustomer_thenThrowException() {\n        assertThrows(CustomException.class, () -> h2CustomerDAO.delete(null));\n        List<Customer<Long>> customers = h2CustomerDAO.findAll();\n        assertEquals(1, customers.size());\n        assertEquals(existingCustomer.getName(), customers.get(0).getName());\n      }\n    }\n\n    @Nested\n    class FindAllCustomers {\n      @Test\n      void givenNonCustomerInDb_whenFindAllCustomer_thenReturnEmptyList() {\n        assertDoesNotThrow(() -> h2CustomerDAO.delete(existingCustomer.getId()));\n        List<Customer<Long>> customers = h2CustomerDAO.findAll();\n        assertEquals(0, customers.size());\n      }\n\n      @Test\n      void givenCustomerExistInDb_whenFindAllCustomer_thenReturnCustomers() {\n        List<Customer<Long>> customers = h2CustomerDAO.findAll();\n        assertEquals(1, customers.size());\n        assertEquals(existingCustomer.getName(), customers.get(0).getName());\n        assertEquals(existingCustomer.getId(), customers.get(0).getId());\n      }\n    }\n\n    @Nested\n    class FindCustomerById {\n      @Test\n      void givenValidId_whenFindById_thenReturnCustomer() {\n        var customerInDb = h2CustomerDAO.findById(existingCustomer.getId());\n        assertTrue(customerInDb.isPresent());\n        assertEquals(existingCustomer.getName(), customerInDb.get().getName());\n        assertEquals(existingCustomer.getId(), customerInDb.get().getId());\n      }\n\n      @Test\n      void givenIdCustomerNotExist_whenFindById_thenReturnEmpty() {\n        var customerNotExist = h2CustomerDAO.findById(100L);\n        assertTrue(customerNotExist.isEmpty());\n      }\n\n      @Test\n      void givenNull_whenFindById_thenThrowException() {\n        assertThrows(CustomException.class, () -> h2CustomerDAO.findById(null));\n      }\n    }\n\n    @Nested\n    class CreateSchema {\n      @Test\n      void whenCreateSchema_thenNotThrowException() {\n        assertDoesNotThrow(() -> h2CustomerDAO.createSchema());\n      }\n    }\n\n    @Nested\n    class DeleteSchema {\n      @Test\n      void whenDeleteSchema_thenNotThrowException() {\n        assertDoesNotThrow(() -> h2CustomerDAO.deleteSchema());\n      }\n    }\n  }\n\n  /** Class test with scenario connect with data source failed */\n  @Nested\n  class ConnectionFailed {\n    private static final String EXCEPTION_CAUSE = \"Connection not available\";\n\n    @BeforeEach\n    void setUp() throws SQLException {\n      h2CustomerDAO = new H2CustomerDAO(mockedDataSource());\n    }\n\n    private DataSource mockedDataSource() throws SQLException {\n      var mockedDataSource = mock(DataSource.class);\n      var mockedConnection = mock(Connection.class);\n      var exception = new SQLException(EXCEPTION_CAUSE);\n      doThrow(exception).when(mockedConnection).prepareStatement(Mockito.anyString());\n      doThrow(exception).when(mockedConnection).createStatement();\n      doReturn(mockedConnection).when(mockedDataSource).getConnection();\n      return mockedDataSource;\n    }\n\n    @Test\n    void givenValidCustomer_whenSaveCustomer_thenThrowException() {\n      var customer = new Customer<>(2L, \"Duc\");\n      CustomException exception =\n          assertThrows(CustomException.class, () -> h2CustomerDAO.save(customer));\n      assertEquals(EXCEPTION_CAUSE, exception.getMessage());\n    }\n\n    @Test\n    void givenValidCustomer_whenUpdateCustomer_thenThrowException() {\n      var customerUpdate = new Customer<>(existingCustomer.getId(), \"Duc\");\n      CustomException exception =\n          assertThrows(CustomException.class, () -> h2CustomerDAO.update(customerUpdate));\n      assertEquals(EXCEPTION_CAUSE, exception.getMessage());\n    }\n\n    @Test\n    void givenValidId_whenDeleteCustomer_thenThrowException() {\n      Long idCustomer = existingCustomer.getId();\n      CustomException exception =\n          assertThrows(CustomException.class, () -> h2CustomerDAO.delete(idCustomer));\n      assertEquals(EXCEPTION_CAUSE, exception.getMessage());\n    }\n\n    @Test\n    void whenFindAll_thenThrowException() {\n      CustomException exception = assertThrows(CustomException.class, h2CustomerDAO::findAll);\n      assertEquals(EXCEPTION_CAUSE, exception.getMessage());\n    }\n\n    @Test\n    void whenFindById_thenThrowException() {\n      Long idCustomer = existingCustomer.getId();\n      CustomException exception =\n          assertThrows(CustomException.class, () -> h2CustomerDAO.findById(idCustomer));\n      assertEquals(EXCEPTION_CAUSE, exception.getMessage());\n    }\n\n    @Test\n    void whenCreateSchema_thenThrowException() {\n      CustomException exception = assertThrows(CustomException.class, h2CustomerDAO::createSchema);\n      assertEquals(EXCEPTION_CAUSE, exception.getMessage());\n    }\n\n    @Test\n    void whenDeleteSchema_thenThrowException() {\n      CustomException exception = assertThrows(CustomException.class, h2CustomerDAO::deleteSchema);\n      assertEquals(EXCEPTION_CAUSE, exception.getMessage());\n    }\n  }\n}\n"
  },
  {
    "path": "dao-factory/src/test/java/com/iluwatar/daofactory/MongoCustomerDAOTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.daofactory;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.argThat;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport com.mongodb.client.FindIterable;\nimport com.mongodb.client.MongoCollection;\nimport com.mongodb.client.MongoCursor;\nimport com.mongodb.client.model.Filters;\nimport com.mongodb.client.result.DeleteResult;\nimport com.mongodb.client.result.UpdateResult;\nimport java.util.List;\nimport java.util.Optional;\nimport org.bson.BsonDocument;\nimport org.bson.Document;\nimport org.bson.conversions.Bson;\nimport org.bson.types.ObjectId;\nimport org.junit.jupiter.api.Test;\n\n/** Tests {@link MongoCustomerDAO} */\nclass MongoCustomerDAOTest {\n  MongoCollection<Document> customerCollection = mock(MongoCollection.class);\n  MongoCustomerDAO mongoCustomerDAO = new MongoCustomerDAO(customerCollection);\n\n  @Test\n  void givenValidCustomer_whenSaveCustomer_thenSaveSucceed() {\n    Customer<ObjectId> customer = new Customer<>(new ObjectId(), \"John\");\n    mongoCustomerDAO.save(customer);\n    verify(customerCollection)\n        .insertOne(\n            argThat(\n                document ->\n                    document.get(\"_id\").equals(customer.getId())\n                        && document.get(\"name\").equals(customer.getName())));\n  }\n\n  @Test\n  void givenValidCustomer_whenUpdateCustomer_thenUpdateSucceed() {\n    ObjectId customerId = new ObjectId();\n    Customer<ObjectId> customerUpdated = new Customer<>(customerId, \"John\");\n    when(customerCollection.updateOne(any(Bson.class), any(Bson.class)))\n        .thenReturn(UpdateResult.acknowledged(1L, 1L, null));\n    mongoCustomerDAO.update(customerUpdated);\n    verify(customerCollection)\n        .updateOne(\n            argThat(\n                (Bson filter) -> {\n                  Document filterDoc = (Document) filter;\n                  return filterDoc.getObjectId(\"_id\").equals(customerId);\n                }),\n            argThat(\n                (Bson update) -> {\n                  BsonDocument bsonDoc = update.toBsonDocument();\n                  BsonDocument setDoc = bsonDoc.getDocument(\"$set\");\n                  return setDoc.getString(\"name\").getValue().equals(customerUpdated.getName());\n                }));\n  }\n\n  @Test\n  void givenValidObjectId_whenDeleteCustomer_thenDeleteSucceed() {\n    ObjectId customerId = new ObjectId();\n    when(customerCollection.deleteOne(any(Bson.class))).thenReturn(DeleteResult.acknowledged(1));\n    mongoCustomerDAO.delete(customerId);\n    verify(customerCollection)\n        .deleteOne(\n            argThat(\n                (Bson filter) -> {\n                  BsonDocument filterDoc = filter.toBsonDocument();\n                  return filterDoc.getObjectId(\"_id\").getValue().equals(customerId);\n                }));\n  }\n\n  @Test\n  void givenIdNotExist_whenDeleteCustomer_thenThrowException() {\n    ObjectId customerId = new ObjectId();\n    when(customerCollection.deleteOne(any(Bson.class))).thenReturn(DeleteResult.acknowledged(0));\n    assertThrows(CustomException.class, () -> mongoCustomerDAO.delete(customerId));\n    verify(customerCollection)\n        .deleteOne(\n            argThat(\n                (Bson filter) -> {\n                  BsonDocument filterDoc = filter.toBsonDocument();\n                  return filterDoc.getObjectId(\"_id\").getValue().equals(customerId);\n                }));\n  }\n\n  @Test\n  void findAll_thenReturnAllCustomers() {\n    FindIterable<Document> findIterable = mock(FindIterable.class);\n    MongoCursor<Document> cursor = mock(MongoCursor.class);\n    Document customerDoc1 = new Document(\"_id\", new ObjectId()).append(\"name\", \"Duc\");\n    Document customerDoc2 = new Document(\"_id\", new ObjectId()).append(\"name\", \"Thanh\");\n    when(customerCollection.find()).thenReturn(findIterable);\n    when(findIterable.iterator()).thenReturn(cursor);\n    when(cursor.hasNext()).thenReturn(true, true, false);\n    when(cursor.next()).thenReturn(customerDoc1, customerDoc2);\n    List<Customer<ObjectId>> customerList = mongoCustomerDAO.findAll();\n    assertEquals(2, customerList.size());\n    verify(customerCollection).find();\n  }\n\n  @Test\n  void givenValidId_whenFindById_thenReturnCustomer() {\n    FindIterable<Document> findIterable = mock(FindIterable.class);\n    ObjectId customerId = new ObjectId();\n    String customerName = \"Duc\";\n    Document customerDoc = new Document(\"_id\", customerId).append(\"name\", customerName);\n    when(customerCollection.find(Filters.eq(\"_id\", customerId))).thenReturn(findIterable);\n    when(findIterable.first()).thenReturn(customerDoc);\n\n    Optional<Customer<ObjectId>> customer = mongoCustomerDAO.findById(customerId);\n    assertTrue(customer.isPresent());\n    assertEquals(customerId, customer.get().getId());\n    assertEquals(customerName, customer.get().getName());\n  }\n\n  @Test\n  void givenNotExistingId_whenFindById_thenReturnEmpty() {\n    FindIterable<Document> findIterable = mock(FindIterable.class);\n    ObjectId customerId = new ObjectId();\n    when(customerCollection.find(Filters.eq(\"_id\", customerId))).thenReturn(findIterable);\n    when(findIterable.first()).thenReturn(null);\n    Optional<Customer<ObjectId>> customer = mongoCustomerDAO.findById(customerId);\n    assertTrue(customer.isEmpty());\n    verify(customerCollection).find(Filters.eq(\"_id\", customerId));\n  }\n\n  @Test\n  void whenDeleteSchema_thenDeleteCollection() {\n    mongoCustomerDAO.deleteSchema();\n    verify(customerCollection).drop();\n  }\n}\n"
  },
  {
    "path": "data-access-object/README.md",
    "content": "---\ntitle: \"Data Access Object Pattern in Java: Streamlining Database Interaction\"\nshortTitle: Data Access Object (DAO)\ndescription: \"Explore the Java Data Access Object (DAO) pattern to effectively separate business logic from database operations. Learn implementation strategies, real-world examples, and best practices.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Abstraction\n  - Data access\n  - Data processing\n  - Decoupling\n  - Layered architecture\n  - Persistence\n---\n\n## Also known as\n\n* Data Access Layer\n* DAO\n\n## Intent of Data Access Object Design Pattern\n\nThe Data Access Object (DAO) design pattern aims to separate the application's business logic from the persistence layer, typically a database or any other storage mechanism. By using DAOs, the application can access and manipulate data without being dependent on the specific database implementation details.\n\n## Detailed Explanation of Data Access Object Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a library system where the main application manages book loans, user accounts, and inventory. The Data Access Object (DAO) pattern in this context would be used to separate the database operations (such as fetching book details, updating user records, and checking inventory) from the business logic of managing loans and accounts. For instance, there would be a `BookDAO` class responsible for all database interactions related to books, such as retrieving a book by its ISBN or updating its availability status. This abstraction allows the library system's main application code to focus on business rules and workflows, while the `BookDAO` handles the complex SQL queries and data management. This separation makes the system easier to maintain and test, as changes to the data source or business logic can be managed independently.\n\nIn plain words\n\n> DAO is an interface we provide over the base persistence mechanism.\n\nWikipedia says\n\n> In computer software, a data access object (DAO) is a pattern that provides an abstract interface to some type of database or other persistence mechanism.\n\nSequence diagram\n\n![Data Access Object sequence diagram](./etc/dao-sequence-diagram.png)\n\n## Programmatic Example of DAO Pattern in Java\n\nThere's a set of customers that need to be persisted to database. Additionally, we need the whole set of CRUD (create/read/update/delete) operations, so we can operate on customers easily.\n\nWalking through our customers example, here's the basic `Customer` entity.\n\n```java\n@Setter\n@Getter\n@ToString\n@EqualsAndHashCode(onlyExplicitlyIncluded = true)\n@AllArgsConstructor\npublic class Customer {\n\n    @EqualsAndHashCode.Include\n    private int id;\n    private String firstName;\n    private String lastName;\n}\n```\n\nHere's the `CustomerDao` interface and two different implementations for it. `InMemoryCustomerDao` keeps a simple map of customers in memory while `DBCustomerDao` is the real RDBMS implementation.\n\n```java\npublic interface CustomerDao {\n\n    Stream<Customer> getAll() throws Exception;\n\n    Optional<Customer> getById(int id) throws Exception;\n\n    boolean add(Customer customer) throws Exception;\n\n    boolean update(Customer customer) throws Exception;\n\n    boolean delete(Customer customer) throws Exception;\n}\n\npublic class InMemoryCustomerDao implements CustomerDao {\n\n    private final Map<Integer, Customer> idToCustomer = new HashMap<>();\n\n    // implement the interface using the map\n}\n\n@Slf4j\n@RequiredArgsConstructor\npublic class DbCustomerDao implements CustomerDao {\n\n  private final DataSource dataSource;\n\n  // implement the interface using the data source\n}\n```\n\nFinally, here's how we use our DAO to manage customers.\n\n```java\n\n@Slf4j\npublic class App {\n    private static final String DB_URL = \"jdbc:h2:mem:dao;DB_CLOSE_DELAY=-1\";\n    private static final String ALL_CUSTOMERS = \"customerDao.getAllCustomers(): \";\n\n    public static void main(final String[] args) throws Exception {\n        final var inMemoryDao = new InMemoryCustomerDao();\n        performOperationsUsing(inMemoryDao);\n\n        final var dataSource = createDataSource();\n        createSchema(dataSource);\n        final var dbDao = new DbCustomerDao(dataSource);\n        performOperationsUsing(dbDao);\n        deleteSchema(dataSource);\n    }\n\n    private static void deleteSchema(DataSource dataSource) throws SQLException {\n        try (var connection = dataSource.getConnection();\n             var statement = connection.createStatement()) {\n            statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL);\n        }\n    }\n\n    private static void createSchema(DataSource dataSource) throws SQLException {\n        try (var connection = dataSource.getConnection();\n             var statement = connection.createStatement()) {\n            statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL);\n        }\n    }\n\n    private static DataSource createDataSource() {\n        var dataSource = new JdbcDataSource();\n        dataSource.setURL(DB_URL);\n        return dataSource;\n    }\n\n    private static void performOperationsUsing(final CustomerDao customerDao) throws Exception {\n        addCustomers(customerDao);\n        LOGGER.info(ALL_CUSTOMERS);\n        try (var customerStream = customerDao.getAll()) {\n            customerStream.forEach(customer -> LOGGER.info(customer.toString()));\n        }\n        LOGGER.info(\"customerDao.getCustomerById(2): \" + customerDao.getById(2));\n        final var customer = new Customer(4, \"Dan\", \"Danson\");\n        customerDao.add(customer);\n        LOGGER.info(ALL_CUSTOMERS + customerDao.getAll());\n        customer.setFirstName(\"Daniel\");\n        customer.setLastName(\"Danielson\");\n        customerDao.update(customer);\n        LOGGER.info(ALL_CUSTOMERS);\n        try (var customerStream = customerDao.getAll()) {\n            customerStream.forEach(cust -> LOGGER.info(cust.toString()));\n        }\n        customerDao.delete(customer);\n        LOGGER.info(ALL_CUSTOMERS + customerDao.getAll());\n    }\n\n    private static void addCustomers(CustomerDao customerDao) throws Exception {\n        for (var customer : generateSampleCustomers()) {\n            customerDao.add(customer);\n        }\n    }\n\n    public static List<Customer> generateSampleCustomers() {\n        final var customer1 = new Customer(1, \"Adam\", \"Adamson\");\n        final var customer2 = new Customer(2, \"Bob\", \"Bobson\");\n        final var customer3 = new Customer(3, \"Carl\", \"Carlson\");\n        return List.of(customer1, customer2, customer3);\n    }\n}\n```\n\nThe program output:\n\n```\n10:02:09.788 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers(): \n10:02:09.793 [main] INFO com.iluwatar.dao.App -- Customer(id=1, firstName=Adam, lastName=Adamson)\n10:02:09.793 [main] INFO com.iluwatar.dao.App -- Customer(id=2, firstName=Bob, lastName=Bobson)\n10:02:09.793 [main] INFO com.iluwatar.dao.App -- Customer(id=3, firstName=Carl, lastName=Carlson)\n10:02:09.794 [main] INFO com.iluwatar.dao.App -- customerDao.getCustomerById(2): Optional[Customer(id=2, firstName=Bob, lastName=Bobson)]\n10:02:09.794 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@4c3e4790\n10:02:09.794 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers(): \n10:02:09.795 [main] INFO com.iluwatar.dao.App -- Customer(id=1, firstName=Adam, lastName=Adamson)\n10:02:09.795 [main] INFO com.iluwatar.dao.App -- Customer(id=2, firstName=Bob, lastName=Bobson)\n10:02:09.795 [main] INFO com.iluwatar.dao.App -- Customer(id=3, firstName=Carl, lastName=Carlson)\n10:02:09.795 [main] INFO com.iluwatar.dao.App -- Customer(id=4, firstName=Daniel, lastName=Danielson)\n10:02:09.795 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@5679c6c6\n10:02:09.894 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers(): \n10:02:09.895 [main] INFO com.iluwatar.dao.App -- Customer(id=1, firstName=Adam, lastName=Adamson)\n10:02:09.895 [main] INFO com.iluwatar.dao.App -- Customer(id=2, firstName=Bob, lastName=Bobson)\n10:02:09.895 [main] INFO com.iluwatar.dao.App -- Customer(id=3, firstName=Carl, lastName=Carlson)\n10:02:09.895 [main] INFO com.iluwatar.dao.App -- customerDao.getCustomerById(2): Optional[Customer(id=2, firstName=Bob, lastName=Bobson)]\n10:02:09.896 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@23282c25\n10:02:09.897 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers(): \n10:02:09.897 [main] INFO com.iluwatar.dao.App -- Customer(id=1, firstName=Adam, lastName=Adamson)\n10:02:09.897 [main] INFO com.iluwatar.dao.App -- Customer(id=2, firstName=Bob, lastName=Bobson)\n10:02:09.898 [main] INFO com.iluwatar.dao.App -- Customer(id=3, firstName=Carl, lastName=Carlson)\n10:02:09.898 [main] INFO com.iluwatar.dao.App -- Customer(id=4, firstName=Daniel, lastName=Danielson)\n10:02:09.898 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@f2f2cc1\n```\n\n## When to Use the Data Access Object Pattern in Java\n\nUse the Data Access Object in any of the following situations:\n\n* There is a need to abstract and encapsulate all access to the data source.\n* The application needs to support multiple types of databases or storage mechanisms without significant code changes.\n* You want to keep the database access clean and simple, and separate from business logic.\n\n## Data Access Object Pattern Java Tutorials\n\n* [The DAO Pattern in Java(Baeldung)](https://www.baeldung.com/java-dao-pattern)\n* [Data Access Object Pattern (TutorialsPoint)](https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm)\n\n## Real-World Applications of DAO Pattern in Java\n\n* Enterprise applications that require database interaction.\n* Applications requiring data access to be adaptable to multiple storage types (relational databases, XML files, flat files, etc.).\n* Frameworks providing generic data access functionalities.\n\n## Benefits and Trade-offs of Data Access Object Pattern\n\nBenefits:\n\n* Decoupling: Separates the data access logic from the business logic, enhancing modularity and clarity.\n* Reusability: DAOs can be reused across different parts of the application or even in different projects.\n* Testability: Simplifies testing by allowing business logic to be tested separately from the data access logic.\n* Flexibility: Makes it easier to switch underlying storage mechanisms with minimal impact on the application code.\n\nTrade-offs:\n\n* Layer Complexity: Introduces additional layers to the application, which can increase complexity and development time.\n* Overhead: For simple applications, the DAO pattern might introduce more overhead than necessary.\n* Learning Curve: Developers might need time to understand and implement the pattern effectively, especially in complex projects.\n\n## Related Java Design Patterns\n\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): Helps in abstracting the creation of DAOs, especially when supporting multiple databases or storage mechanisms.\n* [Factory](https://java-design-patterns.com/patterns/factory/): Can be used to instantiate DAOs dynamically, providing flexibility in the choice of implementation.\n* [Service Layer](https://java-design-patterns.com/patterns/service-layer/): Often used in conjunction with the DAO pattern to define application's boundaries and its set of available operations.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Might be employed to change the data access strategy at runtime, depending on the context.\n\n## References and Credits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/49u3r91)\n* [Expert One-on-One J2EE Design and Development](https://amzn.to/3vK3pfq)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3U5cxEI)\n* [Professional Java Development with the Spring Framework](https://amzn.to/49tANF0)\n"
  },
  {
    "path": "data-access-object/etc/dao.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" always-add-relationships=\"false\" generalizations=\"true\" realizations=\"true\" \n  associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.dao.App\" project=\"dao\" \n    file=\"/dao/src/main/java/com/iluwatar/dao/App.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"910\" y=\"191\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"2\" language=\"java\" name=\"com.iluwatar.dao.CustomerDao\" project=\"dao\" \n    file=\"/dao/src/main/java/com/iluwatar/dao/CustomerDao.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"536\" y=\"187\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.dao.InMemoryCustomerDao\" project=\"dao\" \n    file=\"/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"289\" y=\"455\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.dao.DBCustomerDao\" project=\"dao\" \n    file=\"/dao/src/main/java/com/iluwatar/dao/DBCustomerDao.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"751\" y=\"456\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"5\" language=\"java\" name=\"javax.sql.DataSource\" project=\"dao\" \n    file=\"/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1083\" y=\"459\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <association id=\"6\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"7\" name=\"dataSource\"/>      \n      <multiplicity id=\"8\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"9\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </realization>  \n  <dependency id=\"10\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </dependency>  \n  <realization id=\"11\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "data-access-object/etc/dao.urm.puml",
    "content": "@startuml\npackage com.iluwatar.dao {\n  class App {\n    - ALL_CUSTOMERS : String {static}\n    - DB_URL : String {static}\n    - log : Logger {static}\n    + App()\n    - addCustomers(customerDao : CustomerDao) {static}\n    - createDataSource() : DataSource {static}\n    - createSchema(dataSource : DataSource) {static}\n    - deleteSchema(dataSource : DataSource) {static}\n    + generateSampleCustomers() : List<Customer> {static}\n    + main(args : String[]) {static}\n    - performOperationsUsing(customerDao : CustomerDao) {static}\n  }\n  class Customer {\n    - firstName : String\n    - id : int\n    - lastName : String\n    + Customer(id : int, firstName : String, lastName : String)\n    + equals(that : Object) : boolean\n    + getFirstName() : String\n    + getId() : int\n    + getLastName() : String\n    + hashCode() : int\n    + setFirstName(firstName : String)\n    + setId(id : int)\n    + setLastName(lastName : String)\n    + toString() : String\n  }\n  interface CustomerDao {\n    + add(Customer) : boolean {abstract}\n    + delete(Customer) : boolean {abstract}\n    + getAll() : Stream<Customer> {abstract}\n    + getById(int) : Optional<Customer> {abstract}\n    + update(Customer) : boolean {abstract}\n  }\n  class CustomerSchemaSql {\n    + CREATE_SCHEMA_SQL : String {static}\n    + DELETE_SCHEMA_SQL : String {static}\n    - CustomerSchemaSql()\n  }\n  class DbCustomerDao {\n    - LOGGER : Logger {static}\n    - dataSource : DataSource\n    + DbCustomerDao(dataSource : DataSource)\n    + add(customer : Customer) : boolean\n    - createCustomer(resultSet : ResultSet) : Customer\n    + delete(customer : Customer) : boolean\n    + getAll() : Stream<Customer>\n    + getById(id : int) : Optional<Customer>\n    - getConnection() : Connection\n    - mutedClose(connection : Connection, statement : PreparedStatement, resultSet : ResultSet)\n    + update(customer : Customer) : boolean\n  }\n  class InMemoryCustomerDao {\n    - idToCustomer : Map<Integer, Customer>\n    + InMemoryCustomerDao()\n    + add(customer : Customer) : boolean\n    + delete(customer : Customer) : boolean\n    + getAll() : Stream<Customer>\n    + getById(id : int) : Optional<Customer>\n    + update(customer : Customer) : boolean\n  }\n}\nDbCustomerDao ..|> CustomerDao \nInMemoryCustomerDao ..|> CustomerDao \n@enduml"
  },
  {
    "path": "data-access-object/etc/data-access-object.urm.puml",
    "content": "@startuml\npackage com.iluwatar.dao {\n  class App {\n    - ALL_CUSTOMERS : String {static}\n    - DB_URL : String {static}\n    - LOGGER : Logger {static}\n    + App()\n    - addCustomers(customerDao : CustomerDao) {static}\n    - createDataSource() : DataSource {static}\n    - createSchema(dataSource : DataSource) {static}\n    - deleteSchema(dataSource : DataSource) {static}\n    + generateSampleCustomers() : List<Customer> {static}\n    + main(args : String[]) {static}\n    - performOperationsUsing(customerDao : CustomerDao) {static}\n  }\n  class Customer {\n    - firstName : String\n    - id : int\n    - lastName : String\n    + Customer(id : int, firstName : String, lastName : String)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getFirstName() : String\n    + getId() : int\n    + getLastName() : String\n    + hashCode() : int\n    + setFirstName(firstName : String)\n    + setId(id : int)\n    + setLastName(lastName : String)\n    + toString() : String\n  }\n  interface CustomerDao {\n    + add(Customer) : boolean {abstract}\n    + delete(Customer) : boolean {abstract}\n    + getAll() : Stream<Customer> {abstract}\n    + getById(int) : Optional<Customer> {abstract}\n    + update(Customer) : boolean {abstract}\n  }\n  class CustomerSchemaSql {\n    + CREATE_SCHEMA_SQL : String {static}\n    + DELETE_SCHEMA_SQL : String {static}\n    - CustomerSchemaSql()\n  }\n  class DbCustomerDao {\n    - LOGGER : Logger {static}\n    - dataSource : DataSource\n    + DbCustomerDao(dataSource : DataSource)\n    + add(customer : Customer) : boolean\n    - createCustomer(resultSet : ResultSet) : Customer\n    + delete(customer : Customer) : boolean\n    + getAll() : Stream<Customer>\n    + getById(id : int) : Optional<Customer>\n    - getConnection() : Connection\n    - mutedClose(connection : Connection, statement : PreparedStatement, resultSet : ResultSet)\n    + update(customer : Customer) : boolean\n  }\n  class InMemoryCustomerDao {\n    - idToCustomer : Map<Integer, Customer>\n    + InMemoryCustomerDao()\n    + add(customer : Customer) : boolean\n    + delete(customer : Customer) : boolean\n    + getAll() : Stream<Customer>\n    + getById(id : int) : Optional<Customer>\n    + update(customer : Customer) : boolean\n  }\n}\nDbCustomerDao ..|> CustomerDao \nInMemoryCustomerDao ..|> CustomerDao \n@enduml"
  },
  {
    "path": "data-access-object/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>data-access-object</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>com.h2database</groupId>\n      <artifactId>h2</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.dao.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "data-access-object/src/main/java/com/iluwatar/dao/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dao;\n\nimport java.sql.SQLException;\nimport java.util.List;\nimport javax.sql.DataSource;\nimport lombok.extern.slf4j.Slf4j;\nimport org.h2.jdbcx.JdbcDataSource;\n\n/**\n * Data Access Object (DAO) is an object that provides an abstract interface to some type of\n * database or other persistence mechanism. By mapping application calls to the persistence layer,\n * DAO provide some specific data operations without exposing details of the database. This\n * isolation supports the Single responsibility principle. It separates what data accesses the\n * application needs, in terms of domain-specific objects and data types (the public interface of\n * the DAO), from how these needs can be satisfied with a specific DBMS.\n *\n * <p>With the DAO pattern, we can use various method calls to retrieve/add/delete/update data\n * without directly interacting with the data source. The below example demonstrates basic CRUD\n * operations: select, add, update, and delete.\n */\n@Slf4j\npublic class App {\n  private static final String DB_URL = \"jdbc:h2:mem:dao;DB_CLOSE_DELAY=-1\";\n  private static final String ALL_CUSTOMERS = \"customerDao.getAllCustomers(): \";\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args.\n   * @throws Exception if any error occurs.\n   */\n  public static void main(final String[] args) throws Exception {\n    final var inMemoryDao = new InMemoryCustomerDao();\n    performOperationsUsing(inMemoryDao);\n\n    final var dataSource = createDataSource();\n    createSchema(dataSource);\n    final var dbDao = new DbCustomerDao(dataSource);\n    performOperationsUsing(dbDao);\n    deleteSchema(dataSource);\n  }\n\n  private static void deleteSchema(DataSource dataSource) throws SQLException {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL);\n    }\n  }\n\n  private static void createSchema(DataSource dataSource) throws SQLException {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL);\n    }\n  }\n\n  private static DataSource createDataSource() {\n    var dataSource = new JdbcDataSource();\n    dataSource.setURL(DB_URL);\n    return dataSource;\n  }\n\n  private static void performOperationsUsing(final CustomerDao customerDao) throws Exception {\n    addCustomers(customerDao);\n    LOGGER.info(ALL_CUSTOMERS);\n    try (var customerStream = customerDao.getAll()) {\n      customerStream.forEach(customer -> LOGGER.info(customer.toString()));\n    }\n    LOGGER.info(\"customerDao.getCustomerById(2): \" + customerDao.getById(2));\n    final var customer = new Customer(4, \"Dan\", \"Danson\");\n    customerDao.add(customer);\n    LOGGER.info(ALL_CUSTOMERS + customerDao.getAll());\n    customer.setFirstName(\"Daniel\");\n    customer.setLastName(\"Danielson\");\n    customerDao.update(customer);\n    LOGGER.info(ALL_CUSTOMERS);\n    try (var customerStream = customerDao.getAll()) {\n      customerStream.forEach(cust -> LOGGER.info(cust.toString()));\n    }\n    customerDao.delete(customer);\n    LOGGER.info(ALL_CUSTOMERS + customerDao.getAll());\n  }\n\n  private static void addCustomers(CustomerDao customerDao) throws Exception {\n    for (var customer : generateSampleCustomers()) {\n      customerDao.add(customer);\n    }\n  }\n\n  /**\n   * Generate customers.\n   *\n   * @return list of customers.\n   */\n  public static List<Customer> generateSampleCustomers() {\n    final var customer1 = new Customer(1, \"Adam\", \"Adamson\");\n    final var customer2 = new Customer(2, \"Bob\", \"Bobson\");\n    final var customer3 = new Customer(3, \"Carl\", \"Carlson\");\n    return List.of(customer1, customer2, customer3);\n  }\n}\n"
  },
  {
    "path": "data-access-object/src/main/java/com/iluwatar/dao/CustomException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dao;\n\nimport java.io.Serial;\n\n/** Custom exception. */\npublic class CustomException extends Exception {\n\n  @Serial private static final long serialVersionUID = 1L;\n\n  public CustomException(String message, Throwable cause) {\n    super(message, cause);\n  }\n}\n"
  },
  {
    "path": "data-access-object/src/main/java/com/iluwatar/dao/Customer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dao;\n\nimport lombok.AllArgsConstructor;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\n/** A customer POJO that represents the data that will be read from the data source. */\n@Setter\n@Getter\n@ToString\n@EqualsAndHashCode(onlyExplicitlyIncluded = true)\n@AllArgsConstructor\npublic class Customer {\n\n  @EqualsAndHashCode.Include private int id;\n  private String firstName;\n  private String lastName;\n}\n"
  },
  {
    "path": "data-access-object/src/main/java/com/iluwatar/dao/CustomerDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dao;\n\nimport java.util.Optional;\nimport java.util.stream.Stream;\n\n/**\n * In an application the Data Access Object (DAO) is a part of Data access layer. It is an object\n * that provides an interface to some type of persistence mechanism. By mapping application calls to\n * the persistence layer, DAO provides some specific data operations without exposing details of the\n * database. This isolation supports the Single responsibility principle. It separates what data\n * accesses the application needs, in terms of domain-specific objects and data types (the public\n * interface of the DAO), from how these needs can be satisfied with a specific DBMS, database\n * schema, etc.\n *\n * <p>Any change in the way data is stored and retrieved will not change the client code as the\n * client will be using interface and need not worry about exact source.\n *\n * @see InMemoryCustomerDao\n * @see DbCustomerDao\n */\npublic interface CustomerDao {\n\n  /**\n   * Get all customers.\n   *\n   * @return all the customers as a stream. The stream may be lazily or eagerly evaluated based on\n   *     the implementation. The stream must be closed after use.\n   * @throws Exception if any error occurs.\n   */\n  Stream<Customer> getAll() throws Exception;\n\n  /**\n   * Get customer as Optional by id.\n   *\n   * @param id unique identifier of the customer.\n   * @return an optional with customer if a customer with unique identifier <code>id</code> exists,\n   *     empty optional otherwise.\n   * @throws Exception if any error occurs.\n   */\n  Optional<Customer> getById(int id) throws Exception;\n\n  /**\n   * Add a customer.\n   *\n   * @param customer the customer to be added.\n   * @return true if customer is successfully added, false if customer already exists.\n   * @throws Exception if any error occurs.\n   */\n  boolean add(Customer customer) throws Exception;\n\n  /**\n   * Update a customer.\n   *\n   * @param customer the customer to be updated.\n   * @return true if customer exists and is successfully updated, false otherwise.\n   * @throws Exception if any error occurs.\n   */\n  boolean update(Customer customer) throws Exception;\n\n  /**\n   * Delete a customer.\n   *\n   * @param customer the customer to be deleted.\n   * @return true if customer exists and is successfully deleted, false otherwise.\n   * @throws Exception if any error occurs.\n   */\n  boolean delete(Customer customer) throws Exception;\n}\n"
  },
  {
    "path": "data-access-object/src/main/java/com/iluwatar/dao/CustomerSchemaSql.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dao;\n\n/** Customer Schema SQL Class. */\npublic final class CustomerSchemaSql {\n\n  private CustomerSchemaSql() {}\n\n  public static final String CREATE_SCHEMA_SQL =\n      \"CREATE TABLE CUSTOMERS (ID NUMBER, FNAME VARCHAR(100), \" + \"LNAME VARCHAR(100))\";\n\n  public static final String DELETE_SCHEMA_SQL = \"DROP TABLE CUSTOMERS\";\n}\n"
  },
  {
    "path": "data-access-object/src/main/java/com/iluwatar/dao/DbCustomerDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dao;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Optional;\nimport java.util.Spliterator;\nimport java.util.Spliterators;\nimport java.util.function.Consumer;\nimport java.util.stream.Stream;\nimport java.util.stream.StreamSupport;\nimport javax.sql.DataSource;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/** An implementation of {@link CustomerDao} that persists customers in RDBMS. */\n@Slf4j\n@RequiredArgsConstructor\npublic class DbCustomerDao implements CustomerDao {\n\n  private final DataSource dataSource;\n\n  /**\n   * Get all customers as Java Stream.\n   *\n   * @return a lazily populated stream of customers. Note the stream returned must be closed to free\n   *     all the acquired resources. The stream keeps an open connection to the database till it is\n   *     complete or is closed manually.\n   */\n  @Override\n  public Stream<Customer> getAll() throws Exception {\n    try {\n      var connection = getConnection();\n      var statement = connection.prepareStatement(\"SELECT * FROM CUSTOMERS\"); // NOSONAR\n      var resultSet = statement.executeQuery(); // NOSONAR\n      return StreamSupport.stream(\n              new Spliterators.AbstractSpliterator<Customer>(Long.MAX_VALUE, Spliterator.ORDERED) {\n\n                @Override\n                public boolean tryAdvance(Consumer<? super Customer> action) {\n                  try {\n                    if (!resultSet.next()) {\n                      return false;\n                    }\n                    action.accept(createCustomer(resultSet));\n                    return true;\n                  } catch (SQLException e) {\n                    throw new RuntimeException(e); // NOSONAR\n                  }\n                }\n              },\n              false)\n          .onClose(() -> mutedClose(connection, statement, resultSet));\n    } catch (SQLException e) {\n      throw new CustomException(e.getMessage(), e);\n    }\n  }\n\n  private Connection getConnection() throws SQLException {\n    return dataSource.getConnection();\n  }\n\n  private void mutedClose(Connection connection, PreparedStatement statement, ResultSet resultSet) {\n    try {\n      resultSet.close();\n      statement.close();\n      connection.close();\n    } catch (SQLException e) {\n      LOGGER.info(\"Exception thrown \" + e.getMessage());\n    }\n  }\n\n  private Customer createCustomer(ResultSet resultSet) throws SQLException {\n    return new Customer(\n        resultSet.getInt(\"ID\"), resultSet.getString(\"FNAME\"), resultSet.getString(\"LNAME\"));\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public Optional<Customer> getById(int id) throws Exception {\n\n    ResultSet resultSet = null;\n\n    try (var connection = getConnection();\n        var statement = connection.prepareStatement(\"SELECT * FROM CUSTOMERS WHERE ID = ?\")) {\n\n      statement.setInt(1, id);\n      resultSet = statement.executeQuery();\n      if (resultSet.next()) {\n        return Optional.of(createCustomer(resultSet));\n      } else {\n        return Optional.empty();\n      }\n    } catch (SQLException ex) {\n      throw new CustomException(ex.getMessage(), ex);\n    } finally {\n      if (resultSet != null) {\n        resultSet.close();\n      }\n    }\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public boolean add(Customer customer) throws Exception {\n    if (getById(customer.getId()).isPresent()) {\n      return false;\n    }\n\n    try (var connection = getConnection();\n        var statement = connection.prepareStatement(\"INSERT INTO CUSTOMERS VALUES (?,?,?)\")) {\n      statement.setInt(1, customer.getId());\n      statement.setString(2, customer.getFirstName());\n      statement.setString(3, customer.getLastName());\n      statement.execute();\n      return true;\n    } catch (SQLException ex) {\n      throw new CustomException(ex.getMessage(), ex);\n    }\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public boolean update(Customer customer) throws Exception {\n    try (var connection = getConnection();\n        var statement =\n            connection.prepareStatement(\"UPDATE CUSTOMERS SET FNAME = ?, LNAME = ? WHERE ID = ?\")) {\n      statement.setString(1, customer.getFirstName());\n      statement.setString(2, customer.getLastName());\n      statement.setInt(3, customer.getId());\n      return statement.executeUpdate() > 0;\n    } catch (SQLException ex) {\n      throw new CustomException(ex.getMessage(), ex);\n    }\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public boolean delete(Customer customer) throws Exception {\n    try (var connection = getConnection();\n        var statement = connection.prepareStatement(\"DELETE FROM CUSTOMERS WHERE ID = ?\")) {\n      statement.setInt(1, customer.getId());\n      return statement.executeUpdate() > 0;\n    } catch (SQLException ex) {\n      throw new CustomException(ex.getMessage(), ex);\n    }\n  }\n}\n"
  },
  {
    "path": "data-access-object/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dao;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.stream.Stream;\n\n/**\n * An in memory implementation of {@link CustomerDao}, which stores the customers in JVM memory and\n * data is lost when the application exits. <br>\n * This implementation is useful as temporary database or for testing.\n */\npublic class InMemoryCustomerDao implements CustomerDao {\n\n  private final Map<Integer, Customer> idToCustomer = new HashMap<>();\n\n  /** An eagerly evaluated stream of customers stored in memory. */\n  @Override\n  public Stream<Customer> getAll() {\n    return idToCustomer.values().stream();\n  }\n\n  @Override\n  public Optional<Customer> getById(final int id) {\n    return Optional.ofNullable(idToCustomer.get(id));\n  }\n\n  @Override\n  public boolean add(final Customer customer) {\n    if (getById(customer.getId()).isPresent()) {\n      return false;\n    }\n\n    idToCustomer.put(customer.getId(), customer);\n    return true;\n  }\n\n  @Override\n  public boolean update(final Customer customer) {\n    return idToCustomer.replace(customer.getId(), customer) != null;\n  }\n\n  @Override\n  public boolean delete(final Customer customer) {\n    return idToCustomer.remove(customer.getId()) != null;\n  }\n}\n"
  },
  {
    "path": "data-access-object/src/test/java/com/iluwatar/dao/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dao;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that DAO example runs without errors. */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteDaoWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "data-access-object/src/test/java/com/iluwatar/dao/CustomerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dao;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests {@link Customer}. */\nclass CustomerTest {\n\n  private Customer customer;\n  private static final int ID = 1;\n  private static final String FIRSTNAME = \"Winston\";\n  private static final String LASTNAME = \"Churchill\";\n\n  @BeforeEach\n  void setUp() {\n    customer = new Customer(ID, FIRSTNAME, LASTNAME);\n  }\n\n  @Test\n  void getAndSetId() {\n    final var newId = 2;\n    customer.setId(newId);\n    assertEquals(newId, customer.getId());\n  }\n\n  @Test\n  void getAndSetFirstname() {\n    final var newFirstname = \"Bill\";\n    customer.setFirstName(newFirstname);\n    assertEquals(newFirstname, customer.getFirstName());\n  }\n\n  @Test\n  void getAndSetLastname() {\n    final var newLastname = \"Clinton\";\n    customer.setLastName(newLastname);\n    assertEquals(newLastname, customer.getLastName());\n  }\n\n  @Test\n  void notEqualWithDifferentId() {\n    final var newId = 2;\n    final var otherCustomer = new Customer(newId, FIRSTNAME, LASTNAME);\n    assertNotEquals(customer, otherCustomer);\n    assertNotEquals(customer.hashCode(), otherCustomer.hashCode());\n  }\n\n  @Test\n  void equalsWithSameObjectValues() {\n    final var otherCustomer = new Customer(ID, FIRSTNAME, LASTNAME);\n    assertEquals(customer, otherCustomer);\n    assertEquals(customer.hashCode(), otherCustomer.hashCode());\n  }\n\n  @Test\n  void equalsWithSameObjects() {\n    assertEquals(customer, customer);\n    assertEquals(customer.hashCode(), customer.hashCode());\n  }\n\n  @Test\n  void testToString() {\n    assertEquals(\n        String.format(\n            \"Customer(id=%s, firstName=%s, lastName=%s)\",\n            customer.getId(), customer.getFirstName(), customer.getLastName()),\n        customer.toString());\n  }\n}\n"
  },
  {
    "path": "data-access-object/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dao;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assumptions.assumeTrue;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.SQLException;\nimport javax.sql.DataSource;\nimport org.h2.jdbcx.JdbcDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\n/** Tests {@link DbCustomerDao}. */\nclass DbCustomerDaoTest {\n\n  private static final String DB_URL = \"jdbc:h2:mem:dao;DB_CLOSE_DELAY=-1\";\n  private DbCustomerDao dao;\n  private final Customer existingCustomer = new Customer(1, \"Freddy\", \"Krueger\");\n\n  /**\n   * Creates customers schema.\n   *\n   * @throws SQLException if there is any error while creating schema.\n   */\n  @BeforeEach\n  void createSchema() throws SQLException {\n    try (var connection = DriverManager.getConnection(DB_URL);\n        var statement = connection.createStatement()) {\n      statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL);\n    }\n  }\n\n  /** Represents the scenario where DB connectivity is present. */\n  @Nested\n  class ConnectionSuccess {\n\n    /**\n     * Setup for connection success scenario.\n     *\n     * @throws Exception if any error occurs.\n     */\n    @BeforeEach\n    void setUp() throws Exception {\n      var dataSource = new JdbcDataSource();\n      dataSource.setURL(DB_URL);\n      dao = new DbCustomerDao(dataSource);\n      var result = dao.add(existingCustomer);\n      assertTrue(result);\n    }\n\n    /**\n     * Represents the scenario when DAO operations are being performed on a non-existing customer.\n     */\n    @Nested\n    class NonExistingCustomer {\n\n      @Test\n      void addingShouldResultInSuccess() throws Exception {\n        try (var allCustomers = dao.getAll()) {\n          assumeTrue(allCustomers.count() == 1);\n        }\n\n        final var nonExistingCustomer = new Customer(2, \"Robert\", \"Englund\");\n        var result = dao.add(nonExistingCustomer);\n        assertTrue(result);\n\n        assertCustomerCountIs(2);\n        assertEquals(nonExistingCustomer, dao.getById(nonExistingCustomer.getId()).get());\n      }\n\n      @Test\n      void deletionShouldBeFailureAndNotAffectExistingCustomers() throws Exception {\n        final var nonExistingCustomer = new Customer(2, \"Robert\", \"Englund\");\n        var result = dao.delete(nonExistingCustomer);\n\n        assertFalse(result);\n        assertCustomerCountIs(1);\n      }\n\n      @Test\n      void updationShouldBeFailureAndNotAffectExistingCustomers() throws Exception {\n        final var nonExistingId = getNonExistingCustomerId();\n        final var newFirstname = \"Douglas\";\n        final var newLastname = \"MacArthur\";\n        final var customer = new Customer(nonExistingId, newFirstname, newLastname);\n        var result = dao.update(customer);\n\n        assertFalse(result);\n        assertFalse(dao.getById(nonExistingId).isPresent());\n      }\n\n      @Test\n      void retrieveShouldReturnNoCustomer() throws Exception {\n        assertFalse(dao.getById(getNonExistingCustomerId()).isPresent());\n      }\n    }\n\n    /**\n     * Represents a scenario where DAO operations are being performed on an already existing\n     * customer.\n     */\n    @Nested\n    class ExistingCustomer {\n\n      @Test\n      void addingShouldResultInFailureAndNotAffectExistingCustomers() throws Exception {\n        var existingCustomer = new Customer(1, \"Freddy\", \"Krueger\");\n        var result = dao.add(existingCustomer);\n\n        assertFalse(result);\n        assertCustomerCountIs(1);\n        assertEquals(existingCustomer, dao.getById(existingCustomer.getId()).get());\n      }\n\n      @Test\n      void deletionShouldBeSuccessAndCustomerShouldBeNonAccessible() throws Exception {\n        var result = dao.delete(existingCustomer);\n\n        assertTrue(result);\n        assertCustomerCountIs(0);\n        assertFalse(dao.getById(existingCustomer.getId()).isPresent());\n      }\n\n      @Test\n      void updationShouldBeSuccessAndAccessingTheSameCustomerShouldReturnUpdatedInformation()\n          throws Exception {\n        final var newFirstname = \"Bernard\";\n        final var newLastname = \"Montgomery\";\n        final var customer = new Customer(existingCustomer.getId(), newFirstname, newLastname);\n        var result = dao.update(customer);\n\n        assertTrue(result);\n\n        final var cust = dao.getById(existingCustomer.getId()).get();\n        assertEquals(newFirstname, cust.getFirstName());\n        assertEquals(newLastname, cust.getLastName());\n      }\n    }\n  }\n\n  /**\n   * Represents a scenario where DB connectivity is not present due to network issue, or DB service\n   * unavailable.\n   */\n  @Nested\n  class ConnectivityIssue {\n\n    private static final String EXCEPTION_CAUSE = \"Connection not available\";\n\n    /**\n     * setup a connection failure scenario.\n     *\n     * @throws SQLException if any error occurs.\n     */\n    @BeforeEach\n    void setUp() throws SQLException {\n      dao = new DbCustomerDao(mockedDatasource());\n    }\n\n    private DataSource mockedDatasource() throws SQLException {\n      var mockedDataSource = mock(DataSource.class);\n      var mockedConnection = mock(Connection.class);\n      var exception = new SQLException(EXCEPTION_CAUSE);\n      doThrow(exception).when(mockedConnection).prepareStatement(Mockito.anyString());\n      doReturn(mockedConnection).when(mockedDataSource).getConnection();\n      return mockedDataSource;\n    }\n\n    @Test\n    void addingACustomerFailsWithExceptionAsFeedbackToClient() {\n      assertThrows(Exception.class, () -> dao.add(new Customer(2, \"Bernard\", \"Montgomery\")));\n    }\n\n    @Test\n    void deletingACustomerFailsWithExceptionAsFeedbackToTheClient() {\n      assertThrows(Exception.class, () -> dao.delete(existingCustomer));\n    }\n\n    @Test\n    void updatingACustomerFailsWithFeedbackToTheClient() {\n      final var newFirstname = \"Bernard\";\n      final var newLastname = \"Montgomery\";\n      assertThrows(\n          Exception.class,\n          () -> dao.update(new Customer(existingCustomer.getId(), newFirstname, newLastname)));\n    }\n\n    @Test\n    void retrievingACustomerByIdFailsWithExceptionAsFeedbackToClient() {\n      assertThrows(Exception.class, () -> dao.getById(existingCustomer.getId()));\n    }\n\n    @Test\n    void retrievingAllCustomersFailsWithExceptionAsFeedbackToClient() {\n      assertThrows(Exception.class, () -> dao.getAll());\n    }\n  }\n\n  /**\n   * Delete customer schema for fresh setup per test.\n   *\n   * @throws SQLException if any error occurs.\n   */\n  @AfterEach\n  void deleteSchema() throws SQLException {\n    try (var connection = DriverManager.getConnection(DB_URL);\n        var statement = connection.createStatement()) {\n      statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL);\n    }\n  }\n\n  private void assertCustomerCountIs(int count) throws Exception {\n    try (var allCustomers = dao.getAll()) {\n      assertEquals(count, allCustomers.count());\n    }\n  }\n\n  /**\n   * An arbitrary number which does not correspond to an active Customer id.\n   *\n   * @return an int of a customer id which doesn't exist\n   */\n  private int getNonExistingCustomerId() {\n    return 999;\n  }\n}\n"
  },
  {
    "path": "data-access-object/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dao;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assumptions.assumeTrue;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\n\n/** Tests {@link InMemoryCustomerDao}. */\nclass InMemoryCustomerDaoTest {\n\n  private InMemoryCustomerDao dao;\n  private static final Customer CUSTOMER = new Customer(1, \"Freddy\", \"Krueger\");\n\n  @BeforeEach\n  void setUp() {\n    dao = new InMemoryCustomerDao();\n    assertTrue(dao.add(CUSTOMER));\n  }\n\n  /**\n   * Represents the scenario when the DAO operations are being performed on a non-existent customer.\n   */\n  @Nested\n  class NonExistingCustomer {\n\n    @Test\n    void addingShouldResultInSuccess() throws Exception {\n      try (var allCustomers = dao.getAll()) {\n        assumeTrue(allCustomers.count() == 1);\n      }\n\n      final var nonExistingCustomer = new Customer(2, \"Robert\", \"Englund\");\n      var result = dao.add(nonExistingCustomer);\n      assertTrue(result);\n\n      assertCustomerCountIs(2);\n      assertEquals(nonExistingCustomer, dao.getById(nonExistingCustomer.getId()).get());\n    }\n\n    @Test\n    void deletionShouldBeFailureAndNotAffectExistingCustomers() throws Exception {\n      final var nonExistingCustomer = new Customer(2, \"Robert\", \"Englund\");\n      var result = dao.delete(nonExistingCustomer);\n\n      assertFalse(result);\n      assertCustomerCountIs(1);\n    }\n\n    @Test\n    void updateShouldBeFailureAndNotAffectExistingCustomers() {\n      final var nonExistingId = getNonExistingCustomerId();\n      final var newFirstname = \"Douglas\";\n      final var newLastname = \"MacArthur\";\n      final var customer = new Customer(nonExistingId, newFirstname, newLastname);\n      var result = dao.update(customer);\n\n      assertFalse(result);\n      assertFalse(dao.getById(nonExistingId).isPresent());\n    }\n\n    @Test\n    void retrieveShouldReturnNoCustomer() throws Exception {\n      assertFalse(dao.getById(getNonExistingCustomerId()).isPresent());\n    }\n  }\n\n  /**\n   * Represents the scenario when the DAO operations are being performed on an already existing\n   * customer.\n   */\n  @Nested\n  class ExistingCustomer {\n\n    @Test\n    void addingShouldResultInFailureAndNotAffectExistingCustomers() throws Exception {\n      var result = dao.add(CUSTOMER);\n\n      assertFalse(result);\n      assertCustomerCountIs(1);\n      assertEquals(CUSTOMER, dao.getById(CUSTOMER.getId()).get());\n    }\n\n    @Test\n    void deletionShouldBeSuccessAndCustomerShouldBeNonAccessible() throws Exception {\n      var result = dao.delete(CUSTOMER);\n\n      assertTrue(result);\n      assertCustomerCountIs(0);\n      assertFalse(dao.getById(CUSTOMER.getId()).isPresent());\n    }\n\n    @Test\n    void updationShouldBeSuccessAndAccessingTheSameCustomerShouldReturnUpdatedInformation()\n        throws Exception {\n      final var newFirstname = \"Bernard\";\n      final var newLastname = \"Montgomery\";\n      final var customer = new Customer(CUSTOMER.getId(), newFirstname, newLastname);\n      var result = dao.update(customer);\n\n      assertTrue(result);\n\n      final var cust = dao.getById(CUSTOMER.getId()).get();\n      assertEquals(newFirstname, cust.getFirstName());\n      assertEquals(newLastname, cust.getLastName());\n    }\n\n    @Test\n    void retriveShouldReturnTheCustomer() {\n      var optionalCustomer = dao.getById(CUSTOMER.getId());\n\n      assertTrue(optionalCustomer.isPresent());\n      assertEquals(CUSTOMER, optionalCustomer.get());\n    }\n  }\n\n  /**\n   * An arbitrary number which does not correspond to an active Customer id.\n   *\n   * @return an int of a customer id which doesn't exist\n   */\n  private int getNonExistingCustomerId() {\n    return 999;\n  }\n\n  private void assertCustomerCountIs(int count) throws Exception {\n    try (var allCustomers = dao.getAll()) {\n      assertEquals(count, allCustomers.count());\n    }\n  }\n}\n"
  },
  {
    "path": "data-bus/.gitignore",
    "content": "/target\n"
  },
  {
    "path": "data-bus/README.md",
    "content": "---\ntitle: \"Data Bus Pattern in Java: Unifying Component Communication Efficiently\"\nshortTitle: Data Bus\ndescription: \"Explore the Data Bus pattern in Java for centralized communication and event handling. Learn how to decouple components, enhance scalability, and maintainability with practical examples and real-world applications.\"\ncategory: Messaging\nlanguage: en\ntag:\n  - Decoupling\n  - Event-driven\n  - Messaging\n  - Publish/subscribe\n  - Scalability\n---\n\n## Also known as\n\n* Event Bus\n* Message Bus\n\n## Intent of Data Bus Design Pattern\n\nThe Data Bus design pattern aims to provide a centralized communication channel through which various components of a system can exchange data without being directly connected, thus promoting loose coupling and enhancing scalability and maintainability.\n\n## Detailed Explanation of Data Bus Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a large airport as an analogous real-world example of the Data Bus pattern. In an airport, various airlines, passengers, baggage handlers, and security personnel all need to communicate and share information. Instead of each entity communicating directly with every other entity, the airport uses a centralized announcement system (the Data Bus). Flight information, security alerts, and other critical updates are broadcast over this system, and each entity listens for the messages relevant to them. This setup allows the airport to decouple the communication process, ensuring that each entity only receives the information they need, while allowing the system to scale and integrate new entities without disrupting the existing ones. This is similar to how the Data Bus pattern in Java promotes centralized communication and event handling, enhancing system scalability and maintainability.\n\nIn plain words\n\n> Data Bus is a design pattern that connects components of an application for communication based on the type of message or event being transferred. This pattern promotes decoupling, making it easier to scale and maintain the system by allowing components to communicate without direct dependencies.\n\nSequence diagram\n\n![Data Bus Sequence Diagram](./etc/data-bus-sequence-diagram.png)\n\n## Programmatic Example of Data Bus Pattern in Java\n\nSay you have an app that enables online bookings and participation in events. You want the app to send notifications, such as event advertisements, to all ordinary members of the community or organization holding the events. However, you do not want to send such advertisements to event administrators or organizers. Instead, you want to send them notifications about the timing of new advertisements sent to all members. The Data Bus enables you to selectively notify community members by type (ordinary members or event administrators) by making their classes or components only accept messages of a certain type. Thus, ordinary members and administrators do not need to know about each other or the specific classes or components used to notify the entire community, except for knowing the type of messages being sent.\n\nIn the online events app example above, we first define our `Member` interface and its implementations: `MessageCollectorMember` (ordinary community members) and `StatusMember` (event administrators or organizers).\n\n```java\npublic interface Member extends Consumer<DataType> {\n\n    void accept(DataType event);\n}\n```\n\nNext, we implement a data bus to subscribe or unsubscribe members and to publish events to notify all community members.\n\n```java\npublic class DataBus {\n\n    private static final DataBus INSTANCE = new DataBus();\n\n    private final Set<Member> listeners = new HashSet<>();\n\n    public static DataBus getInstance() {\n        return INSTANCE;\n    }\n\n    public void subscribe(final Member member) {\n        this.listeners.add(member);\n    }\n\n    public void unsubscribe(final Member member) {\n        this.listeners.remove(member);\n    }\n\n    public void publish(final DataType event) {\n        event.setDataBus(this);\n\n        listeners.forEach(\n                listener -> listener.accept(event));\n    }\n}\n```\n\nThe `accept` method is applied to each member in the `publish` method.\n\nFor ordinary community members (`MessageCollectorMember`), the `accept` method can handle only `MessageData` type messages.\n\n```java\npublic class MessageCollectorMember implements Member {\n\n    private final String name;\n\n    private final List<String> messages = new ArrayList<>();\n\n    public MessageCollectorMember(String name) {\n        this.name = name;\n    }\n\n    @Override\n    public void accept(final DataType data) {\n        if (data instanceof MessageData) {\n            handleEvent((MessageData) data);\n        }\n    }\n}\n```\n\nFor event administrators or organizers (`StatusMember`), the `accept` method can handle `StartingData` and `StoppingData` type messages.\n\n```java\npublic class StatusMember implements Member {\n\n    private final int id;\n\n    private LocalDateTime started;\n\n    private LocalDateTime stopped;\n\n    public StatusMember(int id) {\n        this.id = id;\n    }\n\n    @Override\n    public void accept(final DataType data) {\n        if (data instanceof StartingData) {\n            handleEvent((StartingData) data);\n        } else if (data instanceof StoppingData) {\n            handleEvent((StoppingData) data);\n        }\n    }\n}\n```\n\nHere is the `App` class to demonstrate the Data Bus pattern in action:\n\n```java\nclass App {\n\n    public static void main(String[] args) {\n        final var bus = DataBus.getInstance();\n        bus.subscribe(new StatusMember(1));\n        bus.subscribe(new StatusMember(2));\n        final var foo = new MessageCollectorMember(\"Foo\");\n        final var bar = new MessageCollectorMember(\"Bar\");\n        bus.subscribe(foo);\n        bus.publish(StartingData.of(LocalDateTime.now()));\n    }\n}\n```\n\nWhen the data bus publishes a message, the output is as follows:\n\n```\n02:33:57.627 [main] INFO com.iluwatar.databus.members.StatusMember - Receiver 2 sees application started at 2022-10-26T02:33:57.613529100\n02:33:57.633 [main] INFO com.iluwatar.databus.members.StatusMember - Receiver 1 sees application started at 2022-10-26T02:33:57.613529100\n```\n\nAs shown, `MessageCollectorMembers` only accept messages of type `MessageData`, so they do not see the `StartingData` or `StoppingData` messages, which are only visible to `StatusMember` (the event administrators or organizers). This selective message handling prevents ordinary community members from receiving administrative notifications.\n\n## When to Use the Data Bus Pattern in Java\n\n* When multiple components need to share data or events but direct coupling is undesirable.\n* In complex, event-driven systems where the flow of information varies dynamically.\n* In distributed systems where components might be deployed across different environments.\n* In microservices architectures for inter-service communication.\n\n## Real-World Applications of Data Bus Pattern in Java\n\n* Event handling systems in large-scale applications.\n* Microservices architectures for inter-service communication.\n* Real-time data processing systems, such as stock trading platforms.\n* In frameworks like Spring, particularly with its application event mechanism.\n\n## Benefits and Trade-offs of Data Bus Pattern\n\nBenefits:\n\n* Loose Coupling: Components can interact without having direct dependencies on each other.\n* Flexibility: New subscribers or publishers can be added without impacting existing components.\n* Scalability: The pattern supports scaling components independently.\n* Reusability: The bus and components can be reused across different systems.\n\nTrade-offs:\n\n* Complexity: Introducing a data bus can add complexity to the system architecture.\n* Performance Overhead: The additional layer of communication may introduce latency.\n* Debugging Difficulty: Tracing data flow through the bus can be challenging, especially in systems with many events.\n\n## Related Java Design Patterns\n\n* [Mediator](https://java-design-patterns.com/patterns/mediator/): Facilitates communication between components, but unlike Data Bus, it centralizes control.\n* [Observer](https://java-design-patterns.com/patterns/observer/): Similar in nature to the publish-subscribe mechanism used in Data Bus for notifying changes to multiple objects.\n* Publish/Subscribe: The Data Bus pattern is often implemented using the publish-subscribe mechanism, where publishers post messages to the bus without knowledge of the subscribers.\n\n## References and Credits\n\n* [Enterprise Integration Patterns](https://amzn.to/3J6WoYS)\n* [Pattern-Oriented Software Architecture, Volume 4: A Pattern Language for Distributed Computing](https://amzn.to/3PTRGBM)\n"
  },
  {
    "path": "data-bus/etc/data-bus.urm.puml",
    "content": "@startuml\npackage com.iluwatar.databus {\n  class AbstractDataType {\n    - dataBus : DataBus\n    + AbstractDataType()\n    + getDataBus() : DataBus\n    + setDataBus(dataBus : DataBus)\n  }\n  ~class App {\n    ~ App()\n    + main(args : String[]) {static}\n  }\n  class DataBus {\n    - INSTANCE : DataBus {static}\n    - listeners : Set<Member>\n    + DataBus()\n    + getInstance() : DataBus {static}\n    + publish(event : DataType)\n    + subscribe(member : Member)\n    + unsubscribe(member : Member)\n  }\n  interface DataType {\n    + getDataBus() : DataBus {abstract}\n    + setDataBus(DataBus) {abstract}\n  }\n  interface Member {\n    + accept(DataType) {abstract}\n  }\n}\npackage com.iluwatar.databus.data {\n  class MessageData {\n    - message : String\n    + MessageData(message : String)\n    + getMessage() : String\n    + of(message : String) : DataType {static}\n  }\n  class StartingData {\n    - when : LocalDateTime\n    + StartingData(when : LocalDateTime)\n    + getWhen() : LocalDateTime\n    + of(when : LocalDateTime) : DataType {static}\n  }\n  class StoppingData {\n    - when : LocalDateTime\n    + StoppingData(when : LocalDateTime)\n    + getWhen() : LocalDateTime\n    + of(when : LocalDateTime) : DataType {static}\n  }\n}\npackage com.iluwatar.databus.members {\n  class MessageCollectorMember {\n    - LOGGER : Logger {static}\n    - messages : List<String>\n    - name : String\n    + MessageCollectorMember(name : String)\n    + accept(data : DataType)\n    + getMessages() : List<String>\n    - handleEvent(data : MessageData)\n  }\n  class StatusMember {\n    - LOGGER : Logger {static}\n    - id : int\n    - started : LocalDateTime\n    - stopped : LocalDateTime\n    + StatusMember(id : int)\n    + accept(data : DataType)\n    + getStarted() : LocalDateTime\n    + getStopped() : LocalDateTime\n    - handleEvent(data : StartingData)\n    - handleEvent(data : StoppingData)\n  }\n}\nAbstractDataType -->  \"-dataBus\" DataBus\nDataBus -->  \"-INSTANCE\" DataBus\nDataBus -->  \"-listeners\" Member\nAbstractDataType ..|> DataType \nMessageData --|> AbstractDataType \nStartingData --|> AbstractDataType \nStoppingData --|> AbstractDataType \nMessageCollectorMember ..|> Member \nStatusMember ..|> Member \n@enduml"
  },
  {
    "path": "data-bus/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>data-bus</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.databus.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "data-bus/src/main/java/com/iluwatar/databus/AbstractDataType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\nThe MIT License (MIT)\n\nCopyright (c) 2016 Paul Campbell\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\npackage com.iluwatar.databus;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Base for data to send via the Data-Bus. */\n@Getter\n@Setter\npublic class AbstractDataType implements DataType {\n\n  private DataBus dataBus;\n}\n"
  },
  {
    "path": "data-bus/src/main/java/com/iluwatar/databus/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.databus;\n\nimport com.iluwatar.databus.data.MessageData;\nimport com.iluwatar.databus.data.StartingData;\nimport com.iluwatar.databus.data.StoppingData;\nimport com.iluwatar.databus.members.MessageCollectorMember;\nimport com.iluwatar.databus.members.StatusMember;\nimport java.time.LocalDateTime;\n\n/**\n * The Data Bus pattern.\n *\n * @see <a href=\"http://wiki.c2.com/?DataBusPattern\">http://wiki.c2.com/?DataBusPattern</a>\n *     <p>The Data-Bus pattern provides a method where different parts of an application may pass\n *     messages between each other without needing to be aware of the other's existence.\n *     <p>Similar to the {@code ObserverPattern}, members register themselves with the {@link\n *     DataBus} and may then receive each piece of data that is published to the Data-Bus. The\n *     member may react to any given message or not.\n *     <p>It allows for Many-to-Many distribution of data, as there may be any number of publishers\n *     to a Data-Bus, and any number of members receiving the data. All members will receive the\n *     same data, the order each receives a given piece of data, is an implementation detail.\n *     <p>Members may unsubscribe from the Data-Bus to stop receiving data.\n *     <p>This example of the pattern implements a Synchronous Data-Bus, meaning that when data is\n *     published to the Data-Bus, the publish method will not return until all members have received\n *     the data and returned.\n *     <p>The {@link DataBus} class is a Singleton.\n *     <p>Members of the Data-Bus must implement the {@link Member} interface.\n *     <p>Data to be published via the Data-Bus must implement the {@link DataType} interface.\n *     <p>The {@code data} package contains example {@link DataType} implementations.\n *     <p>The {@code members} package contains example {@link Member} implementations.\n *     <p>The {@link StatusMember} demonstrates using the DataBus to publish a message to the\n *     Data-Bus when it receives a message.\n */\nclass App {\n\n  public static void main(String[] args) {\n    final var bus = DataBus.getInstance();\n    bus.subscribe(new StatusMember(1));\n    bus.subscribe(new StatusMember(2));\n    final var foo = new MessageCollectorMember(\"Foo\");\n    final var bar = new MessageCollectorMember(\"Bar\");\n    bus.subscribe(foo);\n    bus.publish(StartingData.of(LocalDateTime.now()));\n    bus.publish(MessageData.of(\"Only Foo should see this\"));\n    bus.subscribe(bar);\n    bus.publish(MessageData.of(\"Foo and Bar should see this\"));\n    bus.unsubscribe(foo);\n    bus.publish(MessageData.of(\"Only Bar should see this\"));\n    bus.publish(StoppingData.of(LocalDateTime.now()));\n  }\n}\n"
  },
  {
    "path": "data-bus/src/main/java/com/iluwatar/databus/DataBus.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.databus;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * The Data-Bus implementation.\n *\n * <p>This implementation uses a Singleton.\n */\npublic class DataBus {\n\n  private static final DataBus INSTANCE = new DataBus();\n\n  private final Set<Member> listeners = new HashSet<>();\n\n  public static DataBus getInstance() {\n    return INSTANCE;\n  }\n\n  /**\n   * Register a member with the data-bus to start receiving events.\n   *\n   * @param member The member to register\n   */\n  public void subscribe(final Member member) {\n    this.listeners.add(member);\n  }\n\n  /**\n   * Deregister a member to stop receiving events.\n   *\n   * @param member The member to deregister\n   */\n  public void unsubscribe(final Member member) {\n    this.listeners.remove(member);\n  }\n\n  /**\n   * Publish and event to all members.\n   *\n   * @param event The event\n   */\n  public void publish(final DataType event) {\n    event.setDataBus(this);\n    listeners.forEach(listener -> listener.accept(event));\n  }\n}\n"
  },
  {
    "path": "data-bus/src/main/java/com/iluwatar/databus/DataType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\nThe MIT License (MIT)\n\nCopyright (c) 2016 Paul Campbell\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\npackage com.iluwatar.databus;\n\n/** Events are sent via the Data-Bus. */\npublic interface DataType {\n\n  /**\n   * Returns the data-bus the event is being sent on.\n   *\n   * @return The data-bus\n   */\n  DataBus getDataBus();\n\n  /**\n   * Set the data-bus the event will be sent on.\n   *\n   * @param dataBus The data-bus\n   */\n  void setDataBus(DataBus dataBus);\n}\n"
  },
  {
    "path": "data-bus/src/main/java/com/iluwatar/databus/Member.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\nThe MIT License (MIT)\n\nCopyright (c) 2016 Paul Campbell\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\npackage com.iluwatar.databus;\n\nimport java.util.function.Consumer;\n\n/** Members receive events from the Data-Bus. */\npublic interface Member extends Consumer<DataType> {\n\n  void accept(DataType event);\n}\n"
  },
  {
    "path": "data-bus/src/main/java/com/iluwatar/databus/data/MessageData.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.databus.data;\n\nimport com.iluwatar.databus.AbstractDataType;\nimport com.iluwatar.databus.DataType;\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\n/** An event raised when a string message is sent. */\n@Getter\n@AllArgsConstructor\npublic class MessageData extends AbstractDataType {\n\n  private final String message;\n\n  public static DataType of(final String message) {\n    return new MessageData(message);\n  }\n}\n"
  },
  {
    "path": "data-bus/src/main/java/com/iluwatar/databus/data/StartingData.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.databus.data;\n\nimport com.iluwatar.databus.AbstractDataType;\nimport com.iluwatar.databus.DataType;\nimport java.time.LocalDateTime;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/** An event raised when applications starts, containing the start time of the application. */\n@RequiredArgsConstructor\n@Getter\npublic class StartingData extends AbstractDataType {\n\n  private final LocalDateTime when;\n\n  public static DataType of(final LocalDateTime when) {\n    return new StartingData(when);\n  }\n}\n"
  },
  {
    "path": "data-bus/src/main/java/com/iluwatar/databus/data/StoppingData.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.databus.data;\n\nimport com.iluwatar.databus.AbstractDataType;\nimport com.iluwatar.databus.DataType;\nimport java.time.LocalDateTime;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/** An event raised when applications stops, containing the stop time of the application. */\n@RequiredArgsConstructor\n@Getter\npublic class StoppingData extends AbstractDataType {\n\n  private final LocalDateTime when;\n\n  public static DataType of(final LocalDateTime when) {\n    return new StoppingData(when);\n  }\n}\n"
  },
  {
    "path": "data-bus/src/main/java/com/iluwatar/databus/members/MessageCollectorMember.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.databus.members;\n\nimport com.iluwatar.databus.DataType;\nimport com.iluwatar.databus.Member;\nimport com.iluwatar.databus.data.MessageData;\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Receiver of Data-Bus events that collects the messages from each {@link MessageData}. */\n@Slf4j\npublic class MessageCollectorMember implements Member {\n\n  private final String name;\n\n  private final List<String> messages = new ArrayList<>();\n\n  public MessageCollectorMember(String name) {\n    this.name = name;\n  }\n\n  @Override\n  public void accept(final DataType data) {\n    if (data instanceof MessageData) {\n      handleEvent((MessageData) data);\n    }\n  }\n\n  private void handleEvent(MessageData data) {\n    LOGGER.info(\"{} sees message {}\", name, data.getMessage());\n    messages.add(data.getMessage());\n  }\n\n  public List<String> getMessages() {\n    return List.copyOf(messages);\n  }\n}\n"
  },
  {
    "path": "data-bus/src/main/java/com/iluwatar/databus/members/StatusMember.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.databus.members;\n\nimport com.iluwatar.databus.DataType;\nimport com.iluwatar.databus.Member;\nimport com.iluwatar.databus.data.MessageData;\nimport com.iluwatar.databus.data.StartingData;\nimport com.iluwatar.databus.data.StoppingData;\nimport java.time.LocalDateTime;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Receiver of Data-Bus events. */\n@Getter\n@Slf4j\n@RequiredArgsConstructor\npublic class StatusMember implements Member {\n\n  private final int id;\n\n  private LocalDateTime started;\n\n  private LocalDateTime stopped;\n\n  @Override\n  public void accept(final DataType data) {\n    if (data instanceof StartingData) {\n      handleEvent((StartingData) data);\n    } else if (data instanceof StoppingData) {\n      handleEvent((StoppingData) data);\n    }\n  }\n\n  private void handleEvent(StartingData data) {\n    started = data.getWhen();\n    LOGGER.info(\"Receiver {} sees application started at {}\", id, started);\n  }\n\n  private void handleEvent(StoppingData data) {\n    stopped = data.getWhen();\n    LOGGER.info(\"Receiver {} sees application stopping at {}\", id, stopped);\n    LOGGER.info(\"Receiver {} sending goodbye message\", id);\n    data.getDataBus().publish(MessageData.of(String.format(\"Goodbye cruel world from #%d!\", id)));\n  }\n}\n"
  },
  {
    "path": "data-bus/src/test/java/com/iluwatar/databus/DataBusTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.databus;\n\nimport static org.mockito.BDDMockito.then;\nimport static org.mockito.Mockito.never;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\n\n/** Tests for {@link DataBus}. */\nclass DataBusTest {\n\n  @Mock private Member member;\n\n  @Mock private DataType event;\n\n  @BeforeEach\n  void setUp() {\n    MockitoAnnotations.openMocks(this);\n  }\n\n  @Test\n  void publishedEventIsReceivedBySubscribedMember() {\n    // given\n    final var dataBus = DataBus.getInstance();\n    dataBus.subscribe(member);\n    // when\n    dataBus.publish(event);\n    // then\n    then(member).should().accept(event);\n  }\n\n  @Test\n  void publishedEventIsNotReceivedByMemberAfterUnsubscribing() {\n    // given\n    final var dataBus = DataBus.getInstance();\n    dataBus.subscribe(member);\n    dataBus.unsubscribe(member);\n    // when\n    dataBus.publish(event);\n    // then\n    then(member).should(never()).accept(event);\n  }\n}\n"
  },
  {
    "path": "data-bus/src/test/java/com/iluwatar/databus/members/MessageCollectorMemberTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.databus.members;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.databus.data.MessageData;\nimport com.iluwatar.databus.data.StartingData;\nimport java.time.LocalDateTime;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for {@link MessageCollectorMember}. */\nclass MessageCollectorMemberTest {\n\n  @Test\n  void collectMessageFromMessageData() {\n    // given\n    final var message = \"message\";\n    final var messageData = new MessageData(message);\n    final var collector = new MessageCollectorMember(\"collector\");\n    // when\n    collector.accept(messageData);\n    // then\n    assertTrue(collector.getMessages().contains(message));\n  }\n\n  @Test\n  void collectIgnoresMessageFromOtherDataTypes() {\n    // given\n    final var startingData = new StartingData(LocalDateTime.now());\n    final var collector = new MessageCollectorMember(\"collector\");\n    // when\n    collector.accept(startingData);\n    // then\n    assertEquals(0, collector.getMessages().size());\n  }\n}\n"
  },
  {
    "path": "data-bus/src/test/java/com/iluwatar/databus/members/StatusMemberTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.databus.members;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nimport com.iluwatar.databus.DataBus;\nimport com.iluwatar.databus.data.MessageData;\nimport com.iluwatar.databus.data.StartingData;\nimport com.iluwatar.databus.data.StoppingData;\nimport java.time.LocalDateTime;\nimport java.time.Month;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for {@link StatusMember}. */\nclass StatusMemberTest {\n\n  @Test\n  void statusRecordsTheStartTime() {\n    // given\n    final var startTime = LocalDateTime.of(2017, Month.APRIL, 1, 19, 9);\n    final var startingData = new StartingData(startTime);\n    final var statusMember = new StatusMember(1);\n    // when\n    statusMember.accept(startingData);\n    // then\n    assertEquals(startTime, statusMember.getStarted());\n  }\n\n  @Test\n  void statusRecordsTheStopTime() {\n    // given\n    final var stop = LocalDateTime.of(2017, Month.APRIL, 1, 19, 12);\n    final var stoppingData = new StoppingData(stop);\n    stoppingData.setDataBus(DataBus.getInstance());\n    final var statusMember = new StatusMember(1);\n    // when\n    statusMember.accept(stoppingData);\n    // then\n    assertEquals(stop, statusMember.getStopped());\n  }\n\n  @Test\n  void statusIgnoresMessageData() {\n    // given\n    final var messageData = new MessageData(\"message\");\n    final var statusMember = new StatusMember(1);\n    // when\n    statusMember.accept(messageData);\n    // then\n    assertNull(statusMember.getStarted());\n    assertNull(statusMember.getStopped());\n  }\n}\n"
  },
  {
    "path": "data-locality/README.md",
    "content": "---\ntitle: \"Data Locality Pattern in Java: Boosting Performance with Efficient Data Management\"\nshortTitle: Data Locality\ndescription: \"Learn about the Data Locality pattern in Java, a technique to optimize performance by improving cache utilization and minimizing data access times. Ideal for game development and high-performance computing.\"\ncategory: Performance optimization\nlanguage: en\ntag:\n  - Caching\n  - Data access\n  - Game programming\n  - Memory management\n  - Performance\n---\n\n## Also known as\n\n* Cache-Friendly Design\n* Data-Oriented Design\n\n## Intent of Data Locality Design Pattern\n\nThe Data Locality design pattern aims to minimize data access times and improve cache utilization by arranging data in memory to take advantage of spatial locality. This pattern is particularly useful in high-performance computing, real-time data processing, and game development where access speed is crucial.\n\n## Detailed Explanation of Data Locality Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a supermarket where items are arranged based on purchase patterns and categories for efficiency. Just like the Data Locality pattern organizes data in memory for quick access, the supermarket places frequently bought items together and in easily accessible areas. This layout minimizes the time shoppers spend searching for items, enhancing their shopping experience by ensuring that related and popular items are close at hand, much like how data locality improves cache utilization and reduces access latency in computing.\n\nIn plain words\n\n> The Data Locality pattern organizes data in memory to reduce access times and improve performance by ensuring that data frequently accessed together is stored close together. This is crucial for high-performance applications like game engines and real-time data processing systems.\n\nMind map\n\n![Data Locality mind map](./etc/data-locality-mind-map.png)\n\nFlowchart\n\n![Data Locality flowchart](./etc/data-locality-flowchart.png)\n\n## Programmatic Example of Data Locality Pattern in Java\n\nThe Data Locality pattern is a design pattern that aims to improve performance by arranging data in memory to take advantage of spatial locality. This pattern is particularly useful in high-performance computing and game development where access speed is crucial.\n\nIn the data-locality module, the pattern is demonstrated using a game loop that processes a bunch of game entities. These entities are decomposed into different domains: AI, physics, and rendering.\n\nThe `GameEntity` class is the main class that represents a game entity. It contains an array of `AiComponent`, `PhysicsComponent`, and `RenderComponent` objects. These components represent different aspects of a game entity.\n\n```java\npublic class GameEntity {\n    private final AiComponent[] aiComponents;\n    private final PhysicsComponent[] physicsComponents;\n    private final RenderComponent[] renderComponents;\n    // Other properties and methods...\n}\n```\n\nThe `GameEntity` class has a start method that initializes all the components.\n\n```java\npublic void start() {\n  for (int i = 0; i < numEntities; i++) {\n    aiComponents[i] = new AiComponent();\n    physicsComponents[i] = new PhysicsComponent();\n    renderComponents[i] = new RenderComponent();\n  }\n}\n```\n\nThe `GameEntity` class also has an update method that updates all the components. This method demonstrates the data locality pattern. Instead of updating all aspects of a single entity at a time (AI, physics, and rendering), it updates the same aspect (e.g., AI) for all entities first, then moves on to the next aspect (e.g., physics). This approach improves cache utilization because it's more likely that the data needed for the update is already in the cache.\n\n```java\npublic void update() {\n  for (int i = 0; i < numEntities; i++) {\n    aiComponents[i].update();\n  }\n  for (int i = 0; i < numEntities; i++) {\n    physicsComponents[i].update();\n  }\n  for (int i = 0; i < numEntities; i++) {\n    renderComponents[i].update();\n  }\n}\n```\n\nThe `Application` class contains the main method that creates a `GameEntity` object and starts the game loop.\n\n```java\npublic class Application {\n  public static void main(String[] args) {\n    var gameEntity = new GameEntity(NUM_ENTITIES);\n    gameEntity.start();\n    gameEntity.update();\n  }\n}\n```\n\nThe console output:\n\n```\n10:19:52.155 [main] INFO com.iluwatar.data.locality.Application -- Start Game Application using Data-Locality pattern\n10:19:52.157 [main] INFO com.iluwatar.data.locality.game.GameEntity -- Init Game with #Entity : 5\n10:19:52.158 [main] INFO com.iluwatar.data.locality.game.GameEntity -- Start Game\n10:19:52.158 [main] INFO com.iluwatar.data.locality.game.component.manager.AiComponentManager -- Start AI Game Component\n10:19:52.158 [main] INFO com.iluwatar.data.locality.game.component.manager.PhysicsComponentManager -- Start Physics Game Component \n10:19:52.159 [main] INFO com.iluwatar.data.locality.game.component.manager.RenderComponentManager -- Start Render Game Component \n10:19:52.159 [main] INFO com.iluwatar.data.locality.game.GameEntity -- Update Game Component\n10:19:52.159 [main] INFO com.iluwatar.data.locality.game.component.manager.AiComponentManager -- Update AI Game Component\n10:19:52.159 [main] INFO com.iluwatar.data.locality.game.component.AiComponent -- update AI component\n10:19:52.159 [main] INFO com.iluwatar.data.locality.game.component.AiComponent -- update AI component\n10:19:52.159 [main] INFO com.iluwatar.data.locality.game.component.AiComponent -- update AI component\n10:19:52.159 [main] INFO com.iluwatar.data.locality.game.component.AiComponent -- update AI component\n10:19:52.159 [main] INFO com.iluwatar.data.locality.game.component.AiComponent -- update AI component\n10:19:52.159 [main] INFO com.iluwatar.data.locality.game.component.manager.PhysicsComponentManager -- Update Physics Game Component \n10:19:52.160 [main] INFO com.iluwatar.data.locality.game.component.PhysicsComponent -- Update physics component of game\n10:19:52.160 [main] INFO com.iluwatar.data.locality.game.component.PhysicsComponent -- Update physics component of game\n10:19:52.160 [main] INFO com.iluwatar.data.locality.game.component.PhysicsComponent -- Update physics component of game\n10:19:52.160 [main] INFO com.iluwatar.data.locality.game.component.PhysicsComponent -- Update physics component of game\n10:19:52.160 [main] INFO com.iluwatar.data.locality.game.component.PhysicsComponent -- Update physics component of game\n10:19:52.160 [main] INFO com.iluwatar.data.locality.game.component.manager.RenderComponentManager -- Update Render Game Component \n10:19:52.160 [main] INFO com.iluwatar.data.locality.game.component.RenderComponent -- Render Component\n10:19:52.160 [main] INFO com.iluwatar.data.locality.game.component.RenderComponent -- Render Component\n10:19:52.160 [main] INFO com.iluwatar.data.locality.game.component.RenderComponent -- Render Component\n10:19:52.160 [main] INFO com.iluwatar.data.locality.game.component.RenderComponent -- Render Component\n10:19:52.160 [main] INFO com.iluwatar.data.locality.game.component.RenderComponent -- Render Component\n```\n\nIn this way, the data-locality module demonstrates the Data Locality pattern. By updating all components of the same type together, it increases the likelihood that the data needed for the update is already in the cache, thereby improving performance.\n\n## When to Use the Data Locality Pattern in Java\n\nThis pattern is applicable in scenarios where large datasets are processed and performance is critical. It's particularly useful in:\n\n* Game development for efficient rendering and physics calculations.\n* High-performance computing tasks that require rapid access to large data sets.\n* Real-time data processing systems where latency is a critical factor.\n* Scientific computing applications needing optimized matrix operations.\n* Data-intensive applications requiring enhanced memory access patterns.\n\n## Real-World Applications of Data Locality Pattern in Java\n\n* Game engines (e.g., Unity, Unreal Engine) to optimize entity and component data access.\n* High-performance matrix libraries in scientific computing to optimize matrix operations.\n* Real-time streaming data processing systems for efficient data manipulation and access.\n\n## Benefits and Trade-offs of Data Locality Pattern\n\nBenefits:\n\n* Improved Cache Utilization: By enhancing spatial locality, data frequently accessed together is stored close together in memory, improving cache hit rates.\n* Reduced Access Latency: Minimizes the time taken to fetch data from memory, leading to performance improvements.\n* Enhanced Performance: Overall system performance is improved due to reduced memory access times and increased efficiency in data processing.\n\nTrade-offs:\n\n* Complexity in Implementation: Managing data layout can add complexity to the system design and implementation.\n* Maintenance Overhead: As data access patterns evolve, the layout may need to be re-evaluated, adding to the maintenance overhead.\n* Less Flexibility: The tight coupling of data layout to access patterns can reduce flexibility in how data structures are used and evolved over time.\n\n## Related Java Design Patterns\n\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Can be used in conjunction with Data Locality to share data efficiently among multiple objects.\n* [Object Pool](https://java-design-patterns.com/patterns/object-pool/): Often used together to manage a group of initialized objects that can be reused, further optimizing memory usage and access.\n* [Iterator](https://java-design-patterns.com/patterns/iterator/): Facilitates navigation through a collection of data laid out with data locality in mind.\n\n## References and Credits\n\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Game Programming Patterns](https://amzn.to/3vK8c0d)\n* [High-Performance Java Persistence](https://amzn.to/3TMc8Wd)\n* [Java Performance: The Definitive Guide](https://amzn.to/3Ua392J)\n* [Game Programming Patterns Optimization Patterns: Data Locality](http://gameprogrammingpatterns.com/data-locality.html)\n"
  },
  {
    "path": "data-locality/etc/data-locality.urm.puml",
    "content": "@startuml\npackage com.iluwatar.data.locality.game.component.manager {\n  class AiComponentManager {\n    - AI_COMPONENTS : Component[] {static}\n    - LOGGER : Logger {static}\n    - MAX_ENTITIES : int {static}\n    - numEntities : int\n    + AiComponentManager(numEntities : int)\n    + start()\n    + update()\n  }\n  class PhysicsComponentManager {\n    - LOGGER : Logger {static}\n    - MAX_ENTITIES : int {static}\n    - PHYSICS_COMPONENTS : Component[] {static}\n    - numEntities : int\n    + PhysicsComponentManager(numEntities : int)\n    + start()\n    + update()\n  }\n  class RenderComponentManager {\n    - LOGGER : Logger {static}\n    - MAX_ENTITIES : int {static}\n    - RENDER_COMPONENTS : Component[] {static}\n    - numEntities : int\n    + RenderComponentManager(numEntities : int)\n    + render()\n    + start()\n  }\n}\npackage com.iluwatar.data.locality {\n  class Application {\n    - LOGGER : Logger {static}\n    - NUM_ENTITIES : int {static}\n    + Application()\n    + main(args : String[]) {static}\n  }\n}\npackage com.iluwatar.data.locality.game {\n  class GameEntity {\n    - LOGGER : Logger {static}\n    - aiComponentManager : AiComponentManager\n    - physicsComponentManager : PhysicsComponentManager\n    - renderComponentManager : RenderComponentManager\n    + GameEntity(numEntities : int)\n    + start()\n    + update()\n  }\n}\npackage com.iluwatar.data.locality.game.component {\n  class AiComponent {\n    - LOGGER : Logger {static}\n    + AiComponent()\n    + render()\n    + update()\n  }\n  interface Component {\n    + render() {abstract}\n    + update() {abstract}\n  }\n  class PhysicsComponent {\n    - LOGGER : Logger {static}\n    + PhysicsComponent()\n    + render()\n    + update()\n  }\n  class RenderComponent {\n    - LOGGER : Logger {static}\n    + RenderComponent()\n    + render()\n    + update()\n  }\n}\nGameEntity -->  \"-physicsComponentManager\" PhysicsComponentManager\nGameEntity -->  \"-aiComponentManager\" AiComponentManager\nGameEntity -->  \"-renderComponentManager\" RenderComponentManager\nAiComponent ..|> Component \nPhysicsComponent ..|> Component \nRenderComponent ..|> Component \n@enduml"
  },
  {
    "path": "data-locality/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>data-locality</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.data.locality.Application</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "data-locality/src/main/java/com/iluwatar/data/locality/Application.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.data.locality;\n\nimport com.iluwatar.data.locality.game.GameEntity;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Use the Data Locality pattern is when you have a performance problem. Take advantage of that to\n * improve performance by increasing data locality — keeping data in contiguous memory in the order\n * that you process it.\n *\n * <p>Example: Game loop that processes a bunch of game entities. Those entities are decomposed into\n * different domains  — AI, physics, and rendering — using the Component pattern.\n */\n@Slf4j\npublic class Application {\n\n  private static final int NUM_ENTITIES = 5;\n\n  /** Start game loop with each component have NUM_ENTITIES instance. */\n  public static void main(String[] args) {\n    LOGGER.info(\"Start Game Application using Data-Locality pattern\");\n    var gameEntity = new GameEntity(NUM_ENTITIES);\n    gameEntity.start();\n    gameEntity.update();\n  }\n}\n"
  },
  {
    "path": "data-locality/src/main/java/com/iluwatar/data/locality/game/GameEntity.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.data.locality.game;\n\nimport com.iluwatar.data.locality.game.component.manager.AiComponentManager;\nimport com.iluwatar.data.locality.game.component.manager.PhysicsComponentManager;\nimport com.iluwatar.data.locality.game.component.manager.RenderComponentManager;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The game Entity maintains a big array of pointers . Each spin of the game loop, we need to run\n * the following:\n *\n * <p>Update the AI components.\n *\n * <p>Update the physics components for them.\n *\n * <p>Render them using their render components.\n */\n@Slf4j\npublic class GameEntity {\n\n  private final AiComponentManager aiComponentManager;\n  private final PhysicsComponentManager physicsComponentManager;\n  private final RenderComponentManager renderComponentManager;\n\n  /** Init components. */\n  public GameEntity(int numEntities) {\n    LOGGER.info(\"Init Game with #Entity : {}\", numEntities);\n    aiComponentManager = new AiComponentManager(numEntities);\n    physicsComponentManager = new PhysicsComponentManager(numEntities);\n    renderComponentManager = new RenderComponentManager(numEntities);\n  }\n\n  /** start all component. */\n  public void start() {\n    LOGGER.info(\"Start Game\");\n    aiComponentManager.start();\n    physicsComponentManager.start();\n    renderComponentManager.start();\n  }\n\n  /** update all component. */\n  public void update() {\n    LOGGER.info(\"Update Game Component\");\n    // Process AI.\n    aiComponentManager.update();\n\n    // update physics.\n    physicsComponentManager.update();\n\n    // Draw to screen.\n    renderComponentManager.render();\n  }\n}\n"
  },
  {
    "path": "data-locality/src/main/java/com/iluwatar/data/locality/game/component/AiComponent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.data.locality.game.component;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Implementation of AI component for Game. */\n@Slf4j\npublic class AiComponent implements Component {\n\n  /** Update ai component. */\n  @Override\n  public void update() {\n    LOGGER.info(\"update AI component\");\n  }\n\n  @Override\n  public void render() {\n    // Do Nothing.\n  }\n}\n"
  },
  {
    "path": "data-locality/src/main/java/com/iluwatar/data/locality/game/component/Component.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.data.locality.game.component;\n\n/** Implement different Game component update and render process. */\npublic interface Component {\n\n  void update();\n\n  void render();\n}\n"
  },
  {
    "path": "data-locality/src/main/java/com/iluwatar/data/locality/game/component/PhysicsComponent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.data.locality.game.component;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Implementation of Physics Component of Game. */\n@Slf4j\npublic class PhysicsComponent implements Component {\n\n  /** update physics component of game. */\n  @Override\n  public void update() {\n    LOGGER.info(\"Update physics component of game\");\n  }\n\n  @Override\n  public void render() {\n    // do nothing\n  }\n}\n"
  },
  {
    "path": "data-locality/src/main/java/com/iluwatar/data/locality/game/component/RenderComponent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.data.locality.game.component;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Implementation of Render Component of Game. */\n@Slf4j\npublic class RenderComponent implements Component {\n\n  @Override\n  public void update() {\n    // do nothing\n  }\n\n  /** render. */\n  @Override\n  public void render() {\n    LOGGER.info(\"Render Component\");\n  }\n}\n"
  },
  {
    "path": "data-locality/src/main/java/com/iluwatar/data/locality/game/component/manager/AiComponentManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.data.locality.game.component.manager;\n\nimport com.iluwatar.data.locality.game.component.AiComponent;\nimport com.iluwatar.data.locality.game.component.Component;\nimport java.util.stream.IntStream;\nimport lombok.extern.slf4j.Slf4j;\n\n/** AI component manager for Game. */\n@Slf4j\npublic class AiComponentManager {\n\n  private static final int MAX_ENTITIES = 10000;\n\n  private final int numEntities;\n\n  private final Component[] aiComponents = new AiComponent[MAX_ENTITIES];\n\n  public AiComponentManager(int numEntities) {\n    this.numEntities = numEntities;\n  }\n\n  /** start AI component of Game. */\n  public void start() {\n    LOGGER.info(\"Start AI Game Component\");\n    IntStream.range(0, numEntities).forEach(i -> aiComponents[i] = new AiComponent());\n  }\n\n  /** Update AI component of Game. */\n  public void update() {\n    LOGGER.info(\"Update AI Game Component\");\n    IntStream.range(0, numEntities)\n        .filter(i -> aiComponents.length > i && aiComponents[i] != null)\n        .forEach(i -> aiComponents[i].update());\n  }\n}\n"
  },
  {
    "path": "data-locality/src/main/java/com/iluwatar/data/locality/game/component/manager/PhysicsComponentManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.data.locality.game.component.manager;\n\nimport com.iluwatar.data.locality.game.component.Component;\nimport com.iluwatar.data.locality.game.component.PhysicsComponent;\nimport java.util.stream.IntStream;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Physics component Manager for Game. */\n@Slf4j\npublic class PhysicsComponentManager {\n\n  private static final int MAX_ENTITIES = 10000;\n\n  private final int numEntities;\n\n  private final Component[] physicsComponents = new PhysicsComponent[MAX_ENTITIES];\n\n  public PhysicsComponentManager(int numEntities) {\n    this.numEntities = numEntities;\n  }\n\n  /** Start physics component of Game. */\n  public void start() {\n    LOGGER.info(\"Start Physics Game Component \");\n    IntStream.range(0, numEntities).forEach(i -> physicsComponents[i] = new PhysicsComponent());\n  }\n\n  /** Update physics component of Game. */\n  public void update() {\n    LOGGER.info(\"Update Physics Game Component \");\n    // Process physics.\n    IntStream.range(0, numEntities)\n        .filter(i -> physicsComponents.length > i && physicsComponents[i] != null)\n        .forEach(i -> physicsComponents[i].update());\n  }\n}\n"
  },
  {
    "path": "data-locality/src/main/java/com/iluwatar/data/locality/game/component/manager/RenderComponentManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.data.locality.game.component.manager;\n\nimport com.iluwatar.data.locality.game.component.Component;\nimport com.iluwatar.data.locality.game.component.RenderComponent;\nimport java.util.stream.IntStream;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Render component manager for Game. */\n@Slf4j\npublic class RenderComponentManager {\n\n  private static final int MAX_ENTITIES = 10000;\n\n  private final int numEntities;\n\n  private final Component[] renderComponents = new RenderComponent[MAX_ENTITIES];\n\n  public RenderComponentManager(int numEntities) {\n    this.numEntities = numEntities;\n  }\n\n  /** Start render component. */\n  public void start() {\n    LOGGER.info(\"Start Render Game Component \");\n    IntStream.range(0, numEntities).forEach(i -> renderComponents[i] = new RenderComponent());\n  }\n\n  /** render component. */\n  public void render() {\n    LOGGER.info(\"Update Render Game Component \");\n    // Process Render.\n    IntStream.range(0, numEntities)\n        .filter(i -> renderComponents.length > i && renderComponents[i] != null)\n        .forEach(i -> renderComponents[i].render());\n  }\n}\n"
  },
  {
    "path": "data-locality/src/test/java/com/iluwatar/data/locality/ApplicationTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.data.locality;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test Game Application */\nclass ApplicationTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link Application#main(String[])} throws an\n   * exception.\n   */\n  @Test\n  void shouldExecuteGameApplicationWithoutException() {\n    assertDoesNotThrow(() -> Application.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "data-mapper/README.md",
    "content": "---\r\ntitle: \"Data Mapper Pattern in Java: Decoupling Data Storage from Business Logic\"\r\nshortTitle: Data Mapper\r\ndescription: \"Explore the Data Mapper pattern in Java, which decouples database operations from business logic. Learn how to implement and utilize this pattern to enhance maintainability and flexibility in your Java applications.\"\r\ncategory: Behavioral\r\nlanguage: en\r\ntag:\r\n  - Data access\r\n  - Decoupling\r\n  - Domain\r\n  - Object mapping\r\n  - Persistence\r\n---\r\n\r\n## Also known as\r\n\r\n* Object-Relational Mapping (ORM)\r\n\r\n## Intent of the Data Mapper Pattern\r\n\r\nThe Data Mapper pattern aims to create an abstraction layer between the database and the business logic, allowing them to evolve independently. It maps data from the database objects to in-memory data structures and vice versa, minimizing direct dependencies between the application's core logic and the underlying database structure. This decoupling is essential in promoting maintainability and flexibility in Java programming.\r\n\r\n## Detailed Explanation of Data Mapper Pattern with Real-World Examples\r\n\r\nReal-world example\r\n\r\n> Consider a library system where books are stored in a database with complex relationships and various attributes such as title, author, publication year, and genre. In this scenario, a Data Mapper pattern can be used to map the database records of books to in-memory objects in the application. The Data Mapper would handle the retrieval, storage, and update of book objects in the database, allowing the application's business logic to work directly with the book objects without concern for the underlying database structure. This separation makes it easier to change the database schema without affecting the business logic, and vice versa.\r\n\r\nIn plain words\r\n\r\n> A layer of mappers that moves data between objects and a database while keeping them independent of each other.\r\n\r\nWikipedia says\r\n\r\n> A Data Mapper is a Data Access Layer that performs bidirectional transfer of data between a persistent data store (often a relational database) and an in-memory data representation (the domain layer). The goal of the pattern is to keep the in-memory representation and the persistent data store independent of each other and the data mapper itself. This is useful when one needs to model and enforce strict business processes on the data in the domain layer that do not map neatly to the persistent data store.\r\n\r\nSequence diagram\r\n\r\n![Data Mapper sequence diagram](./etc/data-mapper-sequence-diagram.png)\r\n\r\n## Programmatic Example of Data Mapper Pattern in Java\r\n\r\nThe Data Mapper is a design pattern that separates the in-memory objects from the database. Its responsibility is to transfer data between the two and also to isolate them from each other. This pattern promotes the [Single Responsibility Principle](https://java-design-patterns.com/principles/#single-responsibility-principle) and [Separation of Concerns](https://java-design-patterns.com/principles/#separation-of-concerns).\r\n\r\nIn the data-mapper module, the pattern is demonstrated using a `Student` class and a `StudentDataMapper` interface.\r\n\r\nThe `Student` class is a simple POJO (Plain Old Java Object) that represents a student. It has properties like studentId, name, and grade.\r\n\r\n```java\r\npublic class Student {\r\n    private int studentId;\r\n    private String name;\r\n    private char grade;\r\n    // ...\r\n}\r\n```\r\n\r\nThe `StudentDataMapper` interface defines the operations that can be performed on `Student` objects. These operations include `insert`, `update`, `delete`, and `find`.\r\n\r\n```java\r\npublic interface StudentDataMapper {\r\n    void insert(final Student student);\r\n\r\n    void update(final Student student);\r\n\r\n    void delete(final Student student);\r\n\r\n    Optional<Student> find(final int studentId);\r\n    // ...\r\n}\r\n```\r\n\r\nThe `StudentDataMapperImpl` class implements the `StudentDataMapper` interface. It contains the actual logic for interacting with the database.\r\n\r\n```java\r\npublic class StudentDataMapperImpl implements StudentDataMapper {\r\n    // ...\r\n    @Override\r\n    public void insert(final Student student) {\r\n        // Insert student into the database\r\n    }\r\n\r\n    @Override\r\n    public void update(final Student student) {\r\n        // Update student in the database\r\n    }\r\n\r\n    @Override\r\n    public void delete(final Student student) {\r\n        // Delete student from the database\r\n    }\r\n\r\n    @Override\r\n    public Optional<Student> find(final int studentId) {\r\n        // Find student in the database\r\n    }\r\n    // ...\r\n}\r\n```\r\n\r\nThe `App` class contains the main method that demonstrates the use of the `StudentDataMapper`. It creates a `Student` object, inserts it into the database, finds it, updates it, and finally deletes it.\r\n\r\n```java\r\npublic class App {\r\n    public static void main(final String... args) {\r\n        final var mapper = new StudentDataMapperImpl();\r\n        var student = new Student(1, \"Adam\", 'A');\r\n        mapper.insert(student);\r\n        final var studentToBeFound = mapper.find(student.getStudentId());\r\n        student = new Student(student.getStudentId(), \"AdamUpdated\", 'A');\r\n        mapper.update(student);\r\n        mapper.delete(student);\r\n    }\r\n}\r\n```\r\n\r\nProgram output:\r\n\r\n```\r\n13:54:29.234 [main] DEBUG com.iluwatar.datamapper.App -- App.main(), student : Student(studentId=1, name=Adam, grade=A), is inserted\r\n13:54:29.237 [main] DEBUG com.iluwatar.datamapper.App -- App.main(), student : Optional[Student(studentId=1, name=Adam, grade=A)], is searched\r\n13:54:29.237 [main] DEBUG com.iluwatar.datamapper.App -- App.main(), student : Student(studentId=1, name=AdamUpdated, grade=A), is updated\r\n13:54:29.238 [main] DEBUG com.iluwatar.datamapper.App -- App.main(), student : Student(studentId=1, name=AdamUpdated, grade=A), is going to be deleted\r\n```\r\n\r\n## When to Use the Data Mapper Pattern in Java\r\n\r\nUse the Data Mapper in any of the following situations\r\n\r\n* When there's a need to decouple the in-memory objects from the database entities to promote the [Single Responsibility Principle](https://java-design-patterns.com/principles/#single-responsibility-principle) and [Separation of Concerns](https://java-design-patterns.com/principles/#separation-of-concerns).\r\n* In applications requiring an ORM tool to bridge the gap between object-oriented models and relational databases.\r\n* When working with complex database schemas where direct data manipulation and object creation lead to cumbersome and error-prone code.\r\n\r\n## Data Mapper Pattern Java Tutorials\r\n\r\n* [Spring Boot RowMapper (ZetCode)](https://zetcode.com/springboot/rowmapper/)\r\n* [Spring BeanPropertyRowMapper tutorial (ZetCode)](https://zetcode.com/spring/beanpropertyrowmapper/)\r\n* [Data Transfer Object Pattern in Java - Implementation and Mapping (StackAbuse)](https://stackabuse.com/data-transfer-object-pattern-in-java-implementation-and-mapping/)\r\n\r\n## Real-World Applications of Data Mapper Pattern in Java\r\n\r\n* ORM frameworks such as Hibernate in Java.\r\n* Data access layers in enterprise applications where business logic and database management are kept separate.\r\n* Applications requiring database interactions without tying the code to a specific database implementation.\r\n\r\n## Benefits and Trade-offs of Data Mapper Pattern\r\n\r\nBenefits:\r\n\r\n* Promotes [Single Responsibility Principle](https://java-design-patterns.com/principles/#single-responsibility-principle) by separating persistence logic from business logic.\r\n* Enhances maintainability and readability by centralizing data interaction logic.\r\n* Improves application's ability to adapt to changes in the database schema with minimal changes to the business logic.\r\n\r\nTrade-offs:\r\n\r\n* Introduces complexity through the additional abstraction layer.\r\n* Might lead to performance overhead due to the abstraction layer, especially in large-scale applications or with complex queries.\r\n* Requires developers to learn and understand the abstraction layer in addition to the database and ORM framework being used.\r\n\r\n## Related Java Design Patterns\r\n\r\n* Active Record: Combines data access logic and business logic in the domain entities themselves, contrary to Data Mapper's separation of concerns.\r\n* Object–Relational Mapping (ORM): A technique to map object-oriented programming language data to a relational database.\r\n* [Repository](https://java-design-patterns.com/patterns/repository/): Provides an abstraction of the data layer, acting as a collection of domain objects in memory.\r\n* [Unit of Work](https://java-design-patterns.com/patterns/unit-of-work/): Manages transactions and keeps track of the objects affected by a business transaction to ensure changes are consistent and transactional.\r\n\r\n## References and Credits\r\n\r\n* [Clean Architecture: A Craftsman's Guide to Software Structure and Design](https://amzn.to/3xyEFag)\r\n* [Java Persistence with Hibernate](https://amzn.to/3VNzlKe)\r\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\r\n"
  },
  {
    "path": "data-mapper/etc/data-mapper.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.9\" icons=\"true\" always-add-relationships=\"false\" generalizations=\"true\" realizations=\"true\" \n  associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.datamapper.Student\" project=\"java-design-patterns\" \n    file=\"/java-design-patterns/java/com/iluwatar/datamapper/Student.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"359\" width=\"148\" x=\"868\" y=\"175\"/>    \n    <display autosize=\"false\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"2\" language=\"java\" name=\"com.iluwatar.datamapper.StudentDataMapper\" project=\"java-design-patterns\" \n    file=\"/java-design-patterns/java/com/iluwatar/datamapper/StudentDataMapper.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"733\" y=\"241\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.datamapper.StudentDataMapperImpl\" project=\"java-design-patterns\" \n    file=\"/java-design-patterns/java/com/iluwatar/datamapper/StudentDataMapperImpl.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"734\" y=\"447\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.datamapper.App\" project=\"java-design-patterns\" \n    file=\"/java-design-patterns/java/com/iluwatar/datamapper/App.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"501\" y=\"341\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <dependency id=\"5\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </dependency>  \n  <dependency id=\"6\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </dependency>  \n  <association id=\"7\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"8\" name=\"students\"/>      \n      <multiplicity id=\"9\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <dependency id=\"10\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </dependency>  \n  <realization id=\"11\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "data-mapper/etc/data-mapper.urm.puml",
    "content": "@startuml\npackage com.iluwatar.datamapper {\n  class App {\n    - STUDENT_STRING : String {static}\n    - log : Logger {static}\n    - App()\n    + main(args : String[]) {static}\n  }\n  class Student {\n    - grade : char\n    - name : String\n    - serialVersionUID : long {static}\n    - studentId : int\n    + Student(studentId : int, name : String, grade : char)\n    + equals(inputObject : Object) : boolean\n    + getGrade() : char\n    + getName() : String\n    + getStudentId() : int\n    + hashCode() : int\n    + setGrade(grade : char)\n    + setName(name : String)\n    + setStudentId(studentId : int)\n    + toString() : String\n  }\n  interface StudentDataMapper {\n    + delete(Student) {abstract}\n    + find(int) : Optional<Student> {abstract}\n    + insert(Student) {abstract}\n    + update(Student) {abstract}\n  }\n  class StudentDataMapperImpl {\n    - students : List<Student>\n    + StudentDataMapperImpl()\n    + delete(studentToBeDeleted : Student)\n    + find(studentId : int) : Optional<Student>\n    + getStudents() : List<Student>\n    + insert(studentToBeInserted : Student)\n    + update(studentToBeUpdated : Student)\n  }\n}\nStudentDataMapperImpl -->  \"-students\" Student\nStudentDataMapperImpl ..|> StudentDataMapper \n@enduml"
  },
  {
    "path": "data-mapper/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>data-mapper</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.datamapper.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "data-mapper/src/main/java/com/iluwatar/datamapper/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datamapper;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Data Mapper (DM) is a layer of software that separates the in-memory objects from the\n * database. Its responsibility is to transfer data between the two and also to isolate them from\n * each other. With Data Mapper the in-memory objects needn't know even that there's a database\n * present; they need no SQL interface code, and certainly no knowledge of the database schema. (The\n * database schema is always ignorant of the objects that use it.) Since it's a form of Mapper ,\n * Data Mapper itself is even unknown to the domain layer.\n *\n * <p>The below example demonstrates basic CRUD operations: Create, Read, Update, and Delete.\n */\n@Slf4j\npublic final class App {\n\n  private static final String STUDENT_STRING = \"App.main(), student : \";\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args.\n   */\n  public static void main(final String... args) {\n\n    /* Create new data mapper for type 'first' */\n    final var mapper = new StudentDataMapperImpl();\n\n    /* Create new student */\n    var student = new Student(1, \"Adam\", 'A');\n\n    /* Add student in respectibe store */\n    mapper.insert(student);\n\n    LOGGER.debug(STUDENT_STRING + student + \", is inserted\");\n\n    /* Find this student */\n    final var studentToBeFound = mapper.find(student.getStudentId());\n\n    LOGGER.debug(STUDENT_STRING + studentToBeFound + \", is searched\");\n\n    /* Update existing student object */\n    student = new Student(student.getStudentId(), \"AdamUpdated\", 'A');\n\n    /* Update student in respectibe db */\n    mapper.update(student);\n\n    LOGGER.debug(STUDENT_STRING + student + \", is updated\");\n    LOGGER.debug(STUDENT_STRING + student + \", is going to be deleted\");\n\n    /* Delete student in db */\n    mapper.delete(student);\n  }\n\n  private App() {}\n}\n"
  },
  {
    "path": "data-mapper/src/main/java/com/iluwatar/datamapper/DataMapperException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datamapper;\n\nimport java.io.Serial;\n\n/**\n * Using Runtime Exception for avoiding dependency on implementation exceptions. This helps in\n * decoupling.\n */\npublic final class DataMapperException extends RuntimeException {\n\n  @Serial private static final long serialVersionUID = 1L;\n\n  /**\n   * Constructs a new runtime exception with the specified detail message. The cause is not\n   * initialized, and may subsequently be initialized by a call to {@link #initCause}.\n   *\n   * @param message the detail message. The detail message is saved for later retrieval by the\n   *     {@link #getMessage()} method.\n   */\n  public DataMapperException(final String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "data-mapper/src/main/java/com/iluwatar/datamapper/Student.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datamapper;\n\nimport java.io.Serial;\nimport java.io.Serializable;\nimport lombok.AllArgsConstructor;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\n/** Class defining Student. */\n@EqualsAndHashCode(onlyExplicitlyIncluded = true)\n@ToString\n@Getter\n@Setter\n@AllArgsConstructor\npublic final class Student implements Serializable {\n\n  @Serial private static final long serialVersionUID = 1L;\n\n  @EqualsAndHashCode.Include private int studentId;\n  private String name;\n  private char grade;\n}\n"
  },
  {
    "path": "data-mapper/src/main/java/com/iluwatar/datamapper/StudentDataMapper.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datamapper;\n\nimport java.util.Optional;\n\n/** Interface lists out the possible behaviour for all possible student mappers. */\npublic interface StudentDataMapper {\n\n  Optional<Student> find(int studentId);\n\n  void insert(Student student) throws DataMapperException;\n\n  void update(Student student) throws DataMapperException;\n\n  void delete(Student student) throws DataMapperException;\n}\n"
  },
  {
    "path": "data-mapper/src/main/java/com/iluwatar/datamapper/StudentDataMapperImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datamapper;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Optional;\nimport lombok.Getter;\n\n/** Implementation of Actions on Students Data. */\n@Getter\npublic final class StudentDataMapperImpl implements StudentDataMapper {\n\n  /* Note: Normally this would be in the form of an actual database */\n  private final List<Student> students = new ArrayList<>();\n\n  @Override\n  public Optional<Student> find(int studentId) {\n    return this.getStudents().stream().filter(x -> x.getStudentId() == studentId).findFirst();\n  }\n\n  @Override\n  public void update(Student studentToBeUpdated) throws DataMapperException {\n    String name = studentToBeUpdated.getName();\n    Integer index =\n        Optional.of(studentToBeUpdated)\n            .map(Student::getStudentId)\n            .flatMap(this::find)\n            .map(students::indexOf)\n            .orElseThrow(() -> new DataMapperException(\"Student [\" + name + \"] is not found\"));\n    students.set(index, studentToBeUpdated);\n  }\n\n  @Override\n  public void insert(Student studentToBeInserted) throws DataMapperException {\n    Optional<Student> student = find(studentToBeInserted.getStudentId());\n    if (student.isPresent()) {\n      String name = studentToBeInserted.getName();\n      throw new DataMapperException(\"Student already [\" + name + \"] exists\");\n    }\n\n    students.add(studentToBeInserted);\n  }\n\n  @Override\n  public void delete(Student studentToBeDeleted) throws DataMapperException {\n    if (!students.remove(studentToBeDeleted)) {\n      String name = studentToBeDeleted.getName();\n      throw new DataMapperException(\"Student [\" + name + \"] is not found\");\n    }\n  }\n}\n"
  },
  {
    "path": "data-mapper/src/test/java/com/iluwatar/datamapper/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datamapper;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.function.Executable;\n\n/** Tests that Data-Mapper example runs without errors. */\nfinal class AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n\n    assertDoesNotThrow((Executable) App::main);\n  }\n}\n"
  },
  {
    "path": "data-mapper/src/test/java/com/iluwatar/datamapper/DataMapperTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datamapper;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\nimport org.junit.jupiter.api.Test;\n\n/**\n * The Data Mapper (DM) is a layer of software that separates the in-memory objects from the\n * database. Its responsibility is to transfer data between the two and also to isolate them from\n * each other. With Data Mapper the in-memory objects needn't know even that there's a database\n * present; they need no SQL interface code, and certainly no knowledge of the database schema. (The\n * database schema is always ignorant of the objects that use it.) Since it's a form of Mapper ,\n * Data Mapper itself is even unknown to the domain layer.\n *\n * <p>\n */\nclass DataMapperTest {\n\n  /** This test verify that first data mapper is able to perform all CRUD operations on Student */\n  @Test\n  void testFirstDataMapper() {\n\n    /* Create new data mapper of first type */\n    final var mapper = new StudentDataMapperImpl();\n\n    /* Create new student */\n    var studentId = 1;\n    var student = new Student(studentId, \"Adam\", 'A');\n\n    /* Add student in respectibe db */\n    mapper.insert(student);\n\n    /* Check if student is added in db */\n    assertEquals(studentId, mapper.find(student.getStudentId()).get().getStudentId());\n\n    /* Update existing student object */\n    var updatedName = \"AdamUpdated\";\n    student = new Student(student.getStudentId(), updatedName, 'A');\n\n    /* Update student in respectibe db */\n    mapper.update(student);\n\n    /* Check if student is updated in db */\n    assertEquals(updatedName, mapper.find(student.getStudentId()).get().getName());\n\n    /* Delete student in db */\n    mapper.delete(student);\n\n    /* Result should be false */\n    assertFalse(mapper.find(student.getStudentId()).isPresent());\n  }\n}\n"
  },
  {
    "path": "data-mapper/src/test/java/com/iluwatar/datamapper/StudentTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datamapper;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests {@link Student}. */\nfinal class StudentTest {\n\n  /**\n   * This API tests the equality behaviour of Student object Object Equality should work as per\n   * logic defined in equals method\n   *\n   * @throws Exception if any execution error during test\n   */\n  @Test\n  void testEquality() {\n\n    /* Create some students */\n    final var firstStudent = new Student(1, \"Adam\", 'A');\n    final var secondStudent = new Student(2, \"Donald\", 'B');\n    final var secondSameStudent = new Student(2, \"Donald\", 'B');\n\n    /* Check equals functionality: should return 'true' */\n    assertEquals(firstStudent, firstStudent);\n\n    /* Check equals functionality: should return 'false' */\n    assertNotEquals(firstStudent, secondStudent);\n\n    /* Check equals functionality: should return 'true' */\n    assertEquals(secondStudent, secondSameStudent);\n  }\n}\n"
  },
  {
    "path": "data-transfer-object/README.md",
    "content": "---\ntitle: \"Data Transfer Object Pattern in Java: Simplifying Data Exchange Between Subsystems\"\nshortTitle: Data Transfer Object (DTO)\ndescription: \"Learn about the Data Transfer Object (DTO) pattern, its implementation, and practical uses in Java applications. Optimize data transfer between layers with this structural design pattern.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Client-server\n  - Data transfer\n  - Decoupling\n  - Layered architecture\n  - Optimization\n---\n\n## Also known as\n\n* Transfer Object\n* Value Object\n\n## Intent of Data Transfer Object Design Pattern\n\nThe Data Transfer Object (DTO) pattern is used to transfer data between software application subsystems or layers, particularly in the context of network calls or database retrieval in Java applications. It reduces the number of method calls by aggregating the data in a single transfer.\n\n## Detailed Explanation of Data Transfer Object Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a large company with several departments (e.g., Sales, HR, and IT) needing to share employee information efficiently. Instead of each department querying and retrieving data like name, address, and role individually, they use a courier service to bundle this data into a single package. This package, representing a Data Transfer Object (DTO), allows the departments to easily receive and process comprehensive employee data without making multiple requests. This simplifies data handling, reduces communication overhead, and ensures a standardized format across the company.\n\nIn plain words\n\n> Using DTO, relevant information can be fetched with a single backend query.\n\nWikipedia says\n\n> In the field of programming a data transfer object (DTO) is an object that carries data between processes. The motivation for its use is that communication between processes is usually done resorting to remote interfaces (e.g. web services), where each call is an expensive operation. Because the majority of the cost of each call is related to the round-trip time between the client and the server, one way of reducing the number of calls is to use an object (the DTO) that aggregates the data that would have been transferred by the several calls, but that is served by one call only.\n\nSequence diagram\n\n![Data Transfer Object sequence diagram](./etc/dto-sequence-diagram.png)\n\n## Programmatic Example of DTO Pattern in Java\n\nLet's first introduce our simple `CustomerDTO` record.\n\n```java\npublic record CustomerDto(String id, String firstName, String lastName) {}\n```\n\n`CustomerResource` record acts as the server for customer information.\n\n```java\npublic record CustomerResource(List<CustomerDto> customers) {\n\n    public void save(CustomerDto customer) {\n        customers.add(customer);\n    }\n    \n    public void delete(String customerId) {\n        customers.removeIf(customer -> customer.id().equals(customerId));\n    }\n}\n```\n\nNow fetching customer information is easy since we have the DTOs. The 2nd example uses `ProductDTO` similarly.\n\n```java\npublic class App {\n\n  public static void main(String[] args) {\n\n    // Example 1: Customer DTO\n    var customerOne = new CustomerDto(\"1\", \"Kelly\", \"Brown\");\n    var customerTwo = new CustomerDto(\"2\", \"Alfonso\", \"Bass\");\n    var customers = new ArrayList<>(List.of(customerOne, customerTwo));\n\n    var customerResource = new CustomerResource(customers);\n\n    LOGGER.info(\"All customers:\");\n    var allCustomers = customerResource.customers();\n    printCustomerDetails(allCustomers);\n\n    LOGGER.info(\"----------------------------------------------------------\");\n\n    LOGGER.info(\"Deleting customer with id {1}\");\n    customerResource.delete(customerOne.id());\n    allCustomers = customerResource.customers();\n    printCustomerDetails(allCustomers);\n\n    LOGGER.info(\"----------------------------------------------------------\");\n\n    LOGGER.info(\"Adding customer three}\");\n    var customerThree = new CustomerDto(\"3\", \"Lynda\", \"Blair\");\n    customerResource.save(customerThree);\n    allCustomers = customerResource.customers();\n    printCustomerDetails(allCustomers);\n\n    // Example 2: Product DTO\n\n    Product tv = Product.builder().id(1L).name(\"TV\").supplier(\"Sony\").price(1000D).cost(1090D).build();\n    Product microwave =\n        Product.builder()\n            .id(2L)\n            .name(\"microwave\")\n            .supplier(\"Delonghi\")\n            .price(1000D)\n            .cost(1090D).build();\n    Product refrigerator =\n        Product.builder()\n            .id(3L)\n            .name(\"refrigerator\")\n            .supplier(\"Botsch\")\n            .price(1000D)\n            .cost(1090D).build();\n    Product airConditioner =\n        Product.builder()\n            .id(4L)\n            .name(\"airConditioner\")\n            .supplier(\"LG\")\n            .price(1000D)\n            .cost(1090D).build();\n    List<Product> products =\n        new ArrayList<>(Arrays.asList(tv, microwave, refrigerator, airConditioner));\n    ProductResource productResource = new ProductResource(products);\n\n    LOGGER.info(\n        \"####### List of products including sensitive data just for admins: \\n {}\",\n        Arrays.toString(productResource.getAllProductsForAdmin().toArray()));\n    LOGGER.info(\n        \"####### List of products for customers: \\n {}\",\n        Arrays.toString(productResource.getAllProductsForCustomer().toArray()));\n\n    LOGGER.info(\"####### Going to save Sony PS5 ...\");\n    ProductDto.Request.Create createProductRequestDto =\n        new ProductDto.Request.Create()\n            .setName(\"PS5\")\n            .setCost(1000D)\n            .setPrice(1220D)\n            .setSupplier(\"Sony\");\n    productResource.save(createProductRequestDto);\n    LOGGER.info(\n        \"####### List of products after adding PS5: {}\",\n        Arrays.toString(productResource.products().toArray()));\n  }\n\n  private static void printCustomerDetails(List<CustomerDto> allCustomers) {\n    allCustomers.forEach(customer -> LOGGER.info(customer.firstName()));\n  }\n}\n```\n\nThe console output:\n\n```\n11:10:51.838 [main] INFO com.iluwatar.datatransfer.App -- All customers:\n11:10:51.840 [main] INFO com.iluwatar.datatransfer.App -- Kelly\n11:10:51.840 [main] INFO com.iluwatar.datatransfer.App -- Alfonso\n11:10:51.840 [main] INFO com.iluwatar.datatransfer.App -- ----------------------------------------------------------\n11:10:51.840 [main] INFO com.iluwatar.datatransfer.App -- Deleting customer with id {1}\n11:10:51.840 [main] INFO com.iluwatar.datatransfer.App -- Alfonso\n11:10:51.840 [main] INFO com.iluwatar.datatransfer.App -- ----------------------------------------------------------\n11:10:51.840 [main] INFO com.iluwatar.datatransfer.App -- Adding customer three}\n11:10:51.840 [main] INFO com.iluwatar.datatransfer.App -- Alfonso\n11:10:51.840 [main] INFO com.iluwatar.datatransfer.App -- Lynda\n11:10:51.848 [main] INFO com.iluwatar.datatransfer.App -- ####### List of products including sensitive data just for admins: \n [Private{id=1, name='TV', price=1000.0, cost=1090.0}, Private{id=2, name='microwave', price=1000.0, cost=1090.0}, Private{id=3, name='refrigerator', price=1000.0, cost=1090.0}, Private{id=4, name='airConditioner', price=1000.0, cost=1090.0}]\n11:10:51.852 [main] INFO com.iluwatar.datatransfer.App -- ####### List of products for customers: \n [Public{id=1, name='TV', price=1000.0}, Public{id=2, name='microwave', price=1000.0}, Public{id=3, name='refrigerator', price=1000.0}, Public{id=4, name='airConditioner', price=1000.0}]\n11:10:51.852 [main] INFO com.iluwatar.datatransfer.App -- ####### Going to save Sony PS5 ...\n11:10:51.856 [main] INFO com.iluwatar.datatransfer.App -- ####### List of products after adding PS5: [Product{id=1, name='TV', price=1000.0, cost=1090.0, supplier='Sony'}, Product{id=2, name='microwave', price=1000.0, cost=1090.0, supplier='Delonghi'}, Product{id=3, name='refrigerator', price=1000.0, cost=1090.0, supplier='Botsch'}, Product{id=4, name='airConditioner', price=1000.0, cost=1090.0, supplier='LG'}, Product{id=5, name='PS5', price=1220.0, cost=1000.0, supplier='Sony'}]\n```\n\n## When to Use the Data Transfer Object Pattern in Java\n\nUse the Data Transfer Object pattern when:\n\n* When you need to optimize network traffic by reducing the number of calls, especially in a client-server architecture.\n* In scenarios where batch processing of data is preferred over individual processing.\n* When working with remote interfaces, to encapsulate the data transfer in a serializable object that can be easily transmitted.\n\n## Data Transfer Object Pattern Java Tutorials\n\n* [Data Transfer Object Pattern in Java - Implementation and Mapping (StackAbuse)](https://stackabuse.com/data-transfer-object-pattern-in-java-implementation-and-mapping/)\n* [Design Pattern - Transfer Object Pattern (TutorialsPoint)](https://www.tutorialspoint.com/design_pattern/transfer_object_pattern.htm)\n* [The DTO Pattern (Baeldung)](https://www.baeldung.com/java-dto-pattern)\n\n## Real-World Applications of DTO Pattern in Java\n\n* Remote Method Invocation (RMI) in Java, where DTOs are used to pass data across network.\n* Enterprise JavaBeans (EJB), particularly when data needs to be transferred from EJBs to clients.\n* Various web service frameworks where DTOs encapsulate request and response data.\n\n## Benefits and Trade-offs of Data Transfer Object Pattern\n\nBenefits:\n\n* Reduces network calls, thereby improving application performance.\n* Decouples the client from the server, leading to more modular and maintainable code.\n* Simplifies data transmission over the network by aggregating data into single objects.\n\nTrade-offs:\n\n* Introduces additional classes into the application, which may increase complexity.\n* Can lead to redundant data structures that mirror domain models, potentially causing synchronization issues.\n* May encourage design that leads to an anemic domain model, where business logic is separated from data.\n\n## Related Patterns\n\n* [Composite Entity](https://java-design-patterns.com/patterns/composite-entity/): DTOs may be used to represent composite entities, particularly in persistence mechanisms.\n* [Facade](https://java-design-patterns.com/patterns/facade/): Similar to DTO, a Facade may aggregate multiple calls into one, improving efficiency.\n* [Service Layer](https://java-design-patterns.com/patterns/service-layer/): Often involves using DTOs to transfer data across the boundary between the service layer and its clients.\n\n## References and Credits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cKndQp)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Data Transfer Object (Microsoft)](https://msdn.microsoft.com/en-us/library/ff649585.aspx)\n"
  },
  {
    "path": "data-transfer-object/etc/data-transfer-object.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.2.0\" icons=\"true\" always-add-relationships=\"false\" generalizations=\"true\" realizations=\"true\" \n  associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.datatransfer.App\" project=\"data-transfer-object\"\n    file=\"/data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerClientApp.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"145\" y=\"93\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.datatransfer.CustomerDto\" project=\"data-transfer-object\" \n    file=\"/data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerDto.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"386\" y=\"329\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.datatransfer.CustomerResource\" project=\"data-transfer-object\" \n    file=\"/data-transfer-object/src/main/java/com/iluwatar/datatransfer/CustomerResource.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"677\" y=\"93\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"4\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"5\" name=\"customers\"/>      \n      <multiplicity id=\"6\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "data-transfer-object/etc/data-transfer-object.urm.puml",
    "content": "@startuml\npackage com.iluwatar.datatransfer {\n  class CustomerClientApp {\n    - LOGGER : Logger {static}\n    + CustomerClientApp()\n    + main(args : String[]) {static}\n    - printCustomerDetails(allCustomers : List<CustomerDto>) {static}\n  }\n  class CustomerDto {\n    - firstName : String\n    - id : String\n    - lastName : String\n    + CustomerDto(id : String, firstName : String, lastName : String)\n    + getFirstName() : String\n    + getId() : String\n    + getLastName() : String\n  }\n  class CustomerResource {\n    - customers : List<CustomerDto>\n    + CustomerResource(customers : List<CustomerDto>)\n    + delete(customerId : String)\n    + getAllCustomers() : List<CustomerDto>\n    + save(customer : CustomerDto)\n  }\n}\nCustomerResource -->  \"-customers\" CustomerDto\n@enduml"
  },
  {
    "path": "data-transfer-object/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>data-transfer-object</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.datatransfer.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "data-transfer-object/src/main/java/com/iluwatar/datatransfer/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datatransfer;\n\nimport com.iluwatar.datatransfer.customer.CustomerDto;\nimport com.iluwatar.datatransfer.customer.CustomerResource;\nimport com.iluwatar.datatransfer.product.Product;\nimport com.iluwatar.datatransfer.product.ProductDto;\nimport com.iluwatar.datatransfer.product.ProductResource;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Data Transfer Object pattern is a design pattern in which an data transfer object is used to\n * serve related information together to avoid multiple call for each piece of information.\n *\n * <p>In the first example, {@link App} is a customer details consumer i.e. client to request for\n * customer details to server. {@link CustomerResource} act as server to serve customer information.\n * {@link CustomerDto} is data transfer object to share customer information.\n *\n * <p>In the second example, {@link App} is a product details consumer i.e. client to request for\n * product details to server. {@link ProductResource} acts as server to serve product information.\n * {@link ProductDto} is data transfer object to share product information.\n *\n * <p>The pattern implementation is a bit different in each of the examples. The first can be\n * thought as a traditional example and the second is an enum based implementation.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Method as act client and request to server for details.\n   *\n   * @param args program argument.\n   */\n  public static void main(String[] args) {\n\n    // Example 1: Customer DTO\n    var customerOne = new CustomerDto(\"1\", \"Kelly\", \"Brown\");\n    var customerTwo = new CustomerDto(\"2\", \"Alfonso\", \"Bass\");\n    var customers = new ArrayList<>(List.of(customerOne, customerTwo));\n\n    var customerResource = new CustomerResource(customers);\n\n    LOGGER.info(\"All customers:\");\n    var allCustomers = customerResource.customers();\n    printCustomerDetails(allCustomers);\n\n    LOGGER.info(\"----------------------------------------------------------\");\n\n    LOGGER.info(\"Deleting customer with id {1}\");\n    customerResource.delete(customerOne.id());\n    allCustomers = customerResource.customers();\n    printCustomerDetails(allCustomers);\n\n    LOGGER.info(\"----------------------------------------------------------\");\n\n    LOGGER.info(\"Adding customer three}\");\n    var customerThree = new CustomerDto(\"3\", \"Lynda\", \"Blair\");\n    customerResource.save(customerThree);\n    allCustomers = customerResource.customers();\n    printCustomerDetails(allCustomers);\n\n    // Example 2: Product DTO\n\n    Product tv =\n        Product.builder().id(1L).name(\"TV\").supplier(\"Sony\").price(1000D).cost(1090D).build();\n    Product microwave =\n        Product.builder()\n            .id(2L)\n            .name(\"microwave\")\n            .supplier(\"Delonghi\")\n            .price(1000D)\n            .cost(1090D)\n            .build();\n    Product refrigerator =\n        Product.builder()\n            .id(3L)\n            .name(\"refrigerator\")\n            .supplier(\"Botsch\")\n            .price(1000D)\n            .cost(1090D)\n            .build();\n    Product airConditioner =\n        Product.builder()\n            .id(4L)\n            .name(\"airConditioner\")\n            .supplier(\"LG\")\n            .price(1000D)\n            .cost(1090D)\n            .build();\n    List<Product> products =\n        new ArrayList<>(Arrays.asList(tv, microwave, refrigerator, airConditioner));\n    ProductResource productResource = new ProductResource(products);\n\n    LOGGER.info(\n        \"####### List of products including sensitive data just for admins: \\n {}\",\n        Arrays.toString(productResource.getAllProductsForAdmin().toArray()));\n    LOGGER.info(\n        \"####### List of products for customers: \\n {}\",\n        Arrays.toString(productResource.getAllProductsForCustomer().toArray()));\n\n    LOGGER.info(\"####### Going to save Sony PS5 ...\");\n    ProductDto.Request.Create createProductRequestDto =\n        new ProductDto.Request.Create()\n            .setName(\"PS5\")\n            .setCost(1000D)\n            .setPrice(1220D)\n            .setSupplier(\"Sony\");\n    productResource.save(createProductRequestDto);\n    LOGGER.info(\n        \"####### List of products after adding PS5: {}\",\n        Arrays.toString(productResource.products().toArray()));\n  }\n\n  private static void printCustomerDetails(List<CustomerDto> allCustomers) {\n    allCustomers.forEach(customer -> LOGGER.info(customer.firstName()));\n  }\n}\n"
  },
  {
    "path": "data-transfer-object/src/main/java/com/iluwatar/datatransfer/customer/CustomerDto.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datatransfer.customer;\n\n/**\n * {@link CustomerDto} is a data transfer object POJO. Instead of sending individual information to\n * client We can send related information together in POJO.\n *\n * <p>Dto will not have any business logic in it.\n */\npublic record CustomerDto(String id, String firstName, String lastName) {}\n"
  },
  {
    "path": "data-transfer-object/src/main/java/com/iluwatar/datatransfer/customer/CustomerResource.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datatransfer.customer;\n\nimport java.util.List;\n\n/**\n * The resource class which serves customer information. This class act as server in the demo. Which\n * has all customer details.\n */\npublic record CustomerResource(List<CustomerDto> customers) {\n  /**\n   * Save new customer.\n   *\n   * @param customer save new customer to list.\n   */\n  public void save(CustomerDto customer) {\n    customers.add(customer);\n  }\n\n  /**\n   * Delete customer with given id.\n   *\n   * @param customerId delete customer with id {@code customerId}\n   */\n  public void delete(String customerId) {\n    customers.removeIf(customer -> customer.id().equals(customerId));\n  }\n}\n"
  },
  {
    "path": "data-transfer-object/src/main/java/com/iluwatar/datatransfer/product/Product.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datatransfer.product;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/** {@link Product} is a entity class for product entity. This class act as entity in the demo. */\n@Data\n@Builder\n@NoArgsConstructor\n@AllArgsConstructor\npublic final class Product {\n  private Long id;\n  private String name;\n  private Double price;\n  private Double cost;\n  private String supplier;\n\n  @Override\n  public String toString() {\n    return \"Product{\"\n        + \"id=\"\n        + id\n        + \", name='\"\n        + name\n        + '\\''\n        + \", price=\"\n        + price\n        + \", cost=\"\n        + cost\n        + \", supplier='\"\n        + supplier\n        + '\\''\n        + '}';\n  }\n}\n"
  },
  {
    "path": "data-transfer-object/src/main/java/com/iluwatar/datatransfer/product/ProductDto.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datatransfer.product;\n\n/**\n * {@link ProductDto} is a data transfer object POJO. Instead of sending individual information to\n * client We can send related information together in POJO.\n *\n * <p>Dto will not have any business logic in it.\n */\npublic enum ProductDto {\n  ;\n\n  /**\n   * This is Request class which consist of Create or any other request DTO's you might want to use\n   * in your API.\n   */\n  public enum Request {\n    ;\n\n    /** This is Create dto class for requesting create new product. */\n    public static final class Create implements Name, Price, Cost, Supplier {\n      private String name;\n      private Double price;\n      private Double cost;\n      private String supplier;\n\n      @Override\n      public String getName() {\n        return name;\n      }\n\n      public Create setName(String name) {\n        this.name = name;\n        return this;\n      }\n\n      @Override\n      public Double getPrice() {\n        return price;\n      }\n\n      public Create setPrice(Double price) {\n        this.price = price;\n        return this;\n      }\n\n      @Override\n      public Double getCost() {\n        return cost;\n      }\n\n      public Create setCost(Double cost) {\n        this.cost = cost;\n        return this;\n      }\n\n      @Override\n      public String getSupplier() {\n        return supplier;\n      }\n\n      public Create setSupplier(String supplier) {\n        this.supplier = supplier;\n        return this;\n      }\n    }\n  }\n\n  /**\n   * This is Response class which consist of any response DTO's you might want to provide to your\n   * clients.\n   */\n  public enum Response {\n    ;\n\n    /** This is Public dto class for API response with the lowest data security. */\n    public static final class Public implements Id, Name, Price {\n      private Long id;\n      private String name;\n      private Double price;\n\n      @Override\n      public Long getId() {\n        return id;\n      }\n\n      public Public setId(Long id) {\n        this.id = id;\n        return this;\n      }\n\n      @Override\n      public String getName() {\n        return name;\n      }\n\n      public Public setName(String name) {\n        this.name = name;\n        return this;\n      }\n\n      @Override\n      public Double getPrice() {\n        return price;\n      }\n\n      public Public setPrice(Double price) {\n        this.price = price;\n        return this;\n      }\n\n      @Override\n      public String toString() {\n        return \"Public{\" + \"id=\" + id + \", name='\" + name + '\\'' + \", price=\" + price + '}';\n      }\n    }\n\n    /** This is Private dto class for API response with the highest data security. */\n    public static final class Private implements Id, Name, Price, Cost {\n      private Long id;\n      private String name;\n      private Double price;\n      private Double cost;\n\n      @Override\n      public Long getId() {\n        return id;\n      }\n\n      public Private setId(Long id) {\n        this.id = id;\n        return this;\n      }\n\n      @Override\n      public String getName() {\n        return name;\n      }\n\n      public Private setName(String name) {\n        this.name = name;\n        return this;\n      }\n\n      @Override\n      public Double getPrice() {\n        return price;\n      }\n\n      public Private setPrice(Double price) {\n        this.price = price;\n        return this;\n      }\n\n      @Override\n      public Double getCost() {\n        return cost;\n      }\n\n      public Private setCost(Double cost) {\n        this.cost = cost;\n        return this;\n      }\n\n      @Override\n      public String toString() {\n        return \"Private{\"\n            + \"id=\"\n            + id\n            + \", name='\"\n            + name\n            + '\\''\n            + \", price=\"\n            + price\n            + \", cost=\"\n            + cost\n            + '}';\n      }\n    }\n  }\n\n  /** Use this interface whenever you want to provide the product Id in your DTO. */\n  private interface Id {\n    /**\n     * Unique identifier of the product.\n     *\n     * @return : id of the product.\n     */\n    Long getId();\n  }\n\n  /** Use this interface whenever you want to provide the product Name in your DTO. */\n  private interface Name {\n    /**\n     * The name of the product.\n     *\n     * @return : name of the product.\n     */\n    String getName();\n  }\n\n  /** Use this interface whenever you want to provide the product Price in your DTO. */\n  private interface Price {\n    /**\n     * The amount we sell a product for. <b>This data is not confidential</b>\n     *\n     * @return : price of the product.\n     */\n    Double getPrice();\n  }\n\n  /** Use this interface whenever you want to provide the product Cost in your DTO. */\n  private interface Cost {\n    /**\n     * The amount that it costs us to purchase this product For the amount we sell a product for,\n     * see the {@link Price Price} parameter. <b>This data is confidential</b>\n     *\n     * @return : cost of the product.\n     */\n    Double getCost();\n  }\n\n  /** Use this interface whenever you want to provide the product Supplier in your DTO. */\n  private interface Supplier {\n    /**\n     * The name of supplier of the product or its manufacturer. <b>This data is highly\n     * confidential</b>\n     *\n     * @return : supplier of the product.\n     */\n    String getSupplier();\n  }\n}\n"
  },
  {
    "path": "data-transfer-object/src/main/java/com/iluwatar/datatransfer/product/ProductResource.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datatransfer.product;\n\nimport java.util.List;\n\n/**\n * The resource class which serves product information. This class act as server in the demo. Which\n * has all product details.\n */\npublic record ProductResource(List<Product> products) {\n  /**\n   * Get all products.\n   *\n   * @return : all products in list but in the scheme of private dto.\n   */\n  public List<ProductDto.Response.Private> getAllProductsForAdmin() {\n    return products.stream()\n        .map(\n            p ->\n                new ProductDto.Response.Private()\n                    .setId(p.getId())\n                    .setName(p.getName())\n                    .setCost(p.getCost())\n                    .setPrice(p.getPrice()))\n        .toList();\n  }\n\n  /**\n   * Get all products.\n   *\n   * @return : all products in list but in the scheme of public dto.\n   */\n  public List<ProductDto.Response.Public> getAllProductsForCustomer() {\n    return products.stream()\n        .map(\n            p ->\n                new ProductDto.Response.Public()\n                    .setId(p.getId())\n                    .setName(p.getName())\n                    .setPrice(p.getPrice()))\n        .toList();\n  }\n\n  /**\n   * Save new product.\n   *\n   * @param createProductDto save new product to list.\n   */\n  public void save(ProductDto.Request.Create createProductDto) {\n    products.add(\n        Product.builder()\n            .id((long) (products.size() + 1))\n            .name(createProductDto.getName())\n            .supplier(createProductDto.getSupplier())\n            .price(createProductDto.getPrice())\n            .cost(createProductDto.getCost())\n            .build());\n  }\n}\n"
  },
  {
    "path": "data-transfer-object/src/test/java/com/iluwatar/datatransfer/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datatransfer;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "data-transfer-object/src/test/java/com/iluwatar/datatransfer/customer/CustomerResourceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.datatransfer.customer;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\n\n/** tests {@link CustomerResource}. */\nclass CustomerResourceTest {\n\n  @Test\n  void shouldGetAllCustomers() {\n    var customers = List.of(new CustomerDto(\"1\", \"Melody\", \"Yates\"));\n    var customerResource = new CustomerResource(customers);\n    var allCustomers = customerResource.customers();\n\n    assertEquals(1, allCustomers.size());\n    assertEquals(\"1\", allCustomers.get(0).id());\n    assertEquals(\"Melody\", allCustomers.get(0).firstName());\n    assertEquals(\"Yates\", allCustomers.get(0).lastName());\n  }\n\n  @Test\n  void shouldSaveCustomer() {\n    var customer = new CustomerDto(\"1\", \"Rita\", \"Reynolds\");\n    var customerResource = new CustomerResource(new ArrayList<>());\n\n    customerResource.save(customer);\n\n    var allCustomers = customerResource.customers();\n    assertEquals(\"1\", allCustomers.get(0).id());\n    assertEquals(\"Rita\", allCustomers.get(0).firstName());\n    assertEquals(\"Reynolds\", allCustomers.get(0).lastName());\n  }\n\n  @Test\n  void shouldDeleteCustomer() {\n    var customer = new CustomerDto(\"1\", \"Terry\", \"Nguyen\");\n    var customers = new ArrayList<>(List.of(customer));\n    var customerResource = new CustomerResource(customers);\n\n    customerResource.delete(customer.id());\n\n    var allCustomers = customerResource.customers();\n    assertTrue(allCustomers.isEmpty());\n  }\n}\n"
  },
  {
    "path": "decorator/README.md",
    "content": "---\ntitle: \"Decorator Pattern in Java: Extending Classes Dynamically\"\nshortTitle: Decorator\ndescription: \"Learn how the Decorator Design Pattern enhances flexibility in Java programming by allowing dynamic addition of responsibilities to objects without modifying their existing code. Explore real-world examples and implementation.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Enhancement\n  - Extensibility\n  - Gang of Four\n  - Object composition \n  - Wrapping\n---\n\n## Also known as\n\n* Smart Proxy\n* Wrapper\n\n## Intent of Decorator Design Pattern\n\nThe Decorator pattern allows for the dynamic addition of responsibilities to objects without modifying their existing code. It achieves this by providing a way to \"wrap\" objects within objects of similar interface, enhancing Java design patterns flexibility.\n\n## Detailed Explanation of Decorator Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a coffee shop where you can customize your coffee order. You start with a basic coffee, and you can add different ingredients like milk, sugar, whipped cream, and so on. Each addition is like a decorator in the Decorator design pattern. The base coffee object can be decorated with additional functionality (flavors, toppings) dynamically. For example, you can start with a plain coffee object, then wrap it with a milk decorator, followed by a sugar decorator, and finally a whipped cream decorator. Each decorator adds new features or modifies the behavior of the coffee object, similar to how the Decorator pattern works in software design.\n\nIn plain words\n\n> Decorator pattern lets you dynamically change the behavior of an object at run time by wrapping them in an object of a decorator class.\n\nWikipedia says\n\n> In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern as well as to the Open-Closed Principle, by allowing the functionality of a class to be extended without being modified.\n\nSequence diagram\n\n![Decorator sequence diagram](./etc/decorator-sequence-diagram.png)\n\n## Programmatic Example of Decorator Pattern in Java\n\nThere is an angry troll living in the nearby hills. Usually, it goes bare-handed, but sometimes it has a weapon. To arm the troll it's not necessary to create a new troll but to decorate it dynamically with a suitable weapon.\n\nFirst, we have a `SimpleTroll` implementing the `Troll` interface:\n\n```java\npublic interface Troll {\n    void attack();\n\n    int getAttackPower();\n\n    void fleeBattle();\n}\n\n@Slf4j\npublic class SimpleTroll implements Troll {\n\n    @Override\n    public void attack() {\n        LOGGER.info(\"The troll tries to grab you!\");\n    }\n\n    @Override\n    public int getAttackPower() {\n        return 10;\n    }\n\n    @Override\n    public void fleeBattle() {\n        LOGGER.info(\"The troll shrieks in horror and runs away!\");\n    }\n}\n```\n\nNext, we want to add a club for the troll. We can do it dynamically by using a decorator:\n\n```java\n@Slf4j\n@RequiredArgsConstructor\npublic class ClubbedTroll implements Troll {\n\n    private final Troll decorated;\n\n    @Override\n    public void attack() {\n        decorated.attack();\n        LOGGER.info(\"The troll swings at you with a club!\");\n    }\n\n    @Override\n    public int getAttackPower() {\n        return decorated.getAttackPower() + 10;\n    }\n\n    @Override\n    public void fleeBattle() {\n        decorated.fleeBattle();\n    }\n}\n```\n\nHere's the troll in action:\n\n```java\n  public static void main(String[] args) {\n\n    // simple troll\n    LOGGER.info(\"A simple looking troll approaches.\");\n    var troll = new SimpleTroll();\n    troll.attack();\n    troll.fleeBattle();\n    LOGGER.info(\"Simple troll power: {}.\\n\", troll.getAttackPower());\n\n    // change the behavior of the simple troll by adding a decorator\n    LOGGER.info(\"A troll with huge club surprises you.\");\n    var clubbedTroll = new ClubbedTroll(troll);\n    clubbedTroll.attack();\n    clubbedTroll.fleeBattle();\n    LOGGER.info(\"Clubbed troll power: {}.\\n\", clubbedTroll.getAttackPower());\n}\n```\n\nProgram output:\n\n```\n11:34:18.098 [main] INFO com.iluwatar.decorator.App -- A simple looking troll approaches.\n11:34:18.100 [main] INFO com.iluwatar.decorator.SimpleTroll -- The troll tries to grab you!\n11:34:18.100 [main] INFO com.iluwatar.decorator.SimpleTroll -- The troll shrieks in horror and runs away!\n11:34:18.100 [main] INFO com.iluwatar.decorator.App -- Simple troll power: 10.\n\n11:34:18.100 [main] INFO com.iluwatar.decorator.App -- A troll with huge club surprises you.\n11:34:18.101 [main] INFO com.iluwatar.decorator.SimpleTroll -- The troll tries to grab you!\n11:34:18.101 [main] INFO com.iluwatar.decorator.ClubbedTroll -- The troll swings at you with a club!\n11:34:18.101 [main] INFO com.iluwatar.decorator.SimpleTroll -- The troll shrieks in horror and runs away!\n11:34:18.101 [main] INFO com.iluwatar.decorator.App -- Clubbed troll power: 20.\n```\n\n## When to Use the Decorator Pattern in Java\n\nDecorator is used to:\n\n* Add responsibilities to individual objects dynamically and transparently, that is, without affecting other objects, a key feature of Java design patterns.\n* For responsibilities that can be withdrawn.\n* When extending a class is impractical due to the proliferation of subclasses that could result.\n* For when a class definition might be hidden or otherwise unavailable for subclassing.\n\n## Decorator Pattern Java Tutorials\n\n* [Decorator Design Pattern in Java Example (DigitalOcean)](https://www.digitalocean.com/community/tutorials/decorator-design-pattern-in-java-example)\n\n## Real-World Applications of Decorator Pattern in Java\n\n* GUI toolkits often use decorators to dynamically add behaviors like scrolling, borders, or layout management to components.\n* The [java.io.InputStream](http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html), [java.io.OutputStream](http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html), [java.io.Reader](http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html) and [java.io.Writer](http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html) classes in Java are well-known examples utilizing the Decorator pattern.\n* [java.util.Collections#synchronizedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedCollection-java.util.Collection-)\n* [java.util.Collections#unmodifiableXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableCollection-java.util.Collection-)\n* [java.util.Collections#checkedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedCollection-java.util.Collection-java.lang.Class-)\n\n## Benefits and Trade-offs of Decorator Pattern\n\nBenefits:\n\n* Greater flexibility than static inheritance.\n* Avoids feature-laden classes high up in the hierarchy, showcasing the power of Java design patterns.\n* A decorator and its component aren't identical.\n* Responsibilities can be added or removed at runtime.\n\nTrade-offs:\n\n* A decorator and its component aren't identical, so tests for object type will fail.\n* Decorators can lead to a system with lots of small objects that look alike to the programmer, making the desired configuration hard to achieve.\n* Overuse can complicate the code structure due to the introduction of numerous small classes.\n\n## Related Java Design Patterns\n\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): A decorator changes an object's responsibilities, while an adapter changes an object's interface.\n* [Composite](https://java-design-patterns.com/patterns/composite/): Decorators can be viewed as a degenerate composite with only one component. However, a decorator adds additional responsibilities—it isn't intended for object aggregation.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Decorator lets you change the skin of an object, while Strategy lets you change the guts.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Functional Programming in Java](https://amzn.to/3JUIc5Q)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/4aKFTgS)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "decorator/etc/decorator.urm.puml",
    "content": "@startuml\npackage com.iluwatar.decorator {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class ClubbedTroll {\n    - LOGGER : Logger {static}\n    - decorated : Troll\n    + ClubbedTroll(decorated : Troll)\n    + attack()\n    + fleeBattle()\n    + getAttackPower() : int\n  }\n  class SimpleTroll {\n    - LOGGER : Logger {static}\n    + SimpleTroll()\n    + attack()\n    + fleeBattle()\n    + getAttackPower() : int\n  }\n  interface Troll {\n    + attack() {abstract}\n    + fleeBattle() {abstract}\n    + getAttackPower() : int {abstract}\n  }\n}\nClubbedTroll -->  \"-decorated\" Troll\nClubbedTroll ..|> Troll \nSimpleTroll ..|> Troll \n@enduml"
  },
  {
    "path": "decorator/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>decorator</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.decorator.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "decorator/src/main/java/com/iluwatar/decorator/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.decorator;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Decorator pattern is a more flexible alternative to subclassing. The Decorator class\n * implements the same interface as the target and uses composition to \"decorate\" calls to the\n * target. Using the Decorator pattern it is possible to change the behavior of the class during\n * runtime.\n *\n * <p>In this example we show how the simple {@link SimpleTroll} first attacks and then flees the\n * battle. Then we decorate the {@link SimpleTroll} with a {@link ClubbedTroll} and perform the\n * attack again. You can see how the behavior changes after the decoration.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    // simple troll\n    LOGGER.info(\"A simple looking troll approaches.\");\n    var troll = new SimpleTroll();\n    troll.attack();\n    troll.fleeBattle();\n    LOGGER.info(\"Simple troll power: {}.\\n\", troll.getAttackPower());\n\n    // change the behavior of the simple troll by adding a decorator\n    LOGGER.info(\"A troll with huge club surprises you.\");\n    var clubbedTroll = new ClubbedTroll(troll);\n    clubbedTroll.attack();\n    clubbedTroll.fleeBattle();\n    LOGGER.info(\"Clubbed troll power: {}.\\n\", clubbedTroll.getAttackPower());\n  }\n}\n"
  },
  {
    "path": "decorator/src/main/java/com/iluwatar/decorator/ClubbedTroll.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.decorator;\n\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Decorator that adds a club for the troll. */\n@Slf4j\n@RequiredArgsConstructor\npublic class ClubbedTroll implements Troll {\n\n  private final Troll decorated;\n\n  @Override\n  public void attack() {\n    decorated.attack();\n    LOGGER.info(\"The troll swings at you with a club!\");\n  }\n\n  @Override\n  public int getAttackPower() {\n    return decorated.getAttackPower() + 10;\n  }\n\n  @Override\n  public void fleeBattle() {\n    decorated.fleeBattle();\n  }\n}\n"
  },
  {
    "path": "decorator/src/main/java/com/iluwatar/decorator/SimpleTroll.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.decorator;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** SimpleTroll implements {@link Troll} interface directly. */\n@Slf4j\npublic class SimpleTroll implements Troll {\n\n  @Override\n  public void attack() {\n    LOGGER.info(\"The troll tries to grab you!\");\n  }\n\n  @Override\n  public int getAttackPower() {\n    return 10;\n  }\n\n  @Override\n  public void fleeBattle() {\n    LOGGER.info(\"The troll shrieks in horror and runs away!\");\n  }\n}\n"
  },
  {
    "path": "decorator/src/main/java/com/iluwatar/decorator/Troll.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.decorator;\n\n/** Interface for trolls. */\npublic interface Troll {\n\n  void attack();\n\n  int getAttackPower();\n\n  void fleeBattle();\n}\n"
  },
  {
    "path": "decorator/src/test/java/com/iluwatar/decorator/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.decorator;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "decorator/src/test/java/com/iluwatar/decorator/ClubbedTrollTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.decorator;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\nimport static org.mockito.internal.verification.VerificationModeFactory.times;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests for {@link ClubbedTroll} */\nclass ClubbedTrollTest {\n\n  @Test\n  void testClubbedTroll() {\n    // Create a normal troll first, but make sure we can spy on it later on.\n    final var simpleTroll = spy(new SimpleTroll());\n\n    // Now we want to decorate the troll to make it stronger ...\n    final var clubbed = new ClubbedTroll(simpleTroll);\n    assertEquals(20, clubbed.getAttackPower());\n    verify(simpleTroll, times(1)).getAttackPower();\n\n    // Check if the clubbed troll actions are delegated to the decorated troll\n    clubbed.attack();\n    verify(simpleTroll, times(1)).attack();\n\n    clubbed.fleeBattle();\n    verify(simpleTroll, times(1)).fleeBattle();\n    verifyNoMoreInteractions(simpleTroll);\n  }\n}\n"
  },
  {
    "path": "decorator/src/test/java/com/iluwatar/decorator/SimpleTrollTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.decorator;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/** Tests for {@link SimpleTroll} */\nclass SimpleTrollTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(SimpleTroll.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  @Test\n  void testTrollActions() {\n    final var troll = new SimpleTroll();\n    assertEquals(10, troll.getAttackPower());\n\n    troll.attack();\n    assertEquals(\"The troll tries to grab you!\", appender.getLastMessage());\n\n    troll.fleeBattle();\n    assertEquals(\"The troll shrieks in horror and runs away!\", appender.getLastMessage());\n\n    assertEquals(2, appender.getLogSize());\n  }\n\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    InMemoryAppender(Class clazz) {\n      ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    String getLastMessage() {\n      return log.get(log.size() - 1).getMessage();\n    }\n\n    int getLogSize() {\n      return log.size();\n    }\n  }\n}\n"
  },
  {
    "path": "delegation/README.md",
    "content": "---\ntitle: \"Delegation Pattern in Java: Mastering Efficient Task Assignment\"\nshortTitle: Delegation\ndescription: \"Explore the Delegation Design Pattern in Java with real-world examples, class diagrams, and its benefits. Learn how to enhance your code flexibility and reuse.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Decoupling\n  - Delegation\n  - Object composition\n---\n\n## Also known as\n\n* Helper\n* Surrogate\n\n## Intent of Delegation Design Pattern\n\nTo allow an object to delegate responsibility for a task to another helper object.\n\n## Detailed Explanation of Delegation Pattern with Real-World Examples\n\nReal-world example\n\n> In a restaurant, the head chef delegates tasks to sous-chefs: one manages grilling, another handles salads, and a third is in charge of desserts. Each sous-chef specializes in their area, allowing the head chef to focus on overall kitchen management. This mirrors the Delegation design pattern, where a main object delegates specific tasks to helper objects, each expert in their domain.\n\nIn plain words\n\n> Delegation is a design pattern where an object passes on a task to a helper object.\n\nWikipedia says\n\n> In object-oriented programming, delegation refers to evaluating a member (property or method) of one object (the receiver) in the context of another original object (the sender). Delegation can be done explicitly, by passing the sending object to the receiving object, which can be done in any object-oriented language; or implicitly, by the member lookup rules of the language, which requires language support for the feature.\n\nSequence diagram\n\n![Delegation sequence diagram](./etc/delegation-sequence-diagram.png)\n\n## Programmatic Example of Delegation Pattern in Java\n\nLet's consider a printing example.\n\nWe have an interface `Printer` and three implementations `CanonPrinter`, `EpsonPrinter` and `HpPrinter`.\n\n```java\npublic interface Printer {\n    void print(final String message);\n}\n\n@Slf4j\npublic class CanonPrinter implements Printer {\n    @Override\n    public void print(String message) {\n        LOGGER.info(\"Canon Printer : {}\", message);\n    }\n}\n\n@Slf4j\npublic class EpsonPrinter implements Printer {\n    @Override\n    public void print(String message) {\n        LOGGER.info(\"Epson Printer : {}\", message);\n    }\n}\n\n@Slf4j\npublic class HpPrinter implements Printer {\n    @Override\n    public void print(String message) {\n        LOGGER.info(\"HP Printer : {}\", message);\n    }\n}\n```\n\nThe `PrinterController` can be used as a `Printer` by delegating any work handled by this interface to an object implementing it.\n\n```java\npublic class PrinterController implements Printer {\n\n    private final Printer printer;\n\n    public PrinterController(Printer printer) {\n        this.printer = printer;\n    }\n\n    @Override\n    public void print(String message) {\n        printer.print(message);\n    }\n}\n```\n\nIn the client code, printer controllers can print messages differently depending on the object they're delegating that work to.\n\n```java\npublic class App {\n\n    private static final String MESSAGE_TO_PRINT = \"hello world\";\n\n    public static void main(String[] args) {\n        var hpPrinterController = new PrinterController(new HpPrinter());\n        var canonPrinterController = new PrinterController(new CanonPrinter());\n        var epsonPrinterController = new PrinterController(new EpsonPrinter());\n\n        hpPrinterController.print(MESSAGE_TO_PRINT);\n        canonPrinterController.print(MESSAGE_TO_PRINT);\n        epsonPrinterController.print(MESSAGE_TO_PRINT);\n    }\n}\n```\n\nProgram output:\n\n```\nHP Printer:hello world\nCanon Printer:hello world\nEpson Printer:hello world\n```\n\n## When to Use the Delegation Pattern in Java\n\n* When you want to pass responsibility from one class to another without inheritance.\n* To achieve composition-based reuse instead of inheritance-based.\n* When you need to use several interchangeable helper classes at runtime.\n\n## Real-World Applications of Delegation Pattern in Java\n\n* Java's java.awt.event package, where listeners are often used to handle events.\n* Wrapper classes in Java's Collections Framework (java.util.Collections), which delegate to other collection objects.\n* In Spring Framework, delegation is used extensively in the IoC container where beans delegate tasks to other beans.\n\n## Benefits and Trade-offs of Delegation Pattern\n\nBenefits:\n\n* Reduces subclassing: Objects can delegate operations to different objects and change them at runtime, reducing the need for subclassing.\n* Encourages reuse: Delegation promotes the reuse of the helper object's code.\n* Increases flexibility: By delegating tasks to helper objects, you can change the behavior of your classes at runtime.\n\nTrade-offs:\n\n* Runtime Overhead: Delegation can introduce additional layers of indirection, which may result in slight performance costs.\n* Complexity: The design can become more complicated since it involves additional classes and interfaces to manage delegation.\n\n## Related Java Design Patterns\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): Delegation can be used within a composite pattern to delegate component-specific behavior to child components.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Delegation is often used in the strategy pattern where a context object delegates tasks to a strategy object.\n* https://java-design-patterns.com/patterns/proxy/: The proxy pattern is a form of delegation where a proxy object controls access to another object, which it delegates work to.\n\n## References and Credits\n\n* [Effective Java](https://amzn.to/4aGE7gX)\n* [Head First Design Patterns](https://amzn.to/3J9tuaB)\n* [Refactoring: Improving the Design of Existing Code](https://amzn.to/3VOcRsw)\n* [Delegate Pattern: Wikipedia ](https://en.wikipedia.org/wiki/Delegation_pattern)\n"
  },
  {
    "path": "delegation/etc/delegation.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.9\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.delegation.simple.printers.HpPrinter\" project=\"delegation\" \n    file=\"/delegation/src/main/java/com/iluwatar/delegation/simple/printers/HpPrinter.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"764\" y=\"272\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.delegation.simple.printers.EpsonPrinter\" project=\"delegation\" \n    file=\"/delegation/src/main/java/com/iluwatar/delegation/simple/printers/EpsonPrinter.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"511\" y=\"270\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.delegation.simple.printers.CanonPrinter\" project=\"delegation\" \n    file=\"/delegation/src/main/java/com/iluwatar/delegation/simple/printers/CanonPrinter.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"252\" y=\"275\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"4\" language=\"java\" name=\"com.iluwatar.delegation.simple.Printer\" project=\"delegation\" \n    file=\"/delegation/src/main/java/com/iluwatar/delegation/simple/Printer.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"524\" y=\"89\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.delegation.simple.PrinterController\" project=\"delegation\" \n    file=\"/delegation/src/main/java/com/iluwatar/delegation/simple/PrinterController.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"112\" y=\"90\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <realization id=\"6\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <association id=\"7\">    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"8\" name=\"printer\"/>      \n      <multiplicity id=\"9\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"10\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <realization id=\"11\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <realization id=\"12\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "delegation/etc/delegation.urm.puml",
    "content": "@startuml\npackage com.iluwatar.delegation.simple.printers {\n  class CanonPrinter {\n    - LOGGER : Logger {static}\n    + CanonPrinter()\n    + print(message : String)\n  }\n  class EpsonPrinter {\n    - LOGGER : Logger {static}\n    + EpsonPrinter()\n    + print(message : String)\n  }\n  class HpPrinter {\n    - LOGGER : Logger {static}\n    + HpPrinter()\n    + print(message : String)\n  }\n}\npackage com.iluwatar.delegation.simple {\n  class App {\n    - MESSAGE_TO_PRINT : String {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  interface Printer {\n    + print(String) {abstract}\n  }\n  class PrinterController {\n    - printer : Printer\n    + PrinterController(printer : Printer)\n    + print(message : String)\n  }\n}\nPrinterController -->  \"-printer\" Printer\nPrinterController ..|> Printer \nCanonPrinter ..|> Printer \nEpsonPrinter ..|> Printer \nHpPrinter ..|> Printer \n@enduml"
  },
  {
    "path": "delegation/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>delegation</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.delegation.simple.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "delegation/src/main/java/com/iluwatar/delegation/simple/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.delegation.simple;\n\nimport com.iluwatar.delegation.simple.printers.CanonPrinter;\nimport com.iluwatar.delegation.simple.printers.EpsonPrinter;\nimport com.iluwatar.delegation.simple.printers.HpPrinter;\n\n/**\n * The delegate pattern provides a mechanism to abstract away the implementation and control of the\n * desired action. The class being called in this case {@link PrinterController} is not responsible\n * for the actual desired action, but is actually delegated to a helper class either {@link\n * CanonPrinter}, {@link EpsonPrinter} or {@link HpPrinter}. The consumer does not have or require\n * knowledge of the actual class carrying out the action, only the container on which they are\n * calling.\n *\n * <p>In this example the delegates are {@link EpsonPrinter}, {@link HpPrinter} and {@link\n * CanonPrinter} they all implement {@link Printer}. The {@link PrinterController} class also\n * implements {@link Printer}. However, neither provide the functionality of {@link Printer} by\n * printing to the screen, they actually call upon the instance of {@link Printer} that they were\n * instantiated with. Therefore, delegating the behaviour to another class.\n */\npublic class App {\n\n  private static final String MESSAGE_TO_PRINT = \"hello world\";\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var hpPrinterController = new PrinterController(new HpPrinter());\n    var canonPrinterController = new PrinterController(new CanonPrinter());\n    var epsonPrinterController = new PrinterController(new EpsonPrinter());\n\n    hpPrinterController.print(MESSAGE_TO_PRINT);\n    canonPrinterController.print(MESSAGE_TO_PRINT);\n    epsonPrinterController.print(MESSAGE_TO_PRINT);\n  }\n}\n"
  },
  {
    "path": "delegation/src/main/java/com/iluwatar/delegation/simple/Printer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.delegation.simple;\n\nimport com.iluwatar.delegation.simple.printers.CanonPrinter;\nimport com.iluwatar.delegation.simple.printers.EpsonPrinter;\nimport com.iluwatar.delegation.simple.printers.HpPrinter;\n\n/**\n * Interface that both the Controller and the Delegate will implement.\n *\n * @see CanonPrinter\n * @see EpsonPrinter\n * @see HpPrinter\n */\npublic interface Printer {\n\n  /**\n   * Method that takes a String to print to the screen. This will be implemented on both the\n   * controller and the delegate allowing the controller to call the same method on the delegate\n   * class.\n   *\n   * @param message to be printed to the screen\n   */\n  void print(final String message);\n}\n"
  },
  {
    "path": "delegation/src/main/java/com/iluwatar/delegation/simple/PrinterController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.delegation.simple;\n\n/**\n * Delegator Class to delegate the implementation of the Printer. This ensures two things: - when\n * the actual implementation of the Printer class changes the delegation will still be operational -\n * the actual benefit is observed when there are more than one implementor, and they share a\n * delegation control\n */\npublic class PrinterController implements Printer {\n\n  private final Printer printer;\n\n  public PrinterController(Printer printer) {\n    this.printer = printer;\n  }\n\n  /**\n   * This method is implemented from {@link Printer} however instead on providing an implementation,\n   * it instead calls upon the class passed through the constructor. This is the delegate, hence the\n   * pattern. Therefore, meaning that the caller does not care of the implementing class only the\n   * owning controller.\n   *\n   * @param message to be printed to the screen\n   */\n  @Override\n  public void print(String message) {\n    printer.print(message);\n  }\n}\n"
  },
  {
    "path": "delegation/src/main/java/com/iluwatar/delegation/simple/printers/CanonPrinter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.delegation.simple.printers;\n\nimport com.iluwatar.delegation.simple.Printer;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Specialised Implementation of {@link Printer} for a Canon Printer, in this case the message to be\n * printed is appended to \"Canon Printer : \".\n *\n * @see Printer\n */\n@Slf4j\npublic class CanonPrinter implements Printer {\n\n  /** {@inheritDoc} */\n  @Override\n  public void print(String message) {\n    LOGGER.info(\"Canon Printer : {}\", message);\n  }\n}\n"
  },
  {
    "path": "delegation/src/main/java/com/iluwatar/delegation/simple/printers/EpsonPrinter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.delegation.simple.printers;\n\nimport com.iluwatar.delegation.simple.Printer;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Specialised Implementation of {@link Printer} for an Epson Printer, in this case the message to\n * be printed is appended to \"Epson Printer : \".\n *\n * @see Printer\n */\n@Slf4j\npublic class EpsonPrinter implements Printer {\n\n  /** {@inheritDoc} */\n  @Override\n  public void print(String message) {\n    LOGGER.info(\"Epson Printer : {}\", message);\n  }\n}\n"
  },
  {
    "path": "delegation/src/main/java/com/iluwatar/delegation/simple/printers/HpPrinter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.delegation.simple.printers;\n\nimport com.iluwatar.delegation.simple.Printer;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Specialised Implementation of {@link Printer} for an HP Printer, in this case the message to be\n * printed is appended to \"HP Printer : \".\n *\n * @see Printer\n */\n@Slf4j\npublic class HpPrinter implements Printer {\n\n  /** {@inheritDoc} */\n  @Override\n  public void print(String message) {\n    LOGGER.info(\"HP Printer : {}\", message);\n  }\n}\n"
  },
  {
    "path": "delegation/src/test/java/com/iluwatar/delegation/simple/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.delegation.simple;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application Test Entry */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "delegation/src/test/java/com/iluwatar/delegation/simple/DelegateTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.delegation.simple;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport com.iluwatar.delegation.simple.printers.CanonPrinter;\nimport com.iluwatar.delegation.simple.printers.EpsonPrinter;\nimport com.iluwatar.delegation.simple.printers.HpPrinter;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/** Test for Delegation Pattern */\nclass DelegateTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  private static final String MESSAGE = \"Test Message Printed\";\n\n  @Test\n  void testCanonPrinter() {\n    var printerController = new PrinterController(new CanonPrinter());\n    printerController.print(MESSAGE);\n\n    assertEquals(\"Canon Printer : Test Message Printed\", appender.getLastMessage());\n  }\n\n  @Test\n  void testHpPrinter() {\n    var printerController = new PrinterController(new HpPrinter());\n    printerController.print(MESSAGE);\n\n    assertEquals(\"HP Printer : Test Message Printed\", appender.getLastMessage());\n  }\n\n  @Test\n  void testEpsonPrinter() {\n    var printerController = new PrinterController(new EpsonPrinter());\n    printerController.print(MESSAGE);\n\n    assertEquals(\"Epson Printer : Test Message Printed\", appender.getLastMessage());\n  }\n\n  /** Logging Appender */\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender() {\n      ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public String getLastMessage() {\n      return log.get(log.size() - 1).getFormattedMessage();\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n  }\n}\n"
  },
  {
    "path": "dependency-injection/README.md",
    "content": "---\ntitle: \"Dependency Injection Pattern in Java: Boosting Maintainability with Loose Coupling\"\nshortTitle: Dependency Injection\ndescription: \"Learn about the Dependency Injection design pattern. Explore its benefits, real-world examples, class diagrams, and best practices for implementation in Java.\"\ncategory: Creational\nlanguage: en\ntag:\n  - Decoupling\n  - Dependency management\n  - Inversion of control\n---\n\n## Also known as\n\n* Inversion of Control (IoC)\n* Dependency Inversion\n\n## Intent of Dependency Injection Design Pattern\n\nTo decouple the creation of object dependencies from their usage, allowing for more flexible and testable code.\n\n## Detailed Explanation of Dependency Injection Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a high-end restaurant where the chef needs various ingredients to prepare dishes. Instead of the chef personally going to different suppliers for each ingredient, a trusted supplier delivers all the required fresh ingredients daily. This allows the chef to focus on cooking without worrying about sourcing the ingredients.\n>\n> In the Dependency Injection design pattern, the trusted supplier acts as the \"injector,\" providing the necessary dependencies (ingredients) to the chef (object). The chef can then use these dependencies without knowing where they came from, ensuring a clean separation between the creation and use of dependencies. This setup enhances efficiency, flexibility, and maintainability in the kitchen, much like in a software system.\n\nIn plain words\n\n> Dependency Injection separates the creation of the client's dependencies from its own behavior.\n\nWikipedia says\n\n> In software engineering, dependency injection is a technique in which an object receives other objects that it depends on. These other objects are called dependencies.\n\nSequence diagram\n\n![Dependency Injection sequence diagram](./etc/dependency-injection-sequence-diagram.png)\n\n## Programmatic Example of Dependency Injection Pattern in Java\n\nThe old wizard likes to fill his pipe and smoke tobacco once in a while. However, he doesn't want to depend on a single tobacco brand only but likes to be able to enjoy them all interchangeably.\n\nLet's first introduce the `Tobacco` interface and the concrete brands.\n\n```java\n\n@Slf4j\npublic abstract class Tobacco {\n\n    public void smoke(Wizard wizard) {\n        LOGGER.info(\"{} smoking {}\", wizard.getClass().getSimpleName(),\n                this.getClass().getSimpleName());\n    }\n}\n\npublic class SecondBreakfastTobacco extends Tobacco {\n}\n\npublic class RivendellTobacco extends Tobacco {\n}\n\npublic class OldTobyTobacco extends Tobacco {\n}\n```\n\nNext here's the `Wizard` class hierarchy.\n\n```java\npublic interface Wizard {\n\n    void smoke();\n}\n\npublic class AdvancedWizard implements Wizard {\n\n    private final Tobacco tobacco;\n\n    public AdvancedWizard(Tobacco tobacco) {\n        this.tobacco = tobacco;\n    }\n\n    @Override\n    public void smoke() {\n        tobacco.smoke(this);\n    }\n}\n```\n\nFinally, we can show how easy it is to give the old wizard any brand of tobacco.\n\n```java\npublic static void main(String[] args) {\n    var simpleWizard = new SimpleWizard();\n    simpleWizard.smoke();\n\n    var advancedWizard = new AdvancedWizard(new SecondBreakfastTobacco());\n    advancedWizard.smoke();\n\n    var advancedSorceress = new AdvancedSorceress();\n    advancedSorceress.setTobacco(new SecondBreakfastTobacco());\n    advancedSorceress.smoke();\n\n    var injector = Guice.createInjector(new TobaccoModule());\n    var guiceWizard = injector.getInstance(GuiceWizard.class);\n    guiceWizard.smoke();\n}\n```\n\nThe program output:\n\n```\n11:54:05.205 [main] INFO com.iluwatar.dependency.injection.Tobacco -- SimpleWizard smoking OldTobyTobacco\n11:54:05.207 [main] INFO com.iluwatar.dependency.injection.Tobacco -- AdvancedWizard smoking SecondBreakfastTobacco\n11:54:05.207 [main] INFO com.iluwatar.dependency.injection.Tobacco -- AdvancedSorceress smoking SecondBreakfastTobacco\n11:54:05.308 [main] INFO com.iluwatar.dependency.injection.Tobacco -- GuiceWizard smoking RivendellTobacco\n```\n\n## When to Use the Dependency Injection Pattern in Java\n\n* When aiming to reduce the coupling between classes and increase the modularity of the application.\n* In scenarios where the object creation process is complex or should be separated from the class usage.\n* In applications requiring easier unit testing by allowing dependencies to be mocked or stubbed.\n* Within frameworks or libraries that manage object lifecycles and dependencies, such as Spring or Jakarta EE (formerly Java EE).\n\n## Real-World Applications of Dependency Injection Pattern in Java\n\n* Frameworks like Spring, Jakarta EE, and Google Guice use Dependency Injection (DI) extensively to manage component lifecycles and dependencies.\n* Desktop and web applications that require flexible architecture with easily interchangeable components.\n\n## Benefits and Trade-offs of Dependency Injection Pattern\n\nBenefits:\n\n* Enhances modularity and separation of concerns.\n* Simplifies unit testing by allowing for easy mocking of dependencies.\n* Increases flexibility and maintainability by promoting loose coupling.\n\nTrade-offs:\n\n* Can introduce complexity in the configuration, especially in large projects.\n* Might increase the learning curve for developers unfamiliar with Dependency Injection patterns or frameworks.\n* Requires careful management of object lifecycles and scopes.\n\n## Related Java Design Patterns\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/) and [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): Used to create instances that the DI mechanism will inject.\n* [Service Locator](https://java-design-patterns.com/patterns/service-locator/): An alternative to DI for locating services or components, though it does not decouple the lookup process as effectively as DI.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Often used in conjunction with DI to provide a single instance of a service across the application.\n\n## References and Credits\n\n* [Clean Code: A Handbook of Agile Software Craftsmanship](https://amzn.to/3wRnjp5)\n* [Dependency Injection: Design patterns using Spring and Guice](https://amzn.to/4aMyHkI)\n* [Dependency Injection Principles, Practices, and Patterns](https://amzn.to/4aupmxe)\n* [Google Guice: Agile Lightweight Dependency Injection Framework](https://amzn.to/4bTDbX0)\n* [Java 9 Dependency Injection: Write loosely coupled code with Spring 5 and Guice](https://amzn.to/4ayCtxp)\n* [Java Design Pattern Essentials](https://amzn.to/3xtPPxa)\n* [Pro Java EE Spring Patterns: Best Practices and Design Strategies Implementing Java EE Patterns with the Spring Framework](https://amzn.to/3J6Teoh)\n* [Spring in Action](https://amzn.to/4asnpSG)\n"
  },
  {
    "path": "dependency-injection/etc/dependency-injection.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.AdvancedWizard\" project=\"dependency-injection\" \n    file=\"/dependency-injection/src/main/java/com/iluwatar/AdvancedWizard.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"179\" x=\"744\" y=\"233\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.Tobacco\" project=\"dependency-injection\" \n    file=\"/dependency-injection/src/main/java/com/iluwatar/Tobacco.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"105\" width=\"140\" x=\"646\" y=\"379\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.RivendellTobacco\" project=\"dependency-injection\" \n    file=\"/dependency-injection/src/main/java/com/iluwatar/RivendellTobacco.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"152\" x=\"570\" y=\"524\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"4\" language=\"java\" name=\"com.iluwatar.Wizard\" project=\"dependency-injection\" \n    file=\"/dependency-injection/src/main/java/com/iluwatar/Wizard.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"120\" x=\"486\" y=\"379\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.SimpleWizard\" project=\"dependency-injection\" \n    file=\"/dependency-injection/src/main/java/com/iluwatar/SimpleWizard.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"120\" x=\"387\" y=\"233\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.TobaccoModule\" project=\"dependency-injection\" \n    file=\"/dependency-injection/src/main/java/com/iluwatar/TobaccoModule.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"137\" x=\"210\" y=\"233\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.GuiceWizard\" project=\"dependency-injection\" \n    file=\"/dependency-injection/src/main/java/com/iluwatar/GuiceWizard.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"157\" x=\"547\" y=\"233\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.OldTobyTobacco\" project=\"dependency-injection\" \n    file=\"/dependency-injection/src/main/java/com/iluwatar/OldTobyTobacco.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"143\" x=\"387\" y=\"524\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"9\" language=\"java\" name=\"com.iluwatar.SecondBreakfastTobacco\" project=\"dependency-injection\" \n    file=\"/dependency-injection/src/main/java/com/iluwatar/SecondBreakfastTobacco.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"206\" x=\"762\" y=\"524\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"10\">    \n    <end type=\"SOURCE\" refId=\"7\" navigable=\"false\">      \n      <attribute id=\"11\" name=\"tobacco\"/>      \n      <multiplicity id=\"12\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"13\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </generalization>  \n  <realization id=\"14\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <generalization id=\"15\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </generalization>  \n  <association id=\"16\">    \n    <bendpoint x=\"396\" y=\"379\"/>    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"17\" name=\"tobacco\"/>      \n      <multiplicity id=\"18\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"8\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"19\">    \n    <end type=\"SOURCE\" refId=\"9\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </generalization>  \n  <realization id=\"20\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <association id=\"21\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"22\" name=\"tobacco\"/>      \n      <multiplicity id=\"23\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"24\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "dependency-injection/etc/dependency-injection.urm.puml",
    "content": "@startuml\npackage com.iluwatar.dependency.injection {\n  class AdvancedSorceress {\n    - tobacco : Tobacco\n    + AdvancedSorceress()\n    + setTobacco(tobacco : Tobacco)\n    + smoke()\n  }\n  class AdvancedWizard {\n    - tobacco : Tobacco\n    + AdvancedWizard(tobacco : Tobacco)\n    + smoke()\n  }\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class GuiceWizard {\n    - tobacco : Tobacco\n    + GuiceWizard(tobacco : Tobacco)\n    + smoke()\n  }\n  class OldTobyTobacco {\n    + OldTobyTobacco()\n  }\n  class RivendellTobacco {\n    + RivendellTobacco()\n  }\n  class SecondBreakfastTobacco {\n    + SecondBreakfastTobacco()\n  }\n  class SimpleWizard {\n    - tobacco : OldTobyTobacco\n    + SimpleWizard()\n    + smoke()\n  }\n  abstract class Tobacco {\n    - LOGGER : Logger {static}\n    + Tobacco()\n    + smoke(wizard : Wizard)\n  }\n  interface Wizard {\n    + smoke() {abstract}\n  }\n}\nAdvancedSorceress -->  \"-tobacco\" Tobacco\nSimpleWizard -->  \"-tobacco\" OldTobyTobacco\nAdvancedWizard -->  \"-tobacco\" Tobacco\nGuiceWizard -->  \"-tobacco\" Tobacco\nAdvancedSorceress ..|> Wizard \nAdvancedWizard ..|> Wizard \nGuiceWizard ..|> Wizard \nOldTobyTobacco --|> Tobacco \nRivendellTobacco --|> Tobacco \nSecondBreakfastTobacco --|> Tobacco \nSimpleWizard ..|> Wizard \n@enduml"
  },
  {
    "path": "dependency-injection/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>dependency-injection</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>com.google.inject</groupId>\n      <artifactId>guice</artifactId>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.dependency.injection.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "dependency-injection/src/main/java/com/iluwatar/dependency/injection/AdvancedSorceress.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\nimport lombok.Setter;\n\n/**\n * AdvancedSorceress implements inversion of control. It depends on abstraction that can be injected\n * through its setter.\n */\n@Setter\npublic class AdvancedSorceress implements Wizard {\n\n  private Tobacco tobacco;\n\n  @Override\n  public void smoke() {\n    tobacco.smoke(this);\n  }\n}\n"
  },
  {
    "path": "dependency-injection/src/main/java/com/iluwatar/dependency/injection/AdvancedWizard.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\nimport lombok.RequiredArgsConstructor;\n\n/**\n * AdvancedWizard implements inversion of control. It depends on abstraction that can be injected\n * through its constructor.\n */\n@RequiredArgsConstructor\npublic class AdvancedWizard implements Wizard {\n\n  private final Tobacco tobacco;\n\n  @Override\n  public void smoke() {\n    tobacco.smoke(this);\n  }\n}\n"
  },
  {
    "path": "dependency-injection/src/main/java/com/iluwatar/dependency/injection/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\nimport com.google.inject.Guice;\n\n/**\n * Dependency Injection pattern deals with how objects handle their dependencies. The pattern\n * implements so-called inversion of control principle. Inversion of control has two specific rules:\n * - High-level modules should not depend on low-level modules. Both should depend on abstractions.\n * - Abstractions should not depend on details. Details should depend on abstractions.\n *\n * <p>In this example we show you three different wizards. The first one ({@link SimpleWizard}) is a\n * naive implementation violating the inversion of control principle. It depends directly on a\n * concrete implementation which cannot be changed.\n *\n * <p>The second and third wizards({@link AdvancedWizard} and {@link AdvancedSorceress}) are more\n * flexible. They do not depend on any concrete implementation but abstraction. They utilize\n * Dependency Injection pattern allowing their {@link Tobacco} dependency to be injected through\n * constructor ({@link AdvancedWizard}) or setter ({@link AdvancedSorceress}). This way, handling\n * the dependency is no longer the wizard's responsibility. It is resolved outside the wizard class.\n *\n * <p>The fourth example takes the pattern a step further. It uses Guice framework for Dependency\n * Injection. {@link TobaccoModule} binds a concrete implementation to abstraction. Injector is then\n * used to create {@link GuiceWizard} object with correct dependencies.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var simpleWizard = new SimpleWizard();\n    simpleWizard.smoke();\n\n    var advancedWizard = new AdvancedWizard(new SecondBreakfastTobacco());\n    advancedWizard.smoke();\n\n    var advancedSorceress = new AdvancedSorceress();\n    advancedSorceress.setTobacco(new SecondBreakfastTobacco());\n    advancedSorceress.smoke();\n\n    var injector = Guice.createInjector(new TobaccoModule());\n    var guiceWizard = injector.getInstance(GuiceWizard.class);\n    guiceWizard.smoke();\n  }\n}\n"
  },
  {
    "path": "dependency-injection/src/main/java/com/iluwatar/dependency/injection/GuiceWizard.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\nimport javax.inject.Inject;\n\n/**\n * GuiceWizard implements inversion of control. Its dependencies are injected through its\n * constructor by Guice framework.\n */\npublic class GuiceWizard implements Wizard {\n\n  private final Tobacco tobacco;\n\n  @Inject\n  public GuiceWizard(Tobacco tobacco) {\n    this.tobacco = tobacco;\n  }\n\n  @Override\n  public void smoke() {\n    tobacco.smoke(this);\n  }\n}\n"
  },
  {
    "path": "dependency-injection/src/main/java/com/iluwatar/dependency/injection/OldTobyTobacco.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\n/** OldTobyTobacco concrete {@link Tobacco} implementation. */\npublic class OldTobyTobacco extends Tobacco {}\n"
  },
  {
    "path": "dependency-injection/src/main/java/com/iluwatar/dependency/injection/RivendellTobacco.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\n/** RivendellTobacco concrete {@link Tobacco} implementation. */\npublic class RivendellTobacco extends Tobacco {}\n"
  },
  {
    "path": "dependency-injection/src/main/java/com/iluwatar/dependency/injection/SecondBreakfastTobacco.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\n/** SecondBreakfastTobacco concrete {@link Tobacco} implementation. */\npublic class SecondBreakfastTobacco extends Tobacco {}\n"
  },
  {
    "path": "dependency-injection/src/main/java/com/iluwatar/dependency/injection/SimpleWizard.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\n/**\n * Naive Wizard implementation violating the inversion of control principle. It should depend on\n * abstraction instead.\n */\npublic class SimpleWizard implements Wizard {\n\n  private final OldTobyTobacco tobacco = new OldTobyTobacco();\n\n  public void smoke() {\n    tobacco.smoke(this);\n  }\n}\n"
  },
  {
    "path": "dependency-injection/src/main/java/com/iluwatar/dependency/injection/Tobacco.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Tobacco abstraction. */\n@Slf4j\npublic abstract class Tobacco {\n\n  public void smoke(Wizard wizard) {\n    LOGGER.info(\n        \"{} smoking {}\", wizard.getClass().getSimpleName(), this.getClass().getSimpleName());\n  }\n}\n"
  },
  {
    "path": "dependency-injection/src/main/java/com/iluwatar/dependency/injection/TobaccoModule.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\nimport com.google.inject.AbstractModule;\n\n/** Guice module for binding certain concrete {@link Tobacco} implementation. */\npublic class TobaccoModule extends AbstractModule {\n\n  @Override\n  protected void configure() {\n    bind(Tobacco.class).to(RivendellTobacco.class);\n  }\n}\n"
  },
  {
    "path": "dependency-injection/src/main/java/com/iluwatar/dependency/injection/Wizard.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\n/** Wizard interface. */\npublic interface Wizard {\n\n  void smoke();\n}\n"
  },
  {
    "path": "dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedSorceressTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.dependency.injection.utils.InMemoryAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** AdvancedSorceressTest */\nclass AdvancedSorceressTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(Tobacco.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /**\n   * Test if the {@link AdvancedSorceress} smokes whatever instance of {@link Tobacco} is passed to\n   * her through the setter's parameter\n   */\n  @Test\n  void testSmokeEveryThing() {\n\n    List<Tobacco> tobaccos =\n        List.of(new OldTobyTobacco(), new RivendellTobacco(), new SecondBreakfastTobacco());\n\n    // Verify if the sorceress is smoking the correct tobacco ...\n    tobaccos.forEach(\n        tobacco -> {\n          final var advancedSorceress = new AdvancedSorceress();\n          advancedSorceress.setTobacco(tobacco);\n          advancedSorceress.smoke();\n          String lastMessage = appender.getLastMessage();\n          assertEquals(\n              \"AdvancedSorceress smoking \" + tobacco.getClass().getSimpleName(), lastMessage);\n        });\n\n    // ... and nothing else is happening.\n    assertEquals(tobaccos.size(), appender.getLogSize());\n  }\n}\n"
  },
  {
    "path": "dependency-injection/src/test/java/com/iluwatar/dependency/injection/AdvancedWizardTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.dependency.injection.utils.InMemoryAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** AdvancedWizardTest */\nclass AdvancedWizardTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(Tobacco.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /**\n   * Test if the {@link AdvancedWizard} smokes whatever instance of {@link Tobacco} is passed to him\n   * through the constructor parameter\n   */\n  @Test\n  void testSmokeEveryThing() {\n\n    List<Tobacco> tobaccos =\n        List.of(new OldTobyTobacco(), new RivendellTobacco(), new SecondBreakfastTobacco());\n\n    // Verify if the wizard is smoking the correct tobacco ...\n    tobaccos.forEach(\n        tobacco -> {\n          final AdvancedWizard advancedWizard = new AdvancedWizard(tobacco);\n          advancedWizard.smoke();\n          String lastMessage = appender.getLastMessage();\n          assertEquals(\"AdvancedWizard smoking \" + tobacco.getClass().getSimpleName(), lastMessage);\n        });\n\n    // ... and nothing else is happening.\n    assertEquals(tobaccos.size(), appender.getLogSize());\n  }\n}\n"
  },
  {
    "path": "dependency-injection/src/test/java/com/iluwatar/dependency/injection/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "dependency-injection/src/test/java/com/iluwatar/dependency/injection/GuiceWizardTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.google.inject.AbstractModule;\nimport com.google.inject.Guice;\nimport com.iluwatar.dependency.injection.utils.InMemoryAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** GuiceWizardTest */\nclass GuiceWizardTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(Tobacco.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /**\n   * Test if the {@link GuiceWizard} smokes whatever instance of {@link Tobacco} is passed to him\n   * through the constructor parameter\n   */\n  @Test\n  void testSmokeEveryThingThroughConstructor() {\n\n    List<Tobacco> tobaccos =\n        List.of(new OldTobyTobacco(), new RivendellTobacco(), new SecondBreakfastTobacco());\n\n    // Verify if the wizard is smoking the correct tobacco ...\n    tobaccos.forEach(\n        tobacco -> {\n          final GuiceWizard guiceWizard = new GuiceWizard(tobacco);\n          guiceWizard.smoke();\n          String lastMessage = appender.getLastMessage();\n          assertEquals(\"GuiceWizard smoking \" + tobacco.getClass().getSimpleName(), lastMessage);\n        });\n\n    // ... and nothing else is happening.\n    assertEquals(tobaccos.size(), appender.getLogSize());\n  }\n\n  /**\n   * Test if the {@link GuiceWizard} smokes whatever instance of {@link Tobacco} is passed to him\n   * through the Guice google inject framework\n   */\n  @Test\n  void testSmokeEveryThingThroughInjectionFramework() {\n\n    List<Class<? extends Tobacco>> tobaccos =\n        List.of(OldTobyTobacco.class, RivendellTobacco.class, SecondBreakfastTobacco.class);\n\n    // Configure the tobacco in the injection framework ...\n    // ... and create a new wizard with it\n    // Verify if the wizard is smoking the correct tobacco ...\n    tobaccos.forEach(\n        tobaccoClass -> {\n          final var injector =\n              Guice.createInjector(\n                  new AbstractModule() {\n                    @Override\n                    protected void configure() {\n                      bind(Tobacco.class).to(tobaccoClass);\n                    }\n                  });\n          final var guiceWizard = injector.getInstance(GuiceWizard.class);\n          guiceWizard.smoke();\n          String lastMessage = appender.getLastMessage();\n          assertEquals(\"GuiceWizard smoking \" + tobaccoClass.getSimpleName(), lastMessage);\n        });\n\n    // ... and nothing else is happening.\n    assertEquals(tobaccos.size(), appender.getLogSize());\n  }\n}\n"
  },
  {
    "path": "dependency-injection/src/test/java/com/iluwatar/dependency/injection/SimpleWizardTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.dependency.injection.utils.InMemoryAppender;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** SimpleWizardTest */\nclass SimpleWizardTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(Tobacco.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /**\n   * Test if the {@link SimpleWizard} does the only thing it can do: Smoke it's {@link\n   * OldTobyTobacco}\n   */\n  @Test\n  void testSmoke() {\n    final var simpleWizard = new SimpleWizard();\n    simpleWizard.smoke();\n    assertEquals(\"SimpleWizard smoking OldTobyTobacco\", appender.getLastMessage());\n    assertEquals(1, appender.getLogSize());\n  }\n}\n"
  },
  {
    "path": "dependency-injection/src/test/java/com/iluwatar/dependency/injection/utils/InMemoryAppender.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dependency.injection.utils;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.slf4j.LoggerFactory;\n\n/** InMemory Log Appender Util. */\npublic class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n\n  private final List<ILoggingEvent> log = new LinkedList<>();\n\n  public InMemoryAppender(Class clazz) {\n    ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this);\n    start();\n  }\n\n  @Override\n  protected void append(ILoggingEvent eventObject) {\n    log.add(eventObject);\n  }\n\n  public String getLastMessage() {\n    return log.get(log.size() - 1).getFormattedMessage();\n  }\n\n  public int getLogSize() {\n    return log.size();\n  }\n}\n"
  },
  {
    "path": "dirty-flag/README.md",
    "content": "---\ntitle: \"Dirty Flag Pattern in Java: Optimizing Performance with Change Tracking\"\nshortTitle: Dirty Flag\ndescription: \"Learn about the Dirty Flag design pattern in Java for efficient state tracking and resource management. Avoid unnecessary computations with practical examples and use cases.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Game programming\n  - Performance\n  - Resource management\n  - State tracking\n---\n\n## Also known as\n\n* Change Tracking\n* Is-Modified Flag\n\n## Intent of Dirty Flag Design Pattern\n\nThe Dirty Flag design pattern is employed to avoid unnecessary computations or resource-heavy operations by maintaining a boolean flag that tracks whether the state of an object has changed ('dirty') or remains unchanged ('clean'). This flag, when set, indicates that a particular operation, such as recalculating or refreshing data, needs to be performed again to reflect the updated state.\n\n## Detailed Explanation of Dirty Flag Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a library with an electronic catalog system that tracks which books are checked out and returned. Each book record has a \"dirty flag\" that gets marked whenever a book is checked out or returned. At the end of each day, the library staff reviews only those records marked as \"dirty\" to update the physical inventory, instead of checking every single book in the library. This system significantly reduces the effort and time required for daily inventory checks by focusing only on the items that have changed status, analogous to how the Dirty Flag design pattern minimizes resource-intensive operations by performing them only when necessary.\n\nIn plain words\n\n> The Dirty Flag design pattern minimizes unnecessary operations by using a flag to track when an object's state has changed and an update is needed.\n\nWikipedia says\n\n> A dirty bit or modified bit is a bit that is associated with a block of computer memory and indicates whether the corresponding block of memory has been modified. The dirty bit is set when the processor writes to (modifies) this memory. The bit indicates that its associated block of memory has been modified and has not been saved to storage yet. When a block of memory is to be replaced, its corresponding dirty bit is checked to see if the block needs to be written back to secondary memory before being replaced or if it can simply be removed. Dirty bits are used by the CPU cache and in the page replacement algorithms of an operating system.\n\nFlowchart\n\n![Dirty Flag flowchart](./etc/dirty-flag-flowchart.png)\n\n## Programmatic Example of Dirty Flag Pattern in Java\n\nThe `DataFetcher` class is responsible for fetching data from a file. It has a dirty flag that indicates whether the data in the file has changed since the last fetch.\n\n```java\npublic class DataFetcher {\n    private long lastFetched;\n    private boolean isDirty = true;\n    // Other properties and methods...\n}\n```\n\nThe `DataFetcher` class has a fetch method that checks the dirty flag before fetching data. If the flag is true, it fetches the data from the file and sets the flag to false. If the flag is false, it returns the previously fetched data.\n\n```java\npublic List<String> fetch() {\n    if (!isDirty) {\n        return data;\n    }\n    data = fetchFromDatabase();\n    isDirty = false;\n    return data;\n}\n```\n\nThe `World` class uses the `DataFetcher` to fetch data. It has a `fetch` method that calls the `fetch` method of the `DataFetcher`.\n\n```java\npublic class World {\n    private final DataFetcher fetcher = new DataFetcher();\n  \n    public List<String> fetch() {\n        return fetcher.fetch();\n    }\n}\n```\n\nThe `App` class contains the `main` method that demonstrates the use of the Dirty Flag pattern. It creates a `World` object and fetches data from it in a loop. The `World` object uses the `DataFetcher` to fetch data, and the `DataFetcher` only fetches data from the file if the dirty flag is true.\n\n```java\n@Slf4j\npublic class App {\n\n  public void run() {\n    final var executorService = Executors.newSingleThreadScheduledExecutor();\n    executorService.scheduleAtFixedRate(new Runnable() {\n      final World world = new World();\n\n      @Override\n      public void run() {\n        var countries = world.fetch();\n        LOGGER.info(\"Our world currently has the following countries:-\");\n        countries.stream().map(country -> \"\\t\" + country).forEach(LOGGER::info);\n      }\n    }, 0, 15, TimeUnit.SECONDS); // Run at every 15 seconds.\n  }\n\n  public static void main(String[] args) {\n    var app = new App();\n    app.run();\n  }\n}\n```\n\nThe program output is as follows:\n\n```\n12:06:02.612 [pool-1-thread-1] INFO com.iluwatar.dirtyflag.DataFetcher -- world.txt is dirty! Re-fetching file content...\n12:06:02.615 [pool-1-thread-1] INFO com.iluwatar.dirtyflag.App -- Our world currently has the following countries:-\n12:06:02.616 [pool-1-thread-1] INFO com.iluwatar.dirtyflag.App -- \tUNITED_KINGDOM\n12:06:02.616 [pool-1-thread-1] INFO com.iluwatar.dirtyflag.App -- \tMALAYSIA\n12:06:02.616 [pool-1-thread-1] INFO com.iluwatar.dirtyflag.App -- \tUNITED_STATES\n```\n\n## When to Use the Dirty Flag Pattern in Java\n\n* When an operation is resource-intensive and only necessary after certain changes have occurred.\n* In scenarios where checking for changes is significantly cheaper than performing the operation itself, enhancing cost-effectiveness.\n* Within systems where objects maintain state that is expensive to update and the updates are infrequent, promoting performance efficiency.\n\n## Dirty Flag Pattern Java Tutorials\n\n* [89: Design Patterns: Dirty Flag (TakeUpCode)](https://www.takeupcode.com/podcast/89-design-patterns-dirty-flag/)\n\n## Real-World Applications of Dirty Flag Pattern in Java\n\n* Graphic rendering engines to update only parts of the scene that have changed, utilizing the Dirty Flag pattern for efficient rendering.\n* Web applications for partial page rendering or caching strategies.\n* Database applications for tracking changes in datasets to minimize write operations, ensuring efficient database management.\n\n## Benefits and Trade-offs of Dirty Flag Pattern\n\nBenefits:\n\n* Reduces computational and resource overhead by avoiding unnecessary operations, leading to performance gains.\n* Can significantly improve performance in systems where operations are costly and changes are infrequent, fostering system optimization.\n* Simplifies the decision-making process about when to perform certain operations, aiding in effective resource allocation.\n\nTrade-offs:\n\n* Introduces complexity by adding state management responsibility to the system.\n* Requires diligent management of the flag to ensure it accurately reflects the state changes, avoiding stale or incorrect data.\n* Potentially increases the risk of bugs related to improper flag resetting, impacting system reliability.\n\n## Related Java Design Patterns\n\n* [Observer](https://java-design-patterns.com/patterns/observer/): Can be used in conjunction to notify interested parties when the dirty flag is set or cleared.\n* [Memento](https://java-design-patterns.com/patterns/memento/): Useful for storing the previous state of an object, which can work hand in hand with dirty flag logic to revert to clean states.\n* [Command](https://java-design-patterns.com/patterns/command/): Commands can set the dirty flag when executed, indicating a change in state that requires attention.\n\n## References and Credits\n\n* [Game Programming Patterns](https://amzn.to/3PUzbgu)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n"
  },
  {
    "path": "dirty-flag/etc/dirty-flag.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.2.2\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.dirtyflag.App\" project=\"dirty-flag\" \n    file=\"/dirty-flag/src/main/java/com/iluwatar/dirtyflag/App.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"266\" y=\"188\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.dirtyflag.DataFetcher\" project=\"dirty-flag\" \n    file=\"/dirty-flag/src/main/java/com/iluwatar/dirtyflag/DataFetcher.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"153\" width=\"125\" x=\"66\" y=\"291\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.dirtyflag.World\" project=\"dirty-flag\" \n    file=\"/dirty-flag/src/main/java/com/iluwatar/dirtyflag/World.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"379\" y=\"366\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"4\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"5\" name=\"df\"/>      \n      <multiplicity id=\"6\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "dirty-flag/etc/dirty-flag.urm.puml",
    "content": "@startuml\npackage com.iluwatar.dirtyflag {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n    + run()\n  }\n  class DataFetcher {\n    - LOGGER : Logger {static}\n    - filename : String\n    - lastFetched : long\n    + DataFetcher()\n    + fetch() : List<String>\n    - isDirty(fileLastModified : long) : boolean\n  }\n  class World {\n    - countries : List<String>\n    - df : DataFetcher\n    + World()\n    + fetch() : List<String>\n  }\n}\nWorld -->  \"-df\" DataFetcher\n@enduml"
  },
  {
    "path": "dirty-flag/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>dirty-flag</artifactId>\n  <version>1.26.0-SNAPSHOT</version>\n  <name>dirty-flag</name>\n  <url>http://maven.apache.org</url>\n  <properties>\n    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n  </properties>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.dirtyflag.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "dirty-flag/src/main/java/com/iluwatar/dirtyflag/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dirtyflag;\n\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This application demonstrates the <b>Dirty Flag</b> pattern. The dirty flag behavioral pattern\n * allows you to avoid expensive operations that would just need to be done again anyway. This is a\n * simple pattern that really just explains how to add a bool value to your class that you can set\n * anytime a property changes. This will let your class know that any results it may have previously\n * calculated will need to be calculated again when they’re requested. Once the results are\n * re-calculated, then the bool value can be cleared.\n *\n * <p>There are some points that need to be considered before diving into using this pattern:- there\n * are some things you’ll need to consider:- (1) Do you need it? This design pattern works well when\n * the results to be calculated are difficult or resource intensive to compute. You want to save\n * them. You also don’t want to be calculating them several times in a row when only the last one\n * counts. (2) When do you set the dirty flag? Make sure that you set the dirty flag within the\n * class itself whenever an important property changes. This property should affect the result of\n * the calculated result and by changing the property, that makes the last result invalid. (3) When\n * do you clear the dirty flag? It might seem obvious that the dirty flag should be cleared whenever\n * the result is calculated with up-to-date information but there are other times when you might\n * want to clear the flag.\n *\n * <p>In this example, the {@link DataFetcher} holds the <i>dirty flag</i>. It fetches and\n * re-fetches from <i>world.txt</i> when needed. {@link World} mainly serves the data to the\n * front-end.\n */\n@Slf4j\npublic class App {\n\n  /** Program execution point. */\n  public void run() {\n    final var executorService = Executors.newSingleThreadScheduledExecutor();\n    try {\n      executorService.scheduleAtFixedRate(\n          new Runnable() {\n            final World world = new World();\n\n            @Override\n            public void run() {\n              var countries = world.fetch();\n              LOGGER.info(\"Our world currently has the following countries:-\");\n              countries.stream().map(country -> \"\\t\" + country).forEach(LOGGER::info);\n            }\n          },\n          0,\n          15,\n          TimeUnit.SECONDS);\n\n      // Keep running for 45 seconds before shutdown (for demo purpose)\n      TimeUnit.SECONDS.sleep(45);\n    } catch (InterruptedException e) {\n      Thread.currentThread().interrupt();\n      LOGGER.error(\"Thread was interrupted\", e);\n    } finally {\n      executorService.shutdown();\n    }\n  }\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var app = new App();\n    app.run();\n  }\n}\n"
  },
  {
    "path": "dirty-flag/src/main/java/com/iluwatar/dirtyflag/DataFetcher.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dirtyflag;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileReader;\nimport java.io.IOException;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport lombok.extern.slf4j.Slf4j;\n\n/** A mock database manager -- Fetches data from a raw file. */\n@Slf4j\npublic class DataFetcher {\n\n  private static final String FILENAME = \"world.txt\";\n  private long lastFetched;\n\n  public DataFetcher() {\n    this.lastFetched = -1;\n  }\n\n  private boolean isDirty(long fileLastModified) {\n    if (lastFetched != fileLastModified) {\n      lastFetched = fileLastModified;\n      return true;\n    }\n    return false;\n  }\n\n  /**\n   * Fetches data/content from raw file.\n   *\n   * @return List of strings\n   */\n  public List<String> fetch() {\n    var classLoader = getClass().getClassLoader();\n    var file = new File(classLoader.getResource(FILENAME).getFile());\n\n    if (isDirty(file.lastModified())) {\n      LOGGER.info(FILENAME + \" is dirty! Re-fetching file content...\");\n      try (var br = new BufferedReader(new FileReader(file))) {\n        return br.lines().collect(Collectors.collectingAndThen(Collectors.toList(), List::copyOf));\n      } catch (IOException e) {\n        LOGGER.error(\"An error occurred: \", e);\n      }\n    }\n\n    return List.of();\n  }\n}\n"
  },
  {
    "path": "dirty-flag/src/main/java/com/iluwatar/dirtyflag/World.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dirtyflag;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** A middle-layer app that calls/passes along data from the back-end. */\npublic class World {\n\n  private List<String> countries;\n  private final DataFetcher df;\n\n  public World() {\n    this.countries = new ArrayList<>();\n    this.df = new DataFetcher();\n  }\n\n  /**\n   * Calls {@link DataFetcher} to fetch data from back-end.\n   *\n   * @return List of strings\n   */\n  public List<String> fetch() {\n    var data = df.fetch();\n    countries = data.isEmpty() ? countries : data;\n    return countries;\n  }\n}\n"
  },
  {
    "path": "dirty-flag/src/main/resources/world.txt",
    "content": "UNITED_KINGDOM\nMALAYSIA\nUNITED_STATES"
  },
  {
    "path": "dirty-flag/src/test/java/org/dirty/flag/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage org.dirty.flag;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport com.iluwatar.dirtyflag.App;\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Dirty-Flag example runs without errors. */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "dirty-flag/src/test/java/org/dirty/flag/DirtyFlagTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage org.dirty.flag;\n\nimport com.iluwatar.dirtyflag.DataFetcher;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass DirtyFlagTest {\n\n  @Test\n  void testIsDirty() {\n    var df = new DataFetcher();\n    var countries = df.fetch();\n    Assertions.assertFalse(countries.isEmpty());\n  }\n\n  @Test\n  void testIsNotDirty() {\n    var df = new DataFetcher();\n    df.fetch();\n    var countries = df.fetch();\n    Assertions.assertTrue(countries.isEmpty());\n  }\n}\n"
  },
  {
    "path": "domain-model/README.md",
    "content": "---\ntitle: \"Domain Model Pattern in Java: Building Robust Business Logic\"\nshortTitle: Domain Model\ndescription: \"Learn about the Domain Model pattern in Java design with detailed explanations, examples, and applications. Improve your software's modularity, maintainability, and scalability.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Abstraction\n  - Business\n  - Data processing\n  - Domain\n  - Encapsulation\n  - Layered architecture\n  - Persistence\n  - Polymorphism\n---\n\n## Also known as\n\n* Conceptual Model\n* Domain Object Model\n\n## Intent of Domain Model Design Pattern\n\nThe Domain Model pattern aims to create a conceptual model in your software that matches the real-world system it's designed to represent. It involves using rich domain objects that encapsulate both data and behavior relevant to the application domain, ensuring business logic is centralized.\n\n## Detailed Explanation of Domain Model Pattern with Real-World Examples\n\nReal-world example\n\n> Consider an online bookstore system that uses the Domain Model design pattern. In this system, various domain objects such as `Book`, `Author`, `Customer`, and `Order` encapsulate the core business logic and rules. For instance, the `Book` object contains attributes like title, author, price, and stock quantity, along with methods to manage these attributes. The `Order` object manages order details, calculates the total price, and verifies stock availability. This approach ensures that the business logic is centralized within the domain objects, making the system more modular, easier to maintain, and scalable as new features are added.\n\nIn plain words\n\n> The Domain Model is an object model of the domain that incorporates both behavior and data.\n\nMind map\n\n![Domain Model mind map](./etc/domain-model-mind-map.png)\n\n## Programmatic Example of Domain Model Pattern in Java\n\nLet's assume that we need to build an e-commerce web application. While analyzing requirements you will notice that there are few nouns you talk about repeatedly. It’s your Customer, and a Product the customer looks for. These two are your domain-specific classes and each of that classes will include some business logic specific to its domain.\n\nIn the example of the e-commerce app, we need to deal with the domain logic of customers who want to buy products and return them if they want. We can use the domain model pattern and create classes `Customer` and `Product` where every single instance of that class incorporates both behavior and data and represents only one record in the underlying table.\n\n```java\npublic class Customer {\n    // Customer properties and methods\n}\n\npublic class Product {\n    // Product properties and methods\n}\n```\n\nData Access Objects (DAOs): These objects provide an abstract interface to the database. They are used to retrieve domain entities and save changes back to the database. In the provided code, `CustomerDaoImpl` and `ProductDaoImpl` are the DAOs.\n\n```java\npublic class CustomerDaoImpl implements CustomerDao {\n    // Implementation of the methods defined in the CustomerDao interface\n}\n\npublic class ProductDaoImpl implements ProductDao {\n    // Implementation of the methods defined in the ProductDao interface\n}\n```\n\nDomain Logic: This is encapsulated within the domain entities. For example, the `Customer` class has methods like `buyProduct` and `returnProduct` which represent the actions a customer can perform.\n\n```java\npublic class Customer {\n    \n    // Other properties and methods...\n\n    public void buyProduct(Product product) {\n        // Implementation of buying a product\n    }\n\n    public void returnProduct(Product product) {\n        // Implementation of returning a product\n    }\n}\n```\n\nApplication: The `App` class uses the domain entities and their methods to implement the business logic of the application.\n\n```java\npublic class App {\n\n    public static final String H2_DB_URL = \"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1\";\n\n    public static final String CREATE_SCHEMA_SQL =\n            \"CREATE TABLE CUSTOMERS (name varchar primary key, money decimal);\"\n                    + \"CREATE TABLE PRODUCTS (name varchar primary key, price decimal, expiration_date date);\"\n                    + \"CREATE TABLE PURCHASES (\"\n                    + \"product_name varchar references PRODUCTS(name),\"\n                    + \"customer_name varchar references CUSTOMERS(name));\";\n\n    public static final String DELETE_SCHEMA_SQL =\n            \"DROP TABLE PURCHASES IF EXISTS;\"\n                    + \"DROP TABLE CUSTOMERS IF EXISTS;\"\n                    + \"DROP TABLE PRODUCTS IF EXISTS;\";\n\n    public static void main(String[] args) throws Exception {\n\n        // Create data source and create the customers, products and purchases tables\n        final var dataSource = createDataSource();\n        deleteSchema(dataSource);\n        createSchema(dataSource);\n\n        // create customer\n        var customerDao = new CustomerDaoImpl(dataSource);\n\n        var tom =\n                Customer.builder()\n                        .name(\"Tom\")\n                        .money(Money.of(USD, 30))\n                        .customerDao(customerDao)\n                        .build();\n\n        tom.save();\n\n        // create products\n        var productDao = new ProductDaoImpl(dataSource);\n\n        var eggs =\n                Product.builder()\n                        .name(\"Eggs\")\n                        .price(Money.of(USD, 10.0))\n                        .expirationDate(LocalDate.now().plusDays(7))\n                        .productDao(productDao)\n                        .build();\n\n        var butter =\n                Product.builder()\n                        .name(\"Butter\")\n                        .price(Money.of(USD, 20.00))\n                        .expirationDate(LocalDate.now().plusDays(9))\n                        .productDao(productDao)\n                        .build();\n\n        var cheese =\n                Product.builder()\n                        .name(\"Cheese\")\n                        .price(Money.of(USD, 25.0))\n                        .expirationDate(LocalDate.now().plusDays(2))\n                        .productDao(productDao)\n                        .build();\n\n        eggs.save();\n        butter.save();\n        cheese.save();\n\n        // show money balance of customer after each purchase\n        tom.showBalance();\n        tom.showPurchases();\n\n        // buy eggs\n        tom.buyProduct(eggs);\n        tom.showBalance();\n\n        // buy butter\n        tom.buyProduct(butter);\n        tom.showBalance();\n\n        // trying to buy cheese, but receive a refusal\n        // because he didn't have enough money\n        tom.buyProduct(cheese);\n        tom.showBalance();\n\n        // return butter and get money back\n        tom.returnProduct(butter);\n        tom.showBalance();\n\n        // Tom can buy cheese now because he has enough money\n        // and there is a discount on cheese because it expires in 2 days\n        tom.buyProduct(cheese);\n\n        tom.save();\n\n        // show money balance and purchases after shopping\n        tom.showBalance();\n        tom.showPurchases();\n    }\n\n    private static DataSource createDataSource() {\n        var dataSource = new JdbcDataSource();\n        dataSource.setUrl(H2_DB_URL);\n        return dataSource;\n    }\n\n    private static void deleteSchema(DataSource dataSource) throws SQLException {\n        try (var connection = dataSource.getConnection();\n             var statement = connection.createStatement()) {\n            statement.execute(DELETE_SCHEMA_SQL);\n        }\n    }\n\n    private static void createSchema(DataSource dataSource) throws SQLException {\n        try (var connection = dataSource.getConnection();\n             var statement = connection.createStatement()) {\n            statement.execute(CREATE_SCHEMA_SQL);\n        }\n    }\n}\n```\n\nThe program output:\n\n```java\n12:17:23.834 [main] INFO com.iluwatar.domainmodel.Customer -- Tom balance: USD 30.00\n12:17:23.836 [main] INFO com.iluwatar.domainmodel.Customer -- Tom didn't bought anything\n12:17:23.841 [main] INFO com.iluwatar.domainmodel.Customer -- Tom want to buy Eggs($10,00)...\n12:17:23.842 [main] INFO com.iluwatar.domainmodel.Customer -- Tom bought Eggs!\n12:17:23.842 [main] INFO com.iluwatar.domainmodel.Customer -- Tom balance: USD 20.00\n12:17:23.842 [main] INFO com.iluwatar.domainmodel.Customer -- Tom want to buy Butter($20,00)...\n12:17:23.843 [main] INFO com.iluwatar.domainmodel.Customer -- Tom bought Butter!\n12:17:23.843 [main] INFO com.iluwatar.domainmodel.Customer -- Tom balance: USD 0.00\n12:17:23.843 [main] INFO com.iluwatar.domainmodel.Customer -- Tom want to buy Cheese($20,00)...\n12:17:23.843 [main] ERROR com.iluwatar.domainmodel.Customer -- Not enough money!\n12:17:23.843 [main] INFO com.iluwatar.domainmodel.Customer -- Tom balance: USD 0.00\n12:17:23.843 [main] INFO com.iluwatar.domainmodel.Customer -- Tom want to return Butter($20,00)...\n12:17:23.844 [main] INFO com.iluwatar.domainmodel.Customer -- Tom returned Butter!\n12:17:23.844 [main] INFO com.iluwatar.domainmodel.Customer -- Tom balance: USD 20.00\n12:17:23.844 [main] INFO com.iluwatar.domainmodel.Customer -- Tom want to buy Cheese($20,00)...\n12:17:23.844 [main] INFO com.iluwatar.domainmodel.Customer -- Tom bought Cheese!\n12:17:23.846 [main] INFO com.iluwatar.domainmodel.Customer -- Tom balance: USD 0.00\n12:17:23.846 [main] INFO com.iluwatar.domainmodel.Customer -- Tom bought: Eggs - $10.00, Cheese - $20.00\n```\n\n## When to Use the Domain Model Pattern in Java\n\n* Appropriate in complex applications with rich business logic.\n* When the business logic or domain complexity is high and requires a model that closely represents real-world entities and their relationships.\n* Suitable for applications where domain experts are involved in the development process to ensure the model accurately reflects domain concepts.\n\n## Domain Model Pattern Java Tutorials\n\n* [Architecture patterns: domain model and friends (Inviqa)](https://inviqa.com/blog/architecture-patterns-domain-model-and-friends)\n\n## Real-World Applications of Domain Model Pattern in Java\n\n* Enterprise applications (ERP, CRM systems)\n* Financial systems (banking, trading platforms)\n* Healthcare applications (patient records management)\n* E-commerce platforms (product catalogs, shopping carts)\n\n## Benefits and Trade-offs of Domain Model Pattern\n\nBenefits:\n\n* Improved Communication: Provides a common language for developers and domain experts, enhancing understanding and collaboration.\n* Flexibility: Encapsulates business logic within domain entities, making it easier to modify and extend without affecting other system parts.\n* Maintainability: A well-structured domain model can simplify maintenance and evolution of the application over time.\n* Reusability: Domain classes can often be reused across different projects within the same domain.\n\nTrade-offs:\n\n* Complexity: Can introduce complexity, especially in simple applications where a domain model might be overkill.\n* Performance Concerns: Rich domain objects with complex behaviors might lead to performance bottlenecks, requiring careful optimization.\n* Learning Curve: Requires a good understanding of the domain and may involve a steep learning curve for developers unfamiliar with the domain concepts.\n\n## Related Java Design Patterns\n\n* [Data Access Object (DAO)](https://java-design-patterns.com/patterns/dao/): For abstracting and encapsulating all access to the data source.\n* [Repository](https://java-design-patterns.com/patterns/repository/): Mediates between the domain and data mapping layers, acting like an in-memory domain object collection.\n* [Service Layer](https://java-design-patterns.com/patterns/service-layer/): Defines an application's boundary with a layer of services that establishes a set of available operations and coordinates the application's response in each operation.\n* [Unit of Work](https://java-design-patterns.com/patterns/unit-of-work/): Maintains a list of objects affected by a business transaction and coordinates the writing out of changes.\n\n## References and Credits\n\n* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3vMCjnP)\n* [Implementing Domain-Driven Design](https://amzn.to/4cUX4OL)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Domain Model (Martin Fowler)](https://martinfowler.com/eaaCatalog/domainModel.html)\n"
  },
  {
    "path": "domain-model/etc/domain-model.urm.puml",
    "content": "@startuml\npackage com.iluwatar.domainmodel {\n  class App {\n    + CREATE_SCHEMA_SQL : String {static}\n    + DELETE_SCHEMA_SQL : String {static}\n    + H2_DB_URL : String {static}\n    + App()\n    - createDataSource() : DataSource {static}\n    - createSchema(dataSource : DataSource) {static}\n    - deleteSchema(dataSource : DataSource) {static}\n    + main(args : String[]) {static}\n  }\n  class Customer {\n    - customerDao : CustomerDao\n    - money : Money\n    - name : String\n    - purchases : List<Product>\n    ~ Customer(customerDao : CustomerDao, purchases : List<Product>, name : String, money : Money)\n    + builder() : CustomerBuilder {static}\n    + buyProduct(product : Product)\n    + getCustomerDao() : CustomerDao\n    + getMoney() : Money\n    + getName() : String\n    + getPurchases() : List<Product>\n    - receiveMoney(amount : Money)\n    + returnProduct(product : Product)\n    + save()\n    + setMoney(money : Money)\n    + setName(name : String)\n    + setPurchases(purchases : List<Product>)\n    + showBalance()\n    + showPurchases()\n    - withdraw(amount : Money)\n  }\n  interface CustomerDao {\n    + addProduct(Product, Customer) {abstract}\n    + deleteProduct(Product, Customer) {abstract}\n    + findByName(String) : Optional<Customer> {abstract}\n    + save(Customer) {abstract}\n    + update(Customer) {abstract}\n  }\n  class CustomerDaoImpl {\n    - dataSource : DataSource\n    + CustomerDaoImpl(userDataSource : DataSource)\n    + addProduct(product : Product, customer : Customer)\n    + deleteProduct(product : Product, customer : Customer)\n    + findByName(name : String) : Optional<Customer>\n    + save(customer : Customer)\n    + update(customer : Customer)\n  }\n  class Product {\n    - expirationDate : LocalDate\n    - name : String\n    - price : Money\n    - productDao : ProductDao\n    + Product(productDao : ProductDao, name : String, price : Money, expirationDate : LocalDate)\n    + builder() : ProductBuilder {static}\n    - calculateDiscount() : Money\n    + getExpirationDate() : LocalDate\n    + getName() : String\n    + getPrice() : Money\n    + getProductDao() : ProductDao\n    + getSalePrice() : Money\n    + save()\n    + setExpirationDate(expirationDate : LocalDate)\n    + setName(name : String)\n    + setPrice(price : Money)\n  }\n  interface ProductDao {\n    + findByName(String) : Optional<Product> {abstract}\n    + save(Product) {abstract}\n    + update(Product) {abstract}\n  }\n  class ProductDaoImpl {\n    - dataSource : DataSource\n    + ProductDaoImpl(userDataSource : DataSource)\n    + findByName(name : String) : Optional<Product>\n    + save(product : Product)\n    + update(product : Product)\n  }\n}\nProduct -->  ProductDao\nCustomer -->  CustomerDao\nCustomer -->  Product\nCustomerDaoImpl ..|> CustomerDao \nProductDaoImpl ..|> ProductDao \n@enduml"
  },
  {
    "path": "domain-model/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>domain-model</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>com.h2database</groupId>\n      <artifactId>h2</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.joda</groupId>\n      <artifactId>joda-money</artifactId>\n      <version>1.0.4</version>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.domainmodel.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "domain-model/src/main/java/com/iluwatar/domainmodel/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport static org.joda.money.CurrencyUnit.USD;\n\nimport java.sql.SQLException;\nimport java.time.LocalDate;\nimport javax.sql.DataSource;\nimport org.h2.jdbcx.JdbcDataSource;\nimport org.joda.money.Money;\n\n/**\n * Domain Model pattern is a more complex solution for organizing domain logic than Transaction\n * Script and Table Module. It provides an object-oriented way of dealing with complicated logic.\n * Instead of having one procedure that handles all business logic for a user action like\n * Transaction Script there are multiple objects and each of them handles a slice of domain logic\n * that is relevant to it. The significant difference between Domain Model and Table Module pattern\n * is that in Table Module a single class encapsulates all the domain logic for all records stored\n * in table when in Domain Model every single class represents only one record in underlying table.\n *\n * <p>In this example, we will use the Domain Model pattern to implement buying of products by\n * customers in a Shop. The main method will create a customer and a few products. Customer will do\n * a few purchases, try to buy product which are too expensive for him, return product which he\n * bought to return money.\n */\npublic class App {\n\n  public static final String H2_DB_URL = \"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1\";\n\n  public static final String CREATE_SCHEMA_SQL =\n      \"CREATE TABLE CUSTOMERS (name varchar primary key, money decimal);\"\n          + \"CREATE TABLE PRODUCTS (name varchar primary key, price decimal, expiration_date date);\"\n          + \"CREATE TABLE PURCHASES (\"\n          + \"product_name varchar references PRODUCTS(name),\"\n          + \"customer_name varchar references CUSTOMERS(name));\";\n\n  public static final String DELETE_SCHEMA_SQL =\n      \"DROP TABLE PURCHASES IF EXISTS;\"\n          + \"DROP TABLE CUSTOMERS IF EXISTS;\"\n          + \"DROP TABLE PRODUCTS IF EXISTS;\";\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line arguments\n   * @throws Exception if any error occurs\n   */\n  public static void main(String[] args) throws Exception {\n\n    // Create data source and create the customers, products and purchases tables\n    final var dataSource = createDataSource();\n    deleteSchema(dataSource);\n    createSchema(dataSource);\n\n    // create customer\n    var customerDao = new CustomerDaoImpl(dataSource);\n\n    var tom =\n        Customer.builder().name(\"Tom\").money(Money.of(USD, 30)).customerDao(customerDao).build();\n\n    tom.save();\n\n    // create products\n    var productDao = new ProductDaoImpl(dataSource);\n\n    var eggs =\n        Product.builder()\n            .name(\"Eggs\")\n            .price(Money.of(USD, 10.0))\n            .expirationDate(LocalDate.now().plusDays(7))\n            .productDao(productDao)\n            .build();\n\n    var butter =\n        Product.builder()\n            .name(\"Butter\")\n            .price(Money.of(USD, 20.00))\n            .expirationDate(LocalDate.now().plusDays(9))\n            .productDao(productDao)\n            .build();\n\n    var cheese =\n        Product.builder()\n            .name(\"Cheese\")\n            .price(Money.of(USD, 25.0))\n            .expirationDate(LocalDate.now().plusDays(2))\n            .productDao(productDao)\n            .build();\n\n    eggs.save();\n    butter.save();\n    cheese.save();\n\n    // show money balance of customer after each purchase\n    tom.showBalance();\n    tom.showPurchases();\n\n    // buy eggs\n    tom.buyProduct(eggs);\n    tom.showBalance();\n\n    // buy butter\n    tom.buyProduct(butter);\n    tom.showBalance();\n\n    // trying to buy cheese, but receive a refusal\n    // because he didn't have enough money\n    tom.buyProduct(cheese);\n    tom.showBalance();\n\n    // return butter and get money back\n    tom.returnProduct(butter);\n    tom.showBalance();\n\n    // Tom can buy cheese now because he has enough money\n    // and there is a discount on cheese because it expires in 2 days\n    tom.buyProduct(cheese);\n\n    tom.save();\n\n    // show money balance and purchases after shopping\n    tom.showBalance();\n    tom.showPurchases();\n  }\n\n  private static DataSource createDataSource() {\n    var dataSource = new JdbcDataSource();\n    dataSource.setUrl(H2_DB_URL);\n    return dataSource;\n  }\n\n  private static void deleteSchema(DataSource dataSource) throws SQLException {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(DELETE_SCHEMA_SQL);\n    }\n  }\n\n  private static void createSchema(DataSource dataSource) throws SQLException {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(CREATE_SCHEMA_SQL);\n    }\n  }\n}\n"
  },
  {
    "path": "domain-model/src/main/java/com/iluwatar/domainmodel/Customer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport java.sql.SQLException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Optional;\nimport lombok.Builder;\nimport lombok.Getter;\nimport lombok.NonNull;\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\nimport org.joda.money.Money;\n\n/**\n * This class organizes domain logic of customer. A single instance of this class contains both the\n * data and behavior of a single customer.\n */\n@Slf4j\n@Getter\n@Setter\n@Builder\npublic class Customer {\n\n  @NonNull private final CustomerDao customerDao;\n  @Builder.Default private List<Product> purchases = new ArrayList<>();\n  @NonNull private String name;\n  @NonNull private Money money;\n\n  /** Save customer or update if customer already exist. */\n  public void save() {\n    try {\n      Optional<Customer> customer = customerDao.findByName(name);\n      if (customer.isPresent()) {\n        customerDao.update(this);\n      } else {\n        customerDao.save(this);\n      }\n    } catch (SQLException ex) {\n      LOGGER.error(ex.getMessage());\n    }\n  }\n\n  /**\n   * Add product to purchases, save to db and withdraw money.\n   *\n   * @param product to buy.\n   */\n  public void buyProduct(Product product) {\n    LOGGER.info(\n        String.format(\n            \"%s want to buy %s($%.2f)...\",\n            name, product.getName(), product.getSalePrice().getAmount()));\n    try {\n      withdraw(product.getSalePrice());\n    } catch (IllegalArgumentException ex) {\n      LOGGER.error(ex.getMessage());\n      return;\n    }\n    try {\n      customerDao.addProduct(product, this);\n      purchases.add(product);\n      LOGGER.info(String.format(\"%s bought %s!\", name, product.getName()));\n    } catch (SQLException exception) {\n      receiveMoney(product.getSalePrice());\n      LOGGER.error(exception.getMessage());\n    }\n  }\n\n  /**\n   * Remove product from purchases, delete from db and return money.\n   *\n   * @param product to return.\n   */\n  public void returnProduct(Product product) {\n    LOGGER.info(\n        String.format(\n            \"%s want to return %s($%.2f)...\",\n            name, product.getName(), product.getSalePrice().getAmount()));\n    if (purchases.contains(product)) {\n      try {\n        customerDao.deleteProduct(product, this);\n        purchases.remove(product);\n        receiveMoney(product.getSalePrice());\n        LOGGER.info(String.format(\"%s returned %s!\", name, product.getName()));\n      } catch (SQLException ex) {\n        LOGGER.error(ex.getMessage());\n      }\n    } else {\n      LOGGER.error(String.format(\"%s didn't buy %s...\", name, product.getName()));\n    }\n  }\n\n  /** Print customer's purchases. */\n  public void showPurchases() {\n    Optional<String> purchasesToShow =\n        purchases.stream()\n            .map(p -> p.getName() + \" - $\" + p.getSalePrice().getAmount())\n            .reduce((p1, p2) -> p1 + \", \" + p2);\n\n    if (purchasesToShow.isPresent()) {\n      LOGGER.info(name + \" bought: \" + purchasesToShow.get());\n    } else {\n      LOGGER.info(name + \" didn't bought anything\");\n    }\n  }\n\n  /** Print customer's money balance. */\n  public void showBalance() {\n    LOGGER.info(name + \" balance: \" + money);\n  }\n\n  private void withdraw(Money amount) throws IllegalArgumentException {\n    if (money.compareTo(amount) < 0) {\n      throw new IllegalArgumentException(\"Not enough money!\");\n    }\n    money = money.minus(amount);\n  }\n\n  private void receiveMoney(Money amount) {\n    money = money.plus(amount);\n  }\n}\n"
  },
  {
    "path": "domain-model/src/main/java/com/iluwatar/domainmodel/CustomerDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport java.sql.SQLException;\nimport java.util.Optional;\n\n/** DAO interface for customer transactions. */\npublic interface CustomerDao {\n\n  Optional<Customer> findByName(String name) throws SQLException;\n\n  void update(Customer customer) throws SQLException;\n\n  void save(Customer customer) throws SQLException;\n\n  void addProduct(Product product, Customer customer) throws SQLException;\n\n  void deleteProduct(Product product, Customer customer) throws SQLException;\n}\n"
  },
  {
    "path": "domain-model/src/main/java/com/iluwatar/domainmodel/CustomerDaoImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport static org.joda.money.CurrencyUnit.USD;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Optional;\nimport javax.sql.DataSource;\nimport org.joda.money.Money;\n\n/** Implementations for database operations of Customer. */\npublic class CustomerDaoImpl implements CustomerDao {\n\n  private final DataSource dataSource;\n\n  public CustomerDaoImpl(final DataSource userDataSource) {\n    this.dataSource = userDataSource;\n  }\n\n  @Override\n  public Optional<Customer> findByName(String name) throws SQLException {\n    var sql = \"select * from CUSTOMERS where name = ?;\";\n\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(sql)) {\n      preparedStatement.setString(1, name);\n\n      ResultSet rs = preparedStatement.executeQuery();\n\n      if (rs.next()) {\n        return Optional.of(\n            Customer.builder()\n                .name(rs.getString(\"name\"))\n                .money(Money.of(USD, rs.getBigDecimal(\"money\")))\n                .customerDao(this)\n                .build());\n      } else {\n        return Optional.empty();\n      }\n    }\n  }\n\n  @Override\n  public void update(Customer customer) throws SQLException {\n    var sql = \"update CUSTOMERS set money = ? where name = ?;\";\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(sql)) {\n      preparedStatement.setBigDecimal(1, customer.getMoney().getAmount());\n      preparedStatement.setString(2, customer.getName());\n      preparedStatement.executeUpdate();\n    }\n  }\n\n  @Override\n  public void save(Customer customer) throws SQLException {\n    var sql = \"insert into CUSTOMERS (name, money) values (?, ?)\";\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(sql)) {\n      preparedStatement.setString(1, customer.getName());\n      preparedStatement.setBigDecimal(2, customer.getMoney().getAmount());\n      preparedStatement.executeUpdate();\n    }\n  }\n\n  @Override\n  public void addProduct(Product product, Customer customer) throws SQLException {\n    var sql = \"insert into PURCHASES (product_name, customer_name) values (?,?)\";\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(sql)) {\n      preparedStatement.setString(1, product.getName());\n      preparedStatement.setString(2, customer.getName());\n      preparedStatement.executeUpdate();\n    }\n  }\n\n  @Override\n  public void deleteProduct(Product product, Customer customer) throws SQLException {\n    var sql = \"delete from PURCHASES where product_name = ? and customer_name = ?\";\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(sql)) {\n      preparedStatement.setString(1, product.getName());\n      preparedStatement.setString(2, customer.getName());\n      preparedStatement.executeUpdate();\n    }\n  }\n}\n"
  },
  {
    "path": "domain-model/src/main/java/com/iluwatar/domainmodel/Product.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport static org.joda.money.CurrencyUnit.USD;\n\nimport java.math.RoundingMode;\nimport java.sql.SQLException;\nimport java.time.LocalDate;\nimport java.time.temporal.ChronoUnit;\nimport java.util.Optional;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Getter;\nimport lombok.NonNull;\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\nimport org.joda.money.Money;\n\n/**\n * This class organizes domain logic of product. A single instance of this class contains both the\n * data and behavior of a single product.\n */\n@Slf4j\n@Getter\n@Setter\n@Builder\n@AllArgsConstructor\npublic class Product {\n\n  private static final int DAYS_UNTIL_EXPIRATION_WHEN_DISCOUNT_ACTIVE = 4;\n  private static final double DISCOUNT_RATE = 0.2;\n\n  @NonNull private final ProductDao productDao;\n  @NonNull private String name;\n  @NonNull private Money price;\n  @NonNull private LocalDate expirationDate;\n\n  /** Save product or update if product already exist. */\n  public void save() {\n    try {\n      Optional<Product> product = productDao.findByName(name);\n      if (product.isPresent()) {\n        productDao.update(this);\n      } else {\n        productDao.save(this);\n      }\n    } catch (SQLException ex) {\n      LOGGER.error(ex.getMessage());\n    }\n  }\n\n  /** Calculate sale price of product with discount. */\n  public Money getSalePrice() {\n    return price.minus(calculateDiscount());\n  }\n\n  private Money calculateDiscount() {\n    if (ChronoUnit.DAYS.between(LocalDate.now(), expirationDate)\n        < DAYS_UNTIL_EXPIRATION_WHEN_DISCOUNT_ACTIVE) {\n\n      return price.multipliedBy(DISCOUNT_RATE, RoundingMode.DOWN);\n    }\n\n    return Money.zero(USD);\n  }\n}\n"
  },
  {
    "path": "domain-model/src/main/java/com/iluwatar/domainmodel/ProductDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport java.sql.SQLException;\nimport java.util.Optional;\n\n/** DAO interface for product transactions. */\npublic interface ProductDao {\n\n  Optional<Product> findByName(String name) throws SQLException;\n\n  void save(Product product) throws SQLException;\n\n  void update(Product product) throws SQLException;\n}\n"
  },
  {
    "path": "domain-model/src/main/java/com/iluwatar/domainmodel/ProductDaoImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport static org.joda.money.CurrencyUnit.USD;\n\nimport java.sql.Date;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Optional;\nimport javax.sql.DataSource;\nimport org.joda.money.Money;\n\n/** Implementations for database transactions of Product. */\npublic class ProductDaoImpl implements ProductDao {\n\n  private final DataSource dataSource;\n\n  public ProductDaoImpl(final DataSource userDataSource) {\n    this.dataSource = userDataSource;\n  }\n\n  @Override\n  public Optional<Product> findByName(String name) throws SQLException {\n    var sql = \"select * from PRODUCTS where name = ?;\";\n\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(sql)) {\n      preparedStatement.setString(1, name);\n\n      ResultSet rs = preparedStatement.executeQuery();\n\n      if (rs.next()) {\n        return Optional.of(\n            Product.builder()\n                .name(rs.getString(\"name\"))\n                .price(Money.of(USD, rs.getBigDecimal(\"price\")))\n                .expirationDate(rs.getDate(\"expiration_date\").toLocalDate())\n                .productDao(this)\n                .build());\n      } else {\n        return Optional.empty();\n      }\n    }\n  }\n\n  @Override\n  public void save(Product product) throws SQLException {\n    var sql = \"insert into PRODUCTS (name, price, expiration_date) values (?, ?, ?)\";\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(sql)) {\n      preparedStatement.setString(1, product.getName());\n      preparedStatement.setBigDecimal(2, product.getPrice().getAmount());\n      preparedStatement.setDate(3, Date.valueOf(product.getExpirationDate()));\n      preparedStatement.executeUpdate();\n    }\n  }\n\n  @Override\n  public void update(Product product) throws SQLException {\n    var sql = \"update PRODUCTS set price = ?, expiration_date = ? where name = ?;\";\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(sql)) {\n      preparedStatement.setBigDecimal(1, product.getPrice().getAmount());\n      preparedStatement.setDate(2, Date.valueOf(product.getExpirationDate()));\n      preparedStatement.setString(3, product.getName());\n      preparedStatement.executeUpdate();\n    }\n  }\n}\n"
  },
  {
    "path": "domain-model/src/test/java/com/iluwatar/domainmodel/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Domain Model example runs without errors. */\nfinal class AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "domain-model/src/test/java/com/iluwatar/domainmodel/CustomerDaoImplTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport static org.joda.money.CurrencyUnit.USD;\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.time.LocalDate;\nimport javax.sql.DataSource;\nimport org.joda.money.CurrencyUnit;\nimport org.joda.money.Money;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass CustomerDaoImplTest {\n\n  public static final String INSERT_CUSTOMER_SQL = \"insert into CUSTOMERS values('customer', 100)\";\n  public static final String SELECT_CUSTOMERS_SQL = \"select name, money from CUSTOMERS\";\n  public static final String INSERT_PURCHASES_SQL =\n      \"insert into PURCHASES values('product', 'customer')\";\n  public static final String SELECT_PURCHASES_SQL =\n      \"select product_name, customer_name from PURCHASES\";\n\n  private DataSource dataSource;\n  private Product product;\n  private Customer customer;\n  private CustomerDao customerDao;\n\n  @BeforeEach\n  void setUp() throws SQLException {\n    // create db schema\n    dataSource = TestUtils.createDataSource();\n\n    TestUtils.deleteSchema(dataSource);\n    TestUtils.createSchema(dataSource);\n\n    // setup objects\n    customerDao = new CustomerDaoImpl(dataSource);\n\n    customer =\n        Customer.builder()\n            .name(\"customer\")\n            .money(Money.of(CurrencyUnit.USD, 100.0))\n            .customerDao(customerDao)\n            .build();\n\n    product =\n        Product.builder()\n            .name(\"product\")\n            .price(Money.of(USD, 100.0))\n            .expirationDate(LocalDate.parse(\"2021-06-27\"))\n            .productDao(new ProductDaoImpl(dataSource))\n            .build();\n  }\n\n  @AfterEach\n  void tearDown() throws SQLException {\n    TestUtils.deleteSchema(dataSource);\n  }\n\n  @Test\n  void shouldFindCustomerByName() throws SQLException {\n    var customer = customerDao.findByName(\"customer\");\n\n    assertTrue(customer.isEmpty());\n\n    TestUtils.executeSQL(INSERT_CUSTOMER_SQL, dataSource);\n\n    customer = customerDao.findByName(\"customer\");\n\n    assertTrue(customer.isPresent());\n    assertEquals(\"customer\", customer.get().getName());\n    assertEquals(Money.of(USD, 100), customer.get().getMoney());\n  }\n\n  @Test\n  void shouldSaveCustomer() throws SQLException {\n    customerDao.save(customer);\n\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement();\n        ResultSet rs = statement.executeQuery(SELECT_CUSTOMERS_SQL)) {\n\n      assertTrue(rs.next());\n      assertEquals(customer.getName(), rs.getString(\"name\"));\n      assertEquals(customer.getMoney(), Money.of(USD, rs.getBigDecimal(\"money\")));\n    }\n\n    assertThrows(SQLException.class, () -> customerDao.save(customer));\n  }\n\n  @Test\n  void shouldUpdateCustomer() throws SQLException {\n    TestUtils.executeSQL(INSERT_CUSTOMER_SQL, dataSource);\n\n    customer.setMoney(Money.of(CurrencyUnit.USD, 99));\n\n    customerDao.update(customer);\n\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement();\n        ResultSet rs = statement.executeQuery(SELECT_CUSTOMERS_SQL)) {\n\n      assertTrue(rs.next());\n      assertEquals(customer.getName(), rs.getString(\"name\"));\n      assertEquals(customer.getMoney(), Money.of(USD, rs.getBigDecimal(\"money\")));\n      assertFalse(rs.next());\n    }\n  }\n\n  @Test\n  void shouldAddProductToPurchases() throws SQLException {\n    TestUtils.executeSQL(INSERT_CUSTOMER_SQL, dataSource);\n    TestUtils.executeSQL(ProductDaoImplTest.INSERT_PRODUCT_SQL, dataSource);\n\n    customerDao.addProduct(product, customer);\n\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement();\n        ResultSet rs = statement.executeQuery(SELECT_PURCHASES_SQL)) {\n\n      assertTrue(rs.next());\n      assertEquals(product.getName(), rs.getString(\"product_name\"));\n      assertEquals(customer.getName(), rs.getString(\"customer_name\"));\n      assertFalse(rs.next());\n    }\n  }\n\n  @Test\n  void shouldDeleteProductFromPurchases() throws SQLException {\n    TestUtils.executeSQL(INSERT_CUSTOMER_SQL, dataSource);\n    TestUtils.executeSQL(ProductDaoImplTest.INSERT_PRODUCT_SQL, dataSource);\n    TestUtils.executeSQL(INSERT_PURCHASES_SQL, dataSource);\n\n    customerDao.deleteProduct(product, customer);\n\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement();\n        ResultSet rs = statement.executeQuery(SELECT_PURCHASES_SQL)) {\n\n      assertFalse(rs.next());\n    }\n  }\n}\n"
  },
  {
    "path": "domain-model/src/test/java/com/iluwatar/domainmodel/CustomerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport static org.joda.money.CurrencyUnit.USD;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.*;\n\nimport java.sql.SQLException;\nimport java.time.LocalDate;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Optional;\nimport org.joda.money.CurrencyUnit;\nimport org.joda.money.Money;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass CustomerTest {\n\n  private CustomerDao customerDao;\n  private Customer customer;\n  private Product product;\n\n  @BeforeEach\n  void setUp() {\n    customerDao = mock(CustomerDao.class);\n\n    customer =\n        Customer.builder()\n            .name(\"customer\")\n            .money(Money.of(CurrencyUnit.USD, 100.0))\n            .customerDao(customerDao)\n            .build();\n\n    product =\n        Product.builder()\n            .name(\"product\")\n            .price(Money.of(USD, 100.0))\n            .expirationDate(LocalDate.now().plusDays(10))\n            .productDao(mock(ProductDao.class))\n            .build();\n  }\n\n  @Test\n  void shouldSaveCustomer() throws SQLException {\n    when(customerDao.findByName(\"customer\")).thenReturn(Optional.empty());\n\n    customer.save();\n\n    verify(customerDao, times(1)).save(customer);\n\n    when(customerDao.findByName(\"customer\")).thenReturn(Optional.of(customer));\n\n    customer.save();\n\n    verify(customerDao, times(1)).update(customer);\n  }\n\n  @Test\n  void shouldAddProductToPurchases() {\n    product.setPrice(Money.of(USD, 200.0));\n\n    customer.buyProduct(product);\n\n    assertEquals(customer.getPurchases(), new ArrayList<>());\n    assertEquals(customer.getMoney(), Money.of(USD, 100));\n\n    product.setPrice(Money.of(USD, 100.0));\n\n    customer.buyProduct(product);\n\n    assertEquals(new ArrayList<>(Arrays.asList(product)), customer.getPurchases());\n    assertEquals(Money.zero(USD), customer.getMoney());\n  }\n\n  @Test\n  void shouldRemoveProductFromPurchases() {\n    customer.setPurchases(new ArrayList<>(Arrays.asList(product)));\n\n    customer.returnProduct(product);\n\n    assertEquals(new ArrayList<>(), customer.getPurchases());\n    assertEquals(Money.of(USD, 200), customer.getMoney());\n\n    customer.returnProduct(product);\n\n    assertEquals(new ArrayList<>(), customer.getPurchases());\n    assertEquals(Money.of(USD, 200), customer.getMoney());\n  }\n}\n"
  },
  {
    "path": "domain-model/src/test/java/com/iluwatar/domainmodel/ProductDaoImplTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport static org.joda.money.CurrencyUnit.USD;\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.time.LocalDate;\nimport javax.sql.DataSource;\nimport org.joda.money.Money;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass ProductDaoImplTest {\n\n  public static final String INSERT_PRODUCT_SQL =\n      \"insert into PRODUCTS values('product', 100, DATE '2021-06-27')\";\n  public static final String SELECT_PRODUCTS_SQL =\n      \"select name, price, expiration_date from PRODUCTS\";\n\n  private DataSource dataSource;\n  private ProductDao productDao;\n  private Product product;\n\n  @BeforeEach\n  void setUp() throws SQLException {\n    // create schema\n    dataSource = TestUtils.createDataSource();\n\n    TestUtils.deleteSchema(dataSource);\n    TestUtils.createSchema(dataSource);\n\n    // setup objects\n    productDao = new ProductDaoImpl(dataSource);\n\n    product =\n        Product.builder()\n            .name(\"product\")\n            .price(Money.of(USD, 100.0))\n            .expirationDate(LocalDate.parse(\"2021-06-27\"))\n            .productDao(productDao)\n            .build();\n  }\n\n  @AfterEach\n  void tearDown() throws SQLException {\n    TestUtils.deleteSchema(dataSource);\n  }\n\n  @Test\n  void shouldFindProductByName() throws SQLException {\n    var product = productDao.findByName(\"product\");\n\n    assertTrue(product.isEmpty());\n\n    TestUtils.executeSQL(INSERT_PRODUCT_SQL, dataSource);\n\n    product = productDao.findByName(\"product\");\n\n    assertTrue(product.isPresent());\n    assertEquals(\"product\", product.get().getName());\n    assertEquals(Money.of(USD, 100), product.get().getPrice());\n    assertEquals(LocalDate.parse(\"2021-06-27\"), product.get().getExpirationDate());\n  }\n\n  @Test\n  void shouldSaveProduct() throws SQLException {\n\n    productDao.save(product);\n\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement();\n        ResultSet rs = statement.executeQuery(SELECT_PRODUCTS_SQL)) {\n\n      assertTrue(rs.next());\n      assertEquals(product.getName(), rs.getString(\"name\"));\n      assertEquals(product.getPrice(), Money.of(USD, rs.getBigDecimal(\"price\")));\n      assertEquals(product.getExpirationDate(), rs.getDate(\"expiration_date\").toLocalDate());\n    }\n\n    assertThrows(SQLException.class, () -> productDao.save(product));\n  }\n\n  @Test\n  void shouldUpdateProduct() throws SQLException {\n    TestUtils.executeSQL(INSERT_PRODUCT_SQL, dataSource);\n\n    product.setPrice(Money.of(USD, 99.0));\n\n    productDao.update(product);\n\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement();\n        ResultSet rs = statement.executeQuery(SELECT_PRODUCTS_SQL)) {\n\n      assertTrue(rs.next());\n      assertEquals(product.getName(), rs.getString(\"name\"));\n      assertEquals(product.getPrice(), Money.of(USD, rs.getBigDecimal(\"price\")));\n      assertEquals(product.getExpirationDate(), rs.getDate(\"expiration_date\").toLocalDate());\n    }\n  }\n}\n"
  },
  {
    "path": "domain-model/src/test/java/com/iluwatar/domainmodel/ProductTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport static org.joda.money.CurrencyUnit.USD;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.*;\n\nimport java.sql.SQLException;\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport org.joda.money.Money;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass ProductTest {\n\n  private ProductDao productDao;\n  private Product product;\n\n  @BeforeEach\n  void setUp() {\n    productDao = mock(ProductDaoImpl.class);\n\n    product =\n        Product.builder()\n            .name(\"product\")\n            .price(Money.of(USD, 100.0))\n            .expirationDate(LocalDate.now().plusDays(10))\n            .productDao(productDao)\n            .build();\n  }\n\n  @Test\n  void shouldSaveProduct() throws SQLException {\n    when(productDao.findByName(\"product\")).thenReturn(Optional.empty());\n\n    product.save();\n\n    verify(productDao, times(1)).save(product);\n\n    when(productDao.findByName(\"product\")).thenReturn(Optional.of(product));\n\n    product.save();\n\n    verify(productDao, times(1)).update(product);\n  }\n\n  @Test\n  void shouldGetSalePriceOfProduct() {\n    assertEquals(Money.of(USD, 100), product.getSalePrice());\n\n    product.setExpirationDate(LocalDate.now().plusDays(2));\n\n    assertEquals(Money.of(USD, 80), product.getSalePrice());\n  }\n}\n"
  },
  {
    "path": "domain-model/src/test/java/com/iluwatar/domainmodel/TestUtils.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.domainmodel;\n\nimport java.sql.SQLException;\nimport javax.sql.DataSource;\nimport org.h2.jdbcx.JdbcDataSource;\n\npublic class TestUtils {\n\n  public static void executeSQL(String sql, DataSource dataSource) throws SQLException {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.executeUpdate(sql);\n    }\n  }\n\n  public static void createSchema(DataSource dataSource) throws SQLException {\n    TestUtils.executeSQL(App.CREATE_SCHEMA_SQL, dataSource);\n  }\n\n  public static void deleteSchema(DataSource dataSource) throws SQLException {\n    TestUtils.executeSQL(App.DELETE_SCHEMA_SQL, dataSource);\n  }\n\n  public static DataSource createDataSource() {\n    var dataSource = new JdbcDataSource();\n    dataSource.setURL(App.H2_DB_URL);\n    return dataSource;\n  }\n}\n"
  },
  {
    "path": "double-buffer/README.md",
    "content": "---\ntitle: \"Double Buffer Pattern in Java: Enhancing Animation and Graphics Performance\"\nshortTitle: Double Buffer\ndescription: \"Learn how the Double Buffer Pattern in Java optimizes performance and ensures smooth graphics rendering for applications. Explore practical examples and real-world use cases.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Buffering\n  - Game programming\n  - Optimization\n  - Performance\n---\n\n## Also known as\n\n* Buffer Switching\n* Ping-Pong Buffer\n\n## Intent of Double Buffer Design Pattern\n\nThe Double Buffer pattern in Java is designed to reduce rendering time and enhance performance in graphical or computational applications by utilizing two buffers. This pattern is crucial for smooth graphics rendering and is commonly used in game development and other real-time applications.\n\n## Detailed Explanation of Double Buffer Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a busy restaurant kitchen where chefs are constantly preparing dishes, and waitstaff are constantly picking up ready dishes to serve to customers. To avoid confusion and delays, the restaurant uses a double buffer system. They have two counters: one for chefs to place newly prepared dishes and another for waitstaff to pick up the dishes. While the chefs are filling one counter with prepared dishes, the waitstaff are simultaneously clearing the other counter by picking up dishes to serve. Once the waitstaff have cleared all dishes from their counter, they switch to the counter where the chefs have placed the newly prepared dishes, and the chefs start filling the now-empty counter. This system ensures a smooth and continuous workflow without either party waiting idly, maximizing efficiency and minimizing downtime.\n\nIn plain words\n\n> It ensures a state that is being rendered correctly while that state is modifying incrementally. It is widely used in computer graphics.\n\nWikipedia says\n\n> In computer science, multiple buffering is the use of more than one buffer to hold a block of data, so that a \"reader\" will see a complete (though perhaps old) version of the data, rather than a partially updated version of the data being created by a \"writer\". It is very commonly used for computer display images.\n\nSequence diagram\n\n![Double Buffer sequence diagram](./etc/double-buffer-sequence-diagram.png)\n\n## Programmatic Example of Double Buffer Pattern in Java\n\nA typical example, and one that every game engine must address, is rendering. When the game draws the world the users see, it does so one piece at a time - the mountains in the distance, the rolling hills, the trees, each in its turn. If the user watched the view draw incrementally like that, the illusion of a coherent world would be shattered. The scene must update smoothly and quickly, displaying a series of complete frames, each appearing instantly. Double buffering solves the problem.\n\n`Buffer` interface that assures basic functionalities of a buffer.\n\n```java\npublic interface Buffer {\n\n    void clear(int x, int y);\n\n    void draw(int x, int y);\n\n    void clearAll();\n\n    Pixel[] getPixels();\n}\n```\n\nOne of the implementations of `Buffer` interface.\n\n```java\npublic class FrameBuffer implements Buffer {\n\n    public static final int WIDTH = 10;\n    public static final int HEIGHT = 8;\n\n    private final Pixel[] pixels = new Pixel[WIDTH * HEIGHT];\n\n    public FrameBuffer() {\n        clearAll();\n    }\n\n    @Override\n    public void clear(int x, int y) {\n        pixels[getIndex(x, y)] = Pixel.WHITE;\n    }\n\n    @Override\n    public void draw(int x, int y) {\n        pixels[getIndex(x, y)] = Pixel.BLACK;\n    }\n\n    @Override\n    public void clearAll() {\n        Arrays.fill(pixels, Pixel.WHITE);\n    }\n\n    @Override\n    public Pixel[] getPixels() {\n        return pixels;\n    }\n\n    private int getIndex(int x, int y) {\n        return x + WIDTH * y;\n    }\n}\n```\n\nWe support black and white pixels.\n\n```java\npublic enum Pixel {\n\n    WHITE,\n    BLACK\n}\n```\n\n`Scene` represents the game scene where current buffer has already been rendered.\n\n```java\n@Slf4j\npublic class Scene {\n\n    private final Buffer[] frameBuffers;\n\n    private int current;\n\n    private int next;\n\n    public Scene() {\n        frameBuffers = new FrameBuffer[2];\n        frameBuffers[0] = new FrameBuffer();\n        frameBuffers[1] = new FrameBuffer();\n        current = 0;\n        next = 1;\n    }\n\n    public void draw(List<? extends Pair<Integer, Integer>> coordinateList) {\n        LOGGER.info(\"Start drawing next frame\");\n        LOGGER.info(\"Current buffer: \" + current + \" Next buffer: \" + next);\n        frameBuffers[next].clearAll();\n        coordinateList.forEach(coordinate -> {\n            var x = coordinate.getKey();\n            var y = coordinate.getValue();\n            frameBuffers[next].draw(x, y);\n        });\n        LOGGER.info(\"Swap current and next buffer\");\n        swap();\n        LOGGER.info(\"Finish swapping\");\n        LOGGER.info(\"Current buffer: \" + current + \" Next buffer: \" + next);\n    }\n\n    public Buffer getBuffer() {\n        LOGGER.info(\"Get current buffer: \" + current);\n        return frameBuffers[current];\n    }\n\n    private void swap() {\n        current = current ^ next;\n        next = current ^ next;\n        current = current ^ next;\n    }\n\n}\n```\n\nNow, we can show the `App` class that drives the double buffering example.\n\n```java\n@Slf4j\npublic class App {\n\n    public static void main(String[] args) {\n        final var scene = new Scene();\n        var drawPixels1 = List.of(\n                new MutablePair<>(1, 1),\n                new MutablePair<>(5, 6),\n                new MutablePair<>(3, 2)\n        );\n        scene.draw(drawPixels1);\n        var buffer1 = scene.getBuffer();\n        printBlackPixelCoordinate(buffer1);\n\n        var drawPixels2 = List.of(\n                new MutablePair<>(3, 7),\n                new MutablePair<>(6, 1)\n        );\n        scene.draw(drawPixels2);\n        var buffer2 = scene.getBuffer();\n        printBlackPixelCoordinate(buffer2);\n    }\n\n    private static void printBlackPixelCoordinate(Buffer buffer) {\n        StringBuilder log = new StringBuilder(\"Black Pixels: \");\n        var pixels = buffer.getPixels();\n        for (var i = 0; i < pixels.length; ++i) {\n            if (pixels[i] == Pixel.BLACK) {\n                var y = i / FrameBuffer.WIDTH;\n                var x = i % FrameBuffer.WIDTH;\n                log.append(\" (\").append(x).append(\", \").append(y).append(\")\");\n            }\n        }\n        LOGGER.info(log.toString());\n    }\n}\n```\n\nThe console output:\n\n```text\n12:33:02.525 [main] INFO com.iluwatar.doublebuffer.Scene -- Start drawing next frame\n12:33:02.529 [main] INFO com.iluwatar.doublebuffer.Scene -- Current buffer: 0 Next buffer: 1\n12:33:02.529 [main] INFO com.iluwatar.doublebuffer.Scene -- Swap current and next buffer\n12:33:02.529 [main] INFO com.iluwatar.doublebuffer.Scene -- Finish swapping\n12:33:02.529 [main] INFO com.iluwatar.doublebuffer.Scene -- Current buffer: 1 Next buffer: 0\n12:33:02.530 [main] INFO com.iluwatar.doublebuffer.Scene -- Get current buffer: 1\n12:33:02.530 [main] INFO com.iluwatar.doublebuffer.App -- Black Pixels:  (1, 1) (3, 2) (5, 6)\n12:33:02.530 [main] INFO com.iluwatar.doublebuffer.Scene -- Start drawing next frame\n12:33:02.530 [main] INFO com.iluwatar.doublebuffer.Scene -- Current buffer: 1 Next buffer: 0\n12:33:02.530 [main] INFO com.iluwatar.doublebuffer.Scene -- Swap current and next buffer\n12:33:02.530 [main] INFO com.iluwatar.doublebuffer.Scene -- Finish swapping\n12:33:02.530 [main] INFO com.iluwatar.doublebuffer.Scene -- Current buffer: 0 Next buffer: 1\n12:33:02.530 [main] INFO com.iluwatar.doublebuffer.Scene -- Get current buffer: 0\n12:33:02.530 [main] INFO com.iluwatar.doublebuffer.App -- Black Pixels:  (6, 1) (3, 7)\n```\n\n## When to Use the Double Buffer Pattern in Java\n\n* Real-time Applications: Ideal for video games, simulations, and GUI applications where frequent and smooth display updates are essential.\n* High Computational Tasks: Suitable for applications that require intensive data preparation, enabling parallel processing and display.\n* Minimizing Lag: Effective in reducing lag or stutter in data or graphics display.\n\n## Real-World Applications of Double Buffer Pattern in Java\n\n* Graphics Rendering Engines: Widely used in 2D and 3D rendering engines to ensure fluid animations and transitions.\n* GUI Frameworks: Enhances the responsiveness and smoothness of user interfaces.\n* Simulation and Modeling: Ensures real-time updates in simulations without interrupting ongoing processes.\n* Video Playback Software: Provides seamless video playback by preloading the next frame during the display of the current one.\n\n## Benefits and Trade-offs of Double Buffer Pattern\n\nBenefits:\n\n* Smooth User Experience: Pre-renders frames to deliver smooth animations and transitions.\n* Performance Optimization: Allows background rendering, optimizing overall application performance.\n* Minimized Flickering: Reduces flickering and visual artifacts in graphical applications.\n\nTrade-offs:\n\n* Memory Overhead: Requires additional memory for the secondary buffer, potentially increasing memory usage.\n* Implementation Complexity: Adds complexity to the architecture, necessitating careful buffer management.\n* Latency: May introduce slight delays as data must be fully rendered in the back buffer before display.\n\n## Related Java Design Patterns\n\n* Triple Buffering: An extension of the Double Buffer pattern, where three buffers are used to further optimize rendering and reduce latency.\n* [Producer-Consumer](https://java-design-patterns.com/patterns/producer-consumer/): The Double Buffer pattern can be seen as a variant of the Producer-Consumer pattern, with one buffer being \"produced\" while the other is \"consumed\".\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Often used in conjunction with the Strategy pattern to dynamically choose the buffering strategy based on runtime conditions.\n\n## References and Credits\n\n* [Game Programming Patterns](https://amzn.to/4ayDNkS)\n* [Real-Time Design Patterns: Robust Scalable Architecture for Real-Time Systems](https://amzn.to/3xFfNxA)\n* [Double Buffer (Game Programming Patterns)](https://gameprogrammingpatterns.com/double-buffer.html)\n"
  },
  {
    "path": "double-buffer/etc/double-buffer.urm.puml",
    "content": "@startuml\npackage com.iluwatar.doublebuffer {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n    - printBlackPixelCoordinate(buffer : Buffer) {static}\n  }\n  interface Buffer {\n    + clear(int, int) {abstract}\n    + clearAll() {abstract}\n    + draw(int, int) {abstract}\n    + getPixels() : Pixel[] {abstract}\n  }\n  class FrameBuffer {\n    + HEIGHT : int {static}\n    + WIDTH : int {static}\n    - pixels : Pixel[]\n    + FrameBuffer()\n    + clear(x : int, y : int)\n    + clearAll()\n    + draw(x : int, y : int)\n    - getIndex(x : int, y : int) : int\n    + getPixels() : Pixel[]\n  }\n  enum Pixel {\n    + BLACK {static}\n    + WHITE {static}\n    - color : int\n    + valueOf(name : String) : Pixel {static}\n    + values() : Pixel[] {static}\n  }\n  class Scene {\n    - LOGGER : Logger {static}\n    - current : int\n    - frameBuffers : Buffer[]\n    - next : int\n    + Scene()\n    + draw(coordinateList : List<Pair<Integer, Integer>>)\n    + getBuffer() : Buffer\n    - swap()\n  }\n}\nFrameBuffer ..|> Buffer \n@enduml"
  },
  {
    "path": "double-buffer/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>double-buffer</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.apache.commons</groupId>\n      <artifactId>commons-lang3</artifactId>\n      <version>3.17.0</version>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.doublebuffer.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "double-buffer/src/main/java/com/iluwatar/doublebuffer/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublebuffer;\n\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\nimport org.apache.commons.lang3.tuple.MutablePair;\n\n/**\n * Double buffering is a term used to describe a device that has two buffers. The usage of multiple\n * buffers increases the overall throughput of a device and helps prevents bottlenecks. This example\n * shows using double buffer pattern on graphics. It is used to show one image or frame while a\n * separate frame is being buffered to be shown next. This method makes animations and games look\n * more realistic than the same done in a single buffer mode.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program main entry point.\n   *\n   * @param args runtime arguments\n   */\n  public static void main(String[] args) {\n    final var scene = new Scene();\n    var drawPixels1 =\n        List.of(new MutablePair<>(1, 1), new MutablePair<>(5, 6), new MutablePair<>(3, 2));\n    scene.draw(drawPixels1);\n    var buffer1 = scene.getBuffer();\n    printBlackPixelCoordinate(buffer1);\n\n    var drawPixels2 = List.of(new MutablePair<>(3, 7), new MutablePair<>(6, 1));\n    scene.draw(drawPixels2);\n    var buffer2 = scene.getBuffer();\n    printBlackPixelCoordinate(buffer2);\n  }\n\n  private static void printBlackPixelCoordinate(Buffer buffer) {\n    StringBuilder log = new StringBuilder(\"Black Pixels: \");\n    var pixels = buffer.getPixels();\n    for (var i = 0; i < pixels.length; ++i) {\n      if (pixels[i] == Pixel.BLACK) {\n        var y = i / FrameBuffer.WIDTH;\n        var x = i % FrameBuffer.WIDTH;\n        log.append(\" (\").append(x).append(\", \").append(y).append(\")\");\n      }\n    }\n    LOGGER.info(log.toString());\n  }\n}\n"
  },
  {
    "path": "double-buffer/src/main/java/com/iluwatar/doublebuffer/Buffer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublebuffer;\n\n/** Buffer interface. */\npublic interface Buffer {\n\n  /**\n   * Clear the pixel in (x, y).\n   *\n   * @param x X coordinate\n   * @param y Y coordinate\n   */\n  void clear(int x, int y);\n\n  /**\n   * Draw the pixel in (x, y).\n   *\n   * @param x X coordinate\n   * @param y Y coordinate\n   */\n  void draw(int x, int y);\n\n  /** Clear all the pixels. */\n  void clearAll();\n\n  /**\n   * Get all the pixels.\n   *\n   * @return pixel list\n   */\n  Pixel[] getPixels();\n}\n"
  },
  {
    "path": "double-buffer/src/main/java/com/iluwatar/doublebuffer/FrameBuffer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublebuffer;\n\nimport java.util.Arrays;\n\n/** FrameBuffer implementation class. */\npublic class FrameBuffer implements Buffer {\n\n  public static final int WIDTH = 10;\n  public static final int HEIGHT = 8;\n\n  private final Pixel[] pixels = new Pixel[WIDTH * HEIGHT];\n\n  public FrameBuffer() {\n    clearAll();\n  }\n\n  @Override\n  public void clear(int x, int y) {\n    pixels[getIndex(x, y)] = Pixel.WHITE;\n  }\n\n  @Override\n  public void draw(int x, int y) {\n    pixels[getIndex(x, y)] = Pixel.BLACK;\n  }\n\n  @Override\n  public void clearAll() {\n    Arrays.fill(pixels, Pixel.WHITE);\n  }\n\n  @Override\n  public Pixel[] getPixels() {\n    return pixels;\n  }\n\n  private int getIndex(int x, int y) {\n    return x + WIDTH * y;\n  }\n}\n"
  },
  {
    "path": "double-buffer/src/main/java/com/iluwatar/doublebuffer/Pixel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublebuffer;\n\n/** Pixel enum. Each pixel can be white (not drawn) or black (drawn). */\npublic enum Pixel {\n  WHITE,\n  BLACK\n}\n"
  },
  {
    "path": "double-buffer/src/main/java/com/iluwatar/doublebuffer/Scene.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublebuffer;\n\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\nimport org.apache.commons.lang3.tuple.Pair;\n\n/** Scene class. Render the output frame. */\n@Slf4j\npublic class Scene {\n\n  private final Buffer[] frameBuffers;\n\n  private int current;\n\n  private int next;\n\n  /** Constructor of Scene. */\n  public Scene() {\n    frameBuffers = new FrameBuffer[2];\n    frameBuffers[0] = new FrameBuffer();\n    frameBuffers[1] = new FrameBuffer();\n    current = 0;\n    next = 1;\n  }\n\n  /**\n   * Draw the next frame.\n   *\n   * @param coordinateList list of pixels of which the color should be black\n   */\n  public void draw(List<? extends Pair<Integer, Integer>> coordinateList) {\n    LOGGER.info(\"Start drawing next frame\");\n    LOGGER.info(\"Current buffer: \" + current + \" Next buffer: \" + next);\n    frameBuffers[next].clearAll();\n    coordinateList.forEach(\n        coordinate -> {\n          var x = coordinate.getKey();\n          var y = coordinate.getValue();\n          frameBuffers[next].draw(x, y);\n        });\n    LOGGER.info(\"Swap current and next buffer\");\n    swap();\n    LOGGER.info(\"Finish swapping\");\n    LOGGER.info(\"Current buffer: \" + current + \" Next buffer: \" + next);\n  }\n\n  public Buffer getBuffer() {\n    LOGGER.info(\"Get current buffer: \" + current);\n    return frameBuffers[current];\n  }\n\n  private void swap() {\n    current = current ^ next;\n    next = current ^ next;\n    current = current ^ next;\n  }\n}\n"
  },
  {
    "path": "double-buffer/src/test/java/com/iluwatar/doublebuffer/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublebuffer;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** App unit test. */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "double-buffer/src/test/java/com/iluwatar/doublebuffer/FrameBufferTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublebuffer;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nimport java.util.Arrays;\nimport org.junit.jupiter.api.Test;\n\n/** FrameBuffer unit test. */\nclass FrameBufferTest {\n\n  @Test\n  void testClearAll() {\n    try {\n      var field = FrameBuffer.class.getDeclaredField(\"pixels\");\n      var pixels = new Pixel[FrameBuffer.HEIGHT * FrameBuffer.WIDTH];\n      Arrays.fill(pixels, Pixel.WHITE);\n      pixels[0] = Pixel.BLACK;\n      var frameBuffer = new FrameBuffer();\n      field.setAccessible(true);\n      field.set(frameBuffer, pixels);\n      frameBuffer.clearAll();\n      assertEquals(Pixel.WHITE, frameBuffer.getPixels()[0]);\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Fail to modify field access.\");\n    }\n  }\n\n  @Test\n  void testClear() {\n    try {\n      var field = FrameBuffer.class.getDeclaredField(\"pixels\");\n      var pixels = new Pixel[FrameBuffer.HEIGHT * FrameBuffer.WIDTH];\n      Arrays.fill(pixels, Pixel.WHITE);\n      pixels[0] = Pixel.BLACK;\n      var frameBuffer = new FrameBuffer();\n      field.setAccessible(true);\n      field.set(frameBuffer, pixels);\n      frameBuffer.clear(0, 0);\n      assertEquals(Pixel.WHITE, frameBuffer.getPixels()[0]);\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Fail to modify field access.\");\n    }\n  }\n\n  @Test\n  void testDraw() {\n    var frameBuffer = new FrameBuffer();\n    frameBuffer.draw(0, 0);\n    assertEquals(Pixel.BLACK, frameBuffer.getPixels()[0]);\n  }\n\n  @Test\n  void testGetPixels() {\n    try {\n      var field = FrameBuffer.class.getDeclaredField(\"pixels\");\n      var pixels = new Pixel[FrameBuffer.HEIGHT * FrameBuffer.WIDTH];\n      Arrays.fill(pixels, Pixel.WHITE);\n      pixels[0] = Pixel.BLACK;\n      var frameBuffer = new FrameBuffer();\n      field.setAccessible(true);\n      field.set(frameBuffer, pixels);\n      assertEquals(pixels, frameBuffer.getPixels());\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Fail to modify field access.\");\n    }\n  }\n}\n"
  },
  {
    "path": "double-buffer/src/test/java/com/iluwatar/doublebuffer/SceneTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublebuffer;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nimport java.util.ArrayList;\nimport org.junit.jupiter.api.Test;\n\n/** Scene unit tests. */\nclass SceneTest {\n\n  @Test\n  void testGetBuffer() {\n    try {\n      var scene = new Scene();\n      var field1 = Scene.class.getDeclaredField(\"current\");\n      field1.setAccessible(true);\n      field1.set(scene, 0);\n      var frameBuffers = new FrameBuffer[2];\n      var frameBuffer = new FrameBuffer();\n      frameBuffer.draw(0, 0);\n      frameBuffers[0] = frameBuffer;\n      var field2 = Scene.class.getDeclaredField(\"frameBuffers\");\n      field2.setAccessible(true);\n      field2.set(scene, frameBuffers);\n      assertEquals(frameBuffer, scene.getBuffer());\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Fail to access private field.\");\n    }\n  }\n\n  @Test\n  void testDraw() {\n    try {\n      var scene = new Scene();\n      var field1 = Scene.class.getDeclaredField(\"current\");\n      var field2 = Scene.class.getDeclaredField(\"next\");\n      field1.setAccessible(true);\n      field1.set(scene, 0);\n      field2.setAccessible(true);\n      field2.set(scene, 1);\n      scene.draw(new ArrayList<>());\n      assertEquals(1, field1.get(scene));\n      assertEquals(0, field2.get(scene));\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Fail to access private field\");\n    }\n  }\n}\n"
  },
  {
    "path": "double-checked-locking/README.md",
    "content": "---\ntitle: \"Double-Checked Locking Pattern in Java: Ensuring Thread Safety with Minimal Overhead\"\nshortTitle: Double-Checked Locking\ndescription: \"Master double-checked locking in Java with our detailed guide and practical examples. Enhance your Java design patterns knowledge today.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Lazy initialization\n  - Optimization\n  - Performance\n  - Thread management\n---\n\n## Intent of Double-Checked Locking Design Pattern\n\nReduce the overhead of acquiring a lock by first testing the locking criterion (the \"lock hint\") without actually acquiring the lock. Only if the locking criterion appears to be true does the actual locking logic proceed. Double-checked locking in Java helps in optimizing performance and ensuring thread safety.\n\n## Detailed Explanation of Double-Checked Locking Pattern with Real-World Examples\n\nReal-world example\n\n> In a company with a high-value equipment room, employees first check a visible sign to see if the room is locked. If the sign shows it's unlocked, they enter directly; if locked, they use a security keycard for access. This two-step verification process efficiently manages security without unnecessary use of the electronic lock system, mirroring the Double-Checked Locking pattern used in software to minimize resource-intensive operations.\n\nIn plain words\n\n> The Double-Checked Locking pattern in software minimizes costly locking operations by first checking the lock status in a low-cost manner before proceeding with a more resource-intensive lock, ensuring efficiency and thread safety during object initialization.\n\nWikipedia says\n\n> In software engineering, double-checked locking (also known as \"double-checked locking optimization\") is a software design pattern used to reduce the overhead of acquiring a lock by testing the locking criterion (the \"lock hint\") before acquiring the lock. Locking occurs only if the locking criterion check indicates that locking is required.\n\nFlowchart\n\n![Double-Checked Locking flowchart](./etc/double-checked-locking-flowchart.png)\n\n## Programmatic Example of Double-Checked Locking Pattern in Java\n\nThe Double-Checked Locking pattern is used in the `HolderThreadSafe` class to ensure that the `Heavy` object is only created once, even when accessed from multiple threads.  Here's how it works:\n\n1. Check if the object is initialized (first check): If it is, return it immediately.\n\n```java\nif (heavy == null) {\n  // ...\n}\n```\n\n2. Synchronize the block of code where the object is created: This ensures that only one thread can create the object.\n\n```java\nsynchronized (this) {\n  // ...\n}\n```\n\n3. Check again if the object is initialized. If another thread has already created the object by the time the current thread enters the synchronized block, return the created object.\n\n```java\nif (heavy == null) {\n  heavy = new Heavy();\n}\n```\n\n4. Return the created object.\n\n```java\nreturn heavy;\n```\n\nHere's the complete code for the `HolderThreadSafe` class:\n\n```java\npublic class HolderThreadSafe {\n\n  private Heavy heavy;\n\n  public HolderThreadSafe() {\n    LOGGER.info(\"Holder created\");\n  }\n\n  public synchronized Heavy getHeavy() {\n    if (heavy == null) {\n      synchronized (this) {\n        if (heavy == null) {\n          heavy = new Heavy();\n        }\n      }\n    }\n    return heavy;\n  }\n}\n```\n\nIn this code, the `Heavy` object is only created when the `getHeavy` method is called for the first time. This is known as lazy initialization. The double-checked locking pattern is used to ensure that the `Heavy` object is only created once, even when the `getHeavy` method is called from multiple threads simultaneously.\n\n## When to Use the Double-Checked Locking Pattern in Java\n\nUse the Double-Checked Locking pattern in Java when all the following conditions are met:\n\n* There is a singleton resource that is expensive to create.\n* There is a need to reduce the overhead of acquiring a lock every time the resource is accessed.\n\n## Real-World Applications of Double-Checked Locking Pattern in Java\n\n* Singleton pattern implementation in multithreading environments.\n* Lazy initialization of resource-intensive objects in Java applications.\n\n## Benefits and Trade-offs of Double-Checked Locking Pattern\n\nBenefits:\n\n* Performance gains from avoiding unnecessary locking after the object is initialized.\n* Thread safety is maintained for critical initialization sections.\n\nTrade-offs:\n\n* Complex implementation can lead to mistakes, such as incorrect publishing of objects due to memory visibility issues.\n* In Java, it can be redundant or broken in some versions unless volatile variables are used with care.\n\n## Related Java Design Patterns\n\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Double-Checked Locking is often used in implementing thread-safe Singletons.\n* [Lazy Loading](https://java-design-patterns.com/patterns/lazy-loading/): Shares the concept of delaying object creation until necessary.\n\n## References and Credits\n\n* [Java Concurrency in Practice](https://amzn.to/4aIAPKa)\n* [Effective Java](https://amzn.to/3xx7KDh)\n"
  },
  {
    "path": "double-checked-locking/etc/double-checked-locking.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.doublechecked.locking.Item\" project=\"double-checked-locking\" \n    file=\"/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Item.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"205\" x=\"146\" y=\"504\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.doublechecked.locking.Inventory\" project=\"double-checked-locking\" \n    file=\"/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"142\" width=\"205\" x=\"146\" y=\"322\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"3\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"4\" name=\"items\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"5\" minimum=\"0\" maximum=\"2147483647\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "double-checked-locking/etc/double-checked-locking.urm.puml",
    "content": "@startuml\npackage com.iluwatar.doublechecked.locking {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Inventory {\n    - LOGGER : Logger {static}\n    - inventorySize : int\n    - items : List<Item>\n    - lock : Lock\n    + Inventory(inventorySize : int)\n    + addItem(item : Item) : boolean\n    + getItems() : List<Item>\n  }\n  class Item {\n    + Item()\n  }\n}\nInventory -->  \"-items\" Item\n@enduml"
  },
  {
    "path": "double-checked-locking/pom.xml",
    "content": "<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>double-checked-locking</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.doublechecked.locking.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublechecked.locking;\n\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.IntStream;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Double Checked Locking is a concurrency design pattern used to reduce the overhead of acquiring a\n * lock by first testing the locking criterion (the \"lock hint\") without actually acquiring the\n * lock. Only if the locking criterion check indicates that locking is required does the actual\n * locking logic proceed.\n *\n * <p>In {@link Inventory} we store the items with a given size. However, we do not store more items\n * than the inventory size. To address concurrent access problems we use double checked locking to\n * add item to inventory. In this method, the thread which gets the lock first adds the item.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    final var inventory = new Inventory(1000);\n    var executorService = Executors.newFixedThreadPool(3);\n    IntStream.range(0, 3)\n        .<Runnable>mapToObj(\n            i ->\n                () -> {\n                  while (inventory.addItem(new Item())) {\n                    LOGGER.info(\"Adding another item\");\n                  }\n                })\n        .forEach(executorService::execute);\n\n    executorService.shutdown();\n    try {\n      executorService.awaitTermination(5, TimeUnit.SECONDS);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Error waiting for ExecutorService shutdown\");\n      Thread.currentThread().interrupt();\n    }\n  }\n}\n"
  },
  {
    "path": "double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublechecked.locking;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Inventory. */\n@Slf4j\npublic class Inventory {\n\n  private final int inventorySize;\n  private final List<Item> items;\n  private final Lock lock;\n\n  /** Constructor. */\n  public Inventory(int inventorySize) {\n    this.inventorySize = inventorySize;\n    this.items = new ArrayList<>(inventorySize);\n    this.lock = new ReentrantLock();\n  }\n\n  /** Add item. */\n  public boolean addItem(Item item) {\n    if (items.size() < inventorySize) {\n      lock.lock();\n      try {\n        if (items.size() < inventorySize) {\n          items.add(item);\n          var thread = Thread.currentThread();\n          LOGGER.info(\"{}: items.size()={}, inventorySize={}\", thread, items.size(), inventorySize);\n          return true;\n        }\n      } finally {\n        lock.unlock();\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Get all the items in the inventory.\n   *\n   * @return All the items of the inventory, as an unmodifiable list\n   */\n  public final List<Item> getItems() {\n    return List.copyOf(items);\n  }\n}\n"
  },
  {
    "path": "double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Item.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublechecked.locking;\n\n/** Item. */\npublic class Item {}\n"
  },
  {
    "path": "double-checked-locking/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<configuration>\n  <appender name=\"FILE\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n    <file>double-checked-locking.log</file>\n    <rollingPolicy class=\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\">\n      <fileNamePattern>double-checked-locking-%d.log</fileNamePattern>\n      <maxHistory>5</maxHistory>\n    </rollingPolicy>\n    <encoder>\n      <pattern>%-5p [%d{ISO8601,UTC}] %c: %m%n</pattern>\n    </encoder>\n  </appender>\n  <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n    <encoder>\n      <pattern>%-5p [%d{ISO8601,UTC}] %c: %m%n</pattern>\n    </encoder>\n  </appender>\n  <logger name=\"com.iluwatar\" additivity=\"false\">\n    <level value=\"DEBUG\" />\n    <appender-ref ref=\"FILE\" />\n  </logger>\n  <root level=\"WARN\">\n    <appender-ref ref=\"STDOUT\" />\n  </root>\n</configuration>\n"
  },
  {
    "path": "double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublechecked.locking;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doublechecked.locking;\n\nimport static java.time.Duration.ofMillis;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTimeout;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.IntStream;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/** InventoryTest */\nclass InventoryTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(Inventory.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /**\n   * The number of threads used to stress test the locking of the {@link Inventory#addItem(Item)}\n   * method\n   */\n  private static final int THREAD_COUNT = 8;\n\n  /** The maximum number of {@link Item}s allowed in the {@link Inventory} */\n  private static final int INVENTORY_SIZE = 1000;\n\n  /**\n   * Concurrently add multiple items to the inventory, and check if the items were added in order by\n   * checking the stdOut for continuous growth of the inventory. When 'items.size()=xx' shows up out\n   * of order, it means that the locking is not ok, increasing the risk of going over the inventory\n   * item limit.\n   */\n  @Test\n  void testAddItem() {\n    assertTimeout(\n        ofMillis(10000),\n        () -> {\n          // Create a new inventory with a limit of 1000 items and put some load on the add method\n          final var inventory = new Inventory(INVENTORY_SIZE);\n          final var executorService = Executors.newFixedThreadPool(THREAD_COUNT);\n          IntStream.range(0, THREAD_COUNT)\n              .<Runnable>mapToObj(\n                  i ->\n                      () -> {\n                        while (inventory.addItem(new Item()))\n                          ;\n                      })\n              .forEach(executorService::execute);\n\n          // Wait until all threads have finished\n          executorService.shutdown();\n          executorService.awaitTermination(5, TimeUnit.SECONDS);\n\n          // Check the number of items in the inventory. It should not have exceeded the allowed\n          // maximum\n          final var items = inventory.getItems();\n          assertNotNull(items);\n          assertEquals(INVENTORY_SIZE, items.size());\n\n          assertEquals(INVENTORY_SIZE, appender.getLogSize());\n\n          // ... and check if the inventory size is increasing continuously\n          IntStream.range(0, items.size())\n              .mapToObj(\n                  i ->\n                      appender.log.get(i).getFormattedMessage().contains(\"items.size()=\" + (i + 1)))\n              .forEach(Assertions::assertTrue);\n        });\n  }\n\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender(Class clazz) {\n      ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n  }\n}\n"
  },
  {
    "path": "double-dispatch/README.md",
    "content": "---\ntitle: \"Double Dispatch Pattern in Java: Enhancing Polymorphic Behavior\"\nshortTitle: Double Dispatch\ndescription: \"Learn the Double Dispatch Pattern in Java with detailed implementation examples. Understand how to use this design pattern to enhance your Java applications. Read our comprehensive guide.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Decoupling\n  - Dynamic typing\n  - Polymorphism\n  - Runtime\n---\n\n## Also known as\n\n* Multi-methods\n\n## Intent of Double Dispatch Design Pattern\n\nThe Double Dispatch pattern is used to achieve dynamic polymorphism based on the types of two objects involved in a method call. It allows method behavior to be different based on the combination of the runtime types of both the object on which the method is called and the object being passed as a parameter.\n\n## Detailed Explanation of Double Dispatch Pattern with Real-World Examples\n\nReal-world example\n\n> In a logistics company, different types of delivery vehicles like trucks, drones, and bikes interact with various types of packages (fragile, oversized, standard). The Double Dispatch design pattern is used to determine the optimal delivery method: trucks might handle oversized items, drones for quick deliveries of light packages, and bikes for urban areas. Each vehicle-package combination results in a different handling and delivery strategy, dynamically determined at runtime based on the types of both the vehicle and the package.\n\nIn plain words\n\n> The Double Dispatch design pattern in Java allows a program to select a different function to execute based on the types of two objects involved in a call, enhancing flexibility in handling interactions between them.\n\nWikipedia says\n\n> In software engineering, double dispatch is a special form of multiple dispatch, and a mechanism that dispatches a function call to different concrete functions depending on the runtime types of two objects involved in the call. In most object-oriented systems, the concrete function that is called from a function call in the code depends on the dynamic type of a single object and therefore they are known as single dispatch calls, or simply virtual function calls.\n\nSequence diagram\n\n![Double Dispatch sequence diagram](./etc/double-dispatch-sequence-diagram.png)\n\n## Programmatic Example of Double Dispatch Pattern in Java\n\nThe Double Dispatch pattern in Java is used to handle collisions between different types of game objects. Each game object is an instance of a class that extends the `GameObject` abstract class. The `GameObject` class has a `collision(GameObject)` method, which is overridden in each subclass to define the behavior when a collision occurs with another game object. Here is a simplified version of the `GameObject` class and its subclasses:\n\n```java\npublic abstract class GameObject {\n  // Other properties and methods...\n\n  public abstract void collision(GameObject gameObject);\n}\n\npublic class FlamingAsteroid extends GameObject {\n  // Other properties and methods...\n\n  @Override\n  public void collision(GameObject gameObject) {\n    gameObject.collisionWithFlamingAsteroid(this);\n  }\n}\n\npublic class SpaceStationMir extends GameObject {\n  // Other properties and methods...\n\n  @Override\n  public void collision(GameObject gameObject) {\n    gameObject.collisionWithSpaceStationMir(this);\n  }\n}\n```\n\nIn the App class, the Double Dispatch pattern is used to check for collisions between all pairs of game objects:\n\n```java\npublic static void main(String[] args) {\n    // initialize game objects and print their status\n    LOGGER.info(\"Init objects and print their status\");\n    var objects = List.of(\n            new FlamingAsteroid(0, 0, 5, 5),\n            new SpaceStationMir(1, 1, 2, 2),\n            new Meteoroid(10, 10, 15, 15),\n            new SpaceStationIss(12, 12, 14, 14)\n    );\n    objects.forEach(o -> LOGGER.info(o.toString()));\n\n    // collision check\n    LOGGER.info(\"Collision check\");\n    objects.forEach(o1 -> objects.forEach(o2 -> {\n        if (o1 != o2 && o1.intersectsWith(o2)) {\n            o1.collision(o2);\n        }\n    }));\n\n    // output eventual object statuses\n    LOGGER.info(\"Print object status after collision checks\");\n    objects.forEach(o -> LOGGER.info(o.toString()));\n}\n```\n\nWhen a collision is detected between two objects, the `collision(GameObject)` method is called on the first object (o1) with the second object (o2) as the argument. This method call is dispatched at runtime to the appropriate `collision(GameObject)` method in the class of o1. Inside this method, another method call `gameObject.collisionWithX(this)` is made on o2 (where X is the type of o1), which is dispatched at runtime to the appropriate `collisionWithX(GameObject)` method in the class of o2. This is the \"double dispatch\" in Java - two method calls are dispatched at runtime based on the types of two objects.\n\nHere is the program output:\n\n```\n15:47:23.763 [main] INFO com.iluwatar.doubledispatch.App -- Init objects and print their status\n15:47:23.772 [main] INFO com.iluwatar.doubledispatch.App -- FlamingAsteroid at [0,0,5,5] damaged=false onFire=true\n15:47:23.772 [main] INFO com.iluwatar.doubledispatch.App -- SpaceStationMir at [1,1,2,2] damaged=false onFire=false\n15:47:23.772 [main] INFO com.iluwatar.doubledispatch.App -- Meteoroid at [10,10,15,15] damaged=false onFire=false\n15:47:23.772 [main] INFO com.iluwatar.doubledispatch.App -- SpaceStationIss at [12,12,14,14] damaged=false onFire=false\n15:47:23.772 [main] INFO com.iluwatar.doubledispatch.App -- Collision check\n15:47:23.772 [main] INFO com.iluwatar.doubledispatch.SpaceStationMir -- FlamingAsteroid hits SpaceStationMir. SpaceStationMir is damaged! SpaceStationMir is set on fire!\n15:47:23.773 [main] INFO com.iluwatar.doubledispatch.Meteoroid -- SpaceStationMir hits FlamingAsteroid.\n15:47:23.773 [main] INFO com.iluwatar.doubledispatch.SpaceStationMir --  {} is damaged! hits Meteoroid.\n15:47:23.773 [main] INFO com.iluwatar.doubledispatch.Meteoroid -- SpaceStationIss hits Meteoroid.\n15:47:23.773 [main] INFO com.iluwatar.doubledispatch.App -- Print object status after collision checks\n15:47:23.773 [main] INFO com.iluwatar.doubledispatch.App -- FlamingAsteroid at [0,0,5,5] damaged=false onFire=true\n15:47:23.773 [main] INFO com.iluwatar.doubledispatch.App -- SpaceStationMir at [1,1,2,2] damaged=true onFire=true\n15:47:23.773 [main] INFO com.iluwatar.doubledispatch.App -- Meteoroid at [10,10,15,15] damaged=false onFire=false\n15:47:23.773 [main] INFO com.iluwatar.doubledispatch.App -- SpaceStationIss at [12,12,14,14] damaged=true onFire=false\n```\n\n## When to Use the Double Dispatch Pattern in Java\n\n* When the behavior of a method needs to vary not just based on the object it is called on, but also based on the type of the argument.\n* In scenarios where if-else or switch-case type checks against the type of objects are cumbersome and not scalable.\n* When implementing operations in domain classes without contaminating their code with complex decision-making logic about other domain classes.\n\n## Real-World Applications of Double Dispatch Pattern in Java\n\n* Graphical user interfaces where different actions are taken based on different types of mouse events interacting with different types of elements.\n* Simulation systems where interactions between different types of objects need to trigger distinct behaviors.\n\n## Benefits and Trade-offs of Double Dispatch Pattern\n\nBenefits:\n\n* Increases the flexibility of code by handling interaction between objects in a manner that is easy to understand and maintain.\n* Helps in adhering to the [Open/Closed Principle](https://java-design-patterns.com/principles/#open-closed-principle) by allowing new classes to be introduced without modifying existing classes.\n\nTrade-offs:\n\n* Can lead to more complex code structures, especially in languages like Java that do not support this pattern natively.\n* May require additional effort in maintaining and extending as new classes are added.\n\n## Related Java Design Patterns\n\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Similar in intent where it's used to choose an algorithm at runtime, though Strategy focuses on single object context rather than interactions between multiple objects.\n* [Visitor](https://java-design-patterns.com/patterns/visitor/): Often used together with Double Dispatch to encapsulate operations performed on a set of element objects.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/4awj7cV)\n* [Java Design Pattern Essentials](https://amzn.to/3Jg8ZZV)\n* [Refactoring to Patterns](https://amzn.to/3vRBJ8k)\n"
  },
  {
    "path": "double-dispatch/etc/double-dispatch.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.SpaceStationIss\" project=\"double-dispatch\" \n    file=\"/double-dispatch/src/main/java/com/iluwatar/SpaceStationIss.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"84\" y=\"1111\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.FlamingAsteroid\" project=\"double-dispatch\" \n    file=\"/double-dispatch/src/main/java/com/iluwatar/FlamingAsteroid.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"372\" y=\"1111\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.SpaceStationMir\" project=\"double-dispatch\" \n    file=\"/double-dispatch/src/main/java/com/iluwatar/SpaceStationMir.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"84\" y=\"929\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.Meteoroid\" project=\"double-dispatch\" \n    file=\"/double-dispatch/src/main/java/com/iluwatar/Meteoroid.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"372\" y=\"929\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.Rectangle\" project=\"double-dispatch\" \n    file=\"/double-dispatch/src/main/java/com/iluwatar/Rectangle.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"254\" y=\"323\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.GameObject\" project=\"double-dispatch\" \n    file=\"/double-dispatch/src/main/java/com/iluwatar/GameObject.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"255\" y=\"648\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <generalization id=\"7\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </generalization>  \n  <generalization id=\"8\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </generalization>  \n  <generalization id=\"9\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </generalization>  \n  <generalization id=\"10\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </generalization>  \n  <generalization id=\"11\">    \n    <end type=\"SOURCE\" refId=\"6\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </generalization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "double-dispatch/etc/double-dispatch.urm.puml",
    "content": "@startuml\npackage com.iluwatar.doubledispatch.constants {\n  class AppConstants {\n    + HITS : String {static}\n    + AppConstants()\n  }\n}\npackage com.iluwatar.doubledispatch {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class FlamingAsteroid {\n    + FlamingAsteroid(left : int, top : int, right : int, bottom : int)\n    + collision(gameObject : GameObject)\n  }\n  abstract class GameObject {\n    - damaged : boolean\n    - onFire : boolean\n    + GameObject(left : int, top : int, right : int, bottom : int)\n    + collision(GameObject) {abstract}\n    + collisionResolve(FlamingAsteroid) {abstract}\n    + collisionResolve(Meteoroid) {abstract}\n    + collisionResolve(SpaceStationIss) {abstract}\n    + collisionResolve(SpaceStationMir) {abstract}\n    + isDamaged() : boolean\n    + isOnFire() : boolean\n    + setDamaged(damaged : boolean)\n    + setOnFire(onFire : boolean)\n    + toString() : String\n  }\n  class Meteoroid {\n    - LOGGER : Logger {static}\n    + Meteoroid(left : int, top : int, right : int, bottom : int)\n    + collision(gameObject : GameObject)\n    + collisionResolve(asteroid : FlamingAsteroid)\n    + collisionResolve(iss : SpaceStationIss)\n    + collisionResolve(meteoroid : Meteoroid)\n    + collisionResolve(mir : SpaceStationMir)\n  }\n  class Rectangle {\n    - bottom : int\n    - left : int\n    - right : int\n    - top : int\n    + Rectangle(left : int, top : int, right : int, bottom : int)\n    + getBottom() : int\n    + getLeft() : int\n    + getRight() : int\n    + getTop() : int\n    ~ intersectsWith(r : Rectangle) : boolean\n    + toString() : String\n  }\n  class SpaceStationIss {\n    + SpaceStationIss(left : int, top : int, right : int, bottom : int)\n    + collision(gameObject : GameObject)\n  }\n  class SpaceStationMir {\n    - LOGGER : Logger {static}\n    + SpaceStationMir(left : int, top : int, right : int, bottom : int)\n    + collision(gameObject : GameObject)\n    + collisionResolve(asteroid : FlamingAsteroid)\n    + collisionResolve(iss : SpaceStationIss)\n    + collisionResolve(meteoroid : Meteoroid)\n    + collisionResolve(mir : SpaceStationMir)\n  }\n}\nFlamingAsteroid --|> Meteoroid \nGameObject --|> Rectangle \nMeteoroid --|> GameObject \nSpaceStationIss --|> SpaceStationMir \nSpaceStationMir --|> GameObject \n@enduml"
  },
  {
    "path": "double-dispatch/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>double-dispatch</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.doubledispatch.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "double-dispatch/src/main/java/com/iluwatar/doubledispatch/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * When a message with a parameter is sent to an object, the resultant behaviour is defined by the\n * implementation of that method in the receiver. Sometimes the behaviour must also be determined by\n * the type of the parameter.\n *\n * <p>One way to implement this would be to create multiple instanceof-checks for the methods\n * parameter. However, this creates a maintenance issue. When new types are added we would also need\n * to change the method's implementation and add a new instanceof-check. This violates the single\n * responsibility principle - a class should have only one reason to change.\n *\n * <p>Instead of the instanceof-checks a better way is to make another virtual call on the parameter\n * object. This way new functionality can be easily added without the need to modify existing\n * implementation (open-closed principle).\n *\n * <p>In this example we have hierarchy of objects ({@link GameObject}) that can collide to each\n * other. Each object has its own coordinates which are checked against the other objects'\n * coordinates. If there is an overlap, then the objects collide utilizing the Double Dispatch\n * pattern.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    // initialize game objects and print their status\n    LOGGER.info(\"Init objects and print their status\");\n    var objects =\n        List.of(\n            new FlamingAsteroid(0, 0, 5, 5),\n            new SpaceStationMir(1, 1, 2, 2),\n            new Meteoroid(10, 10, 15, 15),\n            new SpaceStationIss(12, 12, 14, 14));\n    objects.forEach(o -> LOGGER.info(o.toString()));\n\n    // collision check\n    LOGGER.info(\"Collision check\");\n    objects.forEach(\n        o1 ->\n            objects.forEach(\n                o2 -> {\n                  if (o1 != o2 && o1.intersectsWith(o2)) {\n                    o1.collision(o2);\n                  }\n                }));\n\n    // output eventual object statuses\n    LOGGER.info(\"Print object status after collision checks\");\n    objects.forEach(o -> LOGGER.info(o.toString()));\n  }\n}\n"
  },
  {
    "path": "double-dispatch/src/main/java/com/iluwatar/doubledispatch/FlamingAsteroid.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\n/** Flaming asteroid game object. */\npublic class FlamingAsteroid extends Meteoroid {\n\n  public FlamingAsteroid(int left, int top, int right, int bottom) {\n    super(left, top, right, bottom);\n    setOnFire(true);\n  }\n\n  @Override\n  public void collision(GameObject gameObject) {\n    gameObject.collisionResolve(this);\n  }\n}\n"
  },
  {
    "path": "double-dispatch/src/main/java/com/iluwatar/doubledispatch/GameObject.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Game objects have coordinates and some other status information. */\n@Getter\n@Setter\npublic abstract class GameObject extends Rectangle {\n\n  private boolean damaged;\n  private boolean onFire;\n\n  public GameObject(int left, int top, int right, int bottom) {\n    super(left, top, right, bottom);\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\n        \"%s at %s damaged=%b onFire=%b\",\n        this.getClass().getSimpleName(), super.toString(), isDamaged(), isOnFire());\n  }\n\n  public abstract void collision(GameObject gameObject);\n\n  public abstract void collisionResolve(FlamingAsteroid asteroid);\n\n  public abstract void collisionResolve(Meteoroid meteoroid);\n\n  public abstract void collisionResolve(SpaceStationMir mir);\n\n  public abstract void collisionResolve(SpaceStationIss iss);\n}\n"
  },
  {
    "path": "double-dispatch/src/main/java/com/iluwatar/doubledispatch/Meteoroid.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\nimport com.iluwatar.doubledispatch.constants.AppConstants;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Meteoroid game object. */\n@Slf4j\npublic class Meteoroid extends GameObject {\n\n  public Meteoroid(int left, int top, int right, int bottom) {\n    super(left, top, right, bottom);\n  }\n\n  @Override\n  public void collision(GameObject gameObject) {\n    gameObject.collisionResolve(this);\n  }\n\n  @Override\n  public void collisionResolve(FlamingAsteroid asteroid) {\n    LOGGER.info(\n        AppConstants.HITS, asteroid.getClass().getSimpleName(), this.getClass().getSimpleName());\n  }\n\n  @Override\n  public void collisionResolve(Meteoroid meteoroid) {\n    LOGGER.info(\n        AppConstants.HITS, meteoroid.getClass().getSimpleName(), this.getClass().getSimpleName());\n  }\n\n  @Override\n  public void collisionResolve(SpaceStationMir mir) {\n    LOGGER.info(AppConstants.HITS, mir.getClass().getSimpleName(), this.getClass().getSimpleName());\n  }\n\n  @Override\n  public void collisionResolve(SpaceStationIss iss) {\n    LOGGER.info(AppConstants.HITS, iss.getClass().getSimpleName(), this.getClass().getSimpleName());\n  }\n}\n"
  },
  {
    "path": "double-dispatch/src/main/java/com/iluwatar/doubledispatch/Rectangle.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/** Rectangle has coordinates and can be checked for overlap against other Rectangles. */\n@Getter\n@RequiredArgsConstructor\npublic class Rectangle {\n\n  private final int left;\n  private final int top;\n  private final int right;\n  private final int bottom;\n\n  boolean intersectsWith(Rectangle r) {\n    return !(r.getLeft() > getRight()\n        || r.getRight() < getLeft()\n        || r.getTop() > getBottom()\n        || r.getBottom() < getTop());\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\"[%d,%d,%d,%d]\", getLeft(), getTop(), getRight(), getBottom());\n  }\n}\n"
  },
  {
    "path": "double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationIss.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\n/** Space station ISS game object. */\npublic class SpaceStationIss extends SpaceStationMir {\n\n  public SpaceStationIss(int left, int top, int right, int bottom) {\n    super(left, top, right, bottom);\n  }\n\n  @Override\n  public void collision(GameObject gameObject) {\n    gameObject.collisionResolve(this);\n  }\n}\n"
  },
  {
    "path": "double-dispatch/src/main/java/com/iluwatar/doubledispatch/SpaceStationMir.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\nimport com.iluwatar.doubledispatch.constants.AppConstants;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Space station Mir game object. */\n@Slf4j\npublic class SpaceStationMir extends GameObject {\n\n  public SpaceStationMir(int left, int top, int right, int bottom) {\n    super(left, top, right, bottom);\n  }\n\n  @Override\n  public void collision(GameObject gameObject) {\n    gameObject.collisionResolve(this);\n  }\n\n  @Override\n  public void collisionResolve(FlamingAsteroid asteroid) {\n    LOGGER.info(\n        AppConstants.HITS + \" {} is damaged! {} is set on fire!\",\n        asteroid.getClass().getSimpleName(),\n        this.getClass().getSimpleName(),\n        this.getClass().getSimpleName(),\n        this.getClass().getSimpleName());\n    setDamaged(true);\n    setOnFire(true);\n  }\n\n  @Override\n  public void collisionResolve(Meteoroid meteoroid) {\n    logHits(meteoroid);\n    setDamaged(true);\n  }\n\n  @Override\n  public void collisionResolve(SpaceStationMir mir) {\n    logHits(mir);\n    setDamaged(true);\n  }\n\n  @Override\n  public void collisionResolve(SpaceStationIss iss) {\n    logHits(iss);\n    setDamaged(true);\n  }\n\n  private void logHits(GameObject gameObject) {\n    LOGGER.info(\n        AppConstants.HITS,\n        \" {} is damaged!\",\n        gameObject.getClass().getSimpleName(),\n        this.getClass().getSimpleName(),\n        this.getClass().getSimpleName());\n  }\n}\n"
  },
  {
    "path": "double-dispatch/src/main/java/com/iluwatar/doubledispatch/constants/AppConstants.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch.constants;\n\n/** Constants class to define all constants. */\npublic class AppConstants {\n\n  public static final String HITS = \"{} hits {}.\";\n}\n"
  },
  {
    "path": "double-dispatch/src/test/java/com/iluwatar/doubledispatch/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "double-dispatch/src/test/java/com/iluwatar/doubledispatch/CollisionTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.Objects;\n\n/**\n * CollisionTest\n *\n * @param <O> Type of GameObject\n */\npublic abstract class CollisionTest<O extends GameObject> {\n\n  /**\n   * Get the tested object\n   *\n   * @return The tested object, should never return 'null'\n   */\n  abstract O getTestedObject();\n\n  /**\n   * Collide the tested item with the other given item and verify if the damage and fire state is as\n   * expected\n   *\n   * @param other The other object we have to collide with\n   * @param otherDamaged Indicates if the other object should be damaged after the collision\n   * @param otherOnFire Indicates if the other object should be burning after the collision\n   * @param thisDamaged Indicates if the test object should be damaged after the collision\n   * @param thisOnFire Indicates if the other object should be burning after the collision\n   */\n  void testCollision(\n      final GameObject other,\n      final boolean otherDamaged,\n      final boolean otherOnFire,\n      final boolean thisDamaged,\n      final boolean thisOnFire) {\n\n    Objects.requireNonNull(other);\n    Objects.requireNonNull(getTestedObject());\n\n    final var tested = getTestedObject();\n\n    tested.collision(other);\n\n    testOnFire(other, tested, otherOnFire);\n    testDamaged(other, tested, otherDamaged);\n\n    testOnFire(tested, other, thisOnFire);\n    testDamaged(tested, other, thisDamaged);\n  }\n\n  /**\n   * Test if the fire state of the target matches the expected state after colliding with the given\n   * object\n   *\n   * @param target The target object\n   * @param other The other object\n   * @param expectTargetOnFire The expected state of fire on the target object\n   */\n  private void testOnFire(\n      final GameObject target, final GameObject other, final boolean expectTargetOnFire) {\n    final var targetName = target.getClass().getSimpleName();\n    final var otherName = other.getClass().getSimpleName();\n\n    final var errorMessage =\n        expectTargetOnFire\n            ? \"Expected [\"\n                + targetName\n                + \"] to be on fire after colliding with [\"\n                + otherName\n                + \"] but it was not!\"\n            : \"Expected [\"\n                + targetName\n                + \"] not to be on fire after colliding with [\"\n                + otherName\n                + \"] but it was!\";\n\n    assertEquals(expectTargetOnFire, target.isOnFire(), errorMessage);\n  }\n\n  /**\n   * Test if the damage state of the target matches the expected state after colliding with the\n   * given object\n   *\n   * @param target The target object\n   * @param other The other object\n   * @param expectedDamage The expected state of damage on the target object\n   */\n  private void testDamaged(\n      final GameObject target, final GameObject other, final boolean expectedDamage) {\n    final var targetName = target.getClass().getSimpleName();\n    final var otherName = other.getClass().getSimpleName();\n\n    final var errorMessage =\n        expectedDamage\n            ? \"Expected [\"\n                + targetName\n                + \"] to be damaged after colliding with [\"\n                + otherName\n                + \"] but it was not!\"\n            : \"Expected [\"\n                + targetName\n                + \"] not to be damaged after colliding with [\"\n                + otherName\n                + \"] but it was!\";\n\n    assertEquals(expectedDamage, target.isDamaged(), errorMessage);\n  }\n}\n"
  },
  {
    "path": "double-dispatch/src/test/java/com/iluwatar/doubledispatch/FlamingAsteroidTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** FlamingAsteroidTest */\nclass FlamingAsteroidTest extends CollisionTest<FlamingAsteroid> {\n\n  @Override\n  final FlamingAsteroid getTestedObject() {\n    return new FlamingAsteroid(1, 2, 3, 4);\n  }\n\n  /** Test the constructor parameters */\n  @Test\n  void testConstructor() {\n    final var asteroid = new FlamingAsteroid(1, 2, 3, 4);\n    assertEquals(1, asteroid.getLeft());\n    assertEquals(2, asteroid.getTop());\n    assertEquals(3, asteroid.getRight());\n    assertEquals(4, asteroid.getBottom());\n    assertTrue(asteroid.isOnFire());\n    assertFalse(asteroid.isDamaged());\n    assertEquals(\"FlamingAsteroid at [1,2,3,4] damaged=false onFire=true\", asteroid.toString());\n  }\n\n  /** Test what happens we collide with an asteroid */\n  @Test\n  void testCollideFlamingAsteroid() {\n    testCollision(new FlamingAsteroid(1, 2, 3, 4), false, true, false, true);\n  }\n\n  /** Test what happens we collide with an meteoroid */\n  @Test\n  void testCollideMeteoroid() {\n    testCollision(new Meteoroid(1, 1, 3, 4), false, false, false, true);\n  }\n\n  /** Test what happens we collide with ISS */\n  @Test\n  void testCollideSpaceStationIss() {\n    testCollision(new SpaceStationIss(1, 1, 3, 4), true, true, false, true);\n  }\n\n  /** Test what happens we collide with MIR */\n  @Test\n  void testCollideSpaceStationMir() {\n    testCollision(new SpaceStationMir(1, 1, 3, 4), true, true, false, true);\n  }\n}\n"
  },
  {
    "path": "double-dispatch/src/test/java/com/iluwatar/doubledispatch/MeteoroidTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\nimport org.junit.jupiter.api.Test;\n\n/** MeteoroidTest */\nclass MeteoroidTest extends CollisionTest<Meteoroid> {\n\n  @Override\n  final Meteoroid getTestedObject() {\n    return new Meteoroid(1, 2, 3, 4);\n  }\n\n  /** Test the constructor parameters */\n  @Test\n  void testConstructor() {\n    final var meteoroid = new Meteoroid(1, 2, 3, 4);\n    assertEquals(1, meteoroid.getLeft());\n    assertEquals(2, meteoroid.getTop());\n    assertEquals(3, meteoroid.getRight());\n    assertEquals(4, meteoroid.getBottom());\n    assertFalse(meteoroid.isOnFire());\n    assertFalse(meteoroid.isDamaged());\n    assertEquals(\"Meteoroid at [1,2,3,4] damaged=false onFire=false\", meteoroid.toString());\n  }\n\n  /** Test what happens we collide with an asteroid */\n  @Test\n  void testCollideFlamingAsteroid() {\n    testCollision(new FlamingAsteroid(1, 1, 3, 4), false, true, false, false);\n  }\n\n  /** Test what happens we collide with an meteoroid */\n  @Test\n  void testCollideMeteoroid() {\n    testCollision(new Meteoroid(1, 1, 3, 4), false, false, false, false);\n  }\n\n  /** Test what happens we collide with ISS */\n  @Test\n  void testCollideSpaceStationIss() {\n    testCollision(new SpaceStationIss(1, 1, 3, 4), true, false, false, false);\n  }\n\n  /** Test what happens we collide with MIR */\n  @Test\n  void testCollideSpaceStationMir() {\n    testCollision(new SpaceStationMir(1, 1, 3, 4), true, false, false, false);\n  }\n}\n"
  },
  {
    "path": "double-dispatch/src/test/java/com/iluwatar/doubledispatch/RectangleTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** Unit test for Rectangle */\nclass RectangleTest {\n\n  /**\n   * Test if the values passed through the constructor matches the values fetched from the getters\n   */\n  @Test\n  void testConstructor() {\n    final var rectangle = new Rectangle(1, 2, 3, 4);\n    assertEquals(1, rectangle.getLeft());\n    assertEquals(2, rectangle.getTop());\n    assertEquals(3, rectangle.getRight());\n    assertEquals(4, rectangle.getBottom());\n  }\n\n  /**\n   * Test if the values passed through the constructor matches the values in the {@link #toString()}\n   */\n  @Test\n  void testToString() {\n    final var rectangle = new Rectangle(1, 2, 3, 4);\n    assertEquals(\"[1,2,3,4]\", rectangle.toString());\n  }\n\n  /** Test if the {@link Rectangle} class can detect if it intersects with another rectangle. */\n  @Test\n  void testIntersection() {\n    assertTrue(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(0, 0, 1, 1)));\n    assertTrue(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(-1, -5, 7, 8)));\n    assertFalse(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(2, 2, 3, 3)));\n    assertFalse(new Rectangle(0, 0, 1, 1).intersectsWith(new Rectangle(-2, -2, -1, -1)));\n  }\n}\n"
  },
  {
    "path": "double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationIssTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\nimport org.junit.jupiter.api.Test;\n\n/** SpaceStationIssTest */\nclass SpaceStationIssTest extends CollisionTest<SpaceStationIss> {\n\n  @Override\n  final SpaceStationIss getTestedObject() {\n    return new SpaceStationIss(1, 2, 3, 4);\n  }\n\n  /** Test the constructor parameters */\n  @Test\n  void testConstructor() {\n    final var iss = new SpaceStationIss(1, 2, 3, 4);\n    assertEquals(1, iss.getLeft());\n    assertEquals(2, iss.getTop());\n    assertEquals(3, iss.getRight());\n    assertEquals(4, iss.getBottom());\n    assertFalse(iss.isOnFire());\n    assertFalse(iss.isDamaged());\n    assertEquals(\"SpaceStationIss at [1,2,3,4] damaged=false onFire=false\", iss.toString());\n  }\n\n  /** Test what happens we collide with an asteroid */\n  @Test\n  void testCollideFlamingAsteroid() {\n    testCollision(new FlamingAsteroid(1, 1, 3, 4), false, true, false, false);\n  }\n\n  /** Test what happens we collide with an meteoroid */\n  @Test\n  void testCollideMeteoroid() {\n    testCollision(new Meteoroid(1, 1, 3, 4), false, false, false, false);\n  }\n\n  /** Test what happens we collide with ISS */\n  @Test\n  void testCollideSpaceStationIss() {\n    testCollision(new SpaceStationIss(1, 1, 3, 4), true, false, false, false);\n  }\n\n  /** Test what happens we collide with MIR */\n  @Test\n  void testCollideSpaceStationMir() {\n    testCollision(new SpaceStationMir(1, 1, 3, 4), true, false, false, false);\n  }\n}\n"
  },
  {
    "path": "double-dispatch/src/test/java/com/iluwatar/doubledispatch/SpaceStationMirTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.doubledispatch;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\nimport org.junit.jupiter.api.Test;\n\n/** SpaceStationMirTest */\nclass SpaceStationMirTest extends CollisionTest<SpaceStationMir> {\n\n  @Override\n  final SpaceStationMir getTestedObject() {\n    return new SpaceStationMir(1, 2, 3, 4);\n  }\n\n  /** Test the constructor parameters */\n  @Test\n  void testConstructor() {\n    final var mir = new SpaceStationMir(1, 2, 3, 4);\n    assertEquals(1, mir.getLeft());\n    assertEquals(2, mir.getTop());\n    assertEquals(3, mir.getRight());\n    assertEquals(4, mir.getBottom());\n    assertFalse(mir.isOnFire());\n    assertFalse(mir.isDamaged());\n    assertEquals(\"SpaceStationMir at [1,2,3,4] damaged=false onFire=false\", mir.toString());\n  }\n\n  /** Test what happens we collide with an asteroid */\n  @Test\n  void testCollideFlamingAsteroid() {\n    testCollision(new FlamingAsteroid(1, 1, 3, 4), false, true, false, false);\n  }\n\n  /** Test what happens we collide with an meteoroid */\n  @Test\n  void testCollideMeteoroid() {\n    testCollision(new Meteoroid(1, 1, 3, 4), false, false, false, false);\n  }\n\n  /** Test what happens we collide with ISS */\n  @Test\n  void testCollideSpaceStationIss() {\n    testCollision(new SpaceStationIss(1, 1, 3, 4), true, false, false, false);\n  }\n\n  /** Test what happens we collide with MIR */\n  @Test\n  void testCollideSpaceStationMir() {\n    testCollision(new SpaceStationMir(1, 1, 3, 4), true, false, false, false);\n  }\n}\n"
  },
  {
    "path": "dynamic-proxy/README.md",
    "content": "---\ntitle: \"Dynamic Proxy Pattern in Java: Facilitating Seamless Object Interception\"\nshortTitle: Dynamic Proxy\ndescription: \"Explore the Dynamic Proxy Pattern in Java, a flexible runtime mechanism for creating proxies that enhance functionality and control access to objects. Learn through real-world examples and detailed explanations.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Decoupling\n  - Dynamic typing\n  - Enhancement\n  - Extensibility\n  - Proxy\n  - Runtime\n---\n\n## Also known as\n\n* Runtime Proxy\n\n## Intent of Dynamic Proxy Design Pattern\n\nTo provide a flexible proxy mechanism capable of dynamically creating proxies for various interfaces at runtime, allowing for controlled access or functionality enhancement of objects.\n\n## Detailed Explanation of Dynamic Proxy Pattern with Real-World Examples\n\nReal-world example\n\n> Mockito, a popular Java mocking framework, employs dynamic proxy to create mock objects for testing. Mock objects mimic the behavior of real objects, allowing developers to isolate components and verify interactions in unit tests. Consider a scenario where a service class depends on an external component, such as a database access object (DAO). Instead of interacting with a real DAO in a test, Mockito can dynamically generate a proxy, intercepting method invocations and returning predefined values. This enables focused unit testing without the need for a real database connection.\n\nIn plain words\n\n> The Dynamic Proxy Pattern in Java is a specialized form of proxy, serving as a flexible and dynamic method to intercept and manipulate method calls. By utilizing dynamic proxies, developers can implement additional functionalities without modifying the original class code. This is particularly useful in scenarios requiring enhancement of existing functionalities.\n\nWikipedia says\n\n> A dynamic proxy class is a class that implements a list of interfaces specified at runtime such that a method invocation through one of the interfaces on an instance of the class will be encoded and dispatched to another object through a uniform interface. Thus, a dynamic proxy class can be used to create a type-safe proxy object for a list of interfaces without requiring pre-generation of the proxy class, such as with compile-time tools. Method invocations on an instance of a dynamic proxy class are dispatched to a single method in the instance's invocation handler, and they are encoded with a _java.lang.reflect.Method_ object identifying the method that was invoked and an array of type _Object_ containing the arguments.\n\nSequence diagram\n\n![Dynamic Proxy sequence diagram](./etc/dynamic-proxy-sequence-diagram.png)\n\n## Programmatic Example of Dynamic Proxy Pattern in Java\n\nThis example demonstrates using the Dynamic Proxy pattern in Java to hit the public fake API [JSONPlaceholder](https://jsonplaceholder.typicode.com) for the resource `Album` through an interface. \n\nIn this demo, the Dynamic Proxy pattern helps us run business logic through an interface without explicitly implementing that interface, leveraging Java Reflection.\n\nThe `App` class sets up the dynamic proxy for the `AlbumService` interface and demonstrates how to use the proxy to make API calls.\n\n```java\n@Slf4j\npublic class App {\n\n    static final String REST_API_URL = \"https://jsonplaceholder.typicode.com\";\n    private AlbumService albumServiceProxy;\n\n    public static void main(String[] args) {\n        App app = new App();\n        app.createDynamicProxy();\n        app.callMethods();\n    }\n\n    public void createDynamicProxy() {\n        AlbumInvocationHandler handler = new AlbumInvocationHandler(REST_API_URL, HttpClient.newHttpClient());\n        albumServiceProxy = (AlbumService) Proxy.newProxyInstance(\n                App.class.getClassLoader(), new Class<?>[]{AlbumService.class}, handler);\n    }\n\n    public void callMethods() {\n        var albums = albumServiceProxy.readAlbums();\n        albums.forEach(album -> LOGGER.info(\"{}\", album));\n\n        var album = albumServiceProxy.readAlbum(17);\n        LOGGER.info(\"{}\", album);\n\n        var newAlbum = albumServiceProxy.createAlbum(Album.builder().title(\"Big World\").userId(3).build());\n        LOGGER.info(\"{}\", newAlbum);\n\n        var editAlbum = albumServiceProxy.updateAlbum(17, Album.builder().title(\"Green Valley\").userId(3).build());\n        LOGGER.info(\"{}\", editAlbum);\n\n        var removedAlbum = albumServiceProxy.deleteAlbum(17);\n        LOGGER.info(\"{}\", removedAlbum);\n    }\n}\n```\n\n* The `createDynamicProxy` method uses `Proxy.newProxyInstance` to create a new dynamic proxy for the `AlbumService` interface.\n* The `callMethods` method demonstrates using the dynamic proxy to make various API calls.\n\nThe `AlbumService` interface defines the API operations that can be dynamically proxied. It uses custom annotations to specify HTTP methods and paths.\n\n```java\npublic interface AlbumService {\n    @Get(\"/albums\")\n    List<Album> readAlbums();\n\n    @Get(\"/albums/{albumId}\")\n    Album readAlbum(@Path(\"albumId\") Integer albumId);\n\n    @Post(\"/albums\")\n    Album createAlbum(@Body Album album);\n\n    @Put(\"/albums/{albumId}\")\n    Album updateAlbum(@Path(\"albumId\") Integer albumId, @Body Album album);\n\n    @Delete(\"/albums/{albumId}\")\n    Album deleteAlbum(@Path(\"albumId\") Integer albumId);\n}\n```\n\n* Annotations like `@Get` and `@Post` indicate the HTTP method and the path for each method.\n* These annotations are used by the `TinyRestClient` to construct appropriate HTTP requests.\n\nThe `AlbumInvocationHandler` class is where method calls on the proxy are intercepted and delegated to the `TinyRestClient`.\n\n```java\n@Slf4j\npublic class AlbumInvocationHandler implements InvocationHandler {\n\n    private TinyRestClient restClient;\n\n    public AlbumInvocationHandler(String baseUrl, HttpClient httpClient) {\n        this.restClient = new TinyRestClient(baseUrl, httpClient);\n    }\n\n    @Override\n    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n        LOGGER.info(\"===== Calling the method {}.{}()\",\n                method.getDeclaringClass().getSimpleName(), method.getName());\n        return restClient.send(method, args);\n    }\n}\n```\n\n* Implements `InvocationHandler`, which requires defining the `invoke` method.\n* The `invoke` method is called every time a method on the proxy is invoked. It delegates the call to the `TinyRestClient`, passing along the method and its arguments.\n\nThe `TinyRestClient` handles the construction and sending of HTTP requests based on the annotations and method details.\n\n```java\n@Slf4j\npublic class TinyRestClient {\n    private String baseUrl;\n    private HttpClient httpClient;\n\n    public TinyRestClient(String baseUrl, HttpClient httpClient) {\n        this.baseUrl = baseUrl;\n        this.httpClient = httpClient;\n    }\n\n    public Object send(Method method, Object[] args) throws IOException, InterruptedException {\n        var url = baseUrl + buildUrl(method, args);\n        var httpRequest = HttpRequest.newBuilder().uri(URI.create(url)).build();\n        var httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());\n        return getResponse(method, httpResponse);\n    }\n\n    private String buildUrl(Method method, Object[] args) {\n        // Simplified URL building logic\n        return \"/albums\";\n    }\n\n    private Object getResponse(Method method, HttpResponse<String> httpResponse) {\n        // Simplified response handling logic\n        return httpResponse.body();\n    }\n}\n```\n\n* This class uses Java's `HttpClient` to send HTTP requests.\n* The `send` method constructs a `HttpRequest` using details from the method's annotations, although simplified here to focus on the dynamic proxy mechanism.\n* The response is returned as a simple string, demonstrating basic interaction with an API.\n\nRunning the example produces the following console output showcasing the API calls and responses. See the `App` class and `main` method above.\n\n```\n16:05:41.964 [main] INFO com.iluwatar.dynamicproxy.AlbumInvocationHandler -- ===== Calling the method AlbumService.readAlbums()\n16:05:42.409 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=1, title=quidem molestiae enim, userId=1)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=2, title=sunt qui excepturi placeat culpa, userId=1)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=3, title=omnis laborum odio, userId=1)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=4, title=non esse culpa molestiae omnis sed optio, userId=1)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=5, title=eaque aut omnis a, userId=1)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=6, title=natus impedit quibusdam illo est, userId=1)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=7, title=quibusdam autem aliquid et et quia, userId=1)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=8, title=qui fuga est a eum, userId=1)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=9, title=saepe unde necessitatibus rem, userId=1)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=10, title=distinctio laborum qui, userId=1)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=11, title=quam nostrum impedit mollitia quod et dolor, userId=2)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=12, title=consequatur autem doloribus natus consectetur, userId=2)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=13, title=ab rerum non rerum consequatur ut ea unde, userId=2)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=14, title=ducimus molestias eos animi atque nihil, userId=2)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=15, title=ut pariatur rerum ipsum natus repellendus praesentium, userId=2)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=16, title=voluptatem aut maxime inventore autem magnam atque repellat, userId=2)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=17, title=aut minima voluptatem ut velit, userId=2)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=18, title=nesciunt quia et doloremque, userId=2)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=19, title=velit pariatur quaerat similique libero omnis quia, userId=2)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=20, title=voluptas rerum iure ut enim, userId=2)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=21, title=repudiandae voluptatem optio est consequatur rem in temporibus et, userId=3)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=22, title=et rem non provident vel ut, userId=3)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=23, title=incidunt quisquam hic adipisci sequi, userId=3)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=24, title=dolores ut et facere placeat, userId=3)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=25, title=vero maxime id possimus sunt neque et consequatur, userId=3)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=26, title=quibusdam saepe ipsa vel harum, userId=3)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=27, title=id non nostrum expedita, userId=3)\n16:05:42.410 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=28, title=omnis neque exercitationem sed dolor atque maxime aut cum, userId=3)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=29, title=inventore ut quasi magnam itaque est fugit, userId=3)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=30, title=tempora assumenda et similique odit distinctio error, userId=3)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=31, title=adipisci laborum fuga laboriosam, userId=4)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=32, title=reiciendis dolores a ut qui debitis non quo labore, userId=4)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=33, title=iste eos nostrum, userId=4)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=34, title=cumque voluptatibus rerum architecto blanditiis, userId=4)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=35, title=et impedit nisi quae magni necessitatibus sed aut pariatur, userId=4)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=36, title=nihil cupiditate voluptate neque, userId=4)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=37, title=est placeat dicta ut nisi rerum iste, userId=4)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=38, title=unde a sequi id, userId=4)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=39, title=ratione porro illum labore eum aperiam sed, userId=4)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=40, title=voluptas neque et sint aut quo odit, userId=4)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=41, title=ea voluptates maiores eos accusantium officiis tempore mollitia consequatur, userId=5)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=42, title=tenetur explicabo ea, userId=5)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=43, title=aperiam doloremque nihil, userId=5)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=44, title=sapiente cum numquam officia consequatur vel natus quos suscipit, userId=5)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=45, title=tenetur quos ea unde est enim corrupti qui, userId=5)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=46, title=molestiae voluptate non, userId=5)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=47, title=temporibus molestiae aut, userId=5)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=48, title=modi consequatur culpa aut quam soluta alias perspiciatis laudantium, userId=5)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=49, title=ut aut vero repudiandae voluptas ullam voluptas at consequatur, userId=5)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=50, title=sed qui sed quas sit ducimus dolor, userId=5)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=51, title=odit laboriosam sint quia cupiditate animi quis, userId=6)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=52, title=necessitatibus quas et sunt at voluptatem, userId=6)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=53, title=est vel sequi voluptatem nemo quam molestiae modi enim, userId=6)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=54, title=aut non illo amet perferendis, userId=6)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=55, title=qui culpa itaque omnis in nesciunt architecto error, userId=6)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=56, title=omnis qui maiores tempora officiis omnis rerum sed repellat, userId=6)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=57, title=libero excepturi voluptatem est architecto quae voluptatum officia tempora, userId=6)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=58, title=nulla illo consequatur aspernatur veritatis aut error delectus et, userId=6)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=59, title=eligendi similique provident nihil, userId=6)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=60, title=omnis mollitia sunt aliquid eum consequatur fugit minus laudantium, userId=6)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=61, title=delectus iusto et, userId=7)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=62, title=eos ea non recusandae iste ut quasi, userId=7)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=63, title=velit est quam, userId=7)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=64, title=autem voluptatem amet iure quae, userId=7)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=65, title=voluptates delectus iure iste qui, userId=7)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=66, title=velit sed quia dolor dolores delectus, userId=7)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=67, title=ad voluptas nostrum et nihil, userId=7)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=68, title=qui quasi nihil aut voluptatum sit dolore minima, userId=7)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=69, title=qui aut est, userId=7)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=70, title=et deleniti unde, userId=7)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=71, title=et vel corporis, userId=8)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=72, title=unde exercitationem ut, userId=8)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=73, title=quos omnis officia, userId=8)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=74, title=quia est eius vitae dolor, userId=8)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=75, title=aut quia expedita non, userId=8)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=76, title=dolorem magnam facere itaque ut reprehenderit tenetur corrupti, userId=8)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=77, title=cupiditate sapiente maiores iusto ducimus cum excepturi veritatis quia, userId=8)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=78, title=est minima eius possimus ea ratione velit et, userId=8)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=79, title=ipsa quae voluptas natus ut suscipit soluta quia quidem, userId=8)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=80, title=id nihil reprehenderit, userId=8)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=81, title=quibusdam sapiente et, userId=9)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=82, title=recusandae consequatur vel amet unde, userId=9)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=83, title=aperiam odio fugiat, userId=9)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=84, title=est et at eos expedita, userId=9)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=85, title=qui voluptatem consequatur aut ab quis temporibus praesentium, userId=9)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=86, title=eligendi mollitia alias aspernatur vel ut iusto, userId=9)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=87, title=aut aut architecto, userId=9)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=88, title=quas perspiciatis optio, userId=9)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=89, title=sit optio id voluptatem est eum et, userId=9)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=90, title=est vel dignissimos, userId=9)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=91, title=repellendus praesentium debitis officiis, userId=10)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=92, title=incidunt et et eligendi assumenda soluta quia recusandae, userId=10)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=93, title=nisi qui dolores perspiciatis, userId=10)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=94, title=quisquam a dolores et earum vitae, userId=10)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=95, title=consectetur vel rerum qui aperiam modi eos aspernatur ipsa, userId=10)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=96, title=unde et ut molestiae est molestias voluptatem sint, userId=10)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=97, title=est quod aut, userId=10)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=98, title=omnis quia possimus nesciunt deleniti assumenda sed autem, userId=10)\n16:05:42.411 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=99, title=consectetur ut id impedit dolores sit ad ex aut, userId=10)\n16:05:42.412 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=100, title=enim repellat iste, userId=10)\n16:05:42.412 [main] INFO com.iluwatar.dynamicproxy.AlbumInvocationHandler -- ===== Calling the method AlbumService.readAlbum()\n16:05:42.741 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=17, title=aut minima voluptatem ut velit, userId=2)\n16:05:42.741 [main] INFO com.iluwatar.dynamicproxy.AlbumInvocationHandler -- ===== Calling the method AlbumService.createAlbum()\n16:05:43.073 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=101, title=Big World, userId=3)\n16:05:43.073 [main] INFO com.iluwatar.dynamicproxy.AlbumInvocationHandler -- ===== Calling the method AlbumService.updateAlbum()\n16:05:43.220 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=17, title=Green Valley, userId=3)\n16:05:43.220 [main] INFO com.iluwatar.dynamicproxy.AlbumInvocationHandler -- ===== Calling the method AlbumService.deleteAlbum()\n16:05:43.357 [main] INFO com.iluwatar.dynamicproxy.App -- Album(id=null, title=null, userId=null)\n```\n\n## When to Use the Dynamic Proxy Pattern in Java\n\nDynamic proxy should be used when you need to augment or enhance your current functionality without modifying your current code. Some examples of that usage could be:\n\n* You want to intercept calls to methods of an object at runtime for handling purposes such as logging, transaction management, or security checks.\n* You need to create a proxy object for one or more interfaces dynamically at runtime without coding it explicitly for each interface.\n* You aim to simplify complex systems by decoupling the client and the real object through a flexible proxy mechanism.\n\n## Dynamic Proxy Pattern Java Tutorials\n\n* [Dynamic Proxies in Java (CodeGym)](https://codegym.cc/groups/posts/208-dynamic-proxies)\n* [Introduction To Java Dynamic Proxy (Xperti)](https://xperti.io/blogs/java-dynamic-proxies-introduction/)\n* [Dynamic Proxies in Java (Baeldung)](https://www.baeldung.com/java-dynamic-proxies)\n* [Intro To Java Dynamic Proxies (KapreSoft)](https://www.kapresoft.com/java/2023/12/27/intro-to-java-proxies.html)\n* [Exploring the Depths of Dynamic Proxy in Java: A Comprehensive Guide (Medium)](https://naveen-metta.medium.com/exploring-the-depths-of-dynamic-proxy-in-java-a-comprehensive-guide-f34fb45b38a3)\n\n## Real-World Applications of Dynamic Proxy Pattern in Java\n\nMany frameworks and libraries use dynamic proxy to implement their functionalities:\n\n* Java's `java.lang.reflect.Proxy` class is a built-in dynamic proxy mechanism.\n* [Spring Framework](https://docs.spring.io/spring-framework/reference/core/aop.html), for aspect oriented programming.\n* [Hibernate](https://hibernate.org/orm/), for data lazy loading.\n* [Mockito](https://site.mockito.org/), for mocking objects in testing.\n* [Cleverclient](https://github.com/sashirestela/cleverclient), for calling http endpoints through annotated interfaces.\n* Java Reflection API: Java's built-in support for dynamic proxies with the use of java.lang.reflect.Proxy and java.lang.reflect.InvocationHandler.\n* Frameworks: Extensively used in Java frameworks like Spring for AOP (Aspect-Oriented Programming) to handle transactions, security, logging, etc.\n* Middleware: In middleware services for transparently adding services like load balancing and access control.\n\n## Benefits and Trade-offs of Dynamic Proxy Pattern\n\nBenefits:\n\n* Increased flexibility in code: Dynamic proxies in Java offer a high degree of flexibility, allowing developers to create versatile and adaptable applications. By using dynamic proxies, software engineers can modify the behavior of methods at runtime, which is particularly useful in scenarios where the behavior of classes needs to be augmented or manipulated without altering their source code. This flexibility is crucial in developing applications that require dynamic response to varying conditions or need to integrate with systems where interfaces may change over time.\n* Simplifying complex operations: Dynamic proxies excel in simplifying complex operations, particularly in the areas of cross-cutting concerns such as logging, transaction management, and security. By intercepting method calls, dynamic proxies can uniformly apply certain operations across various methods and classes, thereby reducing the need for repetitive code. This capability is particularly beneficial in large-scale applications where such cross-cutting concerns are prevalent. For example, adding logging or authorization checks across multiple methods becomes a matter of implementing these features once in an invocation handler, rather than modifying each method individually.\n* Enhancing code maintainability: Maintainability is a key advantage of using dynamic proxies. They promote cleaner and more organized code by separating the core business logic from cross-cutting concerns. This separation of concerns not only makes the codebase more understandable but also easier to test and debug. When the business logic is decoupled from aspects like logging or transaction handling, any changes in these areas do not impact the core functionality of the application. As a result, applications become more robust and easier to maintain and update, which is crucial in the fast-paced environment of software development where requirements and technologies are constantly evolving.\n* Separation of Concerns: Promotes separation of concerns by decoupling the client code from the actual handling of method calls.\n\nTrade-offs:\n\n* Performance overhead: The use of reflection and method invocation through proxies can introduce latency, especially in performance-critical applications. This overhead might be negligible in most cases, but it becomes significant in scenarios with high-frequency method calls.\n* Complexity of debugging: Since dynamic proxies introduce an additional layer of abstraction, tracing and debugging issues can be more challenging. It can be difficult to trace the flow of execution through proxies, especially when multiple proxies are involved.\n* Limited to interface-based programming: They can only proxy interfaces, not classes. This limitation requires careful design considerations, particularly in situations where class-based proxies would be more appropriate.\n* Higher level of expertise: Developers are normally not a fan of “magic code” — code that works in a non-transparent or overly complex manner. Those unfamiliar with the proxy pattern or reflection might find the codebase more complex to understand and maintain, potentially leading to errors or misuse of the feature. This complexity can be perceived as a form of “magic” that obscures the underlying process, making the code less intuitive and more challenging to debug or extend. Therefore, while dynamic proxies are powerful, their use should be approached with caution and a thorough understanding of their inner workings.\n\n## Related Java Design Patterns\n\n* [Proxy](https://java-design-patterns.com/patterns/proxy): Static counterpart of the Dynamic Proxy, where proxies are explicitly coded.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Similar in structure by providing additional functionality, but without the dynamic proxy's capability to handle any interface.\n* [Facade](https://java-design-patterns.com/patterns/facade/): Simplifies the interface to complex systems, not through dynamic proxies but through a single simplified interface.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3U0d8Gm)\n* [Java Reflection in Action](https://amzn.to/3TVpe3t)\n* [Pro Spring 6: An In-Depth Guide to the Spring Framework](https://amzn.to/43Zs2Bx)\n* [Dynamic Proxy Classes - Oracle](https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html)\n"
  },
  {
    "path": "dynamic-proxy/etc/dynamic-proxy.urm.puml",
    "content": "@startuml\npackage com.iluwatar.dynamicproxy.tinyrestclient.annotation {\n  interface Body {\n  }\n  interface Delete {\n    + value() : String {abstract}\n  }\n  interface Get {\n    + value() : String {abstract}\n  }\n  interface HttpMethod {\n  }\n  interface Path {\n    + value() : String {abstract}\n  }\n  interface Post {\n    + value() : String {abstract}\n  }\n  interface Put {\n    + value() : String {abstract}\n  }\n}\npackage com.iluwatar.dynamicproxy.tinyrestclient {\n  class JsonUtil {\n    - objectMapper : ObjectMapper {static}\n    - JsonUtil()\n    + jsonToList(json : String, clazz : Class<T>) : List<T> {static}\n    + jsonToObject(json : String, clazz : Class<T>) : T {static}\n    + objectToJson(object : T) : String {static}\n  }\n  class TinyRestClient {\n    - baseUrl : String\n    + TinyRestClient(baseUrl : String)\n    - annotationValue(annotation : Annotation) : String\n    - buildBodyPublisher(method : Method, args : Object[]) : BodyPublisher\n    - buildUrl(method : Method, args : Object[], httpMethodAnnotation : Annotation) : String\n    - getAnnotationOf(annotations : Annotation[], clazz : Class<?>) : Annotation\n    - getHttpMethodAnnotation(annotations : Annotation[]) : Annotation\n    - getResponse(method : Method, httpResponse : HttpResponse<String>) : Object\n    + send(method : Method, args : Object[]) : Object\n  }\n}\npackage com.iluwatar.dynamicproxy {\n  class Album {\n    - id : Integer\n    - title : String\n    - userId : Integer\n    + Album()\n    + Album(id : Integer, title : String, userId : Integer)\n    + builder() : AlbumBuilder {static}\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getId() : Integer\n    + getTitle() : String\n    + getUserId() : Integer\n    + hashCode() : int\n    + setId(id : Integer)\n    + setTitle(title : String)\n    + setUserId(userId : Integer)\n    + toString() : String\n  }\n  class AlbumBuilder {\n    - id : Integer\n    - title : String\n    - userId : Integer\n    ~ AlbumBuilder()\n    + build() : Album\n    + id(id : Integer) : AlbumBuilder\n    + title(title : String) : AlbumBuilder\n    + toString() : String\n    + userId(userId : Integer) : AlbumBuilder\n  }\n  class AlbumInvocationHandler {\n    - restClient : TinyRestClient\n    + AlbumInvocationHandler(baseUrl : String)\n    + invoke(proxy : Object, method : Method, args : Object[]) : Object\n  }\n  interface AlbumService {\n    + createAlbum(Album) : Album {abstract}\n    + deleteAlbum(Integer) : Album {abstract}\n    + readAlbum(Integer) : Album {abstract}\n    + readAlbums() : List<Album> {abstract}\n    + updateAlbum(Integer, Album) : Album {abstract}\n  }\n  class App {\n    ~ REST_API_URL : String {static}\n    - albumServiceProxy : AlbumService\n    + App()\n    + callMethods()\n    + createDynamicProxy()\n    + main(args : String[]) {static}\n  }\n}\nAlbumInvocationHandler -->  \"-restClient\" TinyRestClient\nApp -->  \"-albumServiceProxy\" AlbumService\n@enduml"
  },
  {
    "path": "dynamic-proxy/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>dynamic-proxy</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n        <groupId>com.fasterxml.jackson.core</groupId>\n        <artifactId>jackson-core</artifactId>\n        <version>2.19.0</version>\n    </dependency>\n    <dependency>\n      <groupId>com.fasterxml.jackson.core</groupId>\n      <artifactId>jackson-databind</artifactId>\n      <version>2.18.3</version>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework</groupId>\n      <artifactId>spring-web</artifactId>\n      <version>7.0.0-M4</version>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.dynamicproxy.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/Album.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * This class represents an endpoint resource that we are going to interchange with a Rest API\n * server.\n */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor(force = true)\n@Builder\npublic class Album {\n\n  private Integer id;\n  private String title;\n  private Integer userId;\n}\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/AlbumInvocationHandler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy;\n\nimport com.iluwatar.dynamicproxy.tinyrestclient.TinyRestClient;\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\nimport java.net.http.HttpClient;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Class whose method 'invoke' will be called every time that an interface's method is called. That\n * interface is linked to this class by the Proxy class.\n */\n@Slf4j\npublic class AlbumInvocationHandler implements InvocationHandler {\n\n  private TinyRestClient restClient;\n\n  /**\n   * Class constructor. It instantiates a TinyRestClient object.\n   *\n   * @param baseUrl Root url for endpoints.\n   * @param httpClient Handle the http communication.\n   */\n  public AlbumInvocationHandler(String baseUrl, HttpClient httpClient) {\n    this.restClient = new TinyRestClient(baseUrl, httpClient);\n  }\n\n  @Override\n  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n\n    LOGGER.info(\n        \"===== Calling the method {}.{}()\",\n        method.getDeclaringClass().getSimpleName(),\n        method.getName());\n\n    return restClient.send(method, args);\n  }\n}\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/AlbumService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy;\n\nimport com.iluwatar.dynamicproxy.tinyrestclient.annotation.Body;\nimport com.iluwatar.dynamicproxy.tinyrestclient.annotation.Delete;\nimport com.iluwatar.dynamicproxy.tinyrestclient.annotation.Get;\nimport com.iluwatar.dynamicproxy.tinyrestclient.annotation.Path;\nimport com.iluwatar.dynamicproxy.tinyrestclient.annotation.Post;\nimport com.iluwatar.dynamicproxy.tinyrestclient.annotation.Put;\nimport java.util.List;\n\n/**\n * Every method in this interface is annotated with the necessary metadata to represents an endpoint\n * that we can call to communicate with a host server which is serving a resource by Rest API. This\n * interface is focused in the resource Album.\n */\npublic interface AlbumService {\n\n  /**\n   * Get a list of albums from an endpoint.\n   *\n   * @return List of albums' data.\n   */\n  @Get(\"/albums\")\n  List<Album> readAlbums();\n\n  /**\n   * Get a specific album from an endpoint.\n   *\n   * @param albumId Album's id to search for.\n   * @return Album's data.\n   */\n  @Get(\"/albums/{albumId}\")\n  Album readAlbum(@Path(\"albumId\") Integer albumId);\n\n  /**\n   * Creates a new album.\n   *\n   * @param album Album's data to be created.\n   * @return New album's data.\n   */\n  @Post(\"/albums\")\n  Album createAlbum(@Body Album album);\n\n  /**\n   * Updates an existing album.\n   *\n   * @param albumId Album's id to be modified.\n   * @param album New album's data.\n   * @return Updated album's data.\n   */\n  @Put(\"/albums/{albumId}\")\n  Album updateAlbum(@Path(\"albumId\") Integer albumId, @Body Album album);\n\n  /**\n   * Deletes an album.\n   *\n   * @param albumId Album's id to be deleted.\n   * @return Empty album.\n   */\n  @Delete(\"/albums/{albumId}\")\n  Album deleteAlbum(@Path(\"albumId\") Integer albumId);\n}\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy;\n\nimport java.lang.reflect.Proxy;\nimport java.net.http.HttpClient;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Application to demonstrate the Dynamic Proxy pattern. This application allow us to hit the public\n * fake API https://jsonplaceholder.typicode.com for the resource Album through an interface. The\n * call to Proxy.newProxyInstance creates a new dynamic proxy for the AlbumService interface and\n * sets the AlbumInvocationHandler class as the handler to intercept all the interface's methods.\n * Everytime that we call an AlbumService's method, the handler's method \"invoke\" will be call\n * automatically, and it will pass all the method's metadata and arguments to other specialized\n * class - TinyRestClient - to prepare the Rest API call accordingly. In this demo, the Dynamic\n * Proxy pattern help us to run business logic through interfaces without an explicit implementation\n * of the interfaces and supported on the Java Reflection approach.\n */\n@Slf4j\npublic class App {\n\n  static final String REST_API_URL = \"https://jsonplaceholder.typicode.com\";\n\n  private String baseUrl;\n  private HttpClient httpClient;\n  private AlbumService albumServiceProxy;\n\n  /**\n   * Class constructor.\n   *\n   * @param baseUrl Root url for endpoints.\n   * @param httpClient Handle the http communication.\n   */\n  public App(String baseUrl, HttpClient httpClient) {\n    this.baseUrl = baseUrl;\n    this.httpClient = httpClient;\n  }\n\n  /**\n   * Application entry point.\n   *\n   * @param args External arguments to be passed. Optional.\n   */\n  public static void main(String[] args) {\n    App app = new App(App.REST_API_URL, HttpClient.newHttpClient());\n    app.createDynamicProxy();\n    app.callMethods();\n  }\n\n  /**\n   * Create the Dynamic Proxy linked to the AlbumService interface and to the\n   * AlbumInvocationHandler.\n   */\n  public void createDynamicProxy() {\n    AlbumInvocationHandler albumInvocationHandler = new AlbumInvocationHandler(baseUrl, httpClient);\n\n    albumServiceProxy =\n        (AlbumService)\n            Proxy.newProxyInstance(\n                App.class.getClassLoader(),\n                new Class<?>[] {AlbumService.class},\n                albumInvocationHandler);\n  }\n\n  /**\n   * Call the methods of the Dynamic Proxy, in other words, the AlbumService interface's methods and\n   * receive the responses from the Rest API.\n   */\n  public void callMethods() {\n    int albumId = 17;\n    int userId = 3;\n\n    var albums = albumServiceProxy.readAlbums();\n    albums.forEach(album -> LOGGER.info(\"{}\", album));\n\n    var album = albumServiceProxy.readAlbum(albumId);\n    LOGGER.info(\"{}\", album);\n\n    var newAlbum =\n        albumServiceProxy.createAlbum(Album.builder().title(\"Big World\").userId(userId).build());\n    LOGGER.info(\"{}\", newAlbum);\n\n    var editAlbum =\n        albumServiceProxy.updateAlbum(\n            albumId, Album.builder().title(\"Green Valley\").userId(userId).build());\n    LOGGER.info(\"{}\", editAlbum);\n\n    var removedAlbum = albumServiceProxy.deleteAlbum(albumId);\n    LOGGER.info(\"{}\", removedAlbum);\n  }\n}\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/tinyrestclient/JsonUtil.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy.tinyrestclient;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.type.CollectionType;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Utility class to handle Json operations. */\n@Slf4j\npublic class JsonUtil {\n\n  private static ObjectMapper objectMapper = new ObjectMapper();\n\n  private JsonUtil() {}\n\n  /**\n   * Convert an object to a Json string representation.\n   *\n   * @param object Object to convert.\n   * @param <T> Object's class.\n   * @return Json string.\n   */\n  public static <T> String objectToJson(T object) {\n    try {\n      return objectMapper.writeValueAsString(object);\n    } catch (JsonProcessingException e) {\n      LOGGER.error(\"Cannot convert the object \" + object + \" to Json.\", e);\n      return null;\n    }\n  }\n\n  /**\n   * Convert a Json string to an object of a class.\n   *\n   * @param json Json string to convert.\n   * @param clazz Object's class.\n   * @param <T> Object's generic class.\n   * @return Object.\n   */\n  public static <T> T jsonToObject(String json, Class<T> clazz) {\n    try {\n      return objectMapper.readValue(json, clazz);\n    } catch (IOException e) {\n      LOGGER.error(\"Cannot convert the Json \" + json + \" to class \" + clazz.getName() + \".\", e);\n      return null;\n    }\n  }\n\n  /**\n   * Convert a Json string to a List of objects of a class.\n   *\n   * @param json Json string to convert.\n   * @param clazz Object's class.\n   * @param <T> Object's generic class.\n   * @return List of objects.\n   */\n  public static <T> List<T> jsonToList(String json, Class<T> clazz) {\n    try {\n      CollectionType listType =\n          objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, clazz);\n      return objectMapper.reader().forType(listType).readValue(json);\n    } catch (JsonProcessingException e) {\n      LOGGER.error(\"Cannot convert the Json \" + json + \" to List of \" + clazz.getName() + \".\", e);\n      return List.of();\n    }\n  }\n}\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/tinyrestclient/TinyRestClient.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy.tinyrestclient;\n\nimport com.iluwatar.dynamicproxy.tinyrestclient.annotation.Body;\nimport com.iluwatar.dynamicproxy.tinyrestclient.annotation.Http;\nimport com.iluwatar.dynamicproxy.tinyrestclient.annotation.Path;\nimport java.io.IOException;\nimport java.lang.annotation.Annotation;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.ParameterizedType;\nimport java.lang.reflect.Type;\nimport java.net.HttpURLConnection;\nimport java.net.URI;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.web.util.UriUtils;\n\n/**\n * Class to handle all the http communication with a Rest API. It is supported by the HttpClient\n * Java library.\n */\n@Slf4j\npublic class TinyRestClient {\n\n  private static Map<Method, Annotation> httpAnnotationByMethod = new HashMap<>();\n\n  private String baseUrl;\n  private HttpClient httpClient;\n\n  /**\n   * Class constructor.\n   *\n   * @param baseUrl Root url for endpoints.\n   * @param httpClient Handle the http communication.\n   */\n  public TinyRestClient(String baseUrl, HttpClient httpClient) {\n    this.baseUrl = baseUrl;\n    this.httpClient = httpClient;\n  }\n\n  /**\n   * Creates a http communication to request and receive data from an endpoint.\n   *\n   * @param method Interface's method which is annotated with a http method.\n   * @param args Method's arguments passed in the call.\n   * @return Response from the endpoint.\n   * @throws IOException Exception thrown when any fail happens in the call.\n   * @throws InterruptedException Exception thrown when call is interrupted.\n   */\n  public Object send(Method method, Object[] args) throws IOException, InterruptedException {\n    var httpAnnotation = getHttpAnnotation(method);\n    if (httpAnnotation == null) {\n      return null;\n    }\n    var httpAnnotationName = httpAnnotation.annotationType().getSimpleName().toUpperCase();\n    var url = baseUrl + buildUrl(method, args, httpAnnotation);\n    var bodyPublisher = buildBodyPublisher(method, args);\n    var httpRequest =\n        HttpRequest.newBuilder()\n            .uri(URI.create(url))\n            .header(\"Content-Type\", \"application/json\")\n            .method(httpAnnotationName, bodyPublisher)\n            .build();\n    var httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());\n    var statusCode = httpResponse.statusCode();\n    if (statusCode >= HttpURLConnection.HTTP_BAD_REQUEST) {\n      var errorDetail = httpResponse.body();\n      LOGGER.error(\"Error from server: \" + errorDetail);\n      return null;\n    }\n    return getResponse(method, httpResponse);\n  }\n\n  private String buildUrl(Method method, Object[] args, Annotation httpMethodAnnotation) {\n    var url = annotationValue(httpMethodAnnotation);\n    if (url == null) {\n      return \"\";\n    }\n    var index = 0;\n    for (var parameter : method.getParameters()) {\n      var pathAnnotation = getAnnotationOf(parameter.getDeclaredAnnotations(), Path.class);\n      if (pathAnnotation != null) {\n        var pathParam = \"{\" + annotationValue(pathAnnotation) + \"}\";\n        var pathValue = UriUtils.encodePath(args[index].toString(), StandardCharsets.UTF_8);\n        url = url.replace(pathParam, pathValue);\n      }\n      index++;\n    }\n    return url;\n  }\n\n  private HttpRequest.BodyPublisher buildBodyPublisher(Method method, Object[] args) {\n    var index = 0;\n    for (var parameter : method.getParameters()) {\n      var bodyAnnotation = getAnnotationOf(parameter.getDeclaredAnnotations(), Body.class);\n      if (bodyAnnotation != null) {\n        var body = JsonUtil.objectToJson(args[index]);\n        return HttpRequest.BodyPublishers.ofString(body);\n      }\n      index++;\n    }\n    return HttpRequest.BodyPublishers.noBody();\n  }\n\n  private Object getResponse(Method method, HttpResponse<String> httpResponse) {\n    var rawData = httpResponse.body();\n    Type returnType;\n    try {\n      returnType = method.getGenericReturnType();\n    } catch (Exception e) {\n      LOGGER.error(\"Cannot get the generic return type of the method \" + method.getName() + \"()\");\n      return null;\n    }\n    if (returnType instanceof ParameterizedType) {\n      Class<?> responseClass =\n          (Class<?>) (((ParameterizedType) returnType).getActualTypeArguments()[0]);\n      return JsonUtil.jsonToList(rawData, responseClass);\n    } else {\n      Class<?> responseClass = method.getReturnType();\n      return JsonUtil.jsonToObject(rawData, responseClass);\n    }\n  }\n\n  private Annotation getHttpAnnotation(Method method) {\n    return httpAnnotationByMethod.computeIfAbsent(\n        method,\n        m ->\n            Arrays.stream(m.getDeclaredAnnotations())\n                .filter(annot -> annot.annotationType().isAnnotationPresent(Http.class))\n                .findFirst()\n                .orElse(null));\n  }\n\n  private Annotation getAnnotationOf(Annotation[] annotations, Class<?> clazz) {\n    return Arrays.stream(annotations)\n        .filter(annot -> annot.annotationType().equals(clazz))\n        .findFirst()\n        .orElse(null);\n  }\n\n  private String annotationValue(Annotation annotation) {\n    var valueMethod =\n        Arrays.stream(annotation.annotationType().getDeclaredMethods())\n            .filter(methodAnnot -> methodAnnot.getName().equals(\"value\"))\n            .findFirst()\n            .orElse(null);\n    if (valueMethod == null) {\n      return null;\n    }\n    Object result;\n    try {\n      result = valueMethod.invoke(annotation, (Object[]) null);\n    } catch (Exception e) {\n      LOGGER.error(\n          \"Cannot read the value \"\n              + annotation.annotationType().getSimpleName()\n              + \".\"\n              + valueMethod.getName()\n              + \"()\",\n          e);\n      result = null;\n    }\n    return (result instanceof String strResult ? strResult : null);\n  }\n}\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/tinyrestclient/annotation/Body.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy.tinyrestclient.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * Annotation to mark a method's parameter as a Body parameter. It is typically used on Post and Put\n * http methods.\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.PARAMETER)\npublic @interface Body {}\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/tinyrestclient/annotation/Delete.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy.tinyrestclient.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/** Annotation to mark an interface's method as a DELETE http method. */\n@Http\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.METHOD)\npublic @interface Delete {\n  /**\n   * Set the url for this http method.\n   *\n   * @return Url address.\n   */\n  String value() default \"\";\n}\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/tinyrestclient/annotation/Get.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy.tinyrestclient.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/** Annotation to mark an interface's method as a GET http method. */\n@Http\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.METHOD)\npublic @interface Get {\n  /**\n   * Set the url for this http method.\n   *\n   * @return Url address.\n   */\n  String value() default \"\";\n}\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/tinyrestclient/annotation/Http.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy.tinyrestclient.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/** Annotation to mark other annotations to be recognized as http methods. */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.ANNOTATION_TYPE)\npublic @interface Http {}\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/tinyrestclient/annotation/Path.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy.tinyrestclient.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/** Annotation to mark a method's parameter as a Path parameter. */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.PARAMETER)\npublic @interface Path {\n  /**\n   * Path parameter to be replaced in the url.\n   *\n   * @return Path parameter.\n   */\n  String value();\n}\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/tinyrestclient/annotation/Post.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy.tinyrestclient.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/** Annotation to mark an interface's method as a POST http method. */\n@Http\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.METHOD)\npublic @interface Post {\n  /**\n   * Set the url for this http method.\n   *\n   * @return Url address.\n   */\n  String value() default \"\";\n}\n"
  },
  {
    "path": "dynamic-proxy/src/main/java/com/iluwatar/dynamicproxy/tinyrestclient/annotation/Put.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy.tinyrestclient.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/** Annotation to mark an interface's method as a PUT http method. */\n@Http\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.METHOD)\npublic @interface Put {\n  /**\n   * Set the url for this http method.\n   *\n   * @return Url address.\n   */\n  String value() default \"\";\n}\n"
  },
  {
    "path": "dynamic-proxy/src/test/java/com/iluwatar/dynamicproxy/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.dynamicproxy;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n\n  @Test\n  void shouldRunAppWithoutExceptions() {\n    assertDoesNotThrow(() -> App.main(null));\n  }\n}\n"
  },
  {
    "path": "event-aggregator/README.md",
    "content": "---\ntitle: \"Event Aggregator Pattern in Java: Centralizing Event Management in Large Applications\"\nshortTitle: Event Aggregator\ndescription: \"Explore the Event Aggregator design pattern with our in-depth guide. Learn how to implement it effectively with examples and improve your Java applications. Perfect for developers seeking to enhance their design pattern knowledge.\"\ncategory: Messaging\nlanguage: en\ntag:\n  - Decoupling\n  - Event-driven\n  - Messaging\n  - Publish/subscribe\n  - Reactive\nhead:\n  - - meta\n    - name: keywords\n      content:\n---\n\n## Also known as\n\n* Event Channel\n* Event Central\n* Message Hub\n\n## Intent of Event Aggregator Design Pattern\n\nAn Event Aggregator is a design pattern used for handling events in a system. It centralizes the event handling logic, making it easier to manage and maintain. The Event Aggregator design pattern aims to decouple event generation from event handling. This design pattern collects events from multiple sources and routes them to the appropriate handlers.\n\n## Detailed Explanation of Event Aggregator Pattern with Real-World Examples\n\nReal-world example\n\n> The Event Aggregator pattern is often compared to a hub in a wheel. In this analogy, the Event Aggregator is the hub, and the spokes are the event sources. The hub collects events from all the spokes and then distributes them to the appropriate handlers.\n\nIn Plain Words\n\n> Event Aggregator is a design pattern that allows multiple event sources to communicate with event handlers through a central point, rather than having each event source communicate directly with each handler.\n\nSequence diagram\n\n![Event Aggregator sequence diagram](./etc/event-aggregator-sequence-diagram.png)\n\n## Programmatic Example of Event Aggregator Pattern in Java\n\nConsider the following example where we use the Event Aggregator to handle multiple events.\n\nKing Joffrey sits on the iron throne and rules the seven kingdoms of Westeros. He receives most of his critical information from King's Hand, the second in command. King's hand has many close advisors himself, feeding him with relevant information about events occurring in the kingdom.\n\nIn our programmatic example, we demonstrate the implementation of an event aggregator pattern. Some of the objects are event listeners, some are event emitters, and the event aggregator does both.\n\n```java\npublic interface EventObserver {\n    void onEvent(Event e);\n}\n```\n\n```java\npublic abstract class EventEmitter {\n\n    private final Map<Event, List<EventObserver>> observerLists;\n\n    public EventEmitter() {\n        observerLists = new HashMap<>();\n    }\n\n    public final void registerObserver(EventObserver obs, Event e) {\n      // implementation omitted\n    }\n\n    protected void notifyObservers(Event e) {\n        // implementation omitted\n    }\n}\n```\n\n`KingJoffrey` is listening to events from `KingsHand`.\n\n```java\n\n@Slf4j\npublic class KingJoffrey implements EventObserver {\n    @Override\n    public void onEvent(Event e) {\n        LOGGER.info(\"Received event from the King's Hand: {}\", e.toString());\n    }\n}\n```\n\n`KingsHand` is listening to events from his subordinates `LordBaelish`, `LordVarys`, and `Scout`. Whatever he hears from them, he delivers to `KingJoffrey`.\n\n```java\npublic class KingsHand extends EventEmitter implements EventObserver {\n\n    public KingsHand() {\n    }\n\n    public KingsHand(EventObserver obs, Event e) {\n        super(obs, e);\n    }\n\n    @Override\n    public void onEvent(Event e) {\n        notifyObservers(e);\n    }\n}\n```\n\nFor example, `LordVarys` finds a traitor every Sunday and notifies the `KingsHand`.\n\n```java\n\n@Slf4j\npublic class LordVarys extends EventEmitter implements EventObserver {\n    @Override\n    public void timePasses(Weekday day) {\n        if (day == Weekday.SATURDAY) {\n            notifyObservers(Event.TRAITOR_DETECTED);\n        }\n    }\n}\n```\n\nThe following snippet demonstrates how the objects are constructed and wired together.\n\n```java\npublic static void main(String[] args) {\n\n    var kingJoffrey = new KingJoffrey();\n\n    var kingsHand = new KingsHand();\n    kingsHand.registerObserver(kingJoffrey, Event.TRAITOR_DETECTED);\n    kingsHand.registerObserver(kingJoffrey, Event.STARK_SIGHTED);\n    kingsHand.registerObserver(kingJoffrey, Event.WARSHIPS_APPROACHING);\n    kingsHand.registerObserver(kingJoffrey, Event.WHITE_WALKERS_SIGHTED);\n\n    var varys = new LordVarys();\n    varys.registerObserver(kingsHand, Event.TRAITOR_DETECTED);\n    varys.registerObserver(kingsHand, Event.WHITE_WALKERS_SIGHTED);\n\n    var scout = new Scout();\n    scout.registerObserver(kingsHand, Event.WARSHIPS_APPROACHING);\n    scout.registerObserver(varys, Event.WHITE_WALKERS_SIGHTED);\n\n    var baelish = new LordBaelish(kingsHand, Event.STARK_SIGHTED);\n\n    var emitters = List.of(\n            kingsHand,\n            baelish,\n            varys,\n            scout\n    );\n\n    Arrays.stream(Weekday.values())\n            .<Consumer<? super EventEmitter>>map(day -> emitter -> emitter.timePasses(day))\n            .forEachOrdered(emitters::forEach);\n}\n```\n\nThe console output after running the example.\n\n```\n21:37:38.737 [main] INFO com.iluwatar.event.aggregator.KingJoffrey -- Received event from the King's Hand: Warships approaching\n21:37:38.739 [main] INFO com.iluwatar.event.aggregator.KingJoffrey -- Received event from the King's Hand: White walkers sighted\n21:37:38.739 [main] INFO com.iluwatar.event.aggregator.KingJoffrey -- Received event from the King's Hand: Stark sighted\n21:37:38.739 [main] INFO com.iluwatar.event.aggregator.KingJoffrey -- Received event from the King's Hand: Traitor detected\n```\n\n## When to Use the Event Aggregator Pattern in Java\n\nUse the Event Aggregator pattern when\n\n* You have multiple event sources and handlers.\n* You want to decouple the event generation and handling logic.\n* You need a centralized event management system.\n\n## Real-World Applications of Event Aggregator Pattern in Java\n\n* Enterprise application integrations where systems need a central point to handle events generated by various subsystems.\n* Complex GUI applications where user actions in one part of the interface need to affect other parts without tight coupling between the components.\n\n## Benefits and Trade-offs of Event Aggregator Pattern\n\nBenefits:\n\n* Decoupling: By centralizing event handling, the Event Aggregator minimizes direct interaction between components, leading to a more modular and easier-to-manage system.\n* Improves Flexibility and Scalability: Adding new publishers or subscribers involves less effort since the central aggregator handles all routing.\n* Simplifies Component Interface: Components need to know only about the Event Aggregator, not about other components.\n* Centralizes event management: Makes the system easier to maintain.\n\nTrade-offs:\n\n* Complexity of the Aggregator: The Event Aggregator itself can become a complex and high-maintenance component if not properly designed.\n* Potential Performance Bottleneck: If not scaled properly, the central event handling mechanism can become a bottleneck in the system.\n\n## Related Java Design Patterns\n\n* [Mediator](https://java-design-patterns.com/patterns/mediator/): Similar to Mediator in that it abstracts direct communications between components, but focused specifically on event messages.\n* [Observer](https://java-design-patterns.com/patterns/observer/): The Event Aggregator pattern is often implemented using the Observer pattern, where the aggregator observes events and notifies subscribers.\n* Publish-Subscribe: The Event Aggregator can be seen as a special case of the Publish-Subscribe pattern, with the aggregator acting as the broker.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/44eWKXv)\n* [Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions](https://amzn.to/440b0CZ)\n* [Java Design Pattern Essentials](https://amzn.to/43XHCgM)\n* [Event Aggregator (Martin Fowler)](http://martinfowler.com/eaaDev/EventAggregator.html)\n"
  },
  {
    "path": "event-aggregator/etc/classes.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \r\n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \r\n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.KingsHand\" project=\"event-aggregator\" \r\n    file=\"/event-aggregator/src/main/java/com/iluwatar/KingsHand.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"805\" y=\"431\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <interface id=\"2\" language=\"java\" name=\"com.iluwatar.EventObserver\" project=\"event-aggregator\" \r\n    file=\"/event-aggregator/src/main/java/com/iluwatar/EventObserver.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"784\" y=\"586\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </interface>  \r\n  <enumeration id=\"3\" language=\"java\" name=\"com.iluwatar.Weekday\" project=\"event-aggregator\" \r\n    file=\"/event-aggregator/src/main/java/com/iluwatar/Weekday.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"437\" y=\"195\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </enumeration>  \r\n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.KingJoffrey\" project=\"event-aggregator\" \r\n    file=\"/event-aggregator/src/main/java/com/iluwatar/KingJoffrey.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"380\" y=\"413\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.LordVarys\" project=\"event-aggregator\" \r\n    file=\"/event-aggregator/src/main/java/com/iluwatar/LordVarys.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"581\" y=\"422\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.LordBaelish\" project=\"event-aggregator\" \r\n    file=\"/event-aggregator/src/main/java/com/iluwatar/LordBaelish.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"1050\" y=\"422\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.EventEmitter\" project=\"event-aggregator\" \r\n    file=\"/event-aggregator/src/main/java/com/iluwatar/EventEmitter.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"1036\" y=\"149\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.Scout\" project=\"event-aggregator\" \r\n    file=\"/event-aggregator/src/main/java/com/iluwatar/Scout.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"1275\" y=\"422\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <enumeration id=\"9\" language=\"java\" name=\"com.iluwatar.Event\" project=\"event-aggregator\" \r\n    file=\"/event-aggregator/src/main/java/com/iluwatar/Event.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"721\" y=\"159\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </enumeration>  \r\n  <realization id=\"10\">    \r\n    <end type=\"SOURCE\" refId=\"1\"/>    \r\n    <end type=\"TARGET\" refId=\"2\"/>  \r\n  </realization>  \r\n  <association id=\"11\">    \r\n    <bendpoint x=\"927\" y=\"360\"/>    \r\n    <end type=\"SOURCE\" refId=\"7\" navigable=\"false\">      \r\n      <attribute id=\"12\" name=\"observers\"/>      \r\n      <multiplicity id=\"13\" minimum=\"0\" maximum=\"2147483647\"/>    \r\n    </end>    \r\n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \r\n    <display labels=\"true\" multiplicity=\"true\"/>  \r\n  </association>  \r\n  <generalization id=\"14\">    \r\n    <end type=\"SOURCE\" refId=\"1\"/>    \r\n    <end type=\"TARGET\" refId=\"7\"/>  \r\n  </generalization>  \r\n  <generalization id=\"15\">    \r\n    <end type=\"SOURCE\" refId=\"6\"/>    \r\n    <end type=\"TARGET\" refId=\"7\"/>  \r\n  </generalization>  \r\n  <realization id=\"16\">    \r\n    <end type=\"SOURCE\" refId=\"4\"/>    \r\n    <end type=\"TARGET\" refId=\"2\"/>  \r\n  </realization>  \r\n  <generalization id=\"17\">    \r\n    <end type=\"SOURCE\" refId=\"8\"/>    \r\n    <end type=\"TARGET\" refId=\"7\"/>  \r\n  </generalization>  \r\n  <generalization id=\"18\">    \r\n    <end type=\"SOURCE\" refId=\"5\"/>    \r\n    <end type=\"TARGET\" refId=\"7\"/>  \r\n  </generalization>  \r\n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \r\n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \r\n  </classifier-display>  \r\n  <association-display labels=\"true\" multiplicity=\"true\"/>\r\n</class-diagram>"
  },
  {
    "path": "event-aggregator/etc/event-aggregator.urm.puml",
    "content": "@startuml\npackage com.iluwatar.event.aggregator {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  enum Event {\n    + STARK_SIGHTED {static}\n    + TRAITOR_DETECTED {static}\n    + WARSHIPS_APPROACHING {static}\n    - description : String\n    + toString() : String\n    + valueOf(name : String) : Event {static}\n    + values() : Event[] {static}\n  }\n  abstract class EventEmitter {\n    - observers : List<EventObserver>\n    + EventEmitter()\n    + EventEmitter(obs : EventObserver)\n    # notifyObservers(e : Event)\n    + registerObserver(obs : EventObserver)\n    + timePasses(Weekday) {abstract}\n  }\n  interface EventObserver {\n    + onEvent(Event) {abstract}\n  }\n  class KingJoffrey {\n    - LOGGER : Logger {static}\n    + KingJoffrey()\n    + onEvent(e : Event)\n  }\n  class KingsHand {\n    + KingsHand()\n    + KingsHand(obs : EventObserver)\n    + onEvent(e : Event)\n    + timePasses(day : Weekday)\n  }\n  class LordBaelish {\n    + LordBaelish()\n    + LordBaelish(obs : EventObserver)\n    + timePasses(day : Weekday)\n  }\n  class LordVarys {\n    + LordVarys()\n    + LordVarys(obs : EventObserver)\n    + timePasses(day : Weekday)\n  }\n  class Scout {\n    + Scout()\n    + Scout(obs : EventObserver)\n    + timePasses(day : Weekday)\n  }\n  enum Weekday {\n    + FRIDAY {static}\n    + MONDAY {static}\n    + SATURDAY {static}\n    + SUNDAY {static}\n    + THURSDAY {static}\n    + TUESDAY {static}\n    + WEDNESDAY {static}\n    - description : String\n    + toString() : String\n    + valueOf(name : String) : Weekday {static}\n    + values() : Weekday[] {static}\n  }\n}\nEventEmitter -->  \"-observers\" EventObserver\nKingJoffrey ..|> EventObserver \nKingsHand ..|> EventObserver \nKingsHand --|> EventEmitter \nLordBaelish --|> EventEmitter \nLordVarys --|> EventEmitter \nScout --|> EventEmitter \n@enduml"
  },
  {
    "path": "event-aggregator/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>event-aggregator</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.event.aggregator.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "event-aggregator/src/main/java/com/iluwatar/event/aggregator/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.function.Consumer;\n\n/**\n * A system with lots of objects can lead to complexities when a client wants to subscribe to\n * events. The client has to find and register for each object individually, if each object has\n * multiple events then each event requires a separate subscription.\n *\n * <p>An Event Aggregator acts as a single source of events for many objects. It registers for all\n * the events of the many objects allowing clients to register with just the aggregator.\n *\n * <p>In the example {@link LordBaelish}, {@link LordVarys} and {@link Scout} deliver events to\n * {@link KingsHand}. {@link KingsHand}, the event aggregator, then delivers the events to {@link\n * KingJoffrey}.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var kingJoffrey = new KingJoffrey();\n\n    var kingsHand = new KingsHand();\n    kingsHand.registerObserver(kingJoffrey, Event.TRAITOR_DETECTED);\n    kingsHand.registerObserver(kingJoffrey, Event.STARK_SIGHTED);\n    kingsHand.registerObserver(kingJoffrey, Event.WARSHIPS_APPROACHING);\n    kingsHand.registerObserver(kingJoffrey, Event.WHITE_WALKERS_SIGHTED);\n\n    var varys = new LordVarys();\n    varys.registerObserver(kingsHand, Event.TRAITOR_DETECTED);\n    varys.registerObserver(kingsHand, Event.WHITE_WALKERS_SIGHTED);\n\n    var scout = new Scout();\n    scout.registerObserver(kingsHand, Event.WARSHIPS_APPROACHING);\n    scout.registerObserver(varys, Event.WHITE_WALKERS_SIGHTED);\n\n    var baelish = new LordBaelish(kingsHand, Event.STARK_SIGHTED);\n\n    var emitters = List.of(kingsHand, baelish, varys, scout);\n\n    Arrays.stream(Weekday.values())\n        .<Consumer<? super EventEmitter>>map(day -> emitter -> emitter.timePasses(day))\n        .forEachOrdered(emitters::forEach);\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/main/java/com/iluwatar/event/aggregator/Event.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\nimport lombok.RequiredArgsConstructor;\n\n/** Event enumeration. */\n@RequiredArgsConstructor\npublic enum Event {\n  WHITE_WALKERS_SIGHTED(\"White walkers sighted\"),\n  STARK_SIGHTED(\"Stark sighted\"),\n  WARSHIPS_APPROACHING(\"Warships approaching\"),\n  TRAITOR_DETECTED(\"Traitor detected\");\n\n  private final String description;\n\n  @Override\n  public String toString() {\n    return description;\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/main/java/com/iluwatar/event/aggregator/EventEmitter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\n/** EventEmitter is the base class for event producers that can be observed. */\npublic abstract class EventEmitter {\n\n  private final Map<Event, List<EventObserver>> observerLists;\n\n  public EventEmitter() {\n    observerLists = new HashMap<>();\n  }\n\n  public EventEmitter(EventObserver obs, Event e) {\n    this();\n    registerObserver(obs, e);\n  }\n\n  /**\n   * Registers observer for specific event in the related list.\n   *\n   * @param obs the observer that observers this emitter\n   * @param e the specific event for that observation occurs\n   */\n  public final void registerObserver(EventObserver obs, Event e) {\n    if (!observerLists.containsKey(e)) {\n      observerLists.put(e, new LinkedList<>());\n    }\n    if (!observerLists.get(e).contains(obs)) {\n      observerLists.get(e).add(obs);\n    }\n  }\n\n  protected void notifyObservers(Event e) {\n    if (observerLists.containsKey(e)) {\n      observerLists.get(e).forEach(observer -> observer.onEvent(e));\n    }\n  }\n\n  public abstract void timePasses(Weekday day);\n}\n"
  },
  {
    "path": "event-aggregator/src/main/java/com/iluwatar/event/aggregator/EventObserver.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\n/** Observers of events implement this interface. */\npublic interface EventObserver {\n\n  void onEvent(Event e);\n}\n"
  },
  {
    "path": "event-aggregator/src/main/java/com/iluwatar/event/aggregator/KingJoffrey.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** KingJoffrey observes events from {@link KingsHand}. */\n@Slf4j\npublic class KingJoffrey implements EventObserver {\n\n  @Override\n  public void onEvent(Event e) {\n    LOGGER.info(\"Received event from the King's Hand: {}\", e.toString());\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/main/java/com/iluwatar/event/aggregator/KingsHand.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\n/** KingsHand observes events from multiple sources and delivers them to listeners. */\npublic class KingsHand extends EventEmitter implements EventObserver {\n\n  public KingsHand() {}\n\n  public KingsHand(EventObserver obs, Event e) {\n    super(obs, e);\n  }\n\n  @Override\n  public void onEvent(Event e) {\n    notifyObservers(e);\n  }\n\n  @Override\n  public void timePasses(Weekday day) {\n    // This method is intentionally left empty because KingsHand does not handle time-based events\n    // directly.\n    // It serves as a placeholder to fulfill the EventObserver interface contract.\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/main/java/com/iluwatar/event/aggregator/LordBaelish.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\n/** LordBaelish produces events. */\npublic class LordBaelish extends EventEmitter {\n\n  public LordBaelish() {}\n\n  public LordBaelish(EventObserver obs, Event e) {\n    super(obs, e);\n  }\n\n  @Override\n  public void timePasses(Weekday day) {\n    if (day == Weekday.FRIDAY) {\n      notifyObservers(Event.STARK_SIGHTED);\n    }\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/main/java/com/iluwatar/event/aggregator/LordVarys.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** LordVarys produces events. */\n@Slf4j\npublic class LordVarys extends EventEmitter implements EventObserver {\n\n  public LordVarys() {}\n\n  public LordVarys(EventObserver obs, Event e) {\n    super(obs, e);\n  }\n\n  @Override\n  public void timePasses(Weekday day) {\n    if (day == Weekday.SATURDAY) {\n      notifyObservers(Event.TRAITOR_DETECTED);\n    }\n  }\n\n  @Override\n  public void onEvent(Event e) {\n    notifyObservers(e);\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/main/java/com/iluwatar/event/aggregator/Scout.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\n/** Scout produces events. */\npublic class Scout extends EventEmitter {\n\n  public Scout() {}\n\n  public Scout(EventObserver obs, Event e) {\n    super(obs, e);\n  }\n\n  @Override\n  public void timePasses(Weekday day) {\n    if (day == Weekday.TUESDAY) {\n      notifyObservers(Event.WARSHIPS_APPROACHING);\n    }\n    if (day == Weekday.WEDNESDAY) {\n      notifyObservers(Event.WHITE_WALKERS_SIGHTED);\n    }\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/main/java/com/iluwatar/event/aggregator/Weekday.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\nimport lombok.RequiredArgsConstructor;\n\n/** Weekday enumeration. */\n@RequiredArgsConstructor\npublic enum Weekday {\n  MONDAY(\"Monday\"),\n  TUESDAY(\"Tuesday\"),\n  WEDNESDAY(\"Wednesday\"),\n  THURSDAY(\"Thursday\"),\n  FRIDAY(\"Friday\"),\n  SATURDAY(\"Saturday\"),\n  SUNDAY(\"Sunday\");\n\n  private final String description;\n\n  @Override\n  public String toString() {\n    return description;\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/test/java/com/iluwatar/event/aggregator/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventEmitterTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport java.util.Objects;\nimport java.util.function.BiFunction;\nimport java.util.function.Supplier;\nimport org.junit.jupiter.api.Test;\n\n/**\n * Tests for Event Emitter\n *\n * @param <E> Type of Event Emitter\n */\nabstract class EventEmitterTest<E extends EventEmitter> {\n\n  /** Factory used to create a new instance of the test object with a default observer */\n  private final BiFunction<EventObserver, Event, E> factoryWithDefaultObserver;\n\n  /** Factory used to create a new instance of the test object without passing a default observer */\n  private final Supplier<E> factoryWithoutDefaultObserver;\n\n  /** The day of the week an event is expected */\n  private final Weekday specialDay;\n\n  /** The expected event, emitted on the special day */\n  private final Event event;\n\n  /**\n   * Create a new event emitter test, using the given test object factories, special day and event\n   */\n  EventEmitterTest(\n      final Weekday specialDay,\n      final Event event,\n      final BiFunction<EventObserver, Event, E> factoryWithDefaultObserver,\n      final Supplier<E> factoryWithoutDefaultObserver) {\n\n    this.specialDay = specialDay;\n    this.event = event;\n    this.factoryWithDefaultObserver = Objects.requireNonNull(factoryWithDefaultObserver);\n    this.factoryWithoutDefaultObserver = Objects.requireNonNull(factoryWithoutDefaultObserver);\n  }\n\n  /**\n   * Go over every day of the month, and check if the event is emitted on the given day. This test\n   * is executed twice, once without a default emitter and once with\n   */\n  @Test\n  void testAllDays() {\n    testAllDaysWithoutDefaultObserver(specialDay, event);\n    testAllDaysWithDefaultObserver(specialDay, event);\n  }\n\n  /**\n   * Pass each week of the day, day by day to the event emitter and verify of the given observers\n   * received the correct event on the special day.\n   *\n   * @param specialDay The special day on which an event is emitted\n   * @param event The expected event emitted by the test object\n   * @param emitter The event emitter\n   * @param observers The registered observer mocks\n   */\n  private void testAllDays(\n      final Weekday specialDay,\n      final Event event,\n      final E emitter,\n      final EventObserver... observers) {\n\n    for (final var weekday : Weekday.values()) {\n      // Pass each week of the day, day by day to the event emitter\n      emitter.timePasses(weekday);\n\n      if (weekday == specialDay) {\n        // On a special day, every observer should have received the event\n        for (final var observer : observers) {\n          verify(observer, times(1)).onEvent(eq(event));\n        }\n      } else {\n        // On any other normal day, the observers should have received nothing at all\n        verifyNoMoreInteractions(observers);\n      }\n    }\n\n    // The observers should not have received any additional events after the week\n    verifyNoMoreInteractions(observers);\n  }\n\n  /**\n   * Go over every day of the month, and check if the event is emitted on the given day. Use an\n   * event emitter without a default observer\n   *\n   * @param specialDay The special day on which an event is emitted\n   * @param event The expected event emitted by the test object\n   */\n  private void testAllDaysWithoutDefaultObserver(final Weekday specialDay, final Event event) {\n    final var observer1 = mock(EventObserver.class);\n    final var observer2 = mock(EventObserver.class);\n\n    final var emitter = this.factoryWithoutDefaultObserver.get();\n    emitter.registerObserver(observer1, event);\n    emitter.registerObserver(observer2, event);\n\n    testAllDays(specialDay, event, emitter, observer1, observer2);\n  }\n\n  /**\n   * Go over every day of the month, and check if the event is emitted on the given day.\n   *\n   * @param specialDay The special day on which an event is emitted\n   * @param event The expected event emitted by the test object\n   */\n  private void testAllDaysWithDefaultObserver(final Weekday specialDay, final Event event) {\n    final var defaultObserver = mock(EventObserver.class);\n    final var observer1 = mock(EventObserver.class);\n    final var observer2 = mock(EventObserver.class);\n\n    final var emitter = this.factoryWithDefaultObserver.apply(defaultObserver, event);\n    emitter.registerObserver(observer1, event);\n    emitter.registerObserver(observer2, event);\n\n    testAllDays(specialDay, event, emitter, defaultObserver, observer1, observer2);\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/test/java/com/iluwatar/event/aggregator/EventTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport java.util.Arrays;\nimport org.junit.jupiter.api.Test;\n\n/** EventTest */\nclass EventTest {\n\n  /** Verify if every event has a non-null, non-empty description */\n  @Test\n  void testToString() {\n    Arrays.stream(Event.values())\n        .map(Event::toString)\n        .forEach(\n            toString -> {\n              assertNotNull(toString);\n              assertFalse(toString.trim().isEmpty());\n            });\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingJoffreyTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.stream.IntStream;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/** KingJoffreyTest */\nclass KingJoffreyTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(KingJoffrey.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /** Test if {@link KingJoffrey} tells us what event he received */\n  @Test\n  void testOnEvent() {\n    final var kingJoffrey = new KingJoffrey();\n\n    IntStream.range(0, Event.values().length)\n        .forEach(\n            i -> {\n              assertEquals(i, appender.getLogSize());\n              var event = Event.values()[i];\n              kingJoffrey.onEvent(event);\n              final var expectedMessage = \"Received event from the King's Hand: \" + event;\n              assertEquals(expectedMessage, appender.getLastMessage());\n              assertEquals(i + 1, appender.getLogSize());\n            });\n  }\n\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender(Class<?> clazz) {\n      ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public String getLastMessage() {\n      return log.get(log.size() - 1).getFormattedMessage();\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/test/java/com/iluwatar/event/aggregator/KingsHandTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport java.util.Arrays;\nimport org.junit.jupiter.api.Test;\n\n/** KingsHandTest */\nclass KingsHandTest extends EventEmitterTest<KingsHand> {\n\n  /** Create a new test instance, using the correct object factory */\n  public KingsHandTest() {\n    super(null, null, KingsHand::new, KingsHand::new);\n  }\n\n  /**\n   * The {@link KingsHand} is both an {@link EventEmitter} as an {@link EventObserver} so verify if\n   * every event received is passed up to its superior, in most cases {@link KingJoffrey} but now\n   * just a mocked observer.\n   */\n  @Test\n  void testPassThrough() {\n    final var observer = mock(EventObserver.class);\n    final var kingsHand = new KingsHand();\n    kingsHand.registerObserver(observer, Event.STARK_SIGHTED);\n    kingsHand.registerObserver(observer, Event.WARSHIPS_APPROACHING);\n    kingsHand.registerObserver(observer, Event.TRAITOR_DETECTED);\n    kingsHand.registerObserver(observer, Event.WHITE_WALKERS_SIGHTED);\n\n    // The kings hand should not pass any events before he received one\n    verifyNoMoreInteractions(observer);\n\n    // Verify if each event is passed on to the observer, nothing less, nothing more.\n    Arrays.stream(Event.values())\n        .forEach(\n            event -> {\n              kingsHand.onEvent(event);\n              verify(observer, times(1)).onEvent(eq(event));\n              verifyNoMoreInteractions(observer);\n            });\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordBaelishTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\n/** LordBaelishTest */\nclass LordBaelishTest extends EventEmitterTest<LordBaelish> {\n\n  /** Create a new test instance, using the correct object factory */\n  public LordBaelishTest() {\n    super(Weekday.FRIDAY, Event.STARK_SIGHTED, LordBaelish::new, LordBaelish::new);\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/test/java/com/iluwatar/event/aggregator/LordVarysTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\n/** LordVarysTest */\nclass LordVarysTest extends EventEmitterTest<LordVarys> {\n\n  /** Create a new test instance, using the correct object factory */\n  public LordVarysTest() {\n    super(Weekday.SATURDAY, Event.TRAITOR_DETECTED, LordVarys::new, LordVarys::new);\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/test/java/com/iluwatar/event/aggregator/ScoutTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\n/** ScoutTest */\nclass ScoutTest extends EventEmitterTest<Scout> {\n\n  /** Create a new test instance, using the correct object factory */\n  public ScoutTest() {\n\n    super(Weekday.TUESDAY, Event.WARSHIPS_APPROACHING, Scout::new, Scout::new);\n  }\n}\n"
  },
  {
    "path": "event-aggregator/src/test/java/com/iluwatar/event/aggregator/WeekdayTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.aggregator;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport java.util.Arrays;\nimport org.junit.jupiter.api.Test;\n\n/** WeekdayTest */\nclass WeekdayTest {\n\n  @Test\n  void testToString() {\n    Arrays.stream(Weekday.values())\n        .forEach(\n            weekday -> {\n              final String toString = weekday.toString();\n              assertNotNull(toString);\n              assertEquals(weekday.name(), toString.toUpperCase());\n            });\n  }\n}\n"
  },
  {
    "path": "event-based-asynchronous/README.md",
    "content": "---\ntitle: \"Event-Based Asynchronous Pattern in Java: Mastering Non-Blocking System Design\"\nshortTitle: Event-Based Asynchronous\ndescription: \"Explore the best practices and implementations of event-based asynchronous patterns in Java. Enhance your programming skills with our comprehensive guide and real-world examples.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Asynchronous\n  - Decoupling\n  - Event-driven\n  - Fault tolerance\n  - Messaging\n  - Reactive\n  - Scalability\n---\n\n## Also known as\n\n* Asynchronous Event Handling\n\n## Intent of Event-Based Asynchronous Design Pattern\n\nThe Event-Based Asynchronous pattern allows a system to handle tasks that might take some time to complete without blocking the execution of the program. It enables better resource utilization by freeing up a thread that would otherwise be blocked waiting for the task to complete.\n\n## Detailed Explanation of Event-Based Asynchronous Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy of the Event-Based Asynchronous design pattern is how a restaurant operates. When a customer places an order, the waiter records the order and passes it to the kitchen. Instead of waiting at the kitchen for the food to be prepared, the waiter continues to serve other tables. Once the kitchen completes the order, they signal (event) the waiter, who then delivers the food to the customer. This allows the waiter to handle multiple tasks efficiently without idle waiting, similar to how asynchronous programming handles tasks in parallel, enhancing overall efficiency and responsiveness.\n\nIn Plain Words\n\n> The Event-Based Asynchronous design pattern allows tasks to be executed in the background, notifying the main program via events when completed, thereby enhancing system efficiency and responsiveness without blocking ongoing operations.\n\nSequence diagram\n\n![Event-Based Asynchronous sequence diagram](./etc/event-based-asynchronous-sequence-diagram.png)\n\n## Programmatic Example of Event-Based Asynchronous Pattern in Java\n\nEvent-Based Asynchronous design pattern allows tasks to be executed in the background, notifying the main program via events when completed, thereby enhancing system efficiency and responsiveness without blocking ongoing operations.\n\nIn the provided code, we have several key classes implementing this pattern:\n\n- `App`: The main class that runs the application. It interacts with the `EventManager` to create, start, stop, and check the status of events.\n- `EventManager`: Manages the lifecycle of events, including creating, starting, stopping, and checking the status of events. It maintains a map of event IDs to `Event` objects.\n- `Event`: An abstract class that represents an event. It has two concrete subclasses: `AsyncEvent` and `SyncEvent`.\n- `AsyncEvent` and `SyncEvent`: Represent asynchronous and synchronous events respectively.\n- Custom exceptions: Thrown by the `EventManager` when certain conditions are not met.\n\nHere's a simplified code example of how these classes interact:\n\n```java\n// Create an EventManager\nEventManager eventManager = new EventManager();\n\n// Create an asynchronous event that runs for 60 seconds\nint asyncEventId = eventManager.createAsync(Duration.ofSeconds(60));\n\n// Start the asynchronous event\neventManager.start(asyncEventId);\n\n// Check the status of the asynchronous event\neventManager.status(asyncEventId);\n\n// Stop the asynchronous event\neventManager.cancel(asyncEventId);\n```\n\nIn this example, the `App` class creates an `EventManager`, then uses it to create, start, check the status of, and stop an asynchronous event. The `EventManager` creates an `AsyncEvent` object, starts it in a separate thread, checks its status, and stops it when requested.\n\nThe `EventManager` class is the core of the Event-Based Asynchronous pattern implementation. It manages the lifecycle of events, including creating, starting, stopping, and checking the status of events. It maintains a map of event IDs to `Event` objects. Here's a snippet of how it creates an asynchronous event:\n\n```java\npublic int createAsync(Duration runtime) throws MaxNumOfEventsAllowedException, LongRunningEventException {\n  int id = counter.incrementAndGet();\n  events.put(id, new AsyncEvent(id, runtime));\n  return id;\n}\n```\n\nThe `Event` class is an abstract class that represents an event. It has two concrete subclasses: `AsyncEvent` and `SyncEvent`. An `Event` has an ID, a runtime (how long it should run), and a status (whether it's running, completed, or ready to start). It also has methods to start and stop the event. Here's a snippet of how an `AsyncEvent` starts:\n\n```java\n@Override\npublic void start() {\n  Thread thread = new Thread(() -> {\n    try {\n      handleRunStart();\n      Thread.sleep(getRuntime().toMillis());\n      handleRunComplete();\n    } catch (InterruptedException e) {\n      handleRunFailure(e.getMessage());\n    }\n  });\n  thread.start();\n}\n```\n\nIn this snippet, when an `AsyncEvent` is started, it runs in a separate thread without blocking the main thread.\n\nA synchronous event is created and managed similarly to an asynchronous event. Here's a snippet of how it creates and manages a synchronous event:\n\n```java\n// Create an EventManager\nEventManager eventManager = new EventManager();\n\n// Create a synchronous event that runs for 60 seconds\nint syncEventId = eventManager.create(Duration.ofSeconds(60));\n\n// Start the synchronous event\neventManager.start(syncEventId);\n\n// Check the status of the synchronous event\neventManager.status(syncEventId);\n\n// Stop the synchronous event\neventManager.cancel(syncEventId);\n```\n\nIn the `EventManager` class, a synchronous event is created using the `create` method:\n\n```java\npublic int create(Duration runtime) throws MaxNumOfEventsAllowedException, LongRunningEventException {\n  int id = counter.incrementAndGet();\n  events.put(id, new SyncEvent(id, runtime));\n  return id;\n}\n```\n\nThe `SyncEvent` class is a subclass of `Event` that represents a synchronous event. When a `SyncEvent` is started, it runs on the main thread and blocks it until the event is completed. Here's a snippet of how a `SyncEvent` starts:\n\n```java\n@Override\npublic void start() {\n  try {\n    handleRunStart();\n    Thread.sleep(getRuntime().toMillis());\n    handleRunComplete();\n  } catch (InterruptedException e) {\n    handleRunFailure(e.getMessage());\n  }\n}\n```\n\nIn this snippet, when a `SyncEvent` is started, it runs on the main thread, blocking it until the event is completed. This is in contrast to an `AsyncEvent`, which runs in a separate thread without blocking the main thread.\n\nThese are the key parts of the Event-Based Asynchronous design pattern as implemented in this code. The pattern allows tasks to be executed in the background, notifying the main program via events when completed, thereby enhancing system efficiency and responsiveness without blocking ongoing operations.\n\n## When to Use the Event-Based Asynchronous Pattern in Java\n\n* When multiple tasks can be processed in parallel and independently.\n* Systems that require responsiveness and cannot afford to have threads blocked waiting for an operation to complete.\n* In GUI applications where user interface responsiveness is critical.\n* Distributed systems where long network operations are involved.\n\n## Real-World Applications of Event-Based Asynchronous Pattern in Java\n\n* GUI libraries in Java (e.g., JavaFX, Swing with SwingWorker).\n* Java Message Service (JMS) for handling asynchronous messaging.\n* Java’s CompletableFuture and various Event-Driven Frameworks.\n\n## Benefits and Trade-offs of Event-Based Asynchronous Pattern\n\nBenefits:\n\n* Improves application scalability and responsiveness.\n* Reduces the resources wasted on threads that would simply wait for I/O operations.\n* Enhances fault tolerance through isolation of process execution.\n\nTrade-offs:\n\n* Increases complexity of error handling as errors may occur in different threads or at different times.\n* Can lead to harder-to-follow code and debugging challenges due to the non-linear nature of asynchronous code execution.\n\n## Related Java Design Patterns\n\n* [Observer](https://java-design-patterns.com/patterns/observer/): Often used in conjunction where the observer reacts to events as they occur.\n* Publish/Subscribe: Related in terms of event handling mechanisms, particularly for messaging and event distribution across components.\n* [Command](https://java-design-patterns.com/patterns/command/): Useful for encapsulating all information needed to perform an action or trigger an event.\n\n## References and Credits\n\n* [Java Concurrency in Practice](https://amzn.to/4cYY4kU)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3Uh7rW1)\n* [Pro JavaFX 8: A Definitive Guide to Building Desktop, Mobile, and Embedded Java Clients](https://amzn.to/3vHUqLL)\n* [Event-based Asynchronous Pattern Overview (Microsoft)](https://msdn.microsoft.com/en-us/library/wewwczdw%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396)\n"
  },
  {
    "path": "event-based-asynchronous/etc/event-asynchronous.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.2.2\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <interface id=\"1\" language=\"java\" name=\"com.iluwatar.event.asynchronous.IEvent\" project=\"java-design-patterns\" \n    file=\"/java-design-patterns/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/IEvent.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"117\" width=\"151\" x=\"42\" y=\"15\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"2\" language=\"java\" name=\"com.iluwatar.event.asynchronous.ThreadCompleteListener\" \n    project=\"java-design-patterns\" \n    file=\"/java-design-patterns/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/ThreadCompleteListener.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"326\" y=\"79\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.event.asynchronous.App\" project=\"java-design-patterns\" \n    file=\"/java-design-patterns/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/App.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"554\" y=\"119\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.event.asynchronous.EventAsynchronousTest\" \n    project=\"java-design-patterns\" \n    file=\"/java-design-patterns/event-asynchronous/src/test/java/com/iluwatar/event/asynchronous/EventAsynchronousTest.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"207\" width=\"234\" x=\"669\" y=\"16\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.event.asynchronous.Event\" project=\"java-design-patterns\" \n    file=\"/java-design-patterns/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/Event.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"141\" y=\"441\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.event.asynchronous.EventManager\" project=\"java-design-patterns\" \n    file=\"/java-design-patterns/event-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventManager.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"431\" y=\"439\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"7\">    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"8\" name=\"eventListener\"/>      \n      <multiplicity id=\"9\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"10\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </realization>  \n  <association id=\"11\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"12\" name=\"app\"/>      \n      <multiplicity id=\"13\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"14\">    \n    <end type=\"SOURCE\" refId=\"6\" navigable=\"false\">      \n      <attribute id=\"15\" name=\"eventPool\"/>      \n      <multiplicity id=\"16\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"17\">    \n    <end type=\"SOURCE\" refId=\"6\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "event-based-asynchronous/etc/event-asynchronous.urm.puml",
    "content": "@startuml\npackage com.iluwatar.event.asynchronous {\n  class App {\n    - LOGGER : Logger {static}\n    + PROP_FILE_NAME : String {static}\n    ~ interactiveMode : boolean\n    + App()\n    + main(args : String[]) {static}\n    - processOption1(eventManager : EventManager, s : Scanner)\n    - processOption2(eventManager : EventManager, s : Scanner)\n    - processOption3(eventManager : EventManager, s : Scanner)\n    + quickRun()\n    + run()\n    + runInteractiveMode()\n    + setUp()\n  }\n  class Event {\n    - LOGGER : Logger {static}\n    - eventId : int\n    - eventListener : ThreadCompleteListener\n    - eventTime : int\n    - isComplete : boolean\n    - isSynchronous : boolean\n    - thread : Thread\n    + Event(eventId : int, eventTime : int, isSynchronous : boolean)\n    + addListener(listener : ThreadCompleteListener)\n    - completed()\n    + isSynchronous() : boolean\n    + removeListener(listener : ThreadCompleteListener)\n    + run()\n    + start()\n    + status()\n    + stop()\n  }\n  class EventManager {\n    - DOES_NOT_EXIST : String {static}\n    + MAX_EVENT_TIME : int {static}\n    + MAX_ID : int {static}\n    + MAX_RUNNING_EVENTS : int {static}\n    + MIN_ID : int {static}\n    - currentlyRunningSyncEvent : int\n    - eventPool : Map<Integer, Event>\n    - rand : Random\n    + EventManager()\n    + cancel(eventId : int)\n    + completedEventHandler(eventId : int)\n    + create(eventTime : int) : int\n    + createAsync(eventTime : int) : int\n    - createEvent(eventTime : int, isSynchronous : boolean) : int\n    - generateId() : int\n    + getEventPool() : Map<Integer, Event>\n    + numOfCurrentlyRunningSyncEvent() : int\n    + shutdown()\n    + start(eventId : int)\n    + status(eventId : int)\n    + statusOfAllEvents()\n  }\n  interface IEvent {\n    + start() {abstract}\n    + status() {abstract}\n    + stop() {abstract}\n  }\n  interface ThreadCompleteListener {\n    + completedEventHandler(int) {abstract}\n  }\n}\nEvent -->  \"-eventListener\" ThreadCompleteListener\nEvent ..|> IEvent \nEventManager ..|> ThreadCompleteListener \n@enduml"
  },
  {
    "path": "event-based-asynchronous/etc/event-based-asynchronous.urm.puml",
    "content": "@startuml\npackage com.iluwatar.event.asynchronous {\n  class App {\n    - LOGGER : Logger {static}\n    + PROP_FILE_NAME : String {static}\n    ~ interactiveMode : boolean\n    + App()\n    + main(args : String[]) {static}\n    - processOption1(eventManager : EventManager, s : Scanner)\n    - processOption2(eventManager : EventManager, s : Scanner)\n    - processOption3(eventManager : EventManager, s : Scanner)\n    + quickRun()\n    + run()\n    + runInteractiveMode()\n    + setUp()\n  }\n  class AsyncEvent {\n    - LOGGER : Logger {static}\n    - eventId : int\n    - eventListener : ThreadCompleteListener\n    - eventTime : int\n    - isComplete : AtomicBoolean\n    - synchronous : boolean\n    - thread : Thread\n    + AsyncEvent(eventId : int, eventTime : int, synchronous : boolean)\n    + addListener(listener : ThreadCompleteListener)\n    - completed()\n    + isSynchronous() : boolean\n    + removeListener()\n    + run()\n    + start()\n    + status()\n    + stop()\n  }\n  interface Event {\n    + start() {abstract}\n    + status() {abstract}\n    + stop() {abstract}\n  }\n  class EventManager {\n    - DOES_NOT_EXIST : String {static}\n    + MAX_EVENT_TIME : int {static}\n    + MAX_ID : int {static}\n    + MAX_RUNNING_EVENTS : int {static}\n    + MIN_ID : int {static}\n    - currentlyRunningSyncEvent : int\n    - eventPool : Map<Integer, AsyncEvent>\n    - rand : SecureRandom\n    + EventManager()\n    + cancel(eventId : int)\n    + completedEventHandler(eventId : int)\n    + create(eventTime : int) : int\n    + createAsync(eventTime : int) : int\n    - createEvent(eventTime : int, isSynchronous : boolean) : int\n    - generateId() : int\n    + getEventPool() : Map<Integer, AsyncEvent>\n    + numOfCurrentlyRunningSyncEvent() : int\n    + shutdown()\n    + start(eventId : int)\n    + status(eventId : int)\n    + statusOfAllEvents()\n  }\n  interface ThreadCompleteListener {\n    + completedEventHandler(int) {abstract}\n  }\n}\nAsyncEvent -->  \"-eventListener\" ThreadCompleteListener\nAsyncEvent ..|> Event \nEventManager ..|> ThreadCompleteListener \n@enduml"
  },
  {
    "path": "event-based-asynchronous/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>event-based-asynchronous</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n      <dependency>\n          <groupId>org.awaitility</groupId>\n          <artifactId>awaitility</artifactId>\n          <version>4.3.0</version>\n          <scope>test</scope>\n      </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.event.asynchronous.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>"
  },
  {
    "path": "event-based-asynchronous/src/main/java/com/iluwatar/event/asynchronous/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.asynchronous;\n\nimport java.io.IOException;\nimport java.time.Duration;\nimport java.util.Properties;\nimport java.util.Scanner;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This application demonstrates the <b>Event-based Asynchronous</b> pattern. Essentially, users (of\n * the pattern) may choose to run events in an Asynchronous or Synchronous mode. There can be\n * multiple Asynchronous events running at once but only one Synchronous event can run at a time.\n * Asynchronous events are synonymous to multi-threads. The key point here is that the threads run\n * in the background and the user is free to carry on with other processes. Once an event is\n * complete, the appropriate listener/callback method will be called. The listener then proceeds to\n * carry out further processing depending on the needs of the user.\n *\n * <p>The {@link EventManager} manages the events/threads that the user creates. Currently, the\n * supported event operations are: <code>start</code>, <code>stop</code>, <code>getStatus</code>.\n * For Synchronous events, the user is unable to start another (Synchronous) event if one is already\n * running at the time. The running event would have to either be stopped or completed before a new\n * event can be started.\n *\n * <p>The Event-based Asynchronous Pattern makes available the advantages of multithreaded\n * applications while hiding many of the complex issues inherent in multithreaded design. Using a\n * class that supports this pattern can allow you to:- (1) Perform time-consuming tasks, such as\n * downloads and database operations, \"in the background,\" without interrupting your application.\n * (2) Execute multiple operations simultaneously, receiving notifications when each completes. (3)\n * Wait for resources to become available without stopping (\"hanging\") your application. (4)\n * Communicate with pending asynchronous operations using the familiar events-and-delegates model.\n *\n * @see EventManager\n * @see AsyncEvent\n */\n@Slf4j\npublic class App {\n\n  public static final String PROP_FILE_NAME = \"config.properties\";\n\n  boolean interactiveMode = false;\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var app = new App();\n    app.setUp();\n    app.run();\n  }\n\n  /**\n   * App can run in interactive mode or not. Interactive mode == Allow user interaction with command\n   * line. Non-interactive is a quick sequential run through the available {@link EventManager}\n   * operations.\n   */\n  public void setUp() {\n    var prop = new Properties();\n\n    var inputStream = App.class.getClassLoader().getResourceAsStream(PROP_FILE_NAME);\n\n    if (inputStream != null) {\n      try {\n        prop.load(inputStream);\n      } catch (IOException e) {\n        LOGGER.error(\"{} was not found. Defaulting to non-interactive mode.\", PROP_FILE_NAME, e);\n      }\n      var property = prop.getProperty(\"INTERACTIVE_MODE\");\n      if (property.equalsIgnoreCase(\"YES\")) {\n        interactiveMode = true;\n      }\n    }\n  }\n\n  /** Run program in either interactive mode or not. */\n  public void run() {\n    if (interactiveMode) {\n      runInteractiveMode();\n    } else {\n      quickRun();\n    }\n  }\n\n  /** Run program in non-interactive mode. */\n  public void quickRun() {\n    var eventManager = new EventManager();\n\n    try {\n      // Create an Asynchronous event.\n      var asyncEventId = eventManager.createAsync(Duration.ofSeconds(60));\n      LOGGER.info(\"Async Event [{}] has been created.\", asyncEventId);\n      eventManager.start(asyncEventId);\n      LOGGER.info(\"Async Event [{}] has been started.\", asyncEventId);\n\n      // Create a Synchronous event.\n      var syncEventId = eventManager.create(Duration.ofSeconds(60));\n      LOGGER.info(\"Sync Event [{}] has been created.\", syncEventId);\n      eventManager.start(syncEventId);\n      LOGGER.info(\"Sync Event [{}] has been started.\", syncEventId);\n\n      eventManager.status(asyncEventId);\n      eventManager.status(syncEventId);\n\n      eventManager.cancel(asyncEventId);\n      LOGGER.info(\"Async Event [{}] has been stopped.\", asyncEventId);\n      eventManager.cancel(syncEventId);\n      LOGGER.info(\"Sync Event [{}] has been stopped.\", syncEventId);\n\n    } catch (MaxNumOfEventsAllowedException\n        | LongRunningEventException\n        | EventDoesNotExistException\n        | InvalidOperationException e) {\n      LOGGER.error(e.getMessage());\n    }\n  }\n\n  /** Run program in interactive mode. */\n  public void runInteractiveMode() {\n    var eventManager = new EventManager();\n\n    var s = new Scanner(System.in);\n    var option = -1;\n    while (option != 4) {\n      LOGGER.info(\"Hello. Would you like to boil some eggs?\");\n      LOGGER.info(\n          \"\"\"\n              (1) BOIL AN EGG\n              (2) STOP BOILING THIS EGG\n              (3) HOW ARE MY EGGS?\n              (4) EXIT\n              \"\"\");\n      LOGGER.info(\"Choose [1,2,3,4]: \");\n      option = s.nextInt();\n\n      if (option == 1) {\n        processOption1(eventManager, s);\n      } else if (option == 2) {\n        processOption2(eventManager, s);\n      } else if (option == 3) {\n        processOption3(eventManager, s);\n      } else if (option == 4) {\n        eventManager.shutdown();\n      }\n    }\n\n    s.close();\n  }\n\n  private void processOption3(EventManager eventManager, Scanner s) {\n    s.nextLine();\n    LOGGER.info(\"Just one egg (O) OR all of them (A) ?: \");\n    var eggChoice = s.nextLine();\n\n    if (eggChoice.equalsIgnoreCase(\"O\")) {\n      LOGGER.info(\"Which egg?: \");\n      int eventId = s.nextInt();\n      try {\n        eventManager.status(eventId);\n      } catch (EventDoesNotExistException e) {\n        LOGGER.error(e.getMessage());\n      }\n    } else if (eggChoice.equalsIgnoreCase(\"A\")) {\n      eventManager.statusOfAllEvents();\n    }\n  }\n\n  private void processOption2(EventManager eventManager, Scanner s) {\n    LOGGER.info(\"Which egg?: \");\n    var eventId = s.nextInt();\n    try {\n      eventManager.cancel(eventId);\n      LOGGER.info(\"Egg [{}] is removed from boiler.\", eventId);\n    } catch (EventDoesNotExistException e) {\n      LOGGER.error(e.getMessage());\n    }\n  }\n\n  private void processOption1(EventManager eventManager, Scanner s) {\n    s.nextLine();\n    LOGGER.info(\"Boil multiple eggs at once (A) or boil them one-by-one (S)?: \");\n    var eventType = s.nextLine();\n    LOGGER.info(\"How long should this egg be boiled for (in seconds)?: \");\n    var eventTime = Duration.ofSeconds(s.nextInt());\n    if (eventType.equalsIgnoreCase(\"A\")) {\n      try {\n        var eventId = eventManager.createAsync(eventTime);\n        eventManager.start(eventId);\n        LOGGER.info(\"Egg [{}] is being boiled.\", eventId);\n      } catch (MaxNumOfEventsAllowedException\n          | LongRunningEventException\n          | EventDoesNotExistException e) {\n        LOGGER.error(e.getMessage());\n      }\n    } else if (eventType.equalsIgnoreCase(\"S\")) {\n      try {\n        var eventId = eventManager.create(eventTime);\n        eventManager.start(eventId);\n        LOGGER.info(\"Egg [{}] is being boiled.\", eventId);\n      } catch (MaxNumOfEventsAllowedException\n          | InvalidOperationException\n          | LongRunningEventException\n          | EventDoesNotExistException e) {\n        LOGGER.error(e.getMessage());\n      }\n    } else {\n      LOGGER.info(\"Unknown event type.\");\n    }\n  }\n}\n"
  },
  {
    "path": "event-based-asynchronous/src/main/java/com/iluwatar/event/asynchronous/AsyncEvent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.asynchronous;\n\nimport java.time.Duration;\nimport java.time.Instant;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Each Event runs as a separate/individual thread. */\n@Slf4j\n@RequiredArgsConstructor\npublic class AsyncEvent implements Event, Runnable {\n\n  private final int eventId;\n  private final Duration eventTime;\n  @Getter private final boolean synchronous;\n  private Thread thread;\n  private final AtomicBoolean isComplete = new AtomicBoolean(false);\n  private ThreadCompleteListener eventListener;\n\n  @Override\n  public void start() {\n    thread = new Thread(this);\n    thread.start();\n  }\n\n  @Override\n  public void stop() {\n    if (null == thread) {\n      return;\n    }\n    thread.interrupt();\n  }\n\n  @Override\n  public void status() {\n    if (isComplete.get()) {\n      LOGGER.info(\"[{}] is not done.\", eventId);\n    } else {\n      LOGGER.info(\"[{}] is done.\", eventId);\n    }\n  }\n\n  @Override\n  public void run() {\n\n    var currentTime = Instant.now();\n    var endTime = currentTime.plusSeconds(eventTime.getSeconds());\n    while (Instant.now().compareTo(endTime) < 0) {\n      try {\n        TimeUnit.SECONDS.sleep(1);\n      } catch (InterruptedException e) {\n        LOGGER.error(\"Thread was interrupted: \", e);\n        Thread.currentThread().interrupt();\n        return;\n      }\n    }\n    isComplete.set(true);\n    completed();\n  }\n\n  public final void addListener(final ThreadCompleteListener listener) {\n    this.eventListener = listener;\n  }\n\n  private void completed() {\n    if (eventListener != null) {\n      eventListener.completedEventHandler(eventId);\n    }\n  }\n}\n"
  },
  {
    "path": "event-based-asynchronous/src/main/java/com/iluwatar/event/asynchronous/Event.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.asynchronous;\n\n/**\n * Events that fulfill the start stop and list out current status behaviour follow this interface.\n */\npublic interface Event {\n\n  void start();\n\n  void stop();\n\n  void status();\n}\n"
  },
  {
    "path": "event-based-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventDoesNotExistException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.asynchronous;\n\nimport java.io.Serial;\n\n/** Custom Exception Class for Non-Existent Event. */\npublic class EventDoesNotExistException extends Exception {\n\n  @Serial private static final long serialVersionUID = -3398463738273811509L;\n\n  public EventDoesNotExistException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "event-based-asynchronous/src/main/java/com/iluwatar/event/asynchronous/EventManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.asynchronous;\n\nimport java.security.SecureRandom;\nimport java.time.Duration;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport lombok.Getter;\n\n/**\n * EventManager handles and maintains a pool of event threads. {@link AsyncEvent} threads are\n * created upon user request. Thre are two types of events; Asynchronous and Synchronous. There can\n * be multiple Asynchronous events running at once but only one Synchronous event running at a time.\n * Currently supported event operations are: start, stop, and getStatus. Once an event is complete,\n * it then notifies EventManager through a listener. The EventManager then takes the event out of\n * the pool.\n */\npublic class EventManager implements ThreadCompleteListener {\n\n  public static final int MAX_RUNNING_EVENTS = 1000;\n  // Just don't want to have too many running events. :)\n  public static final int MIN_ID = 1;\n  public static final int MAX_ID = MAX_RUNNING_EVENTS;\n  public static final Duration MAX_EVENT_TIME = Duration.ofSeconds(1800); // 30 minutes.\n  private int currentlyRunningSyncEvent = -1;\n  private final SecureRandom rand;\n\n  @Getter private final Map<Integer, AsyncEvent> eventPool;\n\n  private static final String DOES_NOT_EXIST = \" does not exist.\";\n\n  /** EventManager constructor. */\n  public EventManager() {\n    rand = new SecureRandom();\n    eventPool = new ConcurrentHashMap<>(MAX_RUNNING_EVENTS);\n  }\n\n  /**\n   * Create a Synchronous event.\n   *\n   * @param eventTime Time an event should run for.\n   * @return eventId\n   * @throws MaxNumOfEventsAllowedException When too many events are running at a time.\n   * @throws InvalidOperationException No new synchronous events can be created when one is already\n   *     running.\n   * @throws LongRunningEventException Long-running events are not allowed in the app.\n   */\n  public int create(Duration eventTime)\n      throws MaxNumOfEventsAllowedException, InvalidOperationException, LongRunningEventException {\n    if (currentlyRunningSyncEvent != -1) {\n      throw new InvalidOperationException(\n          \"Event [\"\n              + currentlyRunningSyncEvent\n              + \"] is still\"\n              + \" running. Please wait until it finishes and try again.\");\n    }\n\n    var eventId = createEvent(eventTime, true);\n    currentlyRunningSyncEvent = eventId;\n\n    return eventId;\n  }\n\n  /**\n   * Create an Asynchronous event.\n   *\n   * @param eventTime Time an event should run for.\n   * @return eventId\n   * @throws MaxNumOfEventsAllowedException When too many events are running at a time.\n   * @throws LongRunningEventException Long-running events are not allowed in the app.\n   */\n  public int createAsync(Duration eventTime)\n      throws MaxNumOfEventsAllowedException, LongRunningEventException {\n    return createEvent(eventTime, false);\n  }\n\n  private int createEvent(Duration eventTime, boolean isSynchronous)\n      throws MaxNumOfEventsAllowedException, LongRunningEventException {\n    if (eventTime.isNegative()) {\n      throw new IllegalArgumentException(\"eventTime cannot be negative\");\n    }\n\n    if (eventPool.size() == MAX_RUNNING_EVENTS) {\n      throw new MaxNumOfEventsAllowedException(\n          \"Too many events are running at the moment.\" + \" Please try again later.\");\n    }\n\n    if (eventTime.getSeconds() > MAX_EVENT_TIME.getSeconds()) {\n      throw new LongRunningEventException(\n          \"Maximum event time allowed is \" + MAX_EVENT_TIME + \" seconds. Please try again.\");\n    }\n\n    var newEventId = generateId();\n\n    var newEvent = new AsyncEvent(newEventId, eventTime, isSynchronous);\n    newEvent.addListener(this);\n    eventPool.put(newEventId, newEvent);\n\n    return newEventId;\n  }\n\n  /**\n   * Starts event.\n   *\n   * @param eventId The event that needs to be started.\n   * @throws EventDoesNotExistException If event does not exist in our eventPool.\n   */\n  public void start(int eventId) throws EventDoesNotExistException {\n    if (!eventPool.containsKey(eventId)) {\n      throw new EventDoesNotExistException(eventId + DOES_NOT_EXIST);\n    }\n\n    eventPool.get(eventId).start();\n  }\n\n  /**\n   * Stops event.\n   *\n   * @param eventId The event that needs to be stopped.\n   * @throws EventDoesNotExistException If event does not exist in our eventPool.\n   */\n  public void cancel(int eventId) throws EventDoesNotExistException {\n    if (!eventPool.containsKey(eventId)) {\n      throw new EventDoesNotExistException(eventId + DOES_NOT_EXIST);\n    }\n\n    if (eventId == currentlyRunningSyncEvent) {\n      currentlyRunningSyncEvent = -1;\n    }\n\n    eventPool.get(eventId).stop();\n    eventPool.remove(eventId);\n  }\n\n  /**\n   * Get status of a running event.\n   *\n   * @param eventId The event to inquire status of.\n   * @throws EventDoesNotExistException If event does not exist in our eventPool.\n   */\n  public void status(int eventId) throws EventDoesNotExistException {\n    if (!eventPool.containsKey(eventId)) {\n      throw new EventDoesNotExistException(eventId + DOES_NOT_EXIST);\n    }\n\n    eventPool.get(eventId).status();\n  }\n\n  /** Gets status of all running events. */\n  @SuppressWarnings(\"rawtypes\")\n  public void statusOfAllEvents() {\n    eventPool.entrySet().forEach(entry -> ((AsyncEvent) ((Map.Entry) entry).getValue()).status());\n  }\n\n  /** Stop all running events. */\n  @SuppressWarnings(\"rawtypes\")\n  public void shutdown() {\n    eventPool.entrySet().forEach(entry -> ((AsyncEvent) ((Map.Entry) entry).getValue()).stop());\n  }\n\n  /**\n   * Returns a pseudo-random number between min and max, inclusive. The difference between min and\n   * max can be at most <code>Integer.MAX_VALUE - 1</code>.\n   */\n  private int generateId() {\n    // nextInt is normally exclusive of the top value,\n    // so add 1 to make it inclusive\n    var randomNum = rand.nextInt((MAX_ID - MIN_ID) + 1) + MIN_ID;\n    while (eventPool.containsKey(randomNum)) {\n      randomNum = rand.nextInt((MAX_ID - MIN_ID) + 1) + MIN_ID;\n    }\n\n    return randomNum;\n  }\n\n  /**\n   * Callback from an {@link AsyncEvent} (once it is complete). The Event is then removed from the\n   * pool.\n   */\n  @Override\n  public void completedEventHandler(int eventId) {\n    eventPool.get(eventId).status();\n    if (eventPool.get(eventId).isSynchronous()) {\n      currentlyRunningSyncEvent = -1;\n    }\n    eventPool.remove(eventId);\n  }\n\n  /** Get number of currently running Synchronous events. */\n  public int numOfCurrentlyRunningSyncEvent() {\n    return currentlyRunningSyncEvent;\n  }\n}\n"
  },
  {
    "path": "event-based-asynchronous/src/main/java/com/iluwatar/event/asynchronous/InvalidOperationException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.asynchronous;\n\nimport java.io.Serial;\n\n/** Type of Exception raised when the Operation being invoked is Invalid. */\npublic class InvalidOperationException extends Exception {\n\n  @Serial private static final long serialVersionUID = -6191545255213410803L;\n\n  public InvalidOperationException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "event-based-asynchronous/src/main/java/com/iluwatar/event/asynchronous/LongRunningEventException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.asynchronous;\n\nimport java.io.Serial;\n\n/** Type of Exception raised when the Operation being invoked is Long Running. */\npublic class LongRunningEventException extends Exception {\n\n  @Serial private static final long serialVersionUID = -483423544320148809L;\n\n  public LongRunningEventException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "event-based-asynchronous/src/main/java/com/iluwatar/event/asynchronous/MaxNumOfEventsAllowedException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.asynchronous;\n\nimport java.io.Serial;\n\n/** Type of Exception raised when the max number of allowed events is exceeded. */\npublic class MaxNumOfEventsAllowedException extends Exception {\n\n  @Serial private static final long serialVersionUID = -8430876973516292695L;\n\n  public MaxNumOfEventsAllowedException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "event-based-asynchronous/src/main/java/com/iluwatar/event/asynchronous/ThreadCompleteListener.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.asynchronous;\n\n/** Interface with listener behaviour related to Thread Completion. */\npublic interface ThreadCompleteListener {\n  void completedEventHandler(final int eventId);\n}\n"
  },
  {
    "path": "event-based-asynchronous/src/main/resources/config.properties",
    "content": "#\n# The MIT License\n# Copyright © 2014-2021 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nINTERACTIVE_MODE=NO"
  },
  {
    "path": "event-based-asynchronous/src/test/java/com/iluwatar/event/asynchronous/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.asynchronous;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that EventAsynchronous example runs without errors. */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "event-based-asynchronous/src/test/java/com/iluwatar/event/asynchronous/EventAsynchronousTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.asynchronous;\n\nimport static org.awaitility.Awaitility.await;\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.time.Duration;\nimport lombok.SneakyThrows;\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass EventAsynchronousTest {\n\n  @Test\n  @SneakyThrows\n  void testAsynchronousEvent() {\n    var eventManager = new EventManager();\n    var aEventId = eventManager.createAsync(Duration.ofSeconds(60));\n\n    assertDoesNotThrow(() -> eventManager.start(aEventId));\n\n    assertEquals(1, eventManager.getEventPool().size());\n    assertTrue(eventManager.getEventPool().size() < EventManager.MAX_RUNNING_EVENTS);\n    assertEquals(-1, eventManager.numOfCurrentlyRunningSyncEvent());\n\n    assertDoesNotThrow(() -> eventManager.cancel(aEventId));\n    assertTrue(eventManager.getEventPool().isEmpty());\n  }\n\n  @Test\n  @SneakyThrows\n  void testSynchronousEvent() {\n    var eventManager = new EventManager();\n    var sEventId = eventManager.create(Duration.ofSeconds(60));\n\n    assertDoesNotThrow(() -> eventManager.start(sEventId));\n    assertEquals(1, eventManager.getEventPool().size());\n    assertTrue(eventManager.getEventPool().size() < EventManager.MAX_RUNNING_EVENTS);\n    assertNotEquals(-1, eventManager.numOfCurrentlyRunningSyncEvent());\n\n    assertDoesNotThrow(() -> eventManager.cancel(sEventId));\n    assertTrue(eventManager.getEventPool().isEmpty());\n  }\n\n  @Test\n  @SneakyThrows\n  void testFullSynchronousEvent() {\n    var eventManager = new EventManager();\n\n    var eventTime = Duration.ofSeconds(1);\n\n    var sEventId = eventManager.create(eventTime);\n    assertEquals(1, eventManager.getEventPool().size());\n\n    eventManager.start(sEventId);\n\n    await().until(() -> eventManager.getEventPool().isEmpty());\n  }\n\n  @Test\n  @SneakyThrows\n  void testUnsuccessfulSynchronousEvent() {\n    assertThrows(\n        InvalidOperationException.class,\n        () -> {\n          var eventManager = new EventManager();\n\n          var sEventId = assertDoesNotThrow(() -> eventManager.create(Duration.ofSeconds(60)));\n          eventManager.start(sEventId);\n          sEventId = eventManager.create(Duration.ofSeconds(60));\n          eventManager.start(sEventId);\n        });\n  }\n\n  @Test\n  @SneakyThrows\n  void testFullAsynchronousEvent() {\n    var eventManager = new EventManager();\n    var eventTime = Duration.ofSeconds(1);\n\n    var aEventId1 = assertDoesNotThrow(() -> eventManager.createAsync(eventTime));\n    var aEventId2 = assertDoesNotThrow(() -> eventManager.createAsync(eventTime));\n    var aEventId3 = assertDoesNotThrow(() -> eventManager.createAsync(eventTime));\n    assertEquals(3, eventManager.getEventPool().size());\n\n    eventManager.start(aEventId1);\n    eventManager.start(aEventId2);\n    eventManager.start(aEventId3);\n\n    await().until(() -> eventManager.getEventPool().isEmpty());\n  }\n\n  @Test\n  void testLongRunningEventException() {\n    assertThrows(\n        LongRunningEventException.class,\n        () -> {\n          var eventManager = new EventManager();\n          eventManager.createAsync(Duration.ofMinutes(31));\n        });\n  }\n\n  @Test\n  void testMaxNumOfEventsAllowedException() {\n    assertThrows(\n        MaxNumOfEventsAllowedException.class,\n        () -> {\n          final var eventManager = new EventManager();\n          for (int i = 0; i < 1100; i++) {\n            eventManager.createAsync(Duration.ofSeconds(i));\n          }\n        });\n  }\n}\n"
  },
  {
    "path": "event-driven-architecture/README.md",
    "content": "---\ntitle: \"Event-Driven Architecture Pattern in Java: Building Responsive and Scalable Java Systems\"\nshortTitle: Event-Driven Architecture\ndescription: \"Discover comprehensive guides on Event-Driven Architecture patterns with practical Java examples. Learn to implement effective event-driven systems in your projects.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - Asynchronous\n  - Decoupling\n  - Enterprise patterns\n  - Event-driven\n  - Messaging\n  - Publish/subscribe\n  - Reactive\n  - Scalability\n---\n\n## Also known as\n\n* Event-Driven System\n* Event-Based Architecture\n\n## Intent of Event-Driven Architecture Design Pattern\n\nEvent-Driven Architecture (EDA) is designed to orchestrate behavior around the production, detection, consumption of, and reaction to events. This architecture enables highly decoupled, scalable, and dynamic interconnections between event producers and consumers.\n\n## Detailed Explanation of Event-Driven Architecture Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world example of the Event-Driven Architecture (EDA) pattern is the operation of an air traffic control system. In this system, events such as aircraft entering airspace, changes in weather conditions, and ground vehicle movements trigger specific responses like altering flight paths, scheduling gate assignments, and updating runway usage. This setup allows for highly efficient, responsive, and safe management of airport operations, reflecting EDA's core principles of asynchronous communication and dynamic event handling.\n\nIn plain words\n\n> Event-Driven Architecture is a design pattern where system behavior is dictated by the occurrence of specific events, allowing for dynamic, efficient, and decoupled responses.\n\nWikipedia says\n\n> Event-driven architecture (EDA) is a software architecture paradigm concerning the production and detection of events.\n\nArchitecture diagram\n\n![EDA Architecture Diagram](./etc/eda-architecture-diagram.png)\n\n## Programmatic Example of Event-Driven Architecture in Java\n\nThe Event-Driven Architecture (EDA) pattern in this module is implemented using several key classes and concepts:  \n\n* Event: This is an abstract class that represents an event. It's the base class for all types of events that can occur in the system.  \n* UserCreatedEvent and UserUpdatedEvent: These are concrete classes that extend the Event class. They represent specific types of events that can occur in the system, namely the creation and updating of a user.  \n* EventDispatcher: This class is responsible for dispatching events to their respective handlers. It maintains a mapping of event types to handlers.  \n* UserCreatedEventHandler and UserUpdatedEventHandler: These are the handler classes for the UserCreatedEvent and UserUpdatedEvent respectively. They contain the logic to execute when these events occur.  \n\nFirst, we'll define the `Event` abstract class and the concrete event classes `UserCreatedEvent` and `UserUpdatedEvent`.\n\n```java\npublic abstract class Event {\n  // Event related properties and methods\n}\n```\n\n```java\npublic class UserCreatedEvent extends Event {\n  private User user;\n\n  public UserCreatedEvent(User user) {\n    this.user = user;\n  }\n\n  public User getUser() {\n    return user;\n  }\n}\n```\n\n```java\npublic class UserUpdatedEvent extends Event {\n  private User user;\n\n  public UserUpdatedEvent(User user) {\n    this.user = user;\n  }\n\n  public User getUser() {\n    return user;\n  }\n}\n```\n\nNext, we'll define the event handlers `UserCreatedEventHandler` and `UserUpdatedEventHandler`.\n\n```java\npublic class UserCreatedEventHandler {\n  public void onUserCreated(UserCreatedEvent event) {\n    // Logic to execute when a UserCreatedEvent occurs\n  }\n}\n```\n\n```java\npublic class UserUpdatedEventHandler {\n  public void onUserUpdated(UserUpdatedEvent event) {\n    // Logic to execute when a UserUpdatedEvent occurs\n  }\n}\n```\n\nThen, we'll define the `EventDispatcher` class that is responsible for dispatching events to their respective handlers.\n\n```java\npublic class EventDispatcher {\n  private Map<Class<? extends Event>, List<Consumer<Event>>> handlers = new HashMap<>();\n\n  public <E extends Event> void registerHandler(Class<E> eventType, Consumer<E> handler) {\n    handlers.computeIfAbsent(eventType, k -> new ArrayList<>()).add(handler::accept);\n  }\n\n  public void dispatch(Event event) {\n    List<Consumer<Event>> eventHandlers = handlers.get(event.getClass());\n    if (eventHandlers != null) {\n      eventHandlers.forEach(handler -> handler.accept(event));\n    }\n  }\n}\n```\n\nFinally, we'll demonstrate how to use these classes in the main application.\n\n```java\npublic class App {\n  public static void main(String[] args) {\n    // Create an EventDispatcher\n    EventDispatcher dispatcher = new EventDispatcher();\n\n    // Register handlers for UserCreatedEvent and UserUpdatedEvent\n    dispatcher.registerHandler(UserCreatedEvent.class, new UserCreatedEventHandler()::onUserCreated);\n    dispatcher.registerHandler(UserUpdatedEvent.class, new UserUpdatedEventHandler()::onUserUpdated);\n\n    // Create a User\n    User user = new User(\"iluwatar\");\n\n    // Dispatch UserCreatedEvent\n    dispatcher.dispatch(new UserCreatedEvent(user));\n\n    // Dispatch UserUpdatedEvent\n    dispatcher.dispatch(new UserUpdatedEvent(user));\n  }\n}\n```\n\nRunning the example produces the following console output:\n\n```\n22:15:19.997 [main] INFO com.iluwatar.eda.handler.UserCreatedEventHandler -- User 'iluwatar' has been Created!\n22:15:20.000 [main] INFO com.iluwatar.eda.handler.UserUpdatedEventHandler -- User 'iluwatar' has been Updated!\n```\n\nThis example demonstrates the Event-Driven Architecture pattern, where the occurrence of events drives the flow of the program. The system is designed to respond to events as they occur, which allows for a high degree of flexibility and decoupling between components.\n\n## When to Use the Event-Driven Architecture Pattern in Java\n\nUse an Event-driven architecture when\n\n* Systems where change detection is crucial.\n* Applications that require real-time features and reactive systems.\n* Systems needing to efficiently handle high throughput and sporadic loads.\n* When integrating with microservices to enhance agility and scalability.\n\n## Real-World Applications of Event-Driven Architecture Pattern in Java\n\n* Real-time data processing applications.\n* Complex event processing systems in finance, such as stock trading platforms.\n* IoT systems for dynamic device and information management.\n* Chargify, a billing API, exposes payment activity through various events (https://docs.chargify.com/api-events)\n* Amazon's AWS Lambda, lets you execute code in response to events such as changes to Amazon S3 buckets, updates to an Amazon DynamoDB table, or custom events generated by your applications or devices. (https://aws.amazon.com/lambda)\n* MySQL runs triggers based on events such as inserts and update events happening on database tables.\n\n## Benefits and Trade-offs of Event-Driven Architecture Pattern\n\nBenefits:\n\n* Scalability: Efficiently processes fluctuating loads with asynchronous processing.\n* Flexibility and Agility: New event types and event consumers can be added with minimal impact on existing components.\n* Responsiveness: Improves responsiveness by decoupling event processing and state management.\n\nTrade-offs:\n\n* Complexity in Tracking: Can be challenging to debug and track due to loose coupling and asynchronous behaviors.\n* Dependency on Messaging Systems: Heavily relies on robust messaging infrastructures.\n* Event Consistency: Requires careful design to handle event ordering and consistency.\n\n## Related Java Design Patterns\n\n* Microservices Architecture: Often used together with EDA to enhance agility and scalability.\n* Publish/Subscribe: A common pattern used within EDA for messaging between event producers and consumers.\n\n## References and Credits\n\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3Q3vBki)\n* [Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions](https://amzn.to/49Aljz0)\n* [Reactive Messaging Patterns With the Actor Model: Applications and Integration in Scala and Akka](https://amzn.to/3UeoBUa)\n* [What is an Event-Driven Architecture (Amazon)](https://aws.amazon.com/event-driven-architecture/)\n"
  },
  {
    "path": "event-driven-architecture/etc/eda.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.9\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"true\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"true\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.eda.model.User\" project=\"event-driven-architecture\" \n    file=\"/event-driven-architecture/src/main/java/com/iluwatar/eda/model/User.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"437\" y=\"535\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.eda.handler.UserUpdatedEventHandler\" \n    project=\"event-driven-architecture\" \n    file=\"/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"763\" y=\"379\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.eda.handler.UserCreatedEventHandler\" \n    project=\"event-driven-architecture\" \n    file=\"/event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"596\" y=\"272\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"4\" language=\"java\" name=\"com.iluwatar.eda.framework.Event\" project=\"event-driven-architecture\" \n    file=\"/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Event.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"188\" y=\"121\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"5\" language=\"java\" name=\"com.iluwatar.eda.framework.Handler\" project=\"event-driven-architecture\" \n    file=\"/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Handler.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"755\" y=\"58\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.eda.framework.EventDispatcher\" project=\"event-driven-architecture\" \n    file=\"/event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"499\" y=\"122\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.eda.event.UserCreatedEvent\" project=\"event-driven-architecture\" \n    file=\"/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"102\" y=\"380\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.eda.event.UserUpdatedEvent\" project=\"event-driven-architecture\" \n    file=\"/event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"320\" y=\"382\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"9\" language=\"java\" name=\"com.iluwatar.eda.event.AbstractEvent\" project=\"event-driven-architecture\" \n    file=\"/event-driven-architecture/src/main/java/com/iluwatar/eda/event/AbstractEvent.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"188\" y=\"240\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <dependency id=\"10\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </dependency>  \n  <dependency id=\"11\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </dependency>  \n  <dependency id=\"12\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </dependency>  \n  <realization id=\"13\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </realization>  \n  <generalization id=\"14\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"9\"/>  \n  </generalization>  \n  <realization id=\"15\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </realization>  \n  <association id=\"16\">    \n    <end type=\"SOURCE\" refId=\"6\" navigable=\"false\">      \n      <attribute id=\"17\" name=\"handlers\">        \n        <position height=\"19\" width=\"56\" x=\"672\" y=\"144\"/>      \n      </attribute>      \n      <multiplicity id=\"18\" minimum=\"0\" maximum=\"2147483647\">        \n        <position height=\"17\" width=\"23\" x=\"797\" y=\"142\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"19\">    \n    <end type=\"SOURCE\" refId=\"9\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <dependency id=\"20\">    \n    <end type=\"SOURCE\" refId=\"6\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </dependency>  \n  <dependency id=\"21\">    \n    <bendpoint x=\"187\" y=\"57\"/>    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </dependency>  \n  <association id=\"22\">    \n    <end type=\"SOURCE\" refId=\"8\" navigable=\"false\">      \n      <attribute id=\"23\" name=\"user\">        \n        <position height=\"0\" width=\"0\" x=\"-500\" y=\"-83\"/>      \n      </attribute>      \n      <multiplicity id=\"24\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"-500\" y=\"-83\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"25\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"9\"/>  \n  </generalization>  \n  <association id=\"26\">    \n    <end type=\"SOURCE\" refId=\"7\" navigable=\"false\">      \n      <attribute id=\"27\" name=\"user\">        \n        <position height=\"0\" width=\"0\" x=\"-500\" y=\"-83\"/>      \n      </attribute>      \n      <multiplicity id=\"28\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"-500\" y=\"-83\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <dependency id=\"29\">    \n    <bendpoint x=\"308\" y=\"303\"/>    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </dependency>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"true\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "event-driven-architecture/etc/event-driven-architecture.urm.puml",
    "content": "@startuml\npackage com.iluwatar.eda.handler {\n  class UserCreatedEventHandler {\n    - LOGGER : Logger {static}\n    + UserCreatedEventHandler()\n    + onEvent(event : UserCreatedEvent)\n  }\n  class UserUpdatedEventHandler {\n    - LOGGER : Logger {static}\n    + UserUpdatedEventHandler()\n    + onEvent(event : UserUpdatedEvent)\n  }\n}\npackage com.iluwatar.eda.event {\n  abstract class AbstractEvent {\n    + AbstractEvent()\n    + getType() : Class<? extends Event>\n  }\n  class UserCreatedEvent {\n    - user : User\n    + UserCreatedEvent(user : User)\n    + getUser() : User\n  }\n  class UserUpdatedEvent {\n    - user : User\n    + UserUpdatedEvent(user : User)\n    + getUser() : User\n  }\n}\npackage com.iluwatar.eda.framework {\n  interface Event {\n    + getType() : Class<? extends Event> {abstract}\n  }\n  class EventDispatcher {\n    - handlers : Map<Class<? extends Event>, Handler<? extends Event>>\n    + EventDispatcher()\n    + dispatch(event : E extends Event)\n    + registerHandler(eventType : Class<E extends Event>, handler : Handler<E extends Event>)\n  }\n  interface Handler<E extends Event> {\n    + onEvent(E extends Event) {abstract}\n  }\n}\npackage com.iluwatar.eda.model {\n  class User {\n    - username : String\n    + User(username : String)\n    + getUsername() : String\n  }\n}\npackage com.iluwatar.eda {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n}\nUserCreatedEvent -->  \"-user\" User\nUserUpdatedEvent -->  \"-user\" User\nAbstractEvent ..|> Event \nUserCreatedEvent --|> AbstractEvent \nUserUpdatedEvent --|> AbstractEvent \nUserCreatedEventHandler ..|> Handler \nUserUpdatedEventHandler ..|> Handler \n@enduml"
  },
  {
    "path": "event-driven-architecture/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>event-driven-architecture</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.eda.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "event-driven-architecture/src/main/java/com/iluwatar/eda/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda;\n\nimport com.iluwatar.eda.event.UserCreatedEvent;\nimport com.iluwatar.eda.event.UserUpdatedEvent;\nimport com.iluwatar.eda.framework.Event;\nimport com.iluwatar.eda.framework.EventDispatcher;\nimport com.iluwatar.eda.handler.UserCreatedEventHandler;\nimport com.iluwatar.eda.handler.UserUpdatedEventHandler;\nimport com.iluwatar.eda.model.User;\n\n/**\n * An event-driven architecture (EDA) is a framework that orchestrates behavior around the\n * production, detection and consumption of events as well as the responses they evoke. An event is\n * any identifiable occurrence that has significance for system hardware or software.\n *\n * <p>The example below uses an {@link EventDispatcher} to link/register {@link Event} objects to\n * their respective handlers once an {@link Event} is dispatched, it's respective handler is invoked\n * and the {@link Event} is handled accordingly.\n */\npublic class App {\n\n  /**\n   * Once the {@link EventDispatcher} is initialised, handlers related to specific events have to be\n   * made known to the dispatcher by registering them. In this case the {@link UserCreatedEvent} is\n   * bound to the UserCreatedEventHandler, whilst the {@link UserUpdatedEvent} is bound to the\n   * {@link UserUpdatedEventHandler}. The dispatcher can now be called to dispatch specific events.\n   * When a user is saved, the {@link UserCreatedEvent} can be dispatched. On the other hand, when a\n   * user is updated, {@link UserUpdatedEvent} can be dispatched.\n   */\n  public static void main(String[] args) {\n\n    var dispatcher = new EventDispatcher();\n    dispatcher.registerHandler(UserCreatedEvent.class, new UserCreatedEventHandler());\n    dispatcher.registerHandler(UserUpdatedEvent.class, new UserUpdatedEventHandler());\n\n    var user = new User(\"iluwatar\");\n    dispatcher.dispatch(new UserCreatedEvent(user));\n    dispatcher.dispatch(new UserUpdatedEvent(user));\n  }\n}\n"
  },
  {
    "path": "event-driven-architecture/src/main/java/com/iluwatar/eda/event/AbstractEvent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda.event;\n\nimport com.iluwatar.eda.framework.Event;\nimport com.iluwatar.eda.framework.EventDispatcher;\n\n/**\n * The {@link AbstractEvent} class serves as a base class for defining custom events happening with\n * your system. In this example we have two types of events defined.\n *\n * <ul>\n *   <li>{@link UserCreatedEvent} - used when a user is created\n *   <li>{@link UserUpdatedEvent} - used when a user is updated\n * </ul>\n *\n * Events can be distinguished using the {@link #getType() getType} method.\n */\npublic abstract class AbstractEvent implements Event {\n\n  /**\n   * Returns the event type as a {@link Class} object In this example, this method is used by the\n   * {@link EventDispatcher} to dispatch events depending on their type.\n   *\n   * @return the AbstractEvent type as a {@link Class}.\n   */\n  public Class<? extends Event> getType() {\n    return getClass();\n  }\n}\n"
  },
  {
    "path": "event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserCreatedEvent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda.event;\n\nimport com.iluwatar.eda.model.User;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/**\n * The {@link UserCreatedEvent} should be dispatched whenever a user has been created. This class\n * can be extended to contain details about the user has been created. In this example, the entire\n * {@link User} object is passed on as data with the event.\n */\n@RequiredArgsConstructor\n@Getter\npublic class UserCreatedEvent extends AbstractEvent {\n\n  private final User user;\n}\n"
  },
  {
    "path": "event-driven-architecture/src/main/java/com/iluwatar/eda/event/UserUpdatedEvent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda.event;\n\nimport com.iluwatar.eda.model.User;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/**\n * The {@link UserUpdatedEvent} should be dispatched whenever a user has been updated. This class\n * can be extended to contain details about the user has been updated. In this example, the entire\n * {@link User} object is passed on as data with the event.\n */\n@RequiredArgsConstructor\n@Getter\npublic class UserUpdatedEvent extends AbstractEvent {\n\n  private final User user;\n}\n"
  },
  {
    "path": "event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Event.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda.framework;\n\n/**\n * A {@link Event} is an object with a specific type that is associated to a specific {@link\n * Handler}.\n */\npublic interface Event {\n\n  /**\n   * Returns the message type as a {@link Class} object. In this example the message type is used to\n   * handle events by their type.\n   *\n   * @return the message type as a {@link Class}.\n   */\n  Class<? extends Event> getType();\n}\n"
  },
  {
    "path": "event-driven-architecture/src/main/java/com/iluwatar/eda/framework/EventDispatcher.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda.framework;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Handles the routing of {@link Event} messages to associated handlers. A {@link HashMap} is used\n * to store the association between events and their respective handlers.\n */\npublic class EventDispatcher {\n\n  private final Map<Class<? extends Event>, Handler<? extends Event>> handlers;\n\n  public EventDispatcher() {\n    handlers = new HashMap<>();\n  }\n\n  /**\n   * Links an {@link Event} to a specific {@link Handler}.\n   *\n   * @param eventType The {@link Event} to be registered\n   * @param handler The {@link Handler} that will be handling the {@link Event}\n   */\n  public <E extends Event> void registerHandler(Class<E> eventType, Handler<E> handler) {\n    handlers.put(eventType, handler);\n  }\n\n  /**\n   * Dispatches an {@link Event} depending on its type.\n   *\n   * @param event The {@link Event} to be dispatched\n   */\n  @SuppressWarnings(\"unchecked\")\n  public <E extends Event> void dispatch(E event) {\n    var handler = (Handler<E>) handlers.get(event.getClass());\n    if (handler != null) {\n      handler.onEvent(event);\n    }\n  }\n}\n"
  },
  {
    "path": "event-driven-architecture/src/main/java/com/iluwatar/eda/framework/Handler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda.framework;\n\n/**\n * This interface can be implemented to handle different types of messages. Every handler is\n * responsible for a single of type message\n *\n * @param <E> Handler can handle events of type E\n */\npublic interface Handler<E extends Event> {\n\n  /**\n   * The onEvent method should implement and handle behavior related to the event. This can be as\n   * simple as calling another service to handle the event on publishing the event in a queue to be\n   * consumed by other sub systems.\n   *\n   * @param event the {@link Event} object to be handled.\n   */\n  void onEvent(E event);\n}\n"
  },
  {
    "path": "event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserCreatedEventHandler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda.handler;\n\nimport com.iluwatar.eda.event.UserCreatedEvent;\nimport com.iluwatar.eda.framework.Handler;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Handles the {@link UserCreatedEvent} message. */\n@Slf4j\npublic class UserCreatedEventHandler implements Handler<UserCreatedEvent> {\n\n  @Override\n  public void onEvent(UserCreatedEvent event) {\n    LOGGER.info(\"User '{}' has been Created!\", event.getUser().username());\n  }\n}\n"
  },
  {
    "path": "event-driven-architecture/src/main/java/com/iluwatar/eda/handler/UserUpdatedEventHandler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda.handler;\n\nimport com.iluwatar.eda.event.UserUpdatedEvent;\nimport com.iluwatar.eda.framework.Handler;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Handles the {@link UserUpdatedEvent} message. */\n@Slf4j\npublic class UserUpdatedEventHandler implements Handler<UserUpdatedEvent> {\n\n  @Override\n  public void onEvent(UserUpdatedEvent event) {\n    LOGGER.info(\"User '{}' has been Updated!\", event.getUser().username());\n  }\n}\n"
  },
  {
    "path": "event-driven-architecture/src/main/java/com/iluwatar/eda/model/User.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda.model;\n\nimport com.iluwatar.eda.event.UserCreatedEvent;\nimport com.iluwatar.eda.event.UserUpdatedEvent;\n\n/**\n * This {@link User} class is a basic pojo used to demonstrate user data sent along with the {@link\n * UserCreatedEvent} and {@link UserUpdatedEvent} events.\n */\npublic record User(String username) {}\n"
  },
  {
    "path": "event-driven-architecture/src/test/java/com/iluwatar/eda/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Event Driven Architecture example runs without errors. */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "event-driven-architecture/src/test/java/com/iluwatar/eda/event/UserCreatedEventTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda.event;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.eda.model.User;\nimport org.junit.jupiter.api.Test;\n\n/** {@link UserCreatedEventTest} tests and verifies {@link AbstractEvent} behaviour. */\nclass UserCreatedEventTest {\n\n  /**\n   * This unit test should correctly return the {@link AbstractEvent} class type when calling the\n   * {@link AbstractEvent#getType() getType} method.\n   */\n  @Test\n  void testGetEventType() {\n    var user = new User(\"iluwatar\");\n    var userCreatedEvent = new UserCreatedEvent(user);\n    assertEquals(UserCreatedEvent.class, userCreatedEvent.getType());\n  }\n}\n"
  },
  {
    "path": "event-driven-architecture/src/test/java/com/iluwatar/eda/framework/EventDispatcherTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.eda.framework;\n\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.verify;\n\nimport com.iluwatar.eda.event.UserCreatedEvent;\nimport com.iluwatar.eda.event.UserUpdatedEvent;\nimport com.iluwatar.eda.handler.UserCreatedEventHandler;\nimport com.iluwatar.eda.handler.UserUpdatedEventHandler;\nimport com.iluwatar.eda.model.User;\nimport org.junit.jupiter.api.Test;\n\n/** Event Dispatcher unit tests to assert and verify correct event dispatcher behaviour */\nclass EventDispatcherTest {\n\n  /**\n   * This unit test should register events and event handlers correctly with the event dispatcher\n   * and events should be dispatched accordingly.\n   */\n  @Test\n  void testEventDriverPattern() {\n\n    var dispatcher = spy(new EventDispatcher());\n    var userCreatedEventHandler = spy(new UserCreatedEventHandler());\n    var userUpdatedEventHandler = spy(new UserUpdatedEventHandler());\n    dispatcher.registerHandler(UserCreatedEvent.class, userCreatedEventHandler);\n    dispatcher.registerHandler(UserUpdatedEvent.class, userUpdatedEventHandler);\n\n    var user = new User(\"iluwatar\");\n\n    var userCreatedEvent = new UserCreatedEvent(user);\n    var userUpdatedEvent = new UserUpdatedEvent(user);\n\n    // fire a userCreatedEvent and verify that userCreatedEventHandler has been invoked.\n    dispatcher.dispatch(userCreatedEvent);\n    verify(userCreatedEventHandler).onEvent(userCreatedEvent);\n    verify(dispatcher).dispatch(userCreatedEvent);\n\n    // fire a userCreatedEvent and verify that userUpdatedEventHandler has been invoked.\n    dispatcher.dispatch(userUpdatedEvent);\n    verify(userUpdatedEventHandler).onEvent(userUpdatedEvent);\n    verify(dispatcher).dispatch(userUpdatedEvent);\n  }\n}\n"
  },
  {
    "path": "event-queue/README.md",
    "content": "---\ntitle: \"Event Queue Pattern in Java: Managing Concurrent Events Efficiently\"\nshortTitle: Event Queue\ndescription: \"Learn about the Event Queue design pattern in Java. Discover its best practices, examples, and how to implement it effectively in your Java projects.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Asynchronous\n  - Decoupling\n  - Messaging\n  - Event-driven\n  - Scalability\n---\n\n## Also known as\n\n* Event Stream\n* Message Queue\n\n## Intent of Event Queue Design Pattern\n\nThe Event Queue pattern is designed to manage tasks in an asynchronous manner, allowing applications to handle operations without blocking user interactions or other processes. This improves scalability and system performance.\n\n## Detailed Explanation of Event Queue Pattern with Real-World Examples\n\nReal-world example\n\n> The modern emailing system is an example of the fundamental process behind the event-queue design pattern. When an email is sent, the sender continues their daily tasks without the necessity of an immediate response from the receiver. Additionally, the receiver has the freedom to access and process the email at their leisure. Therefore, this process decouples the sender and receiver so that they are not required to engage with the queue at the same time.\n\nIn plain words\n\n> The buffer between sender and receiver improves maintainability and scalability of a system. Event queues are typically used to organize and carry out interprocess communication (IPC).\n\nWikipedia says\n\n> Message queues (also known as event queues) implement an asynchronous communication pattern between two or more processes/threads whereby the sending and receiving party do not need to interact with the queue at the same time.\n\nSequence diagram\n\n![Event Queue sequence diagram](./etc/event-queue-sequence-diagram.png)\n\n## Programmatic Example of Event Queue Pattern in Java\n\nThis example demonstrates an application using an event queue system to handle audio playback asynchronously.\n\nThe `App` class sets up an instance of `Audio`, plays two sounds, and waits for user input to exit. It demonstrates how an event queue could be used to manage asynchronous operations in a software application.\n\n```java\npublic class App {\n\n    public static void main(String[] args) throws UnsupportedAudioFileException, IOException,\n            InterruptedException {\n        var audio = Audio.getInstance();\n        audio.playSound(audio.getAudioStream(\"./etc/Bass-Drum-1.wav\"), -10.0f);\n        audio.playSound(audio.getAudioStream(\"./etc/Closed-Hi-Hat-1.wav\"), -8.0f);\n\n        LOGGER.info(\"Press Enter key to stop the program...\");\n        try (var br = new BufferedReader(new InputStreamReader(System.in))) {\n            br.read();\n        }\n        audio.stopService();\n    }\n}\n```\n\nThe `Audio` class holds the singleton pattern implementation, manages a queue of audio play requests, and controls thread operations for asynchronous processing.\n\n```java\npublic class Audio {\n    private static final Audio INSTANCE = new Audio();\n\n    private static final int MAX_PENDING = 16;\n\n    private int headIndex;\n\n    private int tailIndex;\n\n    private volatile Thread updateThread = null;\n\n    private final PlayMessage[] pendingAudio = new PlayMessage[MAX_PENDING];\n\n    Audio() {}\n\n    public static Audio getInstance() {\n        return INSTANCE;\n    }\n}\n```\n\nThese methods manage the lifecycle of the thread used to process the audio events. The `init` and `startThread` methods ensure the thread is properly initialized and running.\n\n```java\npublic synchronized void stopService() throws InterruptedException {\n    if(updateThread != null) {\n        updateThread.interrupt();\n        updateThread.join();\n        updateThread = null;\n    }\n}\n\npublic synchronized boolean isServiceRunning() {\n    return updateThread != null && updateThread.isAlive();\n}\n\npublic void init() {\n    if(updateThread == null) {\n        updateThread = new Thread(() -> {\n            while (!Thread.currentThread().isInterrupted()) {\n                update();\n            }\n        });\n        startThread();\n    }\n}\n\nprivate synchronized void startThread() {\n    if (!updateThread.isAlive()) {\n        updateThread.start();\n        headIndex = 0;\n        tailIndex = 0;\n    }\n}\n```\n\nThe `playSound` method checks if the audio is already in the queue and either updates the volume or enqueues a new request, demonstrating the management of asynchronous tasks within the event queue.\n\n```java\npublic void playSound(AudioInputStream stream, float volume) {\n    init();\n    for(var i = headIndex; i != tailIndex; i = (i + 1) % MAX_PENDING) {\n        var playMessage = getPendingAudio()[i];\n        if(playMessage.getStream() == stream) {\n            playMessage.setVolume(Math.max(volume, playMessage.getVolume()));\n            return;\n        }\n    }\n    getPendingAudio()[tailIndex] = new PlayMessage(stream, volume);\n    tailIndex = (tailIndex + 1) % MAX_PENDING;\n}\n```\n\n## When to Use the Event Queue Pattern in Java\n\nThis pattern is applicable in scenarios where tasks can be handled asynchronously outside the main application flow, such as in GUI applications, server-side event handling, or in systems that require task scheduling without immediate execution. In particular:\n\n* The sender does not require a response from the receiver.\n* You wish to decouple the sender & the receiver.\n* You want to process events asynchronously.\n* You have a limited accessibility resource and the asynchronous process is acceptable to reach that.\n\n## Real-World Applications of Event Queue Pattern in Java\n\n* Event-driven architectures\n* GUI frameworks in Java (such as Swing and JavaFX)\n* Server applications handling requests asynchronously\n\n## Benefits and Trade-offs of Event Queue Pattern\n\nBenefits:\n\n* Reduces system coupling.\n* Enhances responsiveness of applications.\n* Improves scalability by allowing event handling to be distributed across multiple threads or processors.\n\nTrade-offs:\n\n* Complexity in managing the event queue.\n* Potential for difficult-to-track bugs due to asynchronous behavior.\n* Overhead of maintaining event queue integrity and performance.\n* As the event queue model decouples the sender-receiver relationship - this means that the event-queue design pattern is unsuitable for scenarios in which the sender requires a response. For example, this is a prominent feature within online multiplayer games, therefore, this approach requires thorough consideration.\n\n## Related Java Design Patterns\n\n* [Command](https://java-design-patterns.com/patterns/command/) (for encapsulating request processing in a command object)\n* [Observer](https://java-design-patterns.com/patterns/observer/) (for subscribing and notifying changes to multiple observers)\n* [Reactor](https://java-design-patterns.com/patterns/reactor/) (handles requests in a non-blocking event-driven manner similar to Event Queue)\n\n## References and Credits\n\n* [Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions](https://amzn.to/3xzSlC2)\n* [Game Programming Patterns](https://amzn.to/3K96fOn)\n* [Java Concurrency in Practice](https://amzn.to/3Ji16mX)\n* [Pattern-Oriented Software Architecture, Volume 2: Patterns for Concurrent and Networked Objects](https://amzn.to/3U2hlcy)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3xtVtPJ)\n* [Event Queue (Game Programming Patterns)](http://gameprogrammingpatterns.com/event-queue.html)\n"
  },
  {
    "path": "event-queue/etc/event-queue.urm.puml",
    "content": "@startuml\npackage com.iluwatar.event.queue {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Audio {\n    - INSTANCE : Audio {static}\n    - LOGGER : Logger {static}\n    - MAX_PENDING : int {static}\n    - headIndex : int\n    - pendingAudio : PlayMessage[]\n    - tailIndex : int\n    - updateThread : Thread\n    ~ Audio()\n    + getAudioStream(filePath : String) : AudioInputStream\n    + getInstance() : Audio {static}\n    + getPendingAudio() : PlayMessage[]\n    + init()\n    + isServiceRunning() : boolean\n    + playSound(stream : AudioInputStream, volume : float)\n    - startThread()\n    + stopService()\n    - update()\n  }\n  class PlayMessage {\n    - stream : AudioInputStream\n    - volume : float\n    + PlayMessage(stream : AudioInputStream, volume : float)\n    + getStream() : AudioInputStream\n    + getVolume() : float\n    - setStream(stream : AudioInputStream)\n    + setVolume(volume : float)\n  }\n}\nAudio -->  \"-INSTANCE\" Audio\n@enduml"
  },
  {
    "path": "event-queue/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>event-queue</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.event.queue.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "event-queue/src/main/java/com/iluwatar/event/queue/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.queue;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport javax.sound.sampled.UnsupportedAudioFileException;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Event or message queues provide an asynchronous communications protocol, meaning that the sender\n * and receiver of the message do not need to interact with the message queue at the same time.\n * Events or messages placed onto the queue are stored until the recipient retrieves them. Event or\n * message queues have implicit or explicit limits on the size of data that may be transmitted in a\n * single message and the number of messages that may remain outstanding on the queue. A queue\n * stores a series of notifications or requests in first-in, first-out order. Sending a notification\n * enqueues the request and returns. The request processor then processes items from the queue at a\n * later time.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   * @throws IOException when there is a problem with the audio file loading\n   * @throws UnsupportedAudioFileException when the loaded audio file is unsupported\n   */\n  public static void main(String[] args)\n      throws UnsupportedAudioFileException, IOException, InterruptedException {\n    var audio = Audio.getInstance();\n    audio.playSound(audio.getAudioStream(\"./etc/Bass-Drum-1.wav\"), -10.0f);\n    audio.playSound(audio.getAudioStream(\"./etc/Closed-Hi-Hat-1.wav\"), -8.0f);\n\n    LOGGER.info(\"Press Enter key to stop the program...\");\n    try (var br = new BufferedReader(new InputStreamReader(System.in))) {\n      br.read();\n    }\n    audio.stopService();\n  }\n}\n"
  },
  {
    "path": "event-queue/src/main/java/com/iluwatar/event/queue/Audio.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.queue;\n\nimport java.io.File;\nimport java.io.IOException;\nimport javax.sound.sampled.AudioInputStream;\nimport javax.sound.sampled.AudioSystem;\nimport javax.sound.sampled.LineUnavailableException;\nimport javax.sound.sampled.UnsupportedAudioFileException;\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/** This class implements the Event Queue pattern. */\n@Slf4j\npublic class Audio {\n  private static final Audio INSTANCE = new Audio();\n\n  private static final int MAX_PENDING = 16;\n\n  private int headIndex;\n\n  private int tailIndex;\n\n  private volatile Thread updateThread = null;\n\n  @Getter private final PlayMessage[] pendingAudio = new PlayMessage[MAX_PENDING];\n\n  // Visible only for testing purposes\n  Audio() {}\n\n  public static Audio getInstance() {\n    return INSTANCE;\n  }\n\n  /** This method stops the Update Method's thread and waits till service stops. */\n  public synchronized void stopService() throws InterruptedException {\n    if (updateThread != null) {\n      updateThread.interrupt();\n    }\n    updateThread.join();\n    updateThread = null;\n  }\n\n  /**\n   * This method check the Update Method's thread is started.\n   *\n   * @return boolean\n   */\n  public synchronized boolean isServiceRunning() {\n    return updateThread != null && updateThread.isAlive();\n  }\n\n  /**\n   * Starts the thread for the Update Method pattern if it was not started previously. Also, when\n   * the thread is ready initializes the indexes of the queue\n   */\n  public void init() {\n    if (updateThread == null) {\n      updateThread =\n          new Thread(\n              () -> {\n                while (!Thread.currentThread().isInterrupted()) {\n                  update();\n                }\n              });\n    }\n    startThread();\n  }\n\n  /** This is a synchronized thread starter. */\n  private synchronized void startThread() {\n    if (!updateThread.isAlive()) {\n      updateThread.start();\n      headIndex = 0;\n      tailIndex = 0;\n    }\n  }\n\n  /**\n   * This method adds a new audio into the queue.\n   *\n   * @param stream is the AudioInputStream for the method\n   * @param volume is the level of the audio's volume\n   */\n  public void playSound(AudioInputStream stream, float volume) {\n    init();\n    // Walk the pending requests.\n    for (var i = headIndex; i != tailIndex; i = (i + 1) % MAX_PENDING) {\n      var playMessage = getPendingAudio()[i];\n      if (playMessage.getStream() == stream) {\n        // Use the larger of the two volumes.\n        playMessage.setVolume(Math.max(volume, playMessage.getVolume()));\n\n        // Don't need to enqueue.\n        return;\n      }\n    }\n    getPendingAudio()[tailIndex] = new PlayMessage(stream, volume);\n    tailIndex = (tailIndex + 1) % MAX_PENDING;\n  }\n\n  /** This method uses the Update Method pattern. It takes the audio from the queue and plays it */\n  private void update() {\n    // If there are no pending requests, do nothing.\n    if (headIndex == tailIndex) {\n      return;\n    }\n    try {\n      var audioStream = getPendingAudio()[headIndex].getStream();\n      headIndex++;\n      var clip = AudioSystem.getClip();\n      clip.open(audioStream);\n      clip.start();\n    } catch (LineUnavailableException e) {\n      LOGGER.trace(\"Error occurred while loading the audio: The line is unavailable\", e);\n    } catch (IOException e) {\n      LOGGER.trace(\"Input/Output error while loading the audio\", e);\n    } catch (IllegalArgumentException e) {\n      LOGGER.trace(\"The system doesn't support the sound: \" + e.getMessage(), e);\n    }\n  }\n\n  /**\n   * Returns the AudioInputStream of a file.\n   *\n   * @param filePath is the path of the audio file\n   * @return AudioInputStream\n   * @throws UnsupportedAudioFileException when the audio file is not supported\n   * @throws IOException when the file is not readable\n   */\n  public AudioInputStream getAudioStream(String filePath)\n      throws UnsupportedAudioFileException, IOException {\n    return AudioSystem.getAudioInputStream(new File(filePath).getAbsoluteFile());\n  }\n}\n"
  },
  {
    "path": "event-queue/src/main/java/com/iluwatar/event/queue/PlayMessage.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.queue;\n\nimport javax.sound.sampled.AudioInputStream;\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** The Event Queue's queue will store the instances of this class. */\n@Getter\n@AllArgsConstructor\npublic class PlayMessage {\n\n  private final AudioInputStream stream;\n\n  @Setter private float volume;\n}\n"
  },
  {
    "path": "event-queue/src/test/java/com/iluwatar/event/queue/AudioTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.queue;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.io.IOException;\nimport javax.sound.sampled.UnsupportedAudioFileException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Testing the Audio service of the Queue */\nclass AudioTest {\n\n  private Audio audio;\n\n  @BeforeEach\n  void createAudioInstance() {\n    audio = new Audio();\n  }\n\n  /**\n   * Test here that the playSound method works correctly\n   *\n   * @throws UnsupportedAudioFileException when the audio file is not supported\n   * @throws IOException when the file is not readable\n   * @throws InterruptedException when the test is interrupted externally\n   */\n  @Test\n  void testPlaySound() throws UnsupportedAudioFileException, IOException, InterruptedException {\n    audio.playSound(audio.getAudioStream(\"./etc/Bass-Drum-1.wav\"), -10.0f);\n    // test that service is started\n    assertTrue(audio.isServiceRunning());\n    // adding a small pause to be sure that the sound is ended\n    Thread.sleep(5000);\n\n    audio.stopService();\n    // test that service is finished\n    assertFalse(audio.isServiceRunning());\n  }\n\n  /**\n   * Test here that the Queue\n   *\n   * @throws UnsupportedAudioFileException when the audio file is not supported\n   * @throws IOException when the file is not readable\n   * @throws InterruptedException when the test is interrupted externally\n   */\n  @Test\n  void testQueue() throws UnsupportedAudioFileException, IOException, InterruptedException {\n    audio.playSound(audio.getAudioStream(\"./etc/Bass-Drum-1.aif\"), -10.0f);\n    audio.playSound(audio.getAudioStream(\"./etc/Bass-Drum-1.aif\"), -10.0f);\n    audio.playSound(audio.getAudioStream(\"./etc/Bass-Drum-1.aif\"), -10.0f);\n    assertTrue(audio.getPendingAudio().length > 0);\n    // test that service is started\n    assertTrue(audio.isServiceRunning());\n    // adding a small pause to be sure that the sound is ended\n    Thread.sleep(10000);\n\n    audio.stopService();\n    // test that service is finished\n    assertFalse(audio.isServiceRunning());\n  }\n}\n"
  },
  {
    "path": "event-sourcing/README.md",
    "content": "---\ntitle: \"Event Sourcing Pattern in Java: Building Immutable Historical Records for Robust Systems\"\nshortTitle: Event Sourcing\ndescription: \"Discover the Event Sourcing design pattern in Java. Learn how it stores state changes as events and benefits complex applications. See examples and explanations on Java Design Patterns.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - Decoupling\n  - Event-driven\n  - Fault tolerance\n  - Messaging\n  - Persistence\n  - Scalability\n  - Transactions\nhead:\n  - - meta\n    - name: keywords\n      content:\n---\n\n## Also known as\n\n* Event Logging\n* Event Streaming\n\n## Intent of Event Sourcing Design Pattern\n\nEvent Sourcing is a design pattern that advocates for the storage of state changes as a sequence of events. Instead of updating a record in a database, all changes are stored as individual events which, when replayed, can recreate the state of an application at any point in time.\n\n## Detailed Explanation of Event Sourcing Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a banking application that tracks all transactions for user accounts. In this system, every deposit, withdrawal, and transfer is recorded as an individual event in an event log. Instead of simply updating the current account balance, each transaction is stored as a discrete event. This approach allows the bank to maintain a complete and immutable history of all account activities. If a discrepancy occurs, the bank can replay the sequence of events to reconstruct the account state at any point in time. This provides a robust audit trail, facilitates debugging, and supports features like transaction rollback and historical data analysis.\n\nIn plain words\n\n> Event Sourcing records all state changes as a sequence of immutable events to ensure reliable state reconstruction and auditability.\n\n[Microsoft's documentation](https://learn.microsoft.com/en-us/azure/architecture/patterns/event-sourcing) says\n\n> The Event Sourcing pattern defines an approach to handling operations on data that's driven by a sequence of events, each of which is recorded in an append-only store. Application code sends a series of events that imperatively describe each action that has occurred on the data to the event store, where they're persisted. Each event represents a set of changes to the data (such as AddedItemToOrder).\n\nArchitecture diagram\n\n![Event Sourcing Architecture Diagram](./etc/event-sourcing-architecture-diagram.png)\n\n## Programmatic Example of Event Sourcing Pattern in Java\n\nIn the programmatic example we transfer some money between bank accounts.\n\nThe `Event` class manages a queue of events and controls thread operations for asynchronous processing. Each event can be seen as a state change that affects the state of the system.\n\n```java\npublic class Event {\n    private static final Event INSTANCE = new Event();\n\n    private static final int MAX_PENDING = 16;\n\n    private int headIndex;\n\n    private int tailIndex;\n\n    private volatile Thread updateThread = null;\n\n    private final EventMessage[] pendingEvents = new EventMessage[MAX_PENDING];\n\n    Event() {}\n\n    public static Event getInstance() {\n        return INSTANCE;\n    }\n}\n```\n\nThe `triggerEvent` method is where the events are created. Each time an event is triggered, it is created and added to the queue. This event contains the details of the state change.\n\n```java\npublic void triggerEvent(EventMessage eventMessage) {\n    init();\n    for(var i = headIndex; i != tailIndex; i = (i + 1) % MAX_PENDING) {\n        var pendingEvent = getPendingEvents()[i];\n        if(pendingEvent.equals(eventMessage)) {\n            return;\n        }\n    }\n    getPendingEvents()[tailIndex] = eventMessage;\n    tailIndex = (tailIndex + 1) % MAX_PENDING;\n}\n```\n\nThe `init` and `startThread` methods ensure the thread is properly initialized and running. The `stopService` method is used to stop the thread when it's no longer needed. These methods manage the lifecycle of the thread used to process the events.\n\n```java\npublic synchronized void stopService() throws InterruptedException {\n    if(updateThread != null) {\n        updateThread.interrupt();\n        updateThread.join();\n        updateThread = null;\n    }\n}\n\npublic synchronized boolean isServiceRunning() {\n    return updateThread != null && updateThread.isAlive();\n}\n\npublic void init() {\n    if(updateThread == null) {\n        updateThread = new Thread(() -> {\n            while (!Thread.currentThread().isInterrupted()) {\n                update();\n            }\n        });\n        startThread();\n    }\n}\n\nprivate synchronized void startThread() {\n    if (!updateThread.isAlive()) {\n        updateThread.start();\n        headIndex = 0;\n        tailIndex = 0;\n    }\n}\n```\n\nThe example is driven by the `App` class and its `main` method.\n\n```java\n@Slf4j\npublic class App {\n\n  public static final int ACCOUNT_OF_DAENERYS = 1;\n\n  public static final int ACCOUNT_OF_JON = 2;\n\n  public static void main(String[] args) {\n\n    var eventProcessor = new DomainEventProcessor(new JsonFileJournal());\n\n    LOGGER.info(\"Running the system first time............\");\n    eventProcessor.reset();\n\n    LOGGER.info(\"Creating the accounts............\");\n\n    eventProcessor.process(new AccountCreateEvent(\n        0, new Date().getTime(), ACCOUNT_OF_DAENERYS, \"Daenerys Targaryen\"));\n\n    eventProcessor.process(new AccountCreateEvent(\n        1, new Date().getTime(), ACCOUNT_OF_JON, \"Jon Snow\"));\n\n    LOGGER.info(\"Do some money operations............\");\n\n    eventProcessor.process(new MoneyDepositEvent(\n        2, new Date().getTime(), ACCOUNT_OF_DAENERYS, new BigDecimal(\"100000\")));\n\n    eventProcessor.process(new MoneyDepositEvent(\n        3, new Date().getTime(), ACCOUNT_OF_JON, new BigDecimal(\"100\")));\n\n    eventProcessor.process(new MoneyTransferEvent(\n        4, new Date().getTime(), new BigDecimal(\"10000\"), ACCOUNT_OF_DAENERYS,\n        ACCOUNT_OF_JON));\n\n    LOGGER.info(\"...............State:............\");\n    LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS).toString());\n    LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_JON).toString());\n\n    LOGGER.info(\"At that point system had a shut down, state in memory is cleared............\");\n    AccountAggregate.resetState();\n\n    LOGGER.info(\"Recover the system by the events in journal file............\");\n\n    eventProcessor = new DomainEventProcessor(new JsonFileJournal());\n    eventProcessor.recover();\n\n    LOGGER.info(\"...............Recovered State:............\");\n    LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS).toString());\n    LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_JON).toString());\n  }\n}\n```\n\nRunning the example produces the following console output.\n\n```\n22:40:47.982 [main] INFO com.iluwatar.event.sourcing.app.App -- Running the system first time............\n22:40:47.984 [main] INFO com.iluwatar.event.sourcing.app.App -- Creating the accounts............\n22:40:47.985 [main] INFO com.iluwatar.event.sourcing.domain.Account -- Some external api for only realtime execution could be called here.\n22:40:48.089 [main] INFO com.iluwatar.event.sourcing.domain.Account -- Some external api for only realtime execution could be called here.\n22:40:48.090 [main] INFO com.iluwatar.event.sourcing.app.App -- Do some money operations............\n22:40:48.090 [main] INFO com.iluwatar.event.sourcing.domain.Account -- Some external api for only realtime execution could be called here.\n22:40:48.095 [main] INFO com.iluwatar.event.sourcing.domain.Account -- Some external api for only realtime execution could be called here.\n22:40:48.099 [main] INFO com.iluwatar.event.sourcing.domain.Account -- Some external api for only realtime execution could be called here.\n22:40:48.099 [main] INFO com.iluwatar.event.sourcing.domain.Account -- Some external api for only realtime execution could be called here.\n22:40:48.101 [main] INFO com.iluwatar.event.sourcing.app.App -- ...............State:............\n22:40:48.104 [main] INFO com.iluwatar.event.sourcing.app.App -- Account{accountNo=1, owner='Daenerys Targaryen', money=90000}\n22:40:48.104 [main] INFO com.iluwatar.event.sourcing.app.App -- Account{accountNo=2, owner='Jon Snow', money=10100}\n22:40:48.104 [main] INFO com.iluwatar.event.sourcing.app.App -- At that point system had a shut down, state in memory is cleared............\n22:40:48.104 [main] INFO com.iluwatar.event.sourcing.app.App -- Recover the system by the events in journal file............\n22:40:48.124 [main] INFO com.iluwatar.event.sourcing.app.App -- ...............Recovered State:............\n22:40:48.124 [main] INFO com.iluwatar.event.sourcing.app.App -- Account{accountNo=1, owner='Daenerys Targaryen', money=90000}\n22:40:48.124 [main] INFO com.iluwatar.event.sourcing.app.App -- Account{accountNo=2, owner='Jon Snow', money=10100}\n```\n\nIn this example, the state of the system can be recreated at any point by replaying the events in the queue. This is a key feature of the Event Sourcing pattern.\n\n## When to Use the Event Sourcing Pattern in Java\n\n* In systems where complete audit trails and historical changes are crucial.\n* In complex domains where the state of an application is derived from a series of changes.\n* For systems that benefit from high availability and scalability as Event Sourcing naturally lends itself to distributed systems.\n\n## Real-World Applications of Event Sourcing Pattern in Java\n\n* Financial systems to track transactions and account balances over time.\n* E-commerce applications for order and inventory management.\n* Real-time data processing systems where event consistency and replayability are critical.\n* [The LMAX Architecture](https://martinfowler.com/articles/lmax.html)\n\n## Benefits and Trade-offs of Event Sourcing Pattern\n\nBenefits:\n\n* Auditability: Each change to the state is recorded, allowing for comprehensive auditing.\n* Replayability: Events can be reprocessed to recreate historical states or move to new states.\n* Scalability: Events can be processed asynchronously and in parallel.\n\nTrade-offs\n\n* Complexity: Implementing and maintaining an event-sourced system can introduce additional complexity.\n* Event store size: Storing every state change can lead to large data volumes.\n* Event versioning: Changes in event structure over time require careful handling to ensure system integrity.\n\n## Related Java Design Patterns\n\n* [Command Query Responsibility Segregation (CQRS)](https://java-design-patterns.com/patterns/cqrs/): Often used together with Event Sourcing to separate read and write responsibilities, enhancing performance and scalability.\n* Snapshot: Used to optimize Event Sourcing systems by periodically saving the current state to avoid replaying a long sequence of events.\n\n## References and Credits\n\n* [Building Microservices: Designing Fine-Grained Systems](https://amzn.to/443WfiS)\n* [Implementing Domain-Driven Design](https://amzn.to/3JgvA8V)\n* [Patterns, Principles, and Practices of Domain-Driven Design](https://amzn.to/3VVhfWX)\n* [Event Sourcing (Martin Fowler)](https://martinfowler.com/eaaDev/EventSourcing.html)\n* [Event Sourcing pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing)\n"
  },
  {
    "path": "event-sourcing/etc/event-sourcing.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.2.0\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"true\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.event.sourcing.event.DomainEvent\" project=\"event-sourcing\" \n    file=\"/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/DomainEvent.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"809\" y=\"161\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.event.sourcing.event.AccountCreateEvent\" project=\"event-sourcing\" \n    file=\"/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/AccountCreateEvent.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"145\" y=\"455\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.event.sourcing.event.MoneyDepositEvent\" project=\"event-sourcing\" \n    file=\"/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyDepositEvent.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"480\" y=\"451\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.event.sourcing.event.MoneyTransferEvent\" project=\"event-sourcing\" \n    file=\"/event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyTransferEvent.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"809\" y=\"472\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.event.sourcing.state.AccountAggregate\" project=\"event-sourcing\" \n    file=\"/event-sourcing/src/main/java/com/iluwatar/event/sourcing/state/AccountAggregate.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"104\" y=\"826\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.event.sourcing.processor.DomainEventProcessor\" \n    project=\"event-sourcing\" \n    file=\"/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/DomainEventProcessor.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"458\" y=\"121\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.event.sourcing.processor.JsonFileJournal\" project=\"event-sourcing\" \n    file=\"/event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"189\" width=\"171\" x=\"69\" y=\"26\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.event.sourcing.domain.Account\" project=\"event-sourcing\" \n    file=\"/event-sourcing/src/main/java/com/iluwatar/event/sourcing/domain/Account.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"472\" y=\"827\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <generalization id=\"9\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <generalization id=\"10\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <association id=\"11\">    \n    <end type=\"SOURCE\" refId=\"6\" navigable=\"false\">      \n      <attribute id=\"12\" name=\"processorJournal\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"13\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"7\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"14\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <association id=\"15\">    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"16\" name=\"accounts\"/>      \n      <multiplicity id=\"17\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"8\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "event-sourcing/etc/event-sourcing.urm.puml",
    "content": "@startuml\npackage com.iluwatar.event.sourcing.processor {\n  class DomainEventProcessor {\n    - processorJournal : JsonFileJournal\n    + DomainEventProcessor()\n    + process(domainEvent : DomainEvent)\n    + recover()\n    + reset()\n  }\n  class JsonFileJournal {\n    - events : List<String>\n    - file : File\n    - index : int\n    + JsonFileJournal()\n    + readNext() : DomainEvent\n    + reset()\n    + write(domainEvent : DomainEvent)\n  }\n}\npackage com.iluwatar.event.sourcing.event {\n  class AccountCreateEvent {\n    - accountNo : int\n    - owner : String\n    + AccountCreateEvent(sequenceId : long, createdTime : long, accountNo : int, owner : String)\n    + getAccountNo() : int\n    + getOwner() : String\n    + process()\n  }\n  abstract class DomainEvent {\n    - createdTime : long\n    - eventClassName : String\n    - realTime : boolean\n    - sequenceId : long\n    + DomainEvent(sequenceId : long, createdTime : long, eventClassName : String)\n    + getCreatedTime() : long\n    + getEventClassName() : String\n    + getSequenceId() : long\n    + isRealTime() : boolean\n    + process() {abstract}\n    + setRealTime(realTime : boolean)\n  }\n  class MoneyDepositEvent {\n    - accountNo : int\n    - money : BigDecimal\n    + MoneyDepositEvent(sequenceId : long, createdTime : long, accountNo : int, money : BigDecimal)\n    + getAccountNo() : int\n    + getMoney() : BigDecimal\n    + process()\n  }\n  class MoneyTransferEvent {\n    - accountNoFrom : int\n    - accountNoTo : int\n    - money : BigDecimal\n    + MoneyTransferEvent(sequenceId : long, createdTime : long, money : BigDecimal, accountNoFrom : int, accountNoTo : int)\n    + getAccountNoFrom() : int\n    + getAccountNoTo() : int\n    + getMoney() : BigDecimal\n    + process()\n  }\n}\npackage com.iluwatar.event.sourcing.app {\n  class App {\n    + ACCOUNT_OF_DAENERYS : int {static}\n    + ACCOUNT_OF_JON : int {static}\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n}\npackage com.iluwatar.event.sourcing.state {\n  class AccountAggregate {\n    - accounts : Map<Integer, Account> {static}\n    - AccountAggregate()\n    + getAccount(accountNo : int) : Account {static}\n    + putAccount(account : Account) {static}\n    + resetState() {static}\n  }\n}\npackage com.iluwatar.event.sourcing.domain {\n  class Account {\n    - LOGGER : Logger {static}\n    - MSG : String {static}\n    - accountNo : int\n    - money : BigDecimal\n    - owner : String\n    + Account(accountNo : int, owner : String)\n    + copy() : Account\n    - depositMoney(money : BigDecimal)\n    + getAccountNo() : int\n    + getMoney() : BigDecimal\n    + getOwner() : String\n    - handleDeposit(money : BigDecimal, realTime : boolean)\n    + handleEvent(accountCreateEvent : AccountCreateEvent)\n    + handleEvent(moneyDepositEvent : MoneyDepositEvent)\n    + handleTransferFromEvent(moneyTransferEvent : MoneyTransferEvent)\n    + handleTransferToEvent(moneyTransferEvent : MoneyTransferEvent)\n    - handleWithdrawal(money : BigDecimal, realTime : boolean)\n    + setMoney(money : BigDecimal)\n    + toString() : String\n    - withdrawMoney(money : BigDecimal)\n  }\n}\nDomainEventProcessor -->  \"-processorJournal\" JsonFileJournal\nAccountCreateEvent --|> DomainEvent \nMoneyDepositEvent --|> DomainEvent \nMoneyTransferEvent --|> DomainEvent \n@enduml"
  },
  {
    "path": "event-sourcing/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>event-sourcing</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n        <groupId>com.fasterxml.jackson.core</groupId>\n        <artifactId>jackson-core</artifactId>\n        <version>2.19.0</version>\n    </dependency>\n    <dependency>\n      <groupId>com.fasterxml.jackson.core</groupId>\n      <artifactId>jackson-databind</artifactId>\n      <version>2.18.3</version>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.event.sourcing.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "event-sourcing/src/main/java/com/iluwatar/event/sourcing/app/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.sourcing.app;\n\nimport com.iluwatar.event.sourcing.event.AccountCreateEvent;\nimport com.iluwatar.event.sourcing.event.MoneyDepositEvent;\nimport com.iluwatar.event.sourcing.event.MoneyTransferEvent;\nimport com.iluwatar.event.sourcing.processor.DomainEventProcessor;\nimport com.iluwatar.event.sourcing.processor.JsonFileJournal;\nimport com.iluwatar.event.sourcing.state.AccountAggregate;\nimport java.math.BigDecimal;\nimport java.util.Date;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Event Sourcing: Instead of storing just the current state of the data in a domain, use an\n * append-only store to record the full series of actions taken on that data. The store acts as the\n * system of record and can be used to materialize the domain objects. This can simplify tasks in\n * complex domains, by avoiding the need to synchronize the data model and the business domain,\n * while improving performance, scalability, and responsiveness. It can also provide consistency for\n * transactional data, and maintain full audit trails and history that can enable compensating\n * actions.\n *\n * <p>This App class is an example usage of an Event Sourcing pattern. As an example, two bank\n * accounts are created, then some money deposit and transfer actions are taken, so a new state of\n * accounts is created. At that point, state is cleared in order to represent a system shut-down.\n * After the shut-down, system state is recovered by re-creating the past events from event\n * journals. Then state is printed so a user can view the last state is same with the state before a\n * system shut-down.\n */\n@Slf4j\npublic class App {\n\n  /** The constant ACCOUNT OF DAENERYS. */\n  public static final int ACCOUNT_OF_DAENERYS = 1;\n\n  /** The constant ACCOUNT OF JON. */\n  public static final int ACCOUNT_OF_JON = 2;\n\n  /**\n   * The entry point of application.\n   *\n   * @param args the input arguments\n   */\n  public static void main(String[] args) {\n\n    var eventProcessor = new DomainEventProcessor(new JsonFileJournal());\n\n    LOGGER.info(\"Running the system first time............\");\n    eventProcessor.reset();\n\n    LOGGER.info(\"Creating the accounts............\");\n\n    eventProcessor.process(\n        new AccountCreateEvent(0, new Date().getTime(), ACCOUNT_OF_DAENERYS, \"Daenerys Targaryen\"));\n\n    eventProcessor.process(\n        new AccountCreateEvent(1, new Date().getTime(), ACCOUNT_OF_JON, \"Jon Snow\"));\n\n    LOGGER.info(\"Do some money operations............\");\n\n    eventProcessor.process(\n        new MoneyDepositEvent(\n            2, new Date().getTime(), ACCOUNT_OF_DAENERYS, new BigDecimal(\"100000\")));\n\n    eventProcessor.process(\n        new MoneyDepositEvent(3, new Date().getTime(), ACCOUNT_OF_JON, new BigDecimal(\"100\")));\n\n    eventProcessor.process(\n        new MoneyTransferEvent(\n            4, new Date().getTime(), new BigDecimal(\"10000\"), ACCOUNT_OF_DAENERYS, ACCOUNT_OF_JON));\n\n    LOGGER.info(\"...............State:............\");\n    LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS).toString());\n    LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_JON).toString());\n\n    LOGGER.info(\"At that point system had a shut down, state in memory is cleared............\");\n    AccountAggregate.resetState();\n\n    LOGGER.info(\"Recover the system by the events in journal file............\");\n\n    eventProcessor = new DomainEventProcessor(new JsonFileJournal());\n    eventProcessor.recover();\n\n    LOGGER.info(\"...............Recovered State:............\");\n    LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS).toString());\n    LOGGER.info(AccountAggregate.getAccount(ACCOUNT_OF_JON).toString());\n  }\n}\n"
  },
  {
    "path": "event-sourcing/src/main/java/com/iluwatar/event/sourcing/domain/Account.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.sourcing.domain;\n\nimport com.iluwatar.event.sourcing.event.AccountCreateEvent;\nimport com.iluwatar.event.sourcing.event.MoneyDepositEvent;\nimport com.iluwatar.event.sourcing.event.MoneyTransferEvent;\nimport com.iluwatar.event.sourcing.state.AccountAggregate;\nimport java.math.BigDecimal;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This is the Account class that holds the account info, the account number, account owner name and\n * money of the account. Account class also have the business logic of events that effects this\n * account.\n *\n * <p>Created by Serdar Hamzaogullari on 06.08.2017.\n */\n@Setter\n@Getter\n@RequiredArgsConstructor\n@Slf4j\npublic class Account {\n\n  private final int accountNo;\n  private final String owner;\n  private BigDecimal money = BigDecimal.ZERO;\n\n  private static final String MSG =\n      \"Some external api for only realtime execution could be called here.\";\n\n  /**\n   * Copy account.\n   *\n   * @return the account\n   */\n  public Account copy() {\n    var account = new Account(accountNo, owner);\n    account.setMoney(money);\n    return account;\n  }\n\n  @Override\n  public String toString() {\n    return \"Account{\"\n        + \"accountNo=\"\n        + accountNo\n        + \", owner='\"\n        + owner\n        + '\\''\n        + \", money=\"\n        + money\n        + '}';\n  }\n\n  private void depositMoney(BigDecimal money) {\n    this.money = this.money.add(money);\n  }\n\n  private void withdrawMoney(BigDecimal money) {\n    this.money = this.money.subtract(money);\n  }\n\n  private void handleDeposit(BigDecimal money, boolean realTime) {\n    depositMoney(money);\n    AccountAggregate.putAccount(this);\n    if (realTime) {\n      LOGGER.info(MSG);\n    }\n  }\n\n  private void handleWithdrawal(BigDecimal money, boolean realTime) {\n    if (this.money.compareTo(money) < 0) {\n      throw new RuntimeException(\"Insufficient Account Balance\");\n    }\n\n    withdrawMoney(money);\n    AccountAggregate.putAccount(this);\n    if (realTime) {\n      LOGGER.info(MSG);\n    }\n  }\n\n  /**\n   * Handles the MoneyDepositEvent.\n   *\n   * @param moneyDepositEvent the money deposit event\n   */\n  public void handleEvent(MoneyDepositEvent moneyDepositEvent) {\n    handleDeposit(moneyDepositEvent.getMoney(), moneyDepositEvent.isRealTime());\n  }\n\n  /**\n   * Handles the AccountCreateEvent.\n   *\n   * @param accountCreateEvent the account created event\n   */\n  public void handleEvent(AccountCreateEvent accountCreateEvent) {\n    AccountAggregate.putAccount(this);\n    if (accountCreateEvent.isRealTime()) {\n      LOGGER.info(MSG);\n    }\n  }\n\n  /**\n   * Handles transfer from account event.\n   *\n   * @param moneyTransferEvent the money transfer event\n   */\n  public void handleTransferFromEvent(MoneyTransferEvent moneyTransferEvent) {\n    handleWithdrawal(moneyTransferEvent.getMoney(), moneyTransferEvent.isRealTime());\n  }\n\n  /**\n   * Handles transfer to account event.\n   *\n   * @param moneyTransferEvent the money transfer event\n   */\n  public void handleTransferToEvent(MoneyTransferEvent moneyTransferEvent) {\n    handleDeposit(moneyTransferEvent.getMoney(), moneyTransferEvent.isRealTime());\n  }\n}\n"
  },
  {
    "path": "event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/AccountCreateEvent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.sourcing.event;\n\nimport com.fasterxml.jackson.annotation.JsonCreator;\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport com.iluwatar.event.sourcing.domain.Account;\nimport com.iluwatar.event.sourcing.state.AccountAggregate;\nimport lombok.Getter;\n\n/**\n * This is the class that implements account created event. Holds the necessary info for an account\n * created event. Implements the process function that finds the event-related domain objects and\n * calls the related domain object's handle event functions\n *\n * <p>Created by Serdar Hamzaogullari on 06.08.2017.\n */\n@Getter\npublic class AccountCreateEvent extends DomainEvent {\n\n  private final int accountNo;\n  private final String owner;\n\n  /**\n   * Instantiates a new Account created event.\n   *\n   * @param sequenceId the sequence id\n   * @param createdTime the created time\n   * @param accountNo the account no\n   * @param owner the owner\n   */\n  @JsonCreator\n  public AccountCreateEvent(\n      @JsonProperty(\"sequenceId\") long sequenceId,\n      @JsonProperty(\"createdTime\") long createdTime,\n      @JsonProperty(\"accountNo\") int accountNo,\n      @JsonProperty(\"owner\") String owner) {\n    super(sequenceId, createdTime, \"AccountCreateEvent\");\n    this.accountNo = accountNo;\n    this.owner = owner;\n  }\n\n  @Override\n  public void process() {\n    var account = AccountAggregate.getAccount(accountNo);\n    if (account != null) {\n      throw new RuntimeException(\"Account already exists\");\n    }\n    account = new Account(accountNo, owner);\n    account.handleEvent(this);\n  }\n}\n"
  },
  {
    "path": "event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/DomainEvent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.sourcing.event;\n\nimport java.io.Serializable;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\nimport lombok.Setter;\n\n/**\n * This is the base class for domain events. All events must extend this class.\n *\n * <p>Created by Serdar Hamzaogullari on 06.08.2017.\n */\n@Setter\n@Getter\n@RequiredArgsConstructor\npublic abstract class DomainEvent implements Serializable {\n\n  private final long sequenceId;\n  private final long createdTime;\n  private final String eventClassName;\n  private boolean realTime = true;\n\n  /** Process. */\n  public abstract void process();\n}\n"
  },
  {
    "path": "event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyDepositEvent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.sourcing.event;\n\nimport com.fasterxml.jackson.annotation.JsonCreator;\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport com.iluwatar.event.sourcing.state.AccountAggregate;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport lombok.Getter;\n\n/**\n * This is the class that implements money deposit event. Holds the necessary info for a money\n * deposit event. Implements the process function that finds the event-related domain objects and\n * calls the related domain object's handle event functions\n *\n * <p>Created by Serdar Hamzaogullari on 06.08.2017.\n */\n@Getter\npublic class MoneyDepositEvent extends DomainEvent {\n\n  private final BigDecimal money;\n  private final int accountNo;\n\n  /**\n   * Instantiates a new Money deposit event.\n   *\n   * @param sequenceId the sequence id\n   * @param createdTime the created time\n   * @param accountNo the account no\n   * @param money the money\n   */\n  @JsonCreator\n  public MoneyDepositEvent(\n      @JsonProperty(\"sequenceId\") long sequenceId,\n      @JsonProperty(\"createdTime\") long createdTime,\n      @JsonProperty(\"accountNo\") int accountNo,\n      @JsonProperty(\"money\") BigDecimal money) {\n    super(sequenceId, createdTime, \"MoneyDepositEvent\");\n    this.money = money;\n    this.accountNo = accountNo;\n  }\n\n  @Override\n  public void process() {\n    var account =\n        Optional.ofNullable(AccountAggregate.getAccount(accountNo))\n            .orElseThrow(() -> new RuntimeException(\"Account not found\"));\n    account.handleEvent(this);\n  }\n}\n"
  },
  {
    "path": "event-sourcing/src/main/java/com/iluwatar/event/sourcing/event/MoneyTransferEvent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.sourcing.event;\n\nimport com.fasterxml.jackson.annotation.JsonCreator;\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport com.iluwatar.event.sourcing.state.AccountAggregate;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport lombok.Getter;\n\n/**\n * This is the class that implements money transfer event. Holds the necessary info for a money\n * transfer event. Implements the process function that finds the event-related domain objects and\n * calls the related domain object's handle event functions\n *\n * <p>Created by Serdar Hamzaogullari on 06.08.2017.\n */\n@Getter\npublic class MoneyTransferEvent extends DomainEvent {\n\n  private final BigDecimal money;\n  private final int accountNoFrom;\n  private final int accountNoTo;\n\n  /**\n   * Instantiates a new Money transfer event.\n   *\n   * @param sequenceId the sequence id\n   * @param createdTime the created time\n   * @param money the money\n   * @param accountNoFrom the account no from\n   * @param accountNoTo the account no to\n   */\n  @JsonCreator\n  public MoneyTransferEvent(\n      @JsonProperty(\"sequenceId\") long sequenceId,\n      @JsonProperty(\"createdTime\") long createdTime,\n      @JsonProperty(\"money\") BigDecimal money,\n      @JsonProperty(\"accountNoFrom\") int accountNoFrom,\n      @JsonProperty(\"accountNoTo\") int accountNoTo) {\n    super(sequenceId, createdTime, \"MoneyTransferEvent\");\n    this.money = money;\n    this.accountNoFrom = accountNoFrom;\n    this.accountNoTo = accountNoTo;\n  }\n\n  @Override\n  public void process() {\n    var accountFrom =\n        Optional.ofNullable(AccountAggregate.getAccount(accountNoFrom))\n            .orElseThrow(() -> new RuntimeException(\"Account not found \" + accountNoFrom));\n    var accountTo =\n        Optional.ofNullable(AccountAggregate.getAccount(accountNoTo))\n            .orElseThrow(() -> new RuntimeException(\"Account not found \" + accountNoTo));\n    accountFrom.handleTransferFromEvent(this);\n    accountTo.handleTransferToEvent(this);\n  }\n}\n"
  },
  {
    "path": "event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/DomainEventProcessor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.sourcing.processor;\n\nimport com.iluwatar.event.sourcing.event.DomainEvent;\n\n/**\n * This is the implementation of event processor. All events are processed by this class. This\n * processor uses eventJournal to persist and recover events.\n *\n * <p>Created by Serdar Hamzaogullari on 06.08.2017.\n */\npublic class DomainEventProcessor {\n\n  private final EventJournal eventJournal;\n\n  public DomainEventProcessor(EventJournal eventJournal) {\n    this.eventJournal = eventJournal;\n  }\n\n  /**\n   * Process.\n   *\n   * @param domainEvent the domain event\n   */\n  public void process(DomainEvent domainEvent) {\n    domainEvent.process();\n    eventJournal.write(domainEvent);\n  }\n\n  /** Reset. */\n  public void reset() {\n    eventJournal.reset();\n  }\n\n  /** Recover. */\n  public void recover() {\n    DomainEvent domainEvent;\n    while ((domainEvent = eventJournal.readNext()) != null) {\n      domainEvent.process();\n    }\n  }\n}\n"
  },
  {
    "path": "event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/EventJournal.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.sourcing.processor;\n\nimport com.iluwatar.event.sourcing.event.DomainEvent;\nimport java.io.File;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Base class for Journaling implementations. */\n@Slf4j\npublic abstract class EventJournal {\n\n  File file;\n\n  /**\n   * Write.\n   *\n   * @param domainEvent the domain event.\n   */\n  abstract void write(DomainEvent domainEvent);\n\n  /** Reset. */\n  void reset() {\n    if (file.delete()) {\n      LOGGER.info(\"File cleared successfully............\");\n    }\n  }\n\n  /**\n   * Read domain event.\n   *\n   * @return the domain event.\n   */\n  abstract DomainEvent readNext();\n}\n"
  },
  {
    "path": "event-sourcing/src/main/java/com/iluwatar/event/sourcing/processor/JsonFileJournal.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.sourcing.processor;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.iluwatar.event.sourcing.event.AccountCreateEvent;\nimport com.iluwatar.event.sourcing.event.DomainEvent;\nimport com.iluwatar.event.sourcing.event.MoneyDepositEvent;\nimport com.iluwatar.event.sourcing.event.MoneyTransferEvent;\nimport java.io.BufferedReader;\nimport java.io.BufferedWriter;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.io.OutputStreamWriter;\nimport java.nio.charset.StandardCharsets;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * This is the implementation of event journal. This implementation serialize/deserialize the events\n * with JSON and writes/reads them on a Journal.json file at the working directory.\n *\n * <p>Created by Serdar Hamzaogullari on 06.08.2017.\n */\npublic class JsonFileJournal extends EventJournal {\n\n  private final List<String> events = new ArrayList<>();\n  private int index = 0;\n\n  /** Instantiates a new Json file journal. */\n  public JsonFileJournal() {\n    file = new File(\"Journal.json\");\n    if (file.exists()) {\n      try (var input =\n          new BufferedReader(\n              new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {\n        String line;\n        while ((line = input.readLine()) != null) {\n          events.add(line);\n        }\n      } catch (IOException e) {\n        throw new RuntimeException(e);\n      }\n    } else {\n      reset();\n    }\n  }\n\n  /**\n   * Write.\n   *\n   * @param domainEvent the domain event\n   */\n  @Override\n  public void write(DomainEvent domainEvent) {\n    var mapper = new ObjectMapper();\n    try (var output =\n        new BufferedWriter(\n            new OutputStreamWriter(new FileOutputStream(file, true), StandardCharsets.UTF_8))) {\n      var eventString = mapper.writeValueAsString(domainEvent);\n      output.write(eventString + \"\\r\\n\");\n    } catch (IOException e) {\n      throw new RuntimeException(e);\n    }\n  }\n\n  /**\n   * Read the next domain event.\n   *\n   * @return the domain event\n   */\n  public DomainEvent readNext() {\n    if (index >= events.size()) {\n      return null;\n    }\n    var event = events.get(index);\n    index++;\n\n    var mapper = new ObjectMapper();\n    DomainEvent domainEvent;\n    try {\n      var jsonElement = mapper.readTree(event);\n      var eventClassName = jsonElement.get(\"eventClassName\").asText();\n      domainEvent =\n          switch (eventClassName) {\n            case \"AccountCreateEvent\" -> mapper.treeToValue(jsonElement, AccountCreateEvent.class);\n            case \"MoneyDepositEvent\" -> mapper.treeToValue(jsonElement, MoneyDepositEvent.class);\n            case \"MoneyTransferEvent\" -> mapper.treeToValue(jsonElement, MoneyTransferEvent.class);\n            default -> throw new RuntimeException(\"Journal Event not recognized\");\n          };\n    } catch (JsonProcessingException jsonProcessingException) {\n      throw new RuntimeException(\"Failed to convert JSON\");\n    }\n\n    domainEvent.setRealTime(false);\n    return domainEvent;\n  }\n}\n"
  },
  {
    "path": "event-sourcing/src/main/java/com/iluwatar/event/sourcing/state/AccountAggregate.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.event.sourcing.state;\n\nimport com.iluwatar.event.sourcing.domain.Account;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Optional;\n\n/**\n * This is the static accounts map holder class. This class holds the state of the accounts.\n *\n * <p>Created by Serdar Hamzaogullari on 06.08.2017.\n */\npublic class AccountAggregate {\n\n  private static Map<Integer, Account> accounts = new HashMap<>();\n\n  private AccountAggregate() {}\n\n  /**\n   * Put account.\n   *\n   * @param account the account\n   */\n  public static void putAccount(Account account) {\n    accounts.put(account.getAccountNo(), account);\n  }\n\n  /**\n   * Gets account.\n   *\n   * @param accountNo the account no\n   * @return the copy of the account or null if not found\n   */\n  public static Account getAccount(int accountNo) {\n    return Optional.of(accountNo).map(accounts::get).map(Account::copy).orElse(null);\n  }\n\n  /** Reset state. */\n  public static void resetState() {\n    accounts = new HashMap<>();\n  }\n}\n"
  },
  {
    "path": "event-sourcing/src/test/java/IntegrationTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport static com.iluwatar.event.sourcing.app.App.ACCOUNT_OF_DAENERYS;\nimport static com.iluwatar.event.sourcing.app.App.ACCOUNT_OF_JON;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.event.sourcing.event.AccountCreateEvent;\nimport com.iluwatar.event.sourcing.event.MoneyDepositEvent;\nimport com.iluwatar.event.sourcing.event.MoneyTransferEvent;\nimport com.iluwatar.event.sourcing.processor.DomainEventProcessor;\nimport com.iluwatar.event.sourcing.processor.JsonFileJournal;\nimport com.iluwatar.event.sourcing.state.AccountAggregate;\nimport java.math.BigDecimal;\nimport java.util.Date;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/**\n * Integration Test for Event-Sourcing state recovery\n *\n * <p>Created by Serdar Hamzaogullari on 19.08.2017.\n */\nclass IntegrationTest {\n\n  /** The Domain event processor. */\n  private DomainEventProcessor eventProcessor;\n\n  /** Initialize. */\n  @BeforeEach\n  void initialize() {\n    eventProcessor = new DomainEventProcessor(new JsonFileJournal());\n  }\n\n  /** Test state recovery. */\n  @Test\n  void testStateRecovery() {\n    eventProcessor.reset();\n\n    eventProcessor.process(\n        new AccountCreateEvent(0, new Date().getTime(), ACCOUNT_OF_DAENERYS, \"Daenerys Targaryen\"));\n\n    eventProcessor.process(\n        new AccountCreateEvent(1, new Date().getTime(), ACCOUNT_OF_JON, \"Jon Snow\"));\n\n    eventProcessor.process(\n        new MoneyDepositEvent(\n            2, new Date().getTime(), ACCOUNT_OF_DAENERYS, new BigDecimal(\"100000\")));\n\n    eventProcessor.process(\n        new MoneyDepositEvent(3, new Date().getTime(), ACCOUNT_OF_JON, new BigDecimal(\"100\")));\n\n    eventProcessor.process(\n        new MoneyTransferEvent(\n            4, new Date().getTime(), new BigDecimal(\"10000\"), ACCOUNT_OF_DAENERYS, ACCOUNT_OF_JON));\n\n    var accountOfDaenerysBeforeShotDown = AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS);\n    var accountOfJonBeforeShotDown = AccountAggregate.getAccount(ACCOUNT_OF_JON);\n\n    AccountAggregate.resetState();\n\n    eventProcessor = new DomainEventProcessor(new JsonFileJournal());\n    eventProcessor.recover();\n\n    var accountOfDaenerysAfterShotDown = AccountAggregate.getAccount(ACCOUNT_OF_DAENERYS);\n    var accountOfJonAfterShotDown = AccountAggregate.getAccount(ACCOUNT_OF_JON);\n\n    assertEquals(\n        accountOfDaenerysBeforeShotDown.getMoney(), accountOfDaenerysAfterShotDown.getMoney());\n    assertEquals(accountOfJonBeforeShotDown.getMoney(), accountOfJonAfterShotDown.getMoney());\n  }\n}\n"
  },
  {
    "path": "execute-around/README.md",
    "content": "---\ntitle: \"Execute Around Pattern in Java: Encapsulating Pre and Post Execution Steps\"\nshortTitle: Execute Around\ndescription: \"Explore the Execute Around Pattern in Java with detailed explanations, real-world examples, and best practices. Learn how to implement this design pattern to streamline resource management.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Closure\n  - Code simplification\n  - Encapsulation\n  - Functional decomposition\n  - Resource management\nhead:\n  - - meta\n    - name: keywords\n      content:\n---\n\n## Also known as\n\n* Around Method Pattern\n* Resource Block Management\n\n## Intent of Execute Around Design Pattern\n\nReal-world business applications often require executing necessary operations before and after the business method invocation. The Execute Around Pattern in Java provides a way to encapsulate these operations, enhancing code readability and reusability.\n\n## Detailed Explanation of Execute Around Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy for the Execute Around pattern can be found in the use of rental cars. When you rent a car, the rental company handles all the setup (cleaning the car, filling it with gas, ensuring it's in good condition) and cleanup (checking the car back in, inspecting it for damage, refueling it if necessary) processes for you. As a customer, you simply use the car for your intended purpose without worrying about the setup and cleanup. This pattern of abstracting away the repetitive tasks around the main operation is similar to the Execute Around pattern in software, where the setup and cleanup of resources are handled by a reusable method, allowing the main logic to be executed seamlessly.\n\nIn plain words\n\n> Execute Around idiom handles boilerplate code before and after business method.\n\n[Stack Overflow](https://stackoverflow.com/questions/341971/what-is-the-execute-around-idiom) says\n\n> Basically it's the pattern where you write a method to do things which are always required, e.g. resource allocation and clean-up, and make the caller pass in \"what we want to do with the resource\".\n\nFlowchart\n\n![Execute Around flowchart](./etc/execute-around-flowchart.png)\n\n## Programmatic Example of Execute Around Pattern in Java\n\nThe Execute Around Pattern is a design pattern that is widely used in Java programming to manage resource allocation and deallocation. It ensures that important setup and cleanup operations are performed reliably around a core business operation. This pattern is particularly useful for resource management, such as handling files, databases, or network connections in Java applications.\n\nA class needs to be provided for writing text strings to files. To make it easy for the user, the service class opens and closes the file automatically. The user only has to specify what is written into which file.\n\n`SimpleFileWriter` class implements the Execute Around idiom. It takes `FileWriterAction` as a constructor argument allowing the user to specify what gets written into the file.\n\n```java\n\n@FunctionalInterface\npublic interface FileWriterAction {\n    void writeFile(FileWriter writer) throws IOException;\n}\n\n@Slf4j\npublic class SimpleFileWriter {\n    public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {\n        LOGGER.info(\"Opening the file\");\n        try (var writer = new FileWriter(filename)) {\n            LOGGER.info(\"Executing the action\");\n            action.writeFile(writer);\n            LOGGER.info(\"Closing the file\");\n        }\n    }\n}\n```\n\nThe following code demonstrates how `SimpleFileWriter` is used. `Scanner` is used to print the file contents after the writing finishes.\n\n```java\n  public static void main(String[] args) throws IOException {\n\n    // create the file writer and execute the custom action\n    FileWriterAction writeHello = writer -> writer.write(\"Gandalf was here\");\n    new SimpleFileWriter(\"testfile.txt\", writeHello);\n\n    // print the file contents\n    try (var scanner = new Scanner(new File(\"testfile.txt\"))) {\n        while (scanner.hasNextLine()) {\n            LOGGER.info(scanner.nextLine());\n        }\n    }\n}\n```\n\nHere's the console output.\n\n```\n21:18:07.185 [main] INFO com.iluwatar.execute.around.SimpleFileWriter - Opening the file\n21:18:07.188 [main] INFO com.iluwatar.execute.around.SimpleFileWriter - Executing the action\n21:18:07.189 [main] INFO com.iluwatar.execute.around.SimpleFileWriter - Closing the file\n21:18:07.199 [main] INFO com.iluwatar.execute.around.App - Gandalf was here\n```\n\n## When to Use the Execute Around Pattern in Java\n\nWhen to use the Execute Around Pattern in Java:\n\n* Useful in scenarios requiring repetitive setup and cleanup activities, particularly in resource management (e.g., files, network connections, database sessions).\n* Ideal for ensuring proper resource handling and cleanup in the face of exceptions, ensuring resources do not leak.\n* Suitable in any Java application where the same preparation and finalization steps are executed around varying core functionalities.\n\n## Real-World Applications of Execute Around Pattern in Java\n\nIn real-world Java applications, the Execute Around Pattern is applied in these scenarios:\n\n* Java's try-with-resources statement, which ensures that resources are closed after execution regardless of whether an exception was thrown.\n* Frameworks like Spring for managing database transactions, where predefined cleanup or rollback operations are performed depending on the execution outcome.\n\n## Benefits and Trade-offs of Execute Around Pattern\n\nImplementing the Execute Around Pattern in Java offers several benefits and trade-offs.\n\nBenefits:\n\n* Reduces boilerplate code by abstracting routine setup and cleanup tasks.\n* Increases code clarity and maintainability by separating business logic from resource management.\n* Ensures robustness by automatically handling resource cleanup, even in error situations.\n\nTrade-offs:\n\n* Introduces additional abstraction layers, which might increase complexity and obscure control flow for some developers.\n* May require more sophisticated understanding of closures and functional interfaces in Java.\n\n## Related Java Design Patterns\n\n* [Template Method](https://java-design-patterns.com/patterns/template-method/): Similar in concept but differs in that it uses inheritance and abstract classes, while Execute Around typically uses interfaces and lambdas.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Shares the concept of adding functionality around a core component; can be extended to wrap additional behaviors dynamically.\n\n## References and Credits\n\n* [Effective Java](https://amzn.to/4aDdWbs)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3vUGApm)\n* [Functional Programming in Java](https://amzn.to/3JUIc5Q)\n"
  },
  {
    "path": "execute-around/etc/execute-around.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.SimpleFileWriter\" project=\"execute-around\" \n    file=\"/execute-around/src/main/java/com/iluwatar/SimpleFileWriter.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"261\" x=\"213\" y=\"298\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"2\" language=\"java\" name=\"com.iluwatar.FileWriterAction\" project=\"execute-around\" \n    file=\"/execute-around/src/main/java/com/iluwatar/FileWriterAction.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"164\" x=\"514\" y=\"298\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "execute-around/etc/execute-around.urm.puml",
    "content": "@startuml\npackage com.iluwatar.execute.around {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  interface FileWriterAction {\n    + writeFile(FileWriter) {abstract}\n  }\n  class SimpleFileWriter {\n    + SimpleFileWriter(filename : String, action : FileWriterAction)\n  }\n}\n@enduml"
  },
  {
    "path": "execute-around/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>execute-around</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-migrationsupport</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.execute.around.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "execute-around/src/main/java/com/iluwatar/execute/around/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.execute.around;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.Scanner;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Execute Around idiom specifies executable code before and after a method. Typically, the\n * idiom is used when the API has methods to be executed in pairs, such as resource\n * allocation/deallocation or lock acquisition/release.\n *\n * <p>In this example, we have {@link SimpleFileWriter} class that opens and closes the file for the\n * user. The user specifies only what to do with the file by providing the {@link FileWriterAction}\n * implementation.\n */\n@Slf4j\npublic class App {\n\n  /** Program entry point. */\n  public static void main(String[] args) throws IOException {\n\n    // create the file writer and execute the custom action\n    FileWriterAction writeHello = writer -> writer.write(\"Gandalf was here\");\n    new SimpleFileWriter(\"testfile.txt\", writeHello);\n\n    // print the file contents\n    try (var scanner = new Scanner(new File(\"testfile.txt\"))) {\n      while (scanner.hasNextLine()) {\n        LOGGER.info(scanner.nextLine());\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "execute-around/src/main/java/com/iluwatar/execute/around/FileWriterAction.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.execute.around;\n\nimport java.io.FileWriter;\nimport java.io.IOException;\n\n/** Interface for specifying what to do with the file resource. */\n@FunctionalInterface\npublic interface FileWriterAction {\n\n  void writeFile(FileWriter writer) throws IOException;\n}\n"
  },
  {
    "path": "execute-around/src/main/java/com/iluwatar/execute/around/SimpleFileWriter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.execute.around;\n\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * SimpleFileWriter handles opening and closing file for the user. The user only has to specify what\n * to do with the file resource through {@link FileWriterAction} parameter.\n */\n@Slf4j\npublic class SimpleFileWriter {\n\n  /** Constructor. */\n  public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {\n    LOGGER.info(\"Opening the file\");\n    try (var writer = new FileWriter(filename)) {\n      LOGGER.info(\"Executing the action\");\n      action.writeFile(writer);\n      LOGGER.info(\"Closing the file\");\n    }\n  }\n}\n"
  },
  {
    "path": "execute-around/src/test/java/com/iluwatar/execute/around/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.execute.around;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport java.io.File;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests execute-around example. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n\n  @BeforeEach\n  @AfterEach\n  void cleanup() {\n    var file = new File(\"testfile.txt\");\n    file.delete();\n  }\n}\n"
  },
  {
    "path": "execute-around/src/test/java/com/iluwatar/execute/around/SimpleFileWriterTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.execute.around;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.file.Files;\nimport lombok.SneakyThrows;\nimport org.junit.Rule;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport;\nimport org.junit.rules.TemporaryFolder;\n\n/** SimpleFileWriterTest */\n@EnableRuleMigrationSupport\nclass SimpleFileWriterTest {\n\n  @Rule public final TemporaryFolder testFolder = new TemporaryFolder();\n\n  @Test\n  void testWriterNotNull() throws Exception {\n    final var temporaryFile = this.testFolder.newFile();\n    new SimpleFileWriter(temporaryFile.getPath(), Assertions::assertNotNull);\n  }\n\n  @Test\n  void testCreatesNonExistentFile() throws Exception {\n    final var nonExistingFile = new File(this.testFolder.getRoot(), \"non-existing-file\");\n    assertFalse(nonExistingFile.exists());\n\n    new SimpleFileWriter(nonExistingFile.getPath(), Assertions::assertNotNull);\n    assertTrue(nonExistingFile.exists());\n  }\n\n  @Test\n  void testContentsAreWrittenToFile() throws Exception {\n    final var testMessage = \"Test message\";\n\n    final var temporaryFile = this.testFolder.newFile();\n    assertTrue(temporaryFile.exists());\n\n    new SimpleFileWriter(temporaryFile.getPath(), writer -> writer.write(testMessage));\n    assertTrue(Files.lines(temporaryFile.toPath()).allMatch(testMessage::equals));\n  }\n\n  @Test\n  @SneakyThrows\n  void testRipplesIoExceptionOccurredWhileWriting() {\n    var message = \"Some error\";\n    final var temporaryFile = this.testFolder.newFile();\n    assertThrows(\n        IOException.class,\n        () ->\n            new SimpleFileWriter(\n                temporaryFile.getPath(),\n                writer -> {\n                  throw new IOException(\"error\");\n                }),\n        message);\n  }\n}\n"
  },
  {
    "path": "extension-objects/README.md",
    "content": "---\ntitle: \"Extension Objects Pattern in Java: Enhancing Object Functionality Flexibly\"\nshortTitle: Extension Objects\ndescription: \"Learn about the Extension Objects Design Pattern in Java. Understand its purpose, benefits, and implementation with examples to enhance your software design.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Encapsulation\n  - Extensibility\n  - Object composition\n  - Polymorphism\n---\n\n## Also known as\n\n* Interface Extensions\n\n## Intent of Extension Objects Design Pattern\n\nThe Extension Objects pattern allows for the flexible extension of an object's behavior without modifying its structure, by attaching additional objects that can dynamically add new functionality.\n\n## Detailed Explanation of Extension Objects Pattern with Real-World Examples\n\nReal-world example\n\n> An analogous real-world example of the Extension Objects design pattern can be found in modular kitchen appliances. Consider a base blender unit to which different attachments can be added, such as a food processor, juicer, or grinder. Each attachment adds new functionality to the blender without altering the base unit itself. Users can dynamically switch between different functionalities based on their current needs, making the blender highly versatile and adaptable to various tasks. This mirrors the Extension Objects pattern in software, where new functionalities are added to an object dynamically and contextually, enhancing flexibility and reuse.\n\nIn plain words\n\n> The Extension Objects pattern is used to dynamically add functionality to objects without modifying their core classes. It is a behavioural design pattern used for adding new functionality to existing classes and objects within a program. This pattern provides programmers with the ability to extend/modify class functionality without having to refactor existing source code.\n\nWikipedia says\n\n> In object-oriented computer programming, an extension objects pattern is a design pattern added to an object after the original object was compiled. The modified object is often a class, a prototype or a type. Extension object patterns are features of some object-oriented programming languages. There is no syntactic difference between calling an extension method and calling a method declared in the type definition.\n\nSequence diagram\n\n![Extension Objects sequence diagram](./etc/extension-objects-sequence-diagram.png)\n\n## Programmatic Example of Extension Objects Pattern in Java\n\nThe Extension Objects pattern allows for the flexible extension of an object's behavior without modifying its structure, by attaching additional objects that can dynamically add new functionality.\n\nIn this Java implementation, we have three types of units: `SoldierUnit`, `SergeantUnit`, and `CommanderUnit`. Each unit can have extensions that provide additional functionality. The extensions are `SoldierExtension`, `SergeantExtension`, and `CommanderExtension`.\n\nThe `Unit` class is the base class for all units. It has a method `getUnitExtension` that returns an extension object based on the extension name.\n\n```java\npublic abstract class Unit {\n  private String name;\n\n  protected Unit(String name) {\n    this.name = name;\n  }\n\n  public String getName() {\n    return name;\n  }\n\n  public abstract UnitExtension getUnitExtension(String extensionName);\n}\n```\n\nThe `UnitExtension` interface is the base interface for all extensions. Each specific extension will implement this interface.\n\n```java\npublic interface UnitExtension {\n  String getName();\n}\n```\n\nThe `SoldierUnit` class is a specific type of unit. It overrides the `getUnitExtension` method to return a `SoldierExtension` object.\n\n```java\npublic class SoldierUnit extends Unit {\n  public SoldierUnit(String name) {\n    super(name);\n  }\n\n  @Override\n  public UnitExtension getUnitExtension(String extensionName) {\n    if (\"SoldierExtension\".equals(extensionName)) {\n      return new SoldierExtension(this);\n    }\n    return null;\n  }\n}\n```\n\nThe `SoldierExtension` class is a specific type of extension. It implements the `UnitExtension` interface and provides additional functionality for the `SoldierUnit`.\n\n```java\npublic class SoldierExtension implements UnitExtension {\n  private SoldierUnit unit;\n\n  public SoldierExtension(SoldierUnit unit) {\n    this.unit = unit;\n  }\n\n  @Override\n  public String getName() {\n    return \"SoldierExtension\";\n  }\n\n  public void soldierReady() {\n    // additional functionality for SoldierUnit\n  }\n}\n```\n\nIn the `main` application, we create different types of units and check for each unit to have an extension. If the extension exists, we call the specific method on the extension object.\n\n```java\npublic class App {\n  public static void main(String[] args) {\n    var soldierUnit = new SoldierUnit(\"SoldierUnit1\");\n    var sergeantUnit = new SergeantUnit(\"SergeantUnit1\");\n    var commanderUnit = new CommanderUnit(\"CommanderUnit1\");\n\n    checkExtensionsForUnit(soldierUnit);\n    checkExtensionsForUnit(sergeantUnit);\n    checkExtensionsForUnit(commanderUnit);\n  }\n\n  private static void checkExtensionsForUnit(Unit unit) {\n    var extension = \"SoldierExtension\";\n    Optional.ofNullable(unit.getUnitExtension(extension))\n        .map(e -> (SoldierExtension) e)\n        .ifPresentOrElse(SoldierExtension::soldierReady, () -> System.out.println(unit.getName() + \" without \" + extension));\n  }\n}\n```\n\nThis produces the following console output.\n\n```\n22:58:03.779 [main] INFO concreteextensions.Soldier -- [Soldier] SoldierUnit1 is ready!\n22:58:03.781 [main] INFO App -- SoldierUnit1 without SergeantExtension\n22:58:03.782 [main] INFO App -- SoldierUnit1 without CommanderExtension\n22:58:03.782 [main] INFO App -- SergeantUnit1 without SoldierExtension\n22:58:03.783 [main] INFO concreteextensions.Sergeant -- [Sergeant] SergeantUnit1 is ready!\n22:58:03.783 [main] INFO App -- SergeantUnit1 without CommanderExtension\n22:58:03.783 [main] INFO App -- CommanderUnit1 without SoldierExtension\n22:58:03.783 [main] INFO App -- CommanderUnit1 without SergeantExtension\n22:58:03.783 [main] INFO concreteextensions.Commander -- [Commander] CommanderUnit1 is ready!\n```\n\nThis example demonstrates how the Extension Objects pattern allows for the flexible extension of an object's behavior without modifying its structure.\n\n## When to Use the Extension Objects Pattern in Java\n\nThis pattern is applicable in scenarios where an object's functionality needs to be extended at runtime, avoiding the complications of subclassing. It's particularly useful in systems where object capabilities need to be augmented post-deployment, or where the capabilities might vary significantly across instances.\n\n## Real-World Applications of Extension Objects Pattern in Java\n\n* Extending services in an application server without altering existing code.\n* Plugins in IDEs like IntelliJ IDEA or Eclipse to add features to the base application.\n* Enabling additional features in enterprise software based on license levels.\n* [OpenDoc](https://en.wikipedia.org/wiki/OpenDoc)\n* [Object Linking and Embedding](https://en.wikipedia.org/wiki/Object_Linking_and_Embedding)\n\n## Benefits and Trade-offs of Extension Objects Pattern\n\nBenefits:\n\n* Enhances flexibility by allowing dynamic extension of an object's capabilities.\n* Promotes loose coupling between the base object and its extensions.\n* Supports the [Open/Closed Principle](https://java-design-patterns.com/principles/#open-closed-principle) by keeping the object open for extension but closed for modification.\n\nTrade-offs:\n\n* Can increase complexity due to the management of extension objects.\n* May introduce performance overhead if the interaction between objects and extensions is not efficiently designed.\n\n## Related Java Design Patterns\n\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Similar in intent to add responsibilities dynamically, but uses a different structure.\n* [Composite](https://java-design-patterns.com/patterns/composite/): Also manages a group of objects, which can be seen as a form of extension.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Offers an alternative way to change the behavior of an object dynamically.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/4aBMuuL)\n* [Pattern-Oriented Software Architecture: A System of Patterns](https://amzn.to/3Q9YOtX)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3W6IZYQ)\n"
  },
  {
    "path": "extension-objects/etc/extension-objects.urm.puml",
    "content": "@startuml\n@enduml"
  },
  {
    "path": "extension-objects/etc/extension_obj.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.2.0\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"concreteextensions.Soldier\" project=\"extension-objects\" \n    file=\"/extension-objects/src/main/java/concreteextensions/Soldier.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"483\" y=\"339\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"units.Unit\" project=\"extension-objects\" \n    file=\"/extension-objects/src/main/java/units/Unit.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"192\" y=\"115\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"3\" language=\"java\" name=\"abstractextensions.SoldierExtension\" project=\"extension-objects\" \n    file=\"/extension-objects/src/main/java/abstractextensions/SoldierExtension.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"510\" y=\"229\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"4\" language=\"java\" name=\"abstractextensions.UnitExtension\" project=\"extension-objects\" \n    file=\"/extension-objects/src/main/java/abstractextensions/UnitExtension.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"510\" y=\"116\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"5\" language=\"java\" name=\"units.SoldierUnit\" project=\"extension-objects\" \n    file=\"/extension-objects/src/main/java/units/SoldierUnit.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"157\" y=\"355\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"6\" language=\"java\" name=\"concreteextensions.Sergeant\" project=\"extension-objects\" \n    file=\"/extension-objects/src/main/java/concreteextensions/Sergeant.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"650\" y=\"375\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"7\" language=\"java\" name=\"abstractextensions.SergeantExtension\" project=\"extension-objects\" \n    file=\"/extension-objects/src/main/java/abstractextensions/SergeantExtension.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"672\" y=\"230\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"8\" language=\"java\" name=\"units.SergeantUnit\" project=\"extension-objects\" \n    file=\"/extension-objects/src/main/java/units/SergeantUnit.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"315\" y=\"460\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"9\" language=\"java\" name=\"units.CommanderUnit\" project=\"extension-objects\" \n    file=\"/extension-objects/src/main/java/units/CommanderUnit.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"99\" width=\"210\" x=\"429\" y=\"476\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"10\" language=\"java\" name=\"concreteextensions.Commander\" project=\"extension-objects\" \n    file=\"/extension-objects/src/main/java/concreteextensions/Commander.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"823\" y=\"477\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"11\" language=\"java\" name=\"abstractextensions.CommanderExtension\" project=\"extension-objects\" \n    file=\"/extension-objects/src/main/java/abstractextensions/CommanderExtension.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"827\" y=\"217\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <realization id=\"12\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </realization>  \n  <realization id=\"13\">    \n    <end type=\"SOURCE\" refId=\"10\"/>    \n    <end type=\"TARGET\" refId=\"11\"/>  \n  </realization>  \n  <generalization id=\"14\">    \n    <end type=\"SOURCE\" refId=\"9\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </generalization>  \n  <association id=\"15\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"16\" name=\"unit\"/>      \n      <multiplicity id=\"17\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"18\">    \n    <end type=\"SOURCE\" refId=\"10\" navigable=\"false\">      \n      <attribute id=\"19\" name=\"unit\"/>      \n      <multiplicity id=\"20\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"9\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"21\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"22\" name=\"unitExtension\"/>      \n      <multiplicity id=\"23\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"24\">    \n    <end type=\"SOURCE\" refId=\"6\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </realization>  \n  <generalization id=\"25\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </generalization>  \n  <generalization id=\"26\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </generalization>  \n  <generalization id=\"27\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </generalization>  \n  <generalization id=\"28\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </generalization>  \n  <association id=\"29\">    \n    <end type=\"SOURCE\" refId=\"6\" navigable=\"false\">      \n      <attribute id=\"30\" name=\"unit\"/>      \n      <multiplicity id=\"31\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"8\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"32\">    \n    <end type=\"SOURCE\" refId=\"11\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </generalization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "extension-objects/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>extension-objects</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "extension-objects/src/main/java/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport abstractextensions.CommanderExtension;\nimport abstractextensions.SergeantExtension;\nimport abstractextensions.SoldierExtension;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport org.slf4j.LoggerFactory;\nimport units.CommanderUnit;\nimport units.SergeantUnit;\nimport units.SoldierUnit;\nimport units.Unit;\n\n/**\n * Anticipate that an object’s interface needs to be extended in the future. Additional interfaces\n * are defined by extension objects.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    // Create 3 different units\n    var soldierUnit = new SoldierUnit(\"SoldierUnit1\");\n    var sergeantUnit = new SergeantUnit(\"SergeantUnit1\");\n    var commanderUnit = new CommanderUnit(\"CommanderUnit1\");\n\n    // check for each unit to have an extension\n    checkExtensionsForUnit(soldierUnit);\n    checkExtensionsForUnit(sergeantUnit);\n    checkExtensionsForUnit(commanderUnit);\n  }\n\n  private static void checkExtensionsForUnit(Unit unit) {\n    final var logger = LoggerFactory.getLogger(App.class);\n\n    var name = unit.getName();\n    Function<String, Runnable> func = e -> () -> logger.info(\"{} without {}\", name, e);\n\n    var extension = \"SoldierExtension\";\n    Optional.ofNullable(unit.getUnitExtension(extension))\n        .map(e -> (SoldierExtension) e)\n        .ifPresentOrElse(SoldierExtension::soldierReady, func.apply(extension));\n\n    extension = \"SergeantExtension\";\n    Optional.ofNullable(unit.getUnitExtension(extension))\n        .map(e -> (SergeantExtension) e)\n        .ifPresentOrElse(SergeantExtension::sergeantReady, func.apply(extension));\n\n    extension = \"CommanderExtension\";\n    Optional.ofNullable(unit.getUnitExtension(extension))\n        .map(e -> (CommanderExtension) e)\n        .ifPresentOrElse(CommanderExtension::commanderReady, func.apply(extension));\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/main/java/abstractextensions/CommanderExtension.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage abstractextensions;\n\n/** Interface with their method. */\npublic interface CommanderExtension extends UnitExtension {\n\n  void commanderReady();\n}\n"
  },
  {
    "path": "extension-objects/src/main/java/abstractextensions/SergeantExtension.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage abstractextensions;\n\n/** Interface with their method. */\npublic interface SergeantExtension extends UnitExtension {\n\n  void sergeantReady();\n}\n"
  },
  {
    "path": "extension-objects/src/main/java/abstractextensions/SoldierExtension.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage abstractextensions;\n\n/** Interface with their method. */\npublic interface SoldierExtension extends UnitExtension {\n  void soldierReady();\n}\n"
  },
  {
    "path": "extension-objects/src/main/java/abstractextensions/UnitExtension.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage abstractextensions;\n\n/** Other Extensions will extend this interface. */\npublic interface UnitExtension {}\n"
  },
  {
    "path": "extension-objects/src/main/java/concreteextensions/Commander.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage concreteextensions;\n\nimport abstractextensions.CommanderExtension;\nimport lombok.extern.slf4j.Slf4j;\nimport units.CommanderUnit;\n\n/** Class defining Commander. */\n@Slf4j\npublic record Commander(CommanderUnit unit) implements CommanderExtension {\n\n  @Override\n  public void commanderReady() {\n    LOGGER.info(\"[Commander] \" + unit.getName() + \" is ready!\");\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/main/java/concreteextensions/Sergeant.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage concreteextensions;\n\nimport abstractextensions.SergeantExtension;\nimport lombok.extern.slf4j.Slf4j;\nimport units.SergeantUnit;\n\n/** Class defining Sergeant. */\n@Slf4j\npublic record Sergeant(SergeantUnit unit) implements SergeantExtension {\n\n  @Override\n  public void sergeantReady() {\n    LOGGER.info(\"[Sergeant] \" + unit.getName() + \" is ready!\");\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/main/java/concreteextensions/Soldier.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage concreteextensions;\n\nimport abstractextensions.SoldierExtension;\nimport lombok.extern.slf4j.Slf4j;\nimport units.SoldierUnit;\n\n/** Class defining Soldier. */\n@Slf4j\npublic record Soldier(SoldierUnit unit) implements SoldierExtension {\n\n  @Override\n  public void soldierReady() {\n    LOGGER.info(\"[Soldier] \" + unit.getName() + \" is ready!\");\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/main/java/units/CommanderUnit.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage units;\n\nimport abstractextensions.UnitExtension;\nimport concreteextensions.Commander;\nimport java.util.Optional;\n\n/** Class defining CommanderUnit. */\npublic class CommanderUnit extends Unit {\n\n  public CommanderUnit(String name) {\n    super(name);\n  }\n\n  @Override\n  public UnitExtension getUnitExtension(String extensionName) {\n\n    if (extensionName.equals(\"CommanderExtension\")) {\n      return Optional.ofNullable(unitExtension).orElseGet(() -> new Commander(this));\n    }\n\n    return super.getUnitExtension(extensionName);\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/main/java/units/SergeantUnit.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage units;\n\nimport abstractextensions.UnitExtension;\nimport concreteextensions.Sergeant;\nimport java.util.Optional;\n\n/** Class defining SergeantUnit. */\npublic class SergeantUnit extends Unit {\n\n  public SergeantUnit(String name) {\n    super(name);\n  }\n\n  @Override\n  public UnitExtension getUnitExtension(String extensionName) {\n\n    if (extensionName.equals(\"SergeantExtension\")) {\n      return Optional.ofNullable(unitExtension).orElseGet(() -> new Sergeant(this));\n    }\n\n    return super.getUnitExtension(extensionName);\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/main/java/units/SoldierUnit.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage units;\n\nimport abstractextensions.UnitExtension;\nimport concreteextensions.Soldier;\nimport java.util.Optional;\n\n/** Class defining SoldierUnit. */\npublic class SoldierUnit extends Unit {\n\n  public SoldierUnit(String name) {\n    super(name);\n  }\n\n  @Override\n  public UnitExtension getUnitExtension(String extensionName) {\n\n    if (extensionName.equals(\"SoldierExtension\")) {\n      return Optional.ofNullable(unitExtension).orElseGet(() -> new Soldier(this));\n    }\n\n    return super.getUnitExtension(extensionName);\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/main/java/units/Unit.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage units;\n\nimport abstractextensions.UnitExtension;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Class defining Unit, other units will extend this class. */\n@Setter\n@Getter\npublic class Unit {\n\n  private String name;\n  protected UnitExtension unitExtension = null;\n\n  public Unit(String name) {\n    this.name = name;\n  }\n\n  public UnitExtension getUnitExtension(String extensionName) {\n    return null;\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/test/java/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Created by Srdjan on 03-May-17. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/test/java/concreteextensions/CommanderTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage concreteextensions;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport ch.qos.logback.classic.Level;\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.read.ListAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\nimport units.CommanderUnit;\n\n/** CommanderTest */\nclass CommanderTest {\n\n  @Test\n  void shouldExecuteCommanderReady() {\n\n    Logger commanderLogger = (Logger) LoggerFactory.getLogger(Commander.class);\n\n    ListAppender<ILoggingEvent> listAppender = new ListAppender<>();\n    listAppender.start();\n\n    commanderLogger.addAppender(listAppender);\n\n    final var commander = new Commander(new CommanderUnit(\"CommanderUnitTest\"));\n    commander.commanderReady();\n\n    List<ILoggingEvent> logsList = listAppender.list;\n    assertEquals(\n        \"[Commander] \" + commander.unit().getName() + \" is ready!\", logsList.get(0).getMessage());\n    assertEquals(Level.INFO, logsList.get(0).getLevel());\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/test/java/concreteextensions/SergeantTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage concreteextensions;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport ch.qos.logback.classic.Level;\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.read.ListAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\nimport units.SergeantUnit;\n\n/** Created by Srdjan on 03-May-17. */\nclass SergeantTest {\n\n  @Test\n  void sergeantReady() {\n\n    Logger sergeantLogger = (Logger) LoggerFactory.getLogger(Sergeant.class);\n\n    ListAppender<ILoggingEvent> listAppender = new ListAppender<>();\n    listAppender.start();\n\n    sergeantLogger.addAppender(listAppender);\n\n    final var sergeant = new Sergeant(new SergeantUnit(\"SergeantUnitTest\"));\n    sergeant.sergeantReady();\n\n    List<ILoggingEvent> logsList = listAppender.list;\n    assertEquals(\n        \"[Sergeant] \" + sergeant.unit().getName() + \" is ready!\", logsList.get(0).getMessage());\n    assertEquals(Level.INFO, logsList.get(0).getLevel());\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/test/java/concreteextensions/SoldierTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage concreteextensions;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport ch.qos.logback.classic.Level;\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.read.ListAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\nimport units.SoldierUnit;\n\n/** Created by Srdjan on 03-May-17. */\nclass SoldierTest {\n\n  @Test\n  void soldierReady() {\n\n    Logger soldierLogger = (Logger) LoggerFactory.getLogger(Soldier.class);\n\n    ListAppender<ILoggingEvent> listAppender = new ListAppender<>();\n    listAppender.start();\n\n    soldierLogger.addAppender(listAppender);\n\n    final var soldier = new Soldier(new SoldierUnit(\"SoldierUnitTest\"));\n    soldier.soldierReady();\n\n    List<ILoggingEvent> logsList = listAppender.list;\n    assertEquals(\n        \"[Soldier] \" + soldier.unit().getName() + \" is ready!\", logsList.get(0).getMessage());\n    assertEquals(Level.INFO, logsList.get(0).getLevel());\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/test/java/units/CommanderUnitTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage units;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nimport org.junit.jupiter.api.Test;\n\n/** Created by Srdjan on 03-May-17. */\nclass CommanderUnitTest {\n\n  @Test\n  void getUnitExtension() {\n    final var unit = new CommanderUnit(\"CommanderUnitName\");\n\n    assertNull(unit.getUnitExtension(\"SoldierExtension\"));\n    assertNull(unit.getUnitExtension(\"SergeantExtension\"));\n    assertNotNull(unit.getUnitExtension(\"CommanderExtension\"));\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/test/java/units/SergeantUnitTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage units;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nimport org.junit.jupiter.api.Test;\n\n/** Created by Srdjan on 03-May-17. */\nclass SergeantUnitTest {\n\n  @Test\n  void getUnitExtension() {\n    final var unit = new SergeantUnit(\"SergeantUnitName\");\n\n    assertNull(unit.getUnitExtension(\"SoldierExtension\"));\n    assertNotNull(unit.getUnitExtension(\"SergeantExtension\"));\n    assertNull(unit.getUnitExtension(\"CommanderExtension\"));\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/test/java/units/SoldierUnitTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage units;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nimport org.junit.jupiter.api.Test;\n\n/** Created by Srdjan on 03-May-17. */\nclass SoldierUnitTest {\n\n  @Test\n  void getUnitExtension() {\n    final var unit = new SoldierUnit(\"SoldierUnitName\");\n\n    assertNotNull(unit.getUnitExtension(\"SoldierExtension\"));\n    assertNull(unit.getUnitExtension(\"SergeantExtension\"));\n    assertNull(unit.getUnitExtension(\"CommanderExtension\"));\n  }\n}\n"
  },
  {
    "path": "extension-objects/src/test/java/units/UnitTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage units;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nimport org.junit.jupiter.api.Test;\n\n/** Created by Srdjan on 03-May-17. */\nclass UnitTest {\n\n  @Test\n  void testConstGetSet() {\n    final var name = \"testName\";\n    final var unit = new Unit(name);\n    assertEquals(name, unit.getName());\n\n    final var newName = \"newName\";\n    unit.setName(newName);\n    assertEquals(newName, unit.getName());\n\n    assertNull(unit.getUnitExtension(\"\"));\n    assertNull(unit.getUnitExtension(\"SoldierExtension\"));\n    assertNull(unit.getUnitExtension(\"SergeantExtension\"));\n    assertNull(unit.getUnitExtension(\"CommanderExtension\"));\n  }\n}\n"
  },
  {
    "path": "facade/README.md",
    "content": "---\ntitle: \"Facade Pattern in Java: Simplifying Complex System Interfaces\"\nshortTitle: Facade\ndescription: \"Learn how to implement the Facade Design Pattern in Java to create a unified interface for complex subsystems. Simplify your code and enhance maintainability with practical examples and use cases.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Abstraction\n  - API design\n  - Code simplification\n  - Decoupling\n  - Encapsulation\n  - Gang of Four\n  - Interface\n  - Object composition\n---\n\n## Intent of Facade Design Pattern\n\nThe Facade Design Pattern provides a unified interface to a set of interfaces in a subsystem. This Java design pattern simplifies complex system interactions.\n\n## Detailed Explanation of Facade Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a home theater system with multiple components: a DVD player, projector, surround sound system, and lights. Each component has a complex interface with numerous functions and settings. To simplify the use of the home theater system, a remote control (the Facade) is provided. The remote control offers a unified interface with simple buttons like \"Play Movie,\" \"Stop,\" \"Pause,\" and \"Volume Up/Down,\" which internally communicate with the various components, managing their interactions. This makes the system easier to use without needing to understand the detailed operations of each component.\n\nIn plain words\n\n> Facade pattern provides a simplified interface to a complex subsystem.\n\nWikipedia says\n\n> A facade is an object that provides a simplified interface to a larger body of code, such as a class library.\n\nSequence diagram\n\n![Facade sequence diagram](./etc/facade-sequence-diagram.png)\n\n## Programmatic Example of Facade Pattern in Java\n\nHere's an example of the Facade Design Pattern in a goldmine scenario, demonstrating how a Java facade can streamline complex operations.\n\nHow does a goldmine work? \"Well, the miners go down there and dig gold!\" you say. That is what you believe because you are using a simple interface that goldmine provides on the outside, internally it has to do a lot of stuff to make it happen. This simple interface to the complex subsystem is a facade.\n\nHere we have the dwarven mine worker hierarchy. First, there's a base class `DwarvenMineWorker`:\n\n```java\n\n@Slf4j\npublic abstract class DwarvenMineWorker {\n\n    public void goToSleep() {\n        LOGGER.info(\"{} goes to sleep.\", name());\n    }\n\n    public void wakeUp() {\n        LOGGER.info(\"{} wakes up.\", name());\n    }\n\n    public void goHome() {\n        LOGGER.info(\"{} goes home.\", name());\n    }\n\n    public void goToMine() {\n        LOGGER.info(\"{} goes to the mine.\", name());\n    }\n\n    private void action(Action action) {\n        switch (action) {\n            case GO_TO_SLEEP -> goToSleep();\n            case WAKE_UP -> wakeUp();\n            case GO_HOME -> goHome();\n            case GO_TO_MINE -> goToMine();\n            case WORK -> work();\n            default -> LOGGER.info(\"Undefined action\");\n        }\n    }\n\n    public void action(Action... actions) {\n        Arrays.stream(actions).forEach(this::action);\n    }\n\n    public abstract void work();\n\n    public abstract String name();\n\n    enum Action {\n        GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK\n    }\n}\n```\n\nThen we have the concrete dwarf classes `DwarvenTunnelDigger`, `DwarvenGoldDigger` and `DwarvenCartOperator`:\n\n```java\n\n@Slf4j\npublic class DwarvenTunnelDigger extends DwarvenMineWorker {\n\n    @Override\n    public void work() {\n        LOGGER.info(\"{} creates another promising tunnel.\", name());\n    }\n\n    @Override\n    public String name() {\n        return \"Dwarven tunnel digger\";\n    }\n}\n\n@Slf4j\npublic class DwarvenGoldDigger extends DwarvenMineWorker {\n\n    @Override\n    public void work() {\n        LOGGER.info(\"{} digs for gold.\", name());\n    }\n\n    @Override\n    public String name() {\n        return \"Dwarf gold digger\";\n    }\n}\n\n@Slf4j\npublic class DwarvenCartOperator extends DwarvenMineWorker {\n\n    @Override\n    public void work() {\n        LOGGER.info(\"{} moves gold chunks out of the mine.\", name());\n    }\n\n    @Override\n    public String name() {\n        return \"Dwarf cart operator\";\n    }\n}\n\n```\n\nTo operate all these goldmine workers we have the `DwarvenGoldmineFacade`:\n\n```java\npublic class DwarvenGoldmineFacade {\n\n    private final List<DwarvenMineWorker> workers;\n\n    public DwarvenGoldmineFacade() {\n        workers = List.of(\n                new DwarvenGoldDigger(),\n                new DwarvenCartOperator(),\n                new DwarvenTunnelDigger());\n    }\n\n    public void startNewDay() {\n        makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE);\n    }\n\n    public void digOutGold() {\n        makeActions(workers, DwarvenMineWorker.Action.WORK);\n    }\n\n    public void endDay() {\n        makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);\n    }\n\n    private static void makeActions(Collection<DwarvenMineWorker> workers,\n                                    DwarvenMineWorker.Action... actions) {\n        workers.forEach(worker -> worker.action(actions));\n    }\n}\n```\n\nNow let's use the facade:\n\n```java\npublic static void main(String[] args) {\n    var facade = new DwarvenGoldmineFacade();\n    facade.startNewDay();\n    facade.digOutGold();\n    facade.endDay();\n}\n```\n\nProgram output:\n\n```\n06:07:20.676 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf gold digger wakes up.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf gold digger goes to the mine.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf cart operator wakes up.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf cart operator goes to the mine.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarven tunnel digger wakes up.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarven tunnel digger goes to the mine.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenGoldDigger -- Dwarf gold digger digs for gold.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenCartOperator -- Dwarf cart operator moves gold chunks out of the mine.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenTunnelDigger -- Dwarven tunnel digger creates another promising tunnel.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf gold digger goes home.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf gold digger goes to sleep.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf cart operator goes home.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarf cart operator goes to sleep.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarven tunnel digger goes home.\n06:07:20.678 [main] INFO com.iluwatar.facade.DwarvenMineWorker -- Dwarven tunnel digger goes to sleep.\n```\n\n## When to Use the Facade Pattern in Java\n\nUse the Facade pattern in Java when:\n\n* You want to provide a simple interface to a complex subsystem.\n* Subsystems are getting more complex and depend on multiple classes, but most clients only need a part of the functionality.\n* There is a need to layer your subsystems. Use a facade to define an entry point to each subsystem level.\n* You want to reduce dependencies and enhance code readability in Java development.\n\n## Facade Pattern Java Tutorials\n\n* [Facade Design Pattern in Java (DigitalOcean)](https://www.digitalocean.com/community/tutorials/facade-design-pattern-in-java)\n* [Facade (Refactoring Guru)](https://refactoring.guru/design-patterns/facade)\n* [Facade Method Design Pattern (GeekforGeeks)](https://www.geeksforgeeks.org/facade-design-pattern-introduction/)\n* [Design Patterns - Facade Pattern (TutorialsPoint)](https://www.tutorialspoint.com/design_pattern/facade_pattern.htm)\n\n## Real-World Applications of Facade Pattern in Java\n\n* Java libraries such as java.net.URL and javax.faces.context.FacesContext use Facade to simplify complex underlying classes.\n* In many Java frameworks, facades are used to simplify the usage of APIs by providing a simpler interface to more complex underlying code structures.\n\n## Benefits and Trade-offs of Facade Pattern\n\nBenefits:\n\nImplementing the Facade Design Pattern in Java:\n\n* Isolates clients from subsystem components, making it easier to use and reducing dependencies.\n* Promotes weak coupling between the subsystem and its clients.\n* Often simplifies the API of complex systems.\n\nTrade-offs:\n\n* A facade can become a god object coupled to all classes of an app if not implemented correctly.\n\n## Related Java Design Patterns\n\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): Facade provides a unified interface while Adapter makes two existing interfaces work together.\n* [Mediator](https://java-design-patterns.com/patterns/mediator/): Facade defines a simpler interface to a subsystem while Mediator centralizes complex communications and control between objects.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3QbO7qN)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/3UpTLrG)\n"
  },
  {
    "path": "facade/etc/facade.urm.puml",
    "content": "@startuml\npackage com.iluwatar.facade {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class DwarvenCartOperator {\n    - LOGGER : Logger {static}\n    + DwarvenCartOperator()\n    + name() : String\n    + work()\n  }\n  class DwarvenGoldDigger {\n    - LOGGER : Logger {static}\n    + DwarvenGoldDigger()\n    + name() : String\n    + work()\n  }\n  class DwarvenGoldmineFacade {\n    - workers : List<DwarvenMineWorker>\n    + DwarvenGoldmineFacade()\n    + digOutGold()\n    + endDay()\n    - makeActions(workers : Collection<DwarvenMineWorker>, actions : Action[]) {static}\n    + startNewDay()\n  }\n  abstract class DwarvenMineWorker {\n    - LOGGER : Logger {static}\n    + DwarvenMineWorker()\n    - action(action : Action)\n    + action(actions : Action[])\n    + goHome()\n    + goToMine()\n    + goToSleep()\n    + name() : String {abstract}\n    + wakeUp()\n    + work() {abstract}\n  }\n  ~enum Action {\n    + GO_HOME {static}\n    + GO_TO_MINE {static}\n    + GO_TO_SLEEP {static}\n    + WAKE_UP {static}\n    + WORK {static}\n    + valueOf(name : String) : Action {static}\n    + values() : Action[] {static}\n  }\n  class DwarvenTunnelDigger {\n    - LOGGER : Logger {static}\n    + DwarvenTunnelDigger()\n    + name() : String\n    + work()\n  }\n}\nDwarvenGoldmineFacade -->  \"-workers\" DwarvenMineWorker\nAction ..+ DwarvenMineWorker\nDwarvenCartOperator --|> DwarvenMineWorker \nDwarvenGoldDigger --|> DwarvenMineWorker \nDwarvenTunnelDigger --|> DwarvenMineWorker \n@enduml"
  },
  {
    "path": "facade/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>facade</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.facade.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "facade/src/main/java/com/iluwatar/facade/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.facade;\n\n/**\n * The Facade design pattern is often used when a system is very complex or difficult to understand\n * because the system has a large number of interdependent classes or its source code is\n * unavailable. This pattern hides the complexities of the larger system and provides a simpler\n * interface to the client. It typically involves a single wrapper class which contains a set of\n * members required by client. These members access the system on behalf of the facade client and\n * hide the implementation details.\n *\n * <p>In this example the Facade is ({@link DwarvenGoldmineFacade}) and it provides a simpler\n * interface to the goldmine subsystem.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var facade = new DwarvenGoldmineFacade();\n    facade.startNewDay();\n    facade.digOutGold();\n    facade.endDay();\n  }\n}\n"
  },
  {
    "path": "facade/src/main/java/com/iluwatar/facade/DwarvenCartOperator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.facade;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** DwarvenCartOperator is one of the goldmine subsystems. */\n@Slf4j\npublic class DwarvenCartOperator extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} moves gold chunks out of the mine.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarf cart operator\";\n  }\n}\n"
  },
  {
    "path": "facade/src/main/java/com/iluwatar/facade/DwarvenGoldDigger.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.facade;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** DwarvenGoldDigger is one of the goldmine subsystems. */\n@Slf4j\npublic class DwarvenGoldDigger extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} digs for gold.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarf gold digger\";\n  }\n}\n"
  },
  {
    "path": "facade/src/main/java/com/iluwatar/facade/DwarvenGoldmineFacade.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.facade;\n\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * DwarvenGoldmineFacade provides a single interface through which users can operate the subsystems.\n *\n * <p>This makes the goldmine easier to operate and cuts the dependencies from the goldmine user to\n * the subsystems.\n */\npublic class DwarvenGoldmineFacade {\n\n  private final List<DwarvenMineWorker> workers;\n\n  /** Constructor. */\n  public DwarvenGoldmineFacade() {\n    workers =\n        List.of(new DwarvenGoldDigger(), new DwarvenCartOperator(), new DwarvenTunnelDigger());\n  }\n\n  public void startNewDay() {\n    makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE);\n  }\n\n  public void digOutGold() {\n    makeActions(workers, DwarvenMineWorker.Action.WORK);\n  }\n\n  public void endDay() {\n    makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);\n  }\n\n  private static void makeActions(\n      Collection<DwarvenMineWorker> workers, DwarvenMineWorker.Action... actions) {\n    workers.forEach(worker -> worker.action(actions));\n  }\n}\n"
  },
  {
    "path": "facade/src/main/java/com/iluwatar/facade/DwarvenMineWorker.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.facade;\n\nimport java.util.Arrays;\nimport lombok.extern.slf4j.Slf4j;\n\n/** DwarvenMineWorker is one of the goldmine subsystems. */\n@Slf4j\npublic abstract class DwarvenMineWorker {\n\n  public void goToSleep() {\n    LOGGER.info(\"{} goes to sleep.\", name());\n  }\n\n  public void wakeUp() {\n    LOGGER.info(\"{} wakes up.\", name());\n  }\n\n  public void goHome() {\n    LOGGER.info(\"{} goes home.\", name());\n  }\n\n  public void goToMine() {\n    LOGGER.info(\"{} goes to the mine.\", name());\n  }\n\n  private void action(Action action) {\n    switch (action) {\n      case GO_TO_SLEEP -> goToSleep();\n      case WAKE_UP -> wakeUp();\n      case GO_HOME -> goHome();\n      case GO_TO_MINE -> goToMine();\n      case WORK -> work();\n      default -> LOGGER.info(\"Undefined action\");\n    }\n  }\n\n  /** Perform actions. */\n  public void action(Action... actions) {\n    Arrays.stream(actions).forEach(this::action);\n  }\n\n  public abstract void work();\n\n  public abstract String name();\n\n  enum Action {\n    GO_TO_SLEEP,\n    WAKE_UP,\n    GO_HOME,\n    GO_TO_MINE,\n    WORK\n  }\n}\n"
  },
  {
    "path": "facade/src/main/java/com/iluwatar/facade/DwarvenTunnelDigger.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.facade;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** DwarvenTunnelDigger is one of the goldmine subsystems. */\n@Slf4j\npublic class DwarvenTunnelDigger extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} creates another promising tunnel.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarven tunnel digger\";\n  }\n}\n"
  },
  {
    "path": "facade/src/test/java/com/iluwatar/facade/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.facade;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "facade/src/test/java/com/iluwatar/facade/DwarvenGoldmineFacadeTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.facade;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/** DwarvenGoldmineFacadeTest */\nclass DwarvenGoldmineFacadeTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /**\n   * Test a complete day cycle in the gold mine by executing all three different steps: {@link\n   * DwarvenGoldmineFacade#startNewDay()}, {@link DwarvenGoldmineFacade#digOutGold()} and {@link\n   * DwarvenGoldmineFacade#endDay()}.\n   *\n   * <p>See if the workers are doing what's expected from them on each step.\n   */\n  @Test\n  void testFullWorkDay() {\n    final var goldMine = new DwarvenGoldmineFacade();\n    goldMine.startNewDay();\n\n    // On the start of a day, all workers should wake up ...\n    assertTrue(appender.logContains(\"Dwarf gold digger wakes up.\"));\n    assertTrue(appender.logContains(\"Dwarf cart operator wakes up.\"));\n    assertTrue(appender.logContains(\"Dwarven tunnel digger wakes up.\"));\n\n    // ... and go to the mine\n    assertTrue(appender.logContains(\"Dwarf gold digger goes to the mine.\"));\n    assertTrue(appender.logContains(\"Dwarf cart operator goes to the mine.\"));\n    assertTrue(appender.logContains(\"Dwarven tunnel digger goes to the mine.\"));\n\n    // No other actions were invoked, so the workers shouldn't have done (printed) anything else\n    assertEquals(6, appender.getLogSize());\n\n    // Now do some actual work, start digging gold!\n    goldMine.digOutGold();\n\n    // Since we gave the dig command, every worker should be doing its job ...\n    assertTrue(appender.logContains(\"Dwarf gold digger digs for gold.\"));\n    assertTrue(appender.logContains(\"Dwarf cart operator moves gold chunks out of the mine.\"));\n    assertTrue(appender.logContains(\"Dwarven tunnel digger creates another promising tunnel.\"));\n\n    // Again, they shouldn't be doing anything else.\n    assertEquals(9, appender.getLogSize());\n\n    // Enough gold, lets end the day.\n    goldMine.endDay();\n\n    // Check if the workers go home ...\n    assertTrue(appender.logContains(\"Dwarf gold digger goes home.\"));\n    assertTrue(appender.logContains(\"Dwarf cart operator goes home.\"));\n    assertTrue(appender.logContains(\"Dwarven tunnel digger goes home.\"));\n\n    // ... and go to sleep. We need well rested workers the next day :)\n    assertTrue(appender.logContains(\"Dwarf gold digger goes to sleep.\"));\n    assertTrue(appender.logContains(\"Dwarf cart operator goes to sleep.\"));\n    assertTrue(appender.logContains(\"Dwarven tunnel digger goes to sleep.\"));\n\n    // Every worker should be sleeping now, no other actions allowed\n    assertEquals(15, appender.getLogSize());\n  }\n\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender() {\n      ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n\n    public boolean logContains(String message) {\n      return log.stream().map(ILoggingEvent::getFormattedMessage).anyMatch(message::equals);\n    }\n  }\n}\n"
  },
  {
    "path": "factory/README.md",
    "content": "---\ntitle: \"Factory Pattern in Java: Streamlining Object Creation\"\nshortTitle: Factory\ndescription: \"Learn the Factory Design Pattern in Java with detailed examples and explanations. Understand how to create flexible and scalable code using the Factory Pattern. Ideal for developers looking to improve their object-oriented design skills.\"\ncategory: Creational\nlanguage: en\ntag:\n  - Abstraction\n  - Encapsulation\n  - Gang of Four\n  - Instantiation\n  - Polymorphism\n---\n\n## Intent of Factory Design Pattern\n\nThe Factory Design Pattern in Java is a creational pattern that defines an interface for creating an object but allows subclasses to alter the type of objects that will be created. This pattern promotes flexibility and scalability in your codebase.\n\n## Detailed Explanation of Factory Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a scenario in a bakery where different types of cakes are made using a Factory Design Pattern. The bakery's `CakeFactory` handles the creation process, allowing easy addition of new cake types without altering the core cake-making process. The `CakeFactory` can produce various types of cakes such as chocolate cake, vanilla cake, and strawberry cake. Instead of the bakery staff manually selecting ingredients and following specific recipes for each type of cake, they use the `CakeFactory` to handle the process. The customer simply requests a cake type, and the `CakeFactory` determines the appropriate ingredients and recipe to use, then creates the specific type of cake. This setup allows the bakery to easily add new cake types without modifying the core cake-making process, promoting flexibility and scalability.\n\nWikipedia says\n\n> Factory is an object for creating other objects – formally a factory is a function or method that returns objects of a varying prototype or class.\n\nSequence diagram\n\n![Factory sequence diagram](./etc/factory-sequence-diagram.png)\n\n## Programmatic Example of Factory Pattern in Java\n\nImagine an alchemist who is about to manufacture coins. The alchemist must be able to create both gold and copper coins and switching between them must be possible without modifying the existing source code. The factory pattern makes it possible by providing a static construction method which can be called with relevant parameters.\n\nIn Java, you can implement the Factory Pattern by defining an interface `Coin` and its implementations `GoldCoin` and `CopperCoin`. The `CoinFactory` class provides a static method `getCoin` to create coin objects based on the type.\n\n```java\npublic interface Coin {\n  String getDescription();\n}\n```\n\n```java\npublic class GoldCoin implements Coin {\n\n  static final String DESCRIPTION = \"This is a gold coin.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n```\n\n```java\npublic class CopperCoin implements Coin {\n   \n  static final String DESCRIPTION = \"This is a copper coin.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n```\n\nEnumeration below represents types of coins that we support (`GoldCoin` and `CopperCoin`).\n\n```java\n@RequiredArgsConstructor\n@Getter\npublic enum CoinType {\n\n  COPPER(CopperCoin::new),\n  GOLD(GoldCoin::new);\n\n  private final Supplier<Coin> constructor;\n}\n```\n\nThen we have the static method `getCoin` to create coin objects encapsulated in the factory class `CoinFactory`.\n\n```java\npublic class CoinFactory {\n\n  public static Coin getCoin(CoinType type) {\n    return type.getConstructor().get();\n  }\n}\n```\n\nNow, in the client code, we can generate various types of coins using the factory class.\n\n```java\npublic static void main(String[] args) {\n    LOGGER.info(\"The alchemist begins his work.\");\n    var coin1 = CoinFactory.getCoin(CoinType.COPPER);\n    var coin2 = CoinFactory.getCoin(CoinType.GOLD);\n    LOGGER.info(coin1.getDescription());\n    LOGGER.info(coin2.getDescription());\n}\n```\n\nProgram output:\n\n```\n06:19:53.530 [main] INFO com.iluwatar.factory.App -- The alchemist begins his work.\n06:19:53.533 [main] INFO com.iluwatar.factory.App -- This is a copper coin.\n06:19:53.533 [main] INFO com.iluwatar.factory.App -- This is a gold coin.\n```\n\n## When to Use the Factory Pattern in Java\n\n* Use the Factory Design Pattern in Java when the class does not know beforehand the exact types and dependencies of the objects it needs to create.\n* When a method returns one of several possible classes that share a common super class and wants to encapsulate the logic of which object to create.\n* The pattern is commonly used when designing frameworks or libraries to give the best flexibility and isolation from concrete class types.\n\n## Real-World Applications of Factory Pattern in Java\n\n* [java.util.Calendar#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)\n* [java.util.ResourceBundle#getBundle()](https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)\n* [java.text.NumberFormat#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)\n* [java.nio.charset.Charset#forName()](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)\n* [java.net.URLStreamHandlerFactory#createURLStreamHandler(String)](https://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html) (returns different singleton objects, depending on a protocol)\n* [java.util.EnumSet#of()](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of(E))\n* [javax.xml.bind.JAXBContext#createMarshaller()](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--) and other similar methods.\n* JavaFX uses Factory patterns for creating various UI controls tailored to the specifics of the user's environment.\n\n## Benefits and Trade-offs of Factory Pattern\n\nBenefits:\n\n* Implementing the Factory Pattern in your Java application reduces coupling between the implementation and the classes it uses.\n* Supports the [Open/Closed Principle](https://java-design-patterns.com/principles/#open-closed-principle), as the system can introduce new types without changing existing code.\n\nTrade-offs:\n\n* The code can become more complicated due to the introduction of multiple additional classes.\n* Overuse can make the code less readable if the underlying complexity of the object creation is low or unnecessary.\n\n## Related Java Design Patterns\n\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): Can be considered a kind of Factory that works with groups of products.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Often used in conjunction with Factory to ensure that a class has only one instance.\n* [Builder](https://java-design-patterns.com/patterns/builder/): Separates the construction of a complex object from its representation, similar to how factories manage instantiation.\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/): Is a factory of immutable content with separated builder and factory interfaces.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0Rk5y)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/3UpTLrG)\n"
  },
  {
    "path": "factory/etc/factory.urm.puml",
    "content": "@startuml\npackage com.iluwatar.factory {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  interface Coin {\n    + getDescription() : String {abstract}\n  }\n  class CoinFactory {\n    + CoinFactory()\n    + getCoin(type : CoinType) : Coin {static}\n  }\n  enum CoinType {\n    + COPPER {static}\n    + GOLD {static}\n    - constructor : Supplier<Coin>\n    + getConstructor() : Supplier<Coin>\n    + valueOf(name : String) : CoinType {static}\n    + values() : CoinType[] {static}\n  }\n  class CopperCoin {\n    ~ DESCRIPTION : String {static}\n    + CopperCoin()\n    + getDescription() : String\n  }\n  class GoldCoin {\n    ~ DESCRIPTION : String {static}\n    + GoldCoin()\n    + getDescription() : String\n  }\n}\nCopperCoin ..|> Coin \nGoldCoin ..|> Coin \n@enduml"
  },
  {
    "path": "factory/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>factory</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <!-- Maven assembly plugin is invoked with default setting which we have \n  in parent pom and specifying the class having main method -->\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.factory.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "factory/src/main/java/com/iluwatar/factory/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Factory is an object for creating other objects. It provides a static method to create and return\n * objects of varying classes, in order to hide the implementation logic and makes client code focus\n * on usage rather than objects initialization and management.\n *\n * <p>In this example an alchemist manufactures coins. CoinFactory is the factory class, and it\n * provides a static method to create different types of coins.\n */\n@Slf4j\npublic class App {\n\n  /** Program main entry point. */\n  public static void main(String[] args) {\n    LOGGER.info(\"The alchemist begins his work.\");\n    var coin1 = CoinFactory.getCoin(CoinType.COPPER);\n    var coin2 = CoinFactory.getCoin(CoinType.GOLD);\n    LOGGER.info(coin1.getDescription());\n    LOGGER.info(coin2.getDescription());\n  }\n}\n"
  },
  {
    "path": "factory/src/main/java/com/iluwatar/factory/Coin.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory;\n\n/** Coin interface. */\npublic interface Coin {\n\n  String getDescription();\n}\n"
  },
  {
    "path": "factory/src/main/java/com/iluwatar/factory/CoinFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory;\n\n/** Factory of coins. */\npublic class CoinFactory {\n\n  /** Factory method takes as a parameter the coin type and calls the appropriate class. */\n  public static Coin getCoin(CoinType type) {\n    return type.getConstructor().get();\n  }\n}\n"
  },
  {
    "path": "factory/src/main/java/com/iluwatar/factory/CoinType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory;\n\nimport java.util.function.Supplier;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/** Enumeration for different types of coins. */\n@RequiredArgsConstructor\n@Getter\npublic enum CoinType {\n  COPPER(CopperCoin::new),\n  GOLD(GoldCoin::new);\n\n  private final Supplier<Coin> constructor;\n}\n"
  },
  {
    "path": "factory/src/main/java/com/iluwatar/factory/CopperCoin.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory;\n\n/** CopperCoin implementation. */\npublic class CopperCoin implements Coin {\n\n  static final String DESCRIPTION = \"This is a copper coin.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n"
  },
  {
    "path": "factory/src/main/java/com/iluwatar/factory/GoldCoin.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory;\n\n/** GoldCoin implementation. */\npublic class GoldCoin implements Coin {\n\n  static final String DESCRIPTION = \"This is a gold coin.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n"
  },
  {
    "path": "factory/src/test/java/com/iluwatar/factory/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutExceptions() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "factory/src/test/java/com/iluwatar/factory/CoinFactoryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass CoinFactoryTest {\n\n  @Test\n  void shouldReturnGoldCoinInstance() {\n    final var goldCoin = CoinFactory.getCoin(CoinType.GOLD);\n    assertTrue(goldCoin instanceof GoldCoin);\n  }\n}\n"
  },
  {
    "path": "factory-kit/README.md",
    "content": "---\ntitle: \"Factory Kit Pattern in Java: Crafting Flexible Component Assemblies\"\nshortTitle: Factory Kit\ndescription: \"Learn about the Factory Kit Pattern in Java with detailed explanations, real-world examples, and practical applications. Improve your Java skills with our comprehensive guide.\"\ncategory: Creational\nlanguage: en\ntag:\n  - Abstraction\n  - Decoupling\n  - Encapsulation\n  - Generic\n  - Instantiation\n  - Object composition\n---\n\n## Also known as\n\n* Object Kit\n* Toolkit\n\n## Intent of Factory Kit Design Pattern\n\nThe Factory Kit Pattern in Java is a powerful design pattern that helps in creating factories with separated builder and factory interfaces. This pattern is essential for managing complex object creation scenarios.\n\n## Detailed Explanation of Factory Kit Pattern with Real-World Examples\n\nReal-world example\n\n> An analogous real-world example of the Factory Kit Pattern is a restaurant kitchen where different types of dishes are prepared efficiently. This setup promotes flexibility and consistency, similar to how the Factory Kit Pattern operates in Java. Imagine the kitchen has a central station with various ingredients and recipes registered for different dishes. When an order comes in, the chef consults this central station to gather the necessary ingredients and follow the registered recipe to prepare the dish. This setup allows the kitchen to efficiently manage and switch between different dish preparations without the need for each chef to know the specifics of every recipe, promoting flexibility and consistency in the cooking process.\n\nIn plain words\n\n> Factory kit is a configurable object builder, a factory to create factories.\n\nSequence diagram\n\n![Factory Kit sequence diagram](./etc/factory-kit-sequence-diagram.png)\n\n## Programmatic Example of Factory Kit Pattern in Java\n\nImagine a magical weapon factory in Java capable of creating any desired weapon using the Factory Kit Pattern. This pattern allows for configurable object builders, making it ideal for scenarios where the types of objects are not known upfront.\n\nUpon activation, the master recites the names of the weapon types needed to configure it. Once set up, any of these weapon types can be summoned instantly.\n\nLet's first define the simple `Weapon` hierarchy.\n\n```java\npublic interface Weapon {\n}\n\npublic enum WeaponType {\n    SWORD,\n    AXE,\n    BOW,\n    SPEAR\n}\n\npublic class Sword implements Weapon {\n    @Override\n    public String toString() {\n        return \"Sword\";\n    }\n}\n\n// Axe, Bow, and Spear are defined similarly...\n```\n\nNext, we define a functional interface that allows adding a builder with a name to the factory.\n\n```java\npublic interface Builder {\n    void add(WeaponType name, Supplier<Weapon> supplier);\n}\n```\n\nThe meat of the example is the `WeaponFactory` interface that effectively implements the factory kit pattern. The method `#factory` is used to configure the factory with the classes it needs to be able to construct. The method `#create` is then used to create object instances.\n\n```java\npublic interface WeaponFactory {\n\n    static WeaponFactory factory(Consumer<Builder> consumer) {\n        var map = new HashMap<WeaponType, Supplier<Weapon>>();\n        consumer.accept(map::put);\n        return name -> map.get(name).get();\n    }\n\n    Weapon create(WeaponType name);\n}\n```\n\nNow, we can show how `WeaponFactory` can be used.\n\n```java\n  public static void main(String[] args) {\n    var factory = WeaponFactory.factory(builder -> {\n        builder.add(WeaponType.SWORD, Sword::new);\n        builder.add(WeaponType.AXE, Axe::new);\n        builder.add(WeaponType.SPEAR, Spear::new);\n        builder.add(WeaponType.BOW, Bow::new);\n    });\n    var list = new ArrayList<Weapon>();\n    list.add(factory.create(WeaponType.AXE));\n    list.add(factory.create(WeaponType.SPEAR));\n    list.add(factory.create(WeaponType.SWORD));\n    list.add(factory.create(WeaponType.BOW));\n    list.forEach(weapon -> LOGGER.info(\"{}\", weapon.toString()));\n}\n```\n\nHere is the console output when the example is run.\n\n```\n06:32:23.026 [main] INFO com.iluwatar.factorykit.App -- Axe\n06:32:23.029 [main] INFO com.iluwatar.factorykit.App -- Spear\n06:32:23.029 [main] INFO com.iluwatar.factorykit.App -- Sword\n06:32:23.029 [main] INFO com.iluwatar.factorykit.App -- Bow\n```\n\n## When to Use the Factory Kit Pattern in Java\n\nUse the Factory Kit Pattern when\n\n* The factory class cannot anticipate the types of objects it must create, and a new instance of a custom builder is needed.\n* A new instance of a custom builder is needed instead of a global one.\n* The types of objects that the factory can build need to be defined outside the class.\n* The builder and creator interfaces need to be separated.\n* Game developments and other applications that have user customization.\n\n## Factory Kit Pattern Java Tutorials\n\n* [Factory Kit Pattern (Diego Pacheco)](https://diego-pacheco.medium.com/factory-kit-pattern-66d5ccb0c405)\n\n## Real-World Applications of Factory Kit Pattern in Java\n\n* In Java libraries such as the Java Development Kit (JDK) where different rendering engines might be instantiated based on the runtime environment.\n* Frameworks like Spring or applications where dependency injection is heavily used, often implement this pattern to manage object creation more flexibly.\n\n## Benefits and Trade-offs of Factory Kit Pattern\n\nBenefits:\n\n* The Factory Kit Pattern in Java promotes loose coupling by eliminating the need to bind application-specific classes into the code.\n* It simplifies the code by shifting the responsibility of instantiation to a factory object, making the development process more efficient.\n\nTrade-offs:\n\n* Can introduce complexity into the code by requiring additional classes and interfaces.\n* Sometimes can lead to dependency issues if not properly managed.\n\n## Related Java Design Patterns\n\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): Often used together with the Factory Kit to create families of related objects.\n* [Builder](https://java-design-patterns.com/patterns/builder/): Can be used to construct complex objects step-by-step using a similar approach.\n* [Prototype](https://java-design-patterns.com/patterns/prototype/): Objects that are created by cloning a prototypical instance often use a factory to manage it.\n\n## References and Credits\n\n* [Design Pattern Reloaded (Remi Forax)](https://www.youtube.com/watch?v=-k2X7guaArU)\n"
  },
  {
    "path": "factory-kit/etc/factory-kit.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.9\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "factory-kit/etc/factory-kit.urm.puml",
    "content": "@startuml\npackage com.iluwatar.factorykit {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Axe {\n    + Axe()\n    + toString() : String\n  }\n  class Bow {\n    + Bow()\n    + toString() : String\n  }\n  interface Builder {\n    + add(WeaponType, Supplier<Weapon>) {abstract}\n  }\n  class Spear {\n    + Spear()\n    + toString() : String\n  }\n  class Sword {\n    + Sword()\n    + toString() : String\n  }\n  interface Weapon {\n  }\n  interface WeaponFactory {\n    + create(WeaponType) : Weapon {abstract}\n    + factory(consumer : Consumer<Builder>) : WeaponFactory {static}\n  }\n  enum WeaponType {\n    + AXE {static}\n    + BOW {static}\n    + SPEAR {static}\n    + SWORD {static}\n    + valueOf(name : String) : WeaponType {static}\n    + values() : WeaponType[] {static}\n  }\n}\nAxe ..|> Weapon \nBow ..|> Weapon \nSpear ..|> Weapon \nSword ..|> Weapon \n@enduml"
  },
  {
    "path": "factory-kit/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>factory-kit</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.factorykit.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "factory-kit/src/main/java/com/iluwatar/factorykit/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factorykit;\n\nimport java.util.ArrayList;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Factory kit is a creational pattern that defines a factory of immutable content with separated\n * builder and factory interfaces to deal with the problem of creating one of the objects specified\n * directly in the factory kit instance.\n *\n * <p>In the given example {@link WeaponFactory} represents the factory kit, that contains four\n * {@link Builder}s for creating new objects of the classes implementing {@link Weapon} interface.\n *\n * <p>Each of them can be called with {@link WeaponFactory#create(WeaponType)} method, with an input\n * representing an instance of {@link WeaponType} that needs to be mapped explicitly with desired\n * class type in the factory instance.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var factory =\n        WeaponFactory.factory(\n            builder -> {\n              builder.add(WeaponType.SWORD, Sword::new);\n              builder.add(WeaponType.AXE, Axe::new);\n              builder.add(WeaponType.SPEAR, Spear::new);\n              builder.add(WeaponType.BOW, Bow::new);\n            });\n    var list = new ArrayList<Weapon>();\n    list.add(factory.create(WeaponType.AXE));\n    list.add(factory.create(WeaponType.SPEAR));\n    list.add(factory.create(WeaponType.SWORD));\n    list.add(factory.create(WeaponType.BOW));\n    list.forEach(weapon -> LOGGER.info(\"{}\", weapon.toString()));\n  }\n}\n"
  },
  {
    "path": "factory-kit/src/main/java/com/iluwatar/factorykit/Axe.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factorykit;\n\n/** Class representing Axe. */\npublic class Axe implements Weapon {\n  @Override\n  public String toString() {\n    return \"Axe\";\n  }\n}\n"
  },
  {
    "path": "factory-kit/src/main/java/com/iluwatar/factorykit/Bow.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factorykit;\n\n/** Class representing Bows. */\npublic class Bow implements Weapon {\n  @Override\n  public String toString() {\n    return \"Bow\";\n  }\n}\n"
  },
  {
    "path": "factory-kit/src/main/java/com/iluwatar/factorykit/Builder.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factorykit;\n\nimport java.util.function.Supplier;\n\n/** Functional interface that allows adding builder with name to the factory. */\npublic interface Builder {\n  void add(WeaponType name, Supplier<Weapon> supplier);\n}\n"
  },
  {
    "path": "factory-kit/src/main/java/com/iluwatar/factorykit/Spear.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factorykit;\n\n/** Class representing Spear. */\npublic class Spear implements Weapon {\n  @Override\n  public String toString() {\n    return \"Spear\";\n  }\n}\n"
  },
  {
    "path": "factory-kit/src/main/java/com/iluwatar/factorykit/Sword.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factorykit;\n\n/** Class representing Swords. */\npublic class Sword implements Weapon {\n  @Override\n  public String toString() {\n    return \"Sword\";\n  }\n}\n"
  },
  {
    "path": "factory-kit/src/main/java/com/iluwatar/factorykit/Weapon.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factorykit;\n\n/** Interface representing weapon. */\npublic interface Weapon {}\n"
  },
  {
    "path": "factory-kit/src/main/java/com/iluwatar/factorykit/WeaponFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factorykit;\n\nimport java.util.HashMap;\nimport java.util.function.Consumer;\nimport java.util.function.Supplier;\n\n/**\n * Functional interface, an example of the factory-kit design pattern. <br>\n * Instance created locally gives an opportunity to strictly define which objects types the instance\n * of a factory will be able to create. <br>\n * Factory is a placeholder for {@link Builder}s with {@link WeaponFactory#create(WeaponType)}\n * method to initialize new objects.\n */\npublic interface WeaponFactory {\n\n  /**\n   * Creates an instance of the given type.\n   *\n   * @param name representing enum of an object type to be created.\n   * @return new instance of a requested class implementing {@link Weapon} interface.\n   */\n  Weapon create(WeaponType name);\n\n  /**\n   * Creates factory - placeholder for specified {@link Builder}s.\n   *\n   * @param consumer for the new builder to the factory.\n   * @return factory with specified {@link Builder}s\n   */\n  static WeaponFactory factory(Consumer<Builder> consumer) {\n    var map = new HashMap<WeaponType, Supplier<Weapon>>();\n    consumer.accept(map::put);\n    return name -> map.get(name).get();\n  }\n}\n"
  },
  {
    "path": "factory-kit/src/main/java/com/iluwatar/factorykit/WeaponType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factorykit;\n\n/** Enumerates {@link Weapon} types. */\npublic enum WeaponType {\n  SWORD,\n  AXE,\n  BOW,\n  SPEAR\n}\n"
  },
  {
    "path": "factory-kit/src/test/java/com/iluwatar/factorykit/app/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factorykit.app;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport com.iluwatar.factorykit.App;\nimport org.junit.jupiter.api.Test;\n\n/** Application Test Entrypoint */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "factory-kit/src/test/java/com/iluwatar/factorykit/factorykit/FactoryKitTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factorykit.factorykit;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.factorykit.Axe;\nimport com.iluwatar.factorykit.Spear;\nimport com.iluwatar.factorykit.Sword;\nimport com.iluwatar.factorykit.Weapon;\nimport com.iluwatar.factorykit.WeaponFactory;\nimport com.iluwatar.factorykit.WeaponType;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Test Factory Kit Pattern */\nclass FactoryKitTest {\n\n  private WeaponFactory factory;\n\n  @BeforeEach\n  void init() {\n    factory =\n        WeaponFactory.factory(\n            builder -> {\n              builder.add(WeaponType.SPEAR, Spear::new);\n              builder.add(WeaponType.AXE, Axe::new);\n              builder.add(WeaponType.SWORD, Sword::new);\n            });\n  }\n\n  /**\n   * Testing {@link WeaponFactory} to produce a SPEAR asserting that the Weapon is an instance of\n   * {@link Spear}\n   */\n  @Test\n  void testSpearWeapon() {\n    var weapon = factory.create(WeaponType.SPEAR);\n    verifyWeapon(weapon, Spear.class);\n  }\n\n  /**\n   * Testing {@link WeaponFactory} to produce a AXE asserting that the Weapon is an instance of\n   * {@link Axe}\n   */\n  @Test\n  void testAxeWeapon() {\n    var weapon = factory.create(WeaponType.AXE);\n    verifyWeapon(weapon, Axe.class);\n  }\n\n  /**\n   * Testing {@link WeaponFactory} to produce a SWORD asserting that the Weapon is an instance of\n   * {@link Sword}\n   */\n  @Test\n  void testWeapon() {\n    var weapon = factory.create(WeaponType.SWORD);\n    verifyWeapon(weapon, Sword.class);\n  }\n\n  /**\n   * This method asserts that the weapon object that is passed is an instance of the clazz\n   *\n   * @param weapon weapon object which is to be verified\n   * @param clazz expected class of the weapon\n   */\n  private void verifyWeapon(Weapon weapon, Class<?> clazz) {\n    assertTrue(clazz.isInstance(weapon), \"Weapon must be an object of: \" + clazz.getName());\n  }\n}\n"
  },
  {
    "path": "factory-method/.gitignore",
    "content": "/target/\n"
  },
  {
    "path": "factory-method/README.md",
    "content": "---\ntitle: \"Factory Method Pattern in Java: Enhancing Flexibility with Polymorphic Manufacturing\"\nshortTitle: Factory Method\ndescription: \"Learn about the Factory Method pattern in Java. Explore examples, uses, benefits, and how it enhances code flexibility and maintenance.\"\ncategory: Creational\nlanguage: en\ntag:\n  - Encapsulation\n  - Gang of Four\n  - Instantiation\n  - Object composition\n  - Polymorphism\n---\n\n## Also known as\n\n* Virtual Constructor\n\n## Intent of Factory Method Design Pattern\n\nDefine an interface for creating an object using the Factory Method Pattern, but let subclasses decide which class to instantiate. This creational design pattern lets a class defer instantiation to subclasses, enhancing code flexibility and maintenance.\n\n## Detailed Explanation of Factory Method Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a logistics company that needs to deliver different types of packages: standard, express, and oversized. The company has a central system that processes delivery requests but does not know the specifics of how each package type is handled. To manage this, the company uses a Factory Method pattern.\n>\n> In this setup, there is a central `DeliveryRequest` class with a method `createPackage()`. This method is overridden in subclasses like `StandardDelivery`, `ExpressDelivery`, and `OversizedDelivery`, each of which knows how to create and manage the respective package type. This way, the central system can handle delivery requests without needing to know the details of how each package type is created and processed, allowing for flexibility and easier maintenance.\n\nIn plain words\n\n> It provides a way to delegate the instantiation logic to child classes.\n\nWikipedia says\n\n> In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method — either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.\n\nSequence diagram\n\n![Factory Method sequence diagram](./etc/factory-method-sequence-diagram.png)\n\n## Programmatic Example of Factory Method Pattern in Java\n\nThe Factory Method approach is pivotal in Java Design Patterns for achieving flexible and maintainable code as we see in the following example.\n\nBlacksmith manufactures weapons. Elves require Elvish weapons and orcs require Orcish weapons. Depending on the customer at hand the right type of blacksmith is summoned.\n\nFirst of all, we have a `Blacksmith` interface and some implementations for it:\n\n```java\npublic interface Blacksmith {\n  Weapon manufactureWeapon(WeaponType weaponType);\n}\n\npublic class ElfBlacksmith implements Blacksmith {\n  public Weapon manufactureWeapon(WeaponType weaponType) {\n    return ELFARSENAL.get(weaponType);\n  }\n}\n\npublic class OrcBlacksmith implements Blacksmith {\n  public Weapon manufactureWeapon(WeaponType weaponType) {\n    return ORCARSENAL.get(weaponType);\n  }\n}\n```\n\nWhen the customers come, the correct type of blacksmith is summoned and requested weapons are manufactured:\n\n```java\npublic static void main(String[] args) {\n\n    Blacksmith blacksmith = new OrcBlacksmith();\n    Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);\n    LOGGER.info(MANUFACTURED, blacksmith, weapon);\n    weapon = blacksmith.manufactureWeapon(WeaponType.AXE);\n    LOGGER.info(MANUFACTURED, blacksmith, weapon);\n\n    blacksmith = new ElfBlacksmith();\n    weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);\n    LOGGER.info(MANUFACTURED, blacksmith, weapon);\n    weapon = blacksmith.manufactureWeapon(WeaponType.AXE);\n    LOGGER.info(MANUFACTURED, blacksmith, weapon);\n}\n```\n\nProgram output:\n```\n06:40:07.269 [main] INFO com.iluwatar.factory.method.App -- The orc blacksmith manufactured an orcish spear\n06:40:07.271 [main] INFO com.iluwatar.factory.method.App -- The orc blacksmith manufactured an orcish axe\n06:40:07.272 [main] INFO com.iluwatar.factory.method.App -- The elf blacksmith manufactured an elven spear\n06:40:07.272 [main] INFO com.iluwatar.factory.method.App -- The elf blacksmith manufactured an elven axe\n```\n\n## When to Use the Factory Method Pattern in Java\n\nUse the Factory Method Pattern in Java when:\n\n* Class cannot anticipate the class of objects it must create.\n* Class wants its subclasses to specify the objects it creates.\n* Classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate.\n\n## Real-World Applications of Factory Method Pattern in Java\n\n* [java.util.Calendar](http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)\n* [java.util.ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)\n* [java.text.NumberFormat](http://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)\n* [java.nio.charset.Charset](http://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)\n* [java.net.URLStreamHandlerFactory](http://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html#createURLStreamHandler-java.lang.String-)\n* [java.util.EnumSet](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of-E-)\n* [javax.xml.bind.JAXBContext](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--)\n* Frameworks that run application components, configured dynamically at runtime.\n\n## Benefits and Trade-offs of Factory Method Pattern\n\nBenefits:\n\n* The Factory Method Pattern provides hooks for subclasses, enhancing code flexibility and maintainability.\n* Connects parallel class hierarchies.\n* Eliminates the need to bind application-specific classes into the code. The code only deals with the product interface; hence it can work with any user-defined concrete product classes.\n\nTrade-offs:\n\n* Can complicate the code by requiring the addition of new subclasses to implement the extended factory methods.\n\n## Related Java Design Patterns\n\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): Factory methods are often called within Abstract Factory patterns.\n* [Prototype](https://java-design-patterns.com/patterns/prototype/): A factory method that returns a new instance of a class that is a clone of a prototype class.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0Rk5y)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/3UpTLrG)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/4b2ZxoM)\n"
  },
  {
    "path": "factory-method/etc/factory-method.urm.puml",
    "content": "@startuml\npackage com.iluwatar.factory.method {\n  class App {\n    - LOGGER : Logger {static}\n    - blacksmith : Blacksmith\n    + App(blacksmith : Blacksmith)\n    + main(args : String[]) {static}\n    - manufactureWeapons()\n  }\n  interface Blacksmith {\n    + manufactureWeapon(WeaponType) : Weapon {abstract}\n  }\n  class ElfBlacksmith {\n    - ELFARSENAL : Map<WeaponType, ElfWeapon> {static}\n    + ElfBlacksmith()\n    + manufactureWeapon(weaponType : WeaponType) : Weapon\n  }\n  class ElfWeapon {\n    - weaponType : WeaponType\n    + ElfWeapon(weaponType : WeaponType)\n    + getWeaponType() : WeaponType\n    + toString() : String\n  }\n  class OrcBlacksmith {\n    - ORCARSENAL : Map<WeaponType, OrcWeapon> {static}\n    + OrcBlacksmith()\n    + manufactureWeapon(weaponType : WeaponType) : Weapon\n  }\n  class OrcWeapon {\n    - weaponType : WeaponType\n    + OrcWeapon(weaponType : WeaponType)\n    + getWeaponType() : WeaponType\n    + toString() : String\n  }\n  interface Weapon {\n    + getWeaponType() : WeaponType {abstract}\n  }\n  enum WeaponType {\n    + AXE {static}\n    + SHORT_SWORD {static}\n    + SPEAR {static}\n    + UNDEFINED {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : WeaponType {static}\n    + values() : WeaponType[] {static}\n  }\n}\nElfWeapon -->  \"-weaponType\" WeaponType\nOrcWeapon -->  \"-weaponType\" WeaponType\nApp -->  \"-blacksmith\" Blacksmith\nElfBlacksmith ..|> Blacksmith \nElfWeapon ..|> Weapon \nOrcBlacksmith ..|> Blacksmith \nOrcWeapon ..|> Weapon \n@enduml"
  },
  {
    "path": "factory-method/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>factory-method</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.factory.method.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "factory-method/src/main/java/com/iluwatar/factory/method/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory.method;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Factory Method is a creational design pattern that uses factory methods to deal with the\n * problem of creating objects without specifying the exact class of object that will be created.\n * This is done by creating objects via calling a factory method either specified in an interface\n * and implemented by child classes, or implemented in a base class and optionally overridden by\n * derived classes—rather than by calling a constructor.\n *\n * <p>In this Factory Method example we have an interface ({@link Blacksmith}) with a method for\n * creating objects ({@link Blacksmith#manufactureWeapon}). The concrete subclasses ( {@link\n * OrcBlacksmith}, {@link ElfBlacksmith}) then override the method to produce objects of their\n * liking.\n */\n@Slf4j\npublic class App {\n\n  private static final String MANUFACTURED = \"{} manufactured {}\";\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    Blacksmith blacksmith = new OrcBlacksmith();\n    Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);\n    LOGGER.info(MANUFACTURED, blacksmith, weapon);\n    weapon = blacksmith.manufactureWeapon(WeaponType.AXE);\n    LOGGER.info(MANUFACTURED, blacksmith, weapon);\n\n    blacksmith = new ElfBlacksmith();\n    weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);\n    LOGGER.info(MANUFACTURED, blacksmith, weapon);\n    weapon = blacksmith.manufactureWeapon(WeaponType.AXE);\n    LOGGER.info(MANUFACTURED, blacksmith, weapon);\n  }\n}\n"
  },
  {
    "path": "factory-method/src/main/java/com/iluwatar/factory/method/Blacksmith.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory.method;\n\n/** The interface containing method for producing objects. */\npublic interface Blacksmith {\n\n  Weapon manufactureWeapon(WeaponType weaponType);\n}\n"
  },
  {
    "path": "factory-method/src/main/java/com/iluwatar/factory/method/ElfBlacksmith.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory.method;\n\nimport java.util.Arrays;\nimport java.util.EnumMap;\nimport java.util.Map;\n\n/** Concrete subclass for creating new objects. */\npublic class ElfBlacksmith implements Blacksmith {\n\n  private static final Map<WeaponType, ElfWeapon> ELFARSENAL;\n\n  static {\n    ELFARSENAL = new EnumMap<>(WeaponType.class);\n    Arrays.stream(WeaponType.values()).forEach(type -> ELFARSENAL.put(type, new ElfWeapon(type)));\n  }\n\n  @Override\n  public Weapon manufactureWeapon(WeaponType weaponType) {\n    return ELFARSENAL.get(weaponType);\n  }\n\n  @Override\n  public String toString() {\n    return \"The elf blacksmith\";\n  }\n}\n"
  },
  {
    "path": "factory-method/src/main/java/com/iluwatar/factory/method/ElfWeapon.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory.method;\n\n/** ElfWeapon. */\npublic record ElfWeapon(WeaponType weaponType) implements Weapon {\n\n  @Override\n  public String toString() {\n    return \"an elven \" + weaponType;\n  }\n}\n"
  },
  {
    "path": "factory-method/src/main/java/com/iluwatar/factory/method/OrcBlacksmith.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory.method;\n\nimport java.util.Arrays;\nimport java.util.EnumMap;\nimport java.util.Map;\n\n/** Concrete subclass for creating new objects. */\npublic class OrcBlacksmith implements Blacksmith {\n\n  private static final Map<WeaponType, OrcWeapon> ORCARSENAL;\n\n  static {\n    ORCARSENAL = new EnumMap<>(WeaponType.class);\n    Arrays.stream(WeaponType.values()).forEach(type -> ORCARSENAL.put(type, new OrcWeapon(type)));\n  }\n\n  @Override\n  public Weapon manufactureWeapon(WeaponType weaponType) {\n    return ORCARSENAL.get(weaponType);\n  }\n\n  @Override\n  public String toString() {\n    return \"The orc blacksmith\";\n  }\n}\n"
  },
  {
    "path": "factory-method/src/main/java/com/iluwatar/factory/method/OrcWeapon.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory.method;\n\n/** OrcWeapon. */\npublic record OrcWeapon(WeaponType weaponType) implements Weapon {\n\n  @Override\n  public String toString() {\n    return \"an orcish \" + weaponType;\n  }\n}\n"
  },
  {
    "path": "factory-method/src/main/java/com/iluwatar/factory/method/Weapon.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory.method;\n\n/** Weapon interface. */\npublic interface Weapon {\n\n  WeaponType weaponType();\n}\n"
  },
  {
    "path": "factory-method/src/main/java/com/iluwatar/factory/method/WeaponType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory.method;\n\nimport lombok.RequiredArgsConstructor;\n\n/** WeaponType enumeration. */\n@RequiredArgsConstructor\npublic enum WeaponType {\n  SHORT_SWORD(\"short sword\"),\n  SPEAR(\"spear\"),\n  AXE(\"axe\"),\n  UNDEFINED(\"\");\n\n  private final String title;\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "factory-method/src/test/java/com/iluwatar/factory/method/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory.method;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Factory Method example runs without errors. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.factory.method;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/**\n * The Factory Method is a creational design pattern which uses factory methods to deal with the\n * problem of creating objects without specifying the exact class of object that will be created.\n * This is done by creating objects via calling a factory method either specified in an interface\n * and implemented by child classes, or implemented in a base class and optionally overridden by\n * derived classes—rather than by calling a constructor.\n *\n * <p>Factory produces the object of its liking. The weapon {@link Weapon} manufactured by the\n * blacksmith depends on the kind of factory implementation it is referring to.\n */\nclass FactoryMethodTest {\n\n  /**\n   * Testing {@link OrcBlacksmith} to produce a SPEAR asserting that the Weapon is an instance of\n   * {@link OrcWeapon}.\n   */\n  @Test\n  void testOrcBlacksmithWithSpear() {\n    var blacksmith = new OrcBlacksmith();\n    var weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);\n    verifyWeapon(weapon, WeaponType.SPEAR, OrcWeapon.class);\n  }\n\n  /**\n   * Testing {@link OrcBlacksmith} to produce an AXE asserting that the Weapon is an instance of\n   * {@link OrcWeapon}.\n   */\n  @Test\n  void testOrcBlacksmithWithAxe() {\n    var blacksmith = new OrcBlacksmith();\n    var weapon = blacksmith.manufactureWeapon(WeaponType.AXE);\n    verifyWeapon(weapon, WeaponType.AXE, OrcWeapon.class);\n  }\n\n  /**\n   * Testing {@link ElfBlacksmith} to produce a SHORT_SWORD asserting that the Weapon is an instance\n   * of {@link ElfWeapon}.\n   */\n  @Test\n  void testElfBlacksmithWithShortSword() {\n    var blacksmith = new ElfBlacksmith();\n    var weapon = blacksmith.manufactureWeapon(WeaponType.SHORT_SWORD);\n    verifyWeapon(weapon, WeaponType.SHORT_SWORD, ElfWeapon.class);\n  }\n\n  /**\n   * Testing {@link ElfBlacksmith} to produce a SPEAR asserting that the Weapon is an instance of\n   * {@link ElfWeapon}.\n   */\n  @Test\n  void testElfBlacksmithWithSpear() {\n    var blacksmith = new ElfBlacksmith();\n    var weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);\n    verifyWeapon(weapon, WeaponType.SPEAR, ElfWeapon.class);\n  }\n\n  /**\n   * This method asserts that the weapon object that is passed is an instance of the clazz and the\n   * weapon is of type expectedWeaponType.\n   *\n   * @param weapon weapon object which is to be verified\n   * @param expectedWeaponType expected WeaponType of the weapon\n   * @param clazz expected class of the weapon\n   */\n  private void verifyWeapon(Weapon weapon, WeaponType expectedWeaponType, Class<?> clazz) {\n    assertTrue(clazz.isInstance(weapon), \"Weapon must be an object of: \" + clazz.getName());\n    assertEquals(\n        expectedWeaponType,\n        weapon.weaponType(),\n        \"Weapon must be of weaponType: \" + expectedWeaponType);\n  }\n}\n"
  },
  {
    "path": "fanout-fanin/README.md",
    "content": "---\ntitle: \"Fan-Out Fan-In Pattern in Java: Maximizing Concurrency for Efficient Data Processing\"\nshortTitle: Fan-Out/Fan-In\ndescription: \"Learn how the Fan-Out/Fan-In design pattern in Java can optimize concurrency and processing efficiency. Explore real-world examples, detailed explanations, and programmatic implementations.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Asynchronous\n  - Data processing\n  - Decoupling\n  - Scalability\n---\n\n## Also known as\n\n* Scatter-Gather\n\n## Intent of Fan-Out/Fan-In Design Pattern\n\nThe Fan-Out/Fan-In design pattern in Java aims to improve concurrency and optimize processing time by dividing a task into multiple sub-tasks that can be processed in parallel (fan-out) and then combining the results of these sub-tasks into a single outcome (fan-in).\n\n## Detailed Explanation of Fan-Out/Fan-In Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world example of the Fan-Out/Fan-In pattern in Java is a food delivery service like UberEats or DoorDash. When a customer places an order, the service (fan-out) sends out individual tasks to different restaurants to prepare the various items. Each restaurant works independently to prepare its part of the order. Once all restaurants have completed their tasks, the delivery service (fan-in) aggregates the items from different restaurants into a single order, ensuring that everything is delivered together to the customer. This parallel processing improves efficiency and ensures timely delivery.\n\nIn plain words\n\n> The Fan-Out/Fan-In pattern distributes tasks across multiple concurrent processes or threads and then aggregates the results.\n\nWikipedia says\n\n> In message-oriented middleware, the fan-out pattern models information exchange by delivering messages to one or multiple destinations in parallel, without waiting for responses. This allows a process to distribute tasks to various receivers simultaneously.\n>\n> The fan-in concept, on the other hand, typically refers to the aggregation of multiple inputs. In digital electronics, it describes the number of inputs a logic gate can handle. Combining these concepts, the Fan-Out/Fan-In pattern in software engineering involves distributing tasks (fan-out) and then aggregating the results (fan-in).\n\nSequence diagram\n\n![Fan-Out/Fan-In flowchart](./etc/fan-out-fan-in-flowchart.png)\n\n## Programmatic Example of Fan-Out/Fan-In Pattern in Java\n\nThe provided implementation involves a list of numbers with the objective to square them and aggregate the results. The `FanOutFanIn` class receives the list of numbers as `SquareNumberRequest` objects and a `Consumer` instance that collects the squared results as the requests complete. Each `SquareNumberRequest` squares its number with a random delay, simulating a long-running process that finishes at unpredictable times. The `Consumer` instance gathers the results from the various `SquareNumberRequest` objects as they become available at different times.\n\nHere's the `FanOutFanIn` class in Java that demonstrates the Fan-Out/Fan-In pattern by asynchronously distributing the requests.\n\n```java\npublic class FanOutFanIn {\n    public static Long fanOutFanIn(final List<SquareNumberRequest> requests, final Consumer consumer) {\n\n        ExecutorService service = Executors.newFixedThreadPool(requests.size());\n\n        // fanning out\n        List<CompletableFuture<Void>> futures = requests\n                .stream()\n                .map(request -> CompletableFuture.runAsync(() -> request.delayedSquaring(consumer), service))\n                .collect(Collectors.toList());\n\n        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();\n\n        return consumer.getSumOfSquaredNumbers().get();\n    }\n}\n```\n\n`Consumer` is used a callback class that will be called when a request is completed. This will aggregate the result from all requests.\n\n```java\npublic class Consumer {\n\n    private final AtomicLong sumOfSquaredNumbers;\n\n    Consumer(Long init) {\n        sumOfSquaredNumbers = new AtomicLong(init);\n    }\n\n    public Long add(final Long num) {\n        return sumOfSquaredNumbers.addAndGet(num);\n    }\n}\n```\n\nRequest is represented as a `SquareNumberRequest` that squares the number with random delay and calls the `Consumer` once it is squared.\n\n```java\npublic class SquareNumberRequest {\n\n    private final Long number;\n\n    public void delayedSquaring(final Consumer consumer) {\n\n        var minTimeOut = 5000L;\n\n        SecureRandom secureRandom = new SecureRandom();\n        var randomTimeOut = secureRandom.nextInt(2000);\n\n        try {\n            // this will make the thread sleep from 5-7s.\n            Thread.sleep(minTimeOut + randomTimeOut);\n        } catch (InterruptedException e) {\n            LOGGER.error(\"Exception while sleep \", e);\n            Thread.currentThread().interrupt();\n        } finally {\n            consumer.add(number * number);\n        }\n    }\n}\n```\n\nHere is the App class with main method to drive the example.\n\n```java\npublic static void main(String[] args) {\n    final List<Long> numbers = Arrays.asList(1L, 3L, 4L, 7L, 8L);\n\n    LOGGER.info(\"Numbers to be squared and get sum --> {}\", numbers);\n\n    final List<SquareNumberRequest> requests =\n        numbers.stream().map(SquareNumberRequest::new).toList();\n\n    var consumer = new Consumer(0L);\n\n    // Pass the request and the consumer to fanOutFanIn or sometimes referred as Orchestrator\n    // function\n    final Long sumOfSquaredNumbers = FanOutFanIn.fanOutFanIn(requests, consumer);\n\n    LOGGER.info(\"Sum of all squared numbers --> {}\", sumOfSquaredNumbers);\n}\n```\n\nRunning the example produces the following console output.\n\n```\n06:52:04.622 [main] INFO com.iluwatar.fanout.fanin.App -- Numbers to be squared and get sum --> [1, 3, 4, 7, 8]\n06:52:11.465 [main] INFO com.iluwatar.fanout.fanin.App -- Sum of all squared numbers --> 139\n```\n\n## When to Use the Fan-Out/Fan-In Pattern in Java\n\nThe Fan-Out/Fan-In design pattern in Java is appropriate in scenarios where tasks can be broken down and executed in parallel, especially suitable for data processing, batch processing, and situations requiring aggregation of results from various sources.\n\n## Fan-Out/Fan-In Pattern Java Tutorials\n\n* [Fan-out/fan-in scenario in Durable Functions - Cloud backup example (Microsoft)](https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-cloud-backup)\n* [Understanding Azure Durable Functions - Part 8: The Fan Out/Fan In Pattern (Don't Code Tired)](http://dontcodetired.com/blog/post/Understanding-Azure-Durable-Functions-Part-8-The-Fan-OutFan-In-Pattern)\n* [Understanding the Fan-Out/Fan-In API Integration Pattern (DZone)](https://dzone.com/articles/understanding-the-fan-out-fan-in-api-integration-p)\n\n## Real-World Applications of Fan-Out/Fan-In Pattern in Java\n\n* The Fan-Out/Fan-In pattern in Java is widely used in large-scale data processing applications.\n* Services requiring aggregation from multiple sources before delivering a response, such as in distributed caching or load balancing systems.\n\n## Benefits and Trade-offs of Fan-Out/Fan-In Pattern\n\nBenefits:\n\n* Enhances performance by parallel processing.\n* Increases responsiveness of systems.\n* Efficient utilization of multi-core processor architectures.\n\nTrade-offs:\n\n* Increased complexity in error handling.\n* Potential for increased overhead due to task synchronization and result aggregation.\n* Dependency on the underlying infrastructure's ability to support concurrent execution.\n\n## Related Java Design Patterns\n\n* MapReduce: Similar to Fan-Out/Fan-In, MapReduce also involves distributing tasks across a number of workers (map) and aggregating the results (reduce), which is particularly useful for processing large data sets.\n* [Command](https://java-design-patterns.com/patterns/command/): Command Pattern facilitates the decoupling of the sender and the receiver, akin to how Fan-Out/Fan-In decouples task submission from task processing.\n* [Producer-Consumer](https://java-design-patterns.com/patterns/producer-consumer/): Works synergistically with Fan-Out/Fan-In by organizing task execution where producers distribute tasks that are processed by multiple consumers, and results are then combined, enhancing throughput and efficiency in data processing.\n\n## References and Credits\n\n* [Java Concurrency in Practice](https://amzn.to/3vXytsb)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/49QQcPD)\n"
  },
  {
    "path": "fanout-fanin/etc/fanout-fanin.urm.puml",
    "content": "@startuml\npackage com.iluwatar.fanout.fanin {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Consumer {\n    - sumOfSquaredNumbers : AtomicLong\n    ~ Consumer(init : Long)\n    + add(num : Long) : Long\n    + getSumOfSquaredNumbers() : AtomicLong\n  }\n  class FanOutFanIn {\n    + FanOutFanIn()\n    + fanOutFanIn(requests : List<SquareNumberRequest>, consumer : Consumer) : Long {static}\n  }\n  class SquareNumberRequest {\n    - LOGGER : Logger {static}\n    - number : Long\n    + SquareNumberRequest(number : Long)\n    + delayedSquaring(consumer : Consumer)\n  }\n\n  object SquareNumberRequest1\n  object SquareNumberRequest2\n  object SquareNumberRequest3\n  diamond dia\n}\n\nApp --> FanOutFanIn\nFanOutFanIn --> \"fan out - running in parallel\" SquareNumberRequest1\nFanOutFanIn --> \"fan out\" SquareNumberRequest2\nFanOutFanIn --> \"fan out\" SquareNumberRequest3\nSquareNumberRequest1 --> \"fan in - aggregate using callback\" dia\nSquareNumberRequest2 --> \"fan in\" dia\nSquareNumberRequest3 --> \"fan in\" dia\ndia --> Consumer\n@enduml"
  },
  {
    "path": "fanout-fanin/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>fanout-fanin</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.fanout.fanin.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fanout.fanin;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * FanOut/FanIn pattern is a concurrency pattern that refers to executing multiple instances of the\n * activity function concurrently. The \"fan out\" part is essentially splitting the data into\n * multiple chunks and then calling the activity function multiple times, passing the chunks.\n *\n * <p>When each chunk has been processed, the \"fan in\" takes place that aggregates results from each\n * instance of function and forms a single final result.\n *\n * <p>This pattern is only really useful if you can “chunk” the workload in a meaningful way for\n * splitting up to be processed in parallel.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Entry point.\n   *\n   * <p>Implementation provided has a list of numbers that has to be squared and added. The list can\n   * be chunked in any way and the \"activity function\" {@link\n   * SquareNumberRequest#delayedSquaring(Consumer)} i.e. squaring the number ca be done\n   * concurrently. The \"fan in\" part is handled by the {@link Consumer} that takes in the result\n   * from each instance of activity and aggregates it whenever that particular activity function\n   * gets over.\n   */\n  public static void main(String[] args) {\n    final List<Long> numbers = Arrays.asList(1L, 3L, 4L, 7L, 8L);\n\n    LOGGER.info(\"Numbers to be squared and get sum --> {}\", numbers);\n\n    final List<SquareNumberRequest> requests =\n        numbers.stream().map(SquareNumberRequest::new).toList();\n\n    var consumer = new Consumer(0L);\n\n    // Pass the request and the consumer to fanOutFanIn or sometimes referred as Orchestrator\n    // function\n    final Long sumOfSquaredNumbers = FanOutFanIn.fanOutFanIn(requests, consumer);\n\n    LOGGER.info(\"Sum of all squared numbers --> {}\", sumOfSquaredNumbers);\n  }\n}\n"
  },
  {
    "path": "fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/Consumer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fanout.fanin;\n\nimport java.util.concurrent.atomic.AtomicLong;\nimport lombok.Getter;\n\n/**\n * Consumer or callback class that will be called every time a request is complete This will\n * aggregate individual result to form a final result.\n */\n@Getter\npublic class Consumer {\n\n  private final AtomicLong sumOfSquaredNumbers;\n\n  Consumer(Long init) {\n    sumOfSquaredNumbers = new AtomicLong(init);\n  }\n\n  public Long add(final Long num) {\n    return sumOfSquaredNumbers.addAndGet(num);\n  }\n}\n"
  },
  {
    "path": "fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/FanOutFanIn.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fanout.fanin;\n\nimport java.util.List;\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\n/**\n * FanOutFanIn class processes long-running requests, when any of the processes gets over, result is\n * passed over to the consumer or the callback function. Consumer will aggregate the results as they\n * keep on completing.\n */\npublic class FanOutFanIn {\n\n  /**\n   * the main fanOutFanIn function or orchestrator function.\n   *\n   * @param requests List of numbers that need to be squared and summed up\n   * @param consumer Takes in the squared number from {@link SquareNumberRequest} and sums it up\n   * @return Aggregated sum of all squared numbers.\n   */\n  public static Long fanOutFanIn(\n      final List<SquareNumberRequest> requests, final Consumer consumer) {\n\n    ExecutorService service = Executors.newFixedThreadPool(requests.size());\n\n    // fanning out\n    List<CompletableFuture<Void>> futures =\n        requests.stream()\n            .map(\n                request ->\n                    CompletableFuture.runAsync(() -> request.delayedSquaring(consumer), service))\n            .toList();\n\n    CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();\n\n    return consumer.getSumOfSquaredNumbers().get();\n  }\n}\n"
  },
  {
    "path": "fanout-fanin/src/main/java/com/iluwatar/fanout/fanin/SquareNumberRequest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fanout.fanin;\n\nimport java.security.SecureRandom;\nimport lombok.AllArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Squares the number with a little timeout to give impression of long-running process that return\n * at different times.\n */\n@Slf4j\n@AllArgsConstructor\npublic class SquareNumberRequest {\n\n  private final Long number;\n\n  /**\n   * Squares the number with a little timeout to give impression of long-running process that return\n   * at different times.\n   *\n   * @param consumer callback class that takes the result after the delay.\n   */\n  public void delayedSquaring(final Consumer consumer) {\n\n    var minTimeOut = 5000L;\n\n    SecureRandom secureRandom = new SecureRandom();\n    var randomTimeOut = secureRandom.nextInt(2000);\n\n    try {\n      // this will make the thread sleep from 5-7s.\n      Thread.sleep(minTimeOut + randomTimeOut);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Exception while sleep \", e);\n      Thread.currentThread().interrupt();\n    } finally {\n      consumer.add(number * number);\n    }\n  }\n}\n"
  },
  {
    "path": "fanout-fanin/src/test/java/com/iluwatar/fanout/fanin/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fanout.fanin;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n\n  @Test\n  void shouldLaunchApp() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "fanout-fanin/src/test/java/com/iluwatar/fanout/fanin/FanOutFanInTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fanout.fanin;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass FanOutFanInTest {\n\n  @Test\n  void fanOutFanInTest() {\n    final List<Long> numbers = Arrays.asList(1L, 3L, 4L, 7L, 8L);\n\n    final List<SquareNumberRequest> requests =\n        numbers.stream().map(SquareNumberRequest::new).toList();\n\n    final Consumer consumer = new Consumer(0L);\n\n    final Long sumOfSquaredNumbers = FanOutFanIn.fanOutFanIn(requests, consumer);\n\n    Assertions.assertEquals(139, sumOfSquaredNumbers);\n  }\n}\n"
  },
  {
    "path": "fanout-fanin/src/test/java/com/iluwatar/fanout/fanin/SquareNumberRequestTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fanout.fanin;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass SquareNumberRequestTest {\n\n  @Test\n  void delayedSquaringTest() {\n    Consumer consumer = new Consumer(10L);\n\n    SquareNumberRequest squareNumberRequest = new SquareNumberRequest(5L);\n\n    squareNumberRequest.delayedSquaring(consumer);\n\n    Assertions.assertEquals(35, consumer.getSumOfSquaredNumbers().get());\n  }\n}\n"
  },
  {
    "path": "feature-toggle/README.md",
    "content": "---\ntitle: \"Feature Toggle Pattern in Java: Managing Features in Production Seamlessly\"\nshortTitle: Feature Toggle\ndescription: \"Learn how to implement the Feature Toggle design pattern in Java. This guide covers dynamic feature management, benefits, use cases, and practical examples to help you enhance your software development process.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Decoupling\n  - Extensibility\n  - Feature management\n  - Scalability\n---\n\n## Also known as\n\n* Feature Flag\n* Feature Switch\n\n## Intent of Feature Toggle Design Pattern\n\nTo enable or disable features in a software application dynamically without deploying new code.\n\n## Detailed Explanation of Feature Toggle Pattern with Real-World Examples\n\nReal-world Example\n\n> A real-world example of the Feature Toggle pattern is Netflix's rollout of new user interface features. When Netflix decides to introduce a new feature, such as a redesigned homepage layout or a new recommendation algorithm, they use feature toggles to control the release. Initially, the new feature is toggled off for most users, allowing only a small group of users (e.g., beta testers) to experience and provide feedback on the feature. Based on the feedback and performance metrics, Netflix can quickly toggle the feature on for a broader audience or turn it off if issues are detected, all without redeploying the application. This approach allows Netflix to continuously innovate and improve their platform while minimizing risk and ensuring a stable user experience.\n\nIn plain words\n\n> The Feature Toggle design pattern in Java allows developers to introduce new features gradually instead of deploying them all at once, facilitating better dynamic feature management.\n\nWikipedia says\n\n> A feature toggle in software development provides an alternative to maintaining multiple feature branches in source code. A condition within the code enables or disables a feature during runtime. In agile settings the toggle is used in production, to switch on the feature on demand, for some or all the users.\n\nFlowchart\n\n![Feature Toggle flowchart](./etc/feature-toggle-flowchart.png)\n\n## Programmatic Example of Feature Toggle Pattern in Java\n\nThis Java code example demonstrates how to display a feature when it is enabled by the developer and the user is a Premium member of the application. This approach is useful for managing subscription-locked features.\n\nThe Feature Toggle pattern enables the seamless activation or deactivation of entire code executions. This allows features to be managed dynamically based on user information or configuration properties.\n\nKey Components:\n\n1. `PropertiesFeatureToggleVersion`: This class uses properties to control the feature toggle. The properties determine whether the enhanced version of the welcome message, which is personalized, is turned on or off.\n\n2. `TieredFeatureToggleVersion`: This class uses user information to control the feature toggle. The feature of the personalized welcome message is dependent on the user group the user is in.\n\n3. `User`: This class represents the user of the application.\n\n4. `UserGroup`: This class represents the group the user belongs to.\n\n```java\npublic static void main(String[] args) {\n\n    // Demonstrates the PropertiesFeatureToggleVersion running with properties\n    // that set the feature toggle to enabled.\n\n    final var properties = new Properties();\n    properties.put(\"enhancedWelcome\", true);\n    var service = new PropertiesFeatureToggleVersion(properties);\n    final var welcomeMessage = service.getWelcomeMessage(new User(\"Jamie No Code\"));\n    LOGGER.info(welcomeMessage);\n\n    // Demonstrates the PropertiesFeatureToggleVersion running with properties\n    // that set the feature toggle to disabled. Note the difference in the printed welcome message\n    // where the username is not included.\n\n    final var turnedOff = new Properties();\n    turnedOff.put(\"enhancedWelcome\", false);\n    var turnedOffService = new PropertiesFeatureToggleVersion(turnedOff);\n    final var welcomeMessageturnedOff =\n            turnedOffService.getWelcomeMessage(new User(\"Jamie No Code\"));\n    LOGGER.info(welcomeMessageturnedOff);\n\n    // Demonstrates the TieredFeatureToggleVersion setup with\n    // two users: one on the free tier and the other on the paid tier. When the\n    // Service#getWelcomeMessage(User) method is called with the paid user, the welcome\n    // message includes their username. In contrast, calling the same service with the free tier user results\n    // in a more generic welcome message without the username.\n\n    var service2 = new TieredFeatureToggleVersion();\n\n    final var paidUser = new User(\"Jamie Coder\");\n    final var freeUser = new User(\"Alan Defect\");\n\n    UserGroup.addUserToPaidGroup(paidUser);\n    UserGroup.addUserToFreeGroup(freeUser);\n\n    final var welcomeMessagePaidUser = service2.getWelcomeMessage(paidUser);\n    final var welcomeMessageFreeUser = service2.getWelcomeMessage(freeUser);\n    LOGGER.info(welcomeMessageFreeUser);\n    LOGGER.info(welcomeMessagePaidUser);\n}\n```\n\nRunning the example produces the following output.\n\n```\n07:31:50.802 [main] INFO com.iluwatar.featuretoggle.App -- Welcome Jamie No Code. You're using the enhanced welcome message.\n07:31:50.804 [main] INFO com.iluwatar.featuretoggle.App -- Welcome to the application.\n07:31:50.804 [main] INFO com.iluwatar.featuretoggle.App -- I suppose you can use this software.\n07:31:50.804 [main] INFO com.iluwatar.featuretoggle.App -- You're amazing Jamie Coder. Thanks for paying for this awesome software.\n```\n\n## When to Use the Feature Toggle Pattern in Java\n\nUse the Feature Toggle Pattern in Java when:\n\n* Dynamic feature management to different users and groups.\n* Rolling out a new feature incrementally.\n* Switching between development and production environments.\n* Quickly disable problematic features\n* External management of feature deployment\n* Ability to maintain multiple version releases of a feature\n* 'Hidden' deployment, releasing a feature in code for designated testing but not publicly making it available\n\n## Real-World Applications of Feature Toggle Pattern in Java\n\n* Many web development platforms utilize the Feature Toggle design pattern to gradually roll out new features to users, ensuring stability and effective dynamic feature management.\n* Enterprise applications use feature toggles to enable or disable features during runtime to cater to different market needs.\n\n## Benefits and Trade-offs of Feature Toggle Pattern\n\nBenefits:\n\n* Facilitates A/B testing and canary releases.\n* Allows for quicker rollback and minimal risk deployments.\n* Enables conditional feature execution without redeploying the application.\n\nTrade-offs:\n\n* Code complexity is increased.\n* Testing of multiple states is harder and more time-consuming.\n* Potential for technical debt if toggles remain in the code longer than necessary.\n* Risk of toggle misconfiguration leading to unexpected behavior.\n\n## Related Java Design Patterns\n\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Both patterns allow changing the behavior of software at runtime. The Feature Toggle changes features dynamically, while the Strategy allows switching algorithms or strategies.\n* [Observer](https://java-design-patterns.com/patterns/observer/): Useful for implementing feature toggles by notifying components of feature state changes, which allows dynamic feature modification without restarts.\n\n## References and Credits\n\n* [Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation](https://amzn.to/4488ESM)\n* [Release It! Design and Deploy Production-Ready Software](https://amzn.to/3UoeJY4)\n* [Feature Toggle (Martin Fowler)](http://martinfowler.com/bliki/FeatureToggle.html)\n"
  },
  {
    "path": "feature-toggle/etc/feature-toggle.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.9\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"true\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"true\" nesting-relationships=\"true\" router=\"FAN\">  \n  <interface id=\"1\" language=\"java\" name=\"com.iluwatar.featuretoggle.pattern.Service\" project=\"feature-toggle\" \n    file=\"/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"238\" y=\"187\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"true\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"2\" language=\"java\" \n    name=\"com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion\" project=\"feature-toggle\" \n    file=\"/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"241\" y=\"449\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"true\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion\" \n    project=\"feature-toggle\" \n    file=\"/feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"149\" width=\"230\" x=\"502\" y=\"119\"/>    \n    <display autosize=\"false\" stereotype=\"true\" package=\"true\" initial-value=\"true\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.featuretoggle.user.User\" project=\"feature-toggle\" \n    file=\"/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/User.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"616\" y=\"453\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"true\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.featuretoggle.user.UserGroup\" project=\"feature-toggle\" \n    file=\"/feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/UserGroup.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"956\" y=\"187\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"true\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <dependency id=\"6\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </dependency>  \n  <dependency id=\"7\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </dependency>  \n  <association id=\"8\">    \n    <bendpoint x=\"911\" y=\"415\"/>    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"9\" name=\"freeGroup\">        \n        <position height=\"19\" width=\"63\" x=\"846\" y=\"368\"/>      \n      </attribute>      \n      <multiplicity id=\"10\" minimum=\"0\" maximum=\"2147483647\">        \n        <position height=\"17\" width=\"23\" x=\"707\" y=\"418\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"11\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </realization>  \n  <dependency id=\"12\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </dependency>  \n  <dependency id=\"13\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </dependency>  \n  <association id=\"14\">    \n    <bendpoint x=\"953\" y=\"459\"/>    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"15\" name=\"paidGroup\">        \n        <position height=\"19\" width=\"66\" x=\"963\" y=\"419\"/>      \n      </attribute>      \n      <multiplicity id=\"16\" minimum=\"0\" maximum=\"2147483647\">        \n        <position height=\"17\" width=\"23\" x=\"711\" y=\"463\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"17\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"true\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "feature-toggle/etc/feature-toggle.urm.puml",
    "content": "@startuml\npackage com.iluwatar.featuretoggle.pattern {\n  interface Service {\n    + getWelcomeMessage(User) : String {abstract}\n    + isEnhanced() : boolean {abstract}\n  }\n}\npackage com.iluwatar.featuretoggle.user {\n  class User {\n    - name : String\n    + User(name : String)\n    + toString() : String\n  }\n  class UserGroup {\n    - freeGroup : List<User> {static}\n    - paidGroup : List<User> {static}\n    + UserGroup()\n    + addUserToFreeGroup(user : User) {static}\n    + addUserToPaidGroup(user : User) {static}\n    + isPaid(user : User) : boolean {static}\n  }\n}\npackage com.iluwatar.featuretoggle.pattern.tieredversion {\n  class TieredFeatureToggleVersion {\n    + TieredFeatureToggleVersion()\n    + getWelcomeMessage(user : User) : String\n    + isEnhanced() : boolean\n  }\n}\npackage com.iluwatar.featuretoggle.pattern.propertiesversion {\n  class PropertiesFeatureToggleVersion {\n    - isEnhanced : boolean\n    + PropertiesFeatureToggleVersion(properties : Properties)\n    + getWelcomeMessage(user : User) : String\n    + isEnhanced() : boolean\n  }\n}\npackage com.iluwatar.featuretoggle {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n}\nUserGroup -->  \"-freeGroup\" User\nPropertiesFeatureToggleVersion ..|> Service \nTieredFeatureToggleVersion ..|> Service \n@enduml"
  },
  {
    "path": "feature-toggle/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>feature-toggle</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.featuretoggle.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "feature-toggle/src/main/java/com/iluwatar/featuretoggle/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.featuretoggle;\n\nimport com.iluwatar.featuretoggle.pattern.Service;\nimport com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion;\nimport com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion;\nimport com.iluwatar.featuretoggle.user.User;\nimport com.iluwatar.featuretoggle.user.UserGroup;\nimport java.util.Properties;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Feature Toggle pattern allows for complete code executions to be turned on or off with ease.\n * This allows features to be controlled by either dynamic methods just as {@link User} information\n * or by {@link Properties}. In the App below there are two examples. Firstly the {@link Properties}\n * version of the feature toggle, where the enhanced version of the welcome message which is\n * personalised is turned either on or off at instance creation. This method is not as dynamic as\n * the {@link User} driven version where the feature of the personalised welcome message is\n * dependent on the {@link UserGroup} the {@link User} is in. So if the user is a member of the\n * {@link UserGroup#isPaid(User)} then they get an enhanced version of the welcome message.\n *\n * <p>Note that this pattern can easily introduce code complexity, and if not kept in check can\n * result in redundant unmaintained code within the codebase.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Block 1 shows the {@link PropertiesFeatureToggleVersion} being run with {@link Properties}\n   * setting the feature toggle to enabled.\n   *\n   * <p>Block 2 shows the {@link PropertiesFeatureToggleVersion} being run with {@link Properties}\n   * setting the feature toggle to disabled. Notice the difference with the printed welcome message\n   * the username is not included.\n   *\n   * <p>Block 3 shows the {@link\n   * com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} being set up with\n   * two users on who is on the free level, while the other is on the paid level. When the {@link\n   * Service#getWelcomeMessage(User)} is called with the paid {@link User} note that the welcome\n   * message contains their username, while the same service call with the free tier user is more\n   * generic. No username is printed.\n   *\n   * @see User\n   * @see UserGroup\n   * @see Service\n   * @see PropertiesFeatureToggleVersion\n   * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion\n   */\n  public static void main(String[] args) {\n\n    // Demonstrates the PropertiesFeatureToggleVersion running with properties\n    // that set the feature toggle to enabled.\n\n    final var properties = new Properties();\n    properties.put(\"enhancedWelcome\", true);\n    var service = new PropertiesFeatureToggleVersion(properties);\n    final var welcomeMessage = service.getWelcomeMessage(new User(\"Jamie No Code\"));\n    LOGGER.info(welcomeMessage);\n\n    // Demonstrates the PropertiesFeatureToggleVersion running with properties\n    // that set the feature toggle to disabled. Note the difference in the printed welcome message\n    // where the username is not included.\n\n    final var turnedOff = new Properties();\n    turnedOff.put(\"enhancedWelcome\", false);\n    var turnedOffService = new PropertiesFeatureToggleVersion(turnedOff);\n    final var welcomeMessageturnedOff =\n        turnedOffService.getWelcomeMessage(new User(\"Jamie No Code\"));\n    LOGGER.info(welcomeMessageturnedOff);\n\n    // Demonstrates the TieredFeatureToggleVersion setup with\n    // two users: one on the free tier and the other on the paid tier. When the\n    // Service#getWelcomeMessage(User) method is called with the paid user, the welcome\n    // message includes their username. In contrast, calling the same service with the free tier\n    // user results\n    // in a more generic welcome message without the username.\n\n    var service2 = new TieredFeatureToggleVersion();\n\n    final var paidUser = new User(\"Jamie Coder\");\n    final var freeUser = new User(\"Alan Defect\");\n\n    UserGroup.addUserToPaidGroup(paidUser);\n    UserGroup.addUserToFreeGroup(freeUser);\n\n    final var welcomeMessagePaidUser = service2.getWelcomeMessage(paidUser);\n    final var welcomeMessageFreeUser = service2.getWelcomeMessage(freeUser);\n    LOGGER.info(welcomeMessageFreeUser);\n    LOGGER.info(welcomeMessagePaidUser);\n  }\n}\n"
  },
  {
    "path": "feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/Service.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.featuretoggle.pattern;\n\nimport com.iluwatar.featuretoggle.user.User;\n\n/**\n * Simple interfaces to allow the calling of the method to generate the welcome message for a given\n * user. While there is a helper method to gather the status of the feature toggle. In some cases\n * there is no need for the {@link Service#isEnhanced()} in {@link\n * com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} where the toggle is\n * determined by the actual {@link User}.\n *\n * @see com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion\n * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion\n * @see User\n */\npublic interface Service {\n\n  /**\n   * Generates a welcome message for the passed user.\n   *\n   * @param user the {@link User} to be used if the message is to be personalised.\n   * @return Generated {@link String} welcome message\n   */\n  String getWelcomeMessage(User user);\n\n  /**\n   * Returns if the welcome message to be displayed will be the enhanced version.\n   *\n   * @return Boolean {@code true} if enhanced.\n   */\n  boolean isEnhanced();\n}\n"
  },
  {
    "path": "feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersion.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.featuretoggle.pattern.propertiesversion;\n\nimport com.iluwatar.featuretoggle.pattern.Service;\nimport com.iluwatar.featuretoggle.user.User;\nimport java.util.Properties;\nimport lombok.Getter;\n\n/**\n * This example of the Feature Toggle pattern is less dynamic version than {@link\n * com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion} where the feature is\n * turned on or off at the time of creation of the service. This example uses simple Java {@link\n * Properties} however it could as easily be done with an external configuration file loaded by\n * Spring and so on. A good example of when to use this version of the feature toggle is when new\n * features are being developed. So you could have a configuration property boolean named\n * development or some sort of system environment variable.\n *\n * @see Service\n * @see com.iluwatar.featuretoggle.pattern.tieredversion.TieredFeatureToggleVersion\n * @see User\n */\n@Getter\npublic class PropertiesFeatureToggleVersion implements Service {\n\n  /**\n   * True if the welcome message to be returned is the enhanced venison or not. For this service it\n   * will see the value of the boolean that was set in the constructor {@link\n   * PropertiesFeatureToggleVersion#PropertiesFeatureToggleVersion(Properties)}\n   */\n  private final boolean enhanced;\n\n  /**\n   * Creates an instance of {@link PropertiesFeatureToggleVersion} using the passed {@link\n   * Properties} to determine, the status of the feature toggle {@link\n   * PropertiesFeatureToggleVersion#isEnhanced()}. There is also some defensive code to ensure the\n   * {@link Properties} passed are as expected.\n   *\n   * @param properties {@link Properties} used to configure the service and toggle features.\n   * @throws IllegalArgumentException when the passed {@link Properties} is not as expected\n   * @see Properties\n   */\n  public PropertiesFeatureToggleVersion(final Properties properties) {\n    if (properties == null) {\n      throw new IllegalArgumentException(\"No Properties Provided.\");\n    } else {\n      try {\n        enhanced = (boolean) properties.get(\"enhancedWelcome\");\n      } catch (Exception e) {\n        throw new IllegalArgumentException(\"Invalid Enhancement Settings Provided.\");\n      }\n    }\n  }\n\n  /**\n   * Generate a welcome message based on the user being passed and the status of the feature toggle.\n   * If the enhanced version is enabled, then the message will be personalised with the name of the\n   * passed {@link User}. However, if disabled then a generic version fo the message is returned.\n   *\n   * @param user the {@link User} to be displayed in the message if the enhanced version is enabled\n   *     see {@link PropertiesFeatureToggleVersion#isEnhanced()}. If the enhanced version is\n   *     enabled, then the message will be personalised with the name of the passed {@link User}.\n   *     However, if disabled then a generic version fo the message is returned.\n   * @return Resulting welcome message.\n   * @see User\n   */\n  @Override\n  public String getWelcomeMessage(final User user) {\n\n    if (isEnhanced()) {\n      return \"Welcome \" + user + \". You're using the enhanced welcome message.\";\n    }\n\n    return \"Welcome to the application.\";\n  }\n}\n"
  },
  {
    "path": "feature-toggle/src/main/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersion.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.featuretoggle.pattern.tieredversion;\n\nimport com.iluwatar.featuretoggle.pattern.Service;\nimport com.iluwatar.featuretoggle.user.User;\nimport com.iluwatar.featuretoggle.user.UserGroup;\n\n/**\n * This example of the Feature Toggle pattern shows how it could be implemented based on a {@link\n * User}. Therefore, showing its use within a tiered application where the paying users get access\n * to different content or better versions of features. So in this instance a {@link User} is passed\n * in and if they are found to be on the {@link UserGroup#isPaid(User)} they are welcomed with a\n * personalised message. While the other is more generic. However, this pattern is limited to simple\n * examples such as the one below.\n *\n * @see Service\n * @see User\n * @see com.iluwatar.featuretoggle.pattern.propertiesversion.PropertiesFeatureToggleVersion\n * @see UserGroup\n */\npublic class TieredFeatureToggleVersion implements Service {\n\n  /**\n   * Generates a welcome message from the passed {@link User}. The resulting message depends on the\n   * group of the {@link User}. So if the {@link User} is in the {@link UserGroup#paidGroup} then\n   * the enhanced version of the welcome message will be returned where the username is displayed.\n   *\n   * @param user the {@link User} to generate the welcome message for, different messages are\n   *     displayed if the user is in the {@link UserGroup#isPaid(User)} or {@link\n   *     UserGroup#freeGroup}\n   * @return Resulting welcome message.\n   * @see User\n   * @see UserGroup\n   */\n  @Override\n  public String getWelcomeMessage(User user) {\n    if (UserGroup.isPaid(user)) {\n      return \"You're amazing \" + user + \". Thanks for paying for this awesome software.\";\n    }\n\n    return \"I suppose you can use this software.\";\n  }\n\n  /**\n   * Method that checks if the welcome message to be returned is the enhanced version. For this\n   * instance as the logic is driven by the user group. This method is a little redundant. However,\n   * can be used to show that there is an enhanced version available.\n   *\n   * @return Boolean value {@code true} if enhanced.\n   */\n  @Override\n  public boolean isEnhanced() {\n    return true;\n  }\n}\n"
  },
  {
    "path": "feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/User.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.featuretoggle.user;\n\nimport lombok.RequiredArgsConstructor;\n\n/**\n * Used to demonstrate the purpose of the feature toggle. This class actually has nothing to do with\n * the pattern.\n */\n@RequiredArgsConstructor\npublic class User {\n\n  private final String name;\n\n  /**\n   * {@inheritDoc}\n   *\n   * @return The {@link String} representation of the User, in this case just return the name of the\n   *     user.\n   */\n  @Override\n  public String toString() {\n    return name;\n  }\n}\n"
  },
  {
    "path": "feature-toggle/src/main/java/com/iluwatar/featuretoggle/user/UserGroup.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.featuretoggle.user;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Contains the lists of users of different groups paid and free. Used to demonstrate the tiered\n * example of feature toggle. Allowing certain features to be available to only certain groups of\n * users.\n *\n * @see User\n */\npublic class UserGroup {\n\n  private static final List<User> freeGroup = new ArrayList<>();\n  private static final List<User> paidGroup = new ArrayList<>();\n\n  /**\n   * Add the passed {@link User} to the free user group list.\n   *\n   * @param user {@link User} to be added to the free group\n   * @throws IllegalArgumentException when user is already added to the paid group\n   * @see User\n   */\n  public static void addUserToFreeGroup(final User user) throws IllegalArgumentException {\n    if (paidGroup.contains(user)) {\n      throw new IllegalArgumentException(\"User already member of paid group.\");\n    } else {\n      if (!freeGroup.contains(user)) {\n        freeGroup.add(user);\n      }\n    }\n  }\n\n  /**\n   * Add the passed {@link User} to the paid user group list.\n   *\n   * @param user {@link User} to be added to the paid group\n   * @throws IllegalArgumentException when the user is already added to the free group\n   * @see User\n   */\n  public static void addUserToPaidGroup(final User user) throws IllegalArgumentException {\n    if (freeGroup.contains(user)) {\n      throw new IllegalArgumentException(\"User already member of free group.\");\n    } else {\n      if (!paidGroup.contains(user)) {\n        paidGroup.add(user);\n      }\n    }\n  }\n\n  /**\n   * Method to take a {@link User} to determine if the user is in the {@link UserGroup#paidGroup}.\n   *\n   * @param user {@link User} to check if they are in the {@link UserGroup#paidGroup}\n   * @return true if the {@link User} is in {@link UserGroup#paidGroup}\n   */\n  public static boolean isPaid(User user) {\n    return paidGroup.contains(user);\n  }\n}\n"
  },
  {
    "path": "feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/propertiesversion/PropertiesFeatureToggleVersionTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.featuretoggle.pattern.propertiesversion;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.featuretoggle.user.User;\nimport java.util.Properties;\nimport org.junit.jupiter.api.Test;\n\n/** Test Properties Toggle */\nclass PropertiesFeatureToggleVersionTest {\n\n  @Test\n  void testNullPropertiesPassed() {\n    assertThrows(IllegalArgumentException.class, () -> new PropertiesFeatureToggleVersion(null));\n  }\n\n  @Test\n  void testNonBooleanProperty() {\n    assertThrows(\n        IllegalArgumentException.class,\n        () -> {\n          final var properties = new Properties();\n          properties.setProperty(\"enhancedWelcome\", \"Something\");\n          new PropertiesFeatureToggleVersion(properties);\n        });\n  }\n\n  @Test\n  void testFeatureTurnedOn() {\n    final var properties = new Properties();\n    properties.put(\"enhancedWelcome\", true);\n    var service = new PropertiesFeatureToggleVersion(properties);\n    assertTrue(service.isEnhanced());\n    final var welcomeMessage = service.getWelcomeMessage(new User(\"Jamie No Code\"));\n    assertEquals(\n        \"Welcome Jamie No Code. You're using the enhanced welcome message.\", welcomeMessage);\n  }\n\n  @Test\n  void testFeatureTurnedOff() {\n    final var properties = new Properties();\n    properties.put(\"enhancedWelcome\", false);\n    var service = new PropertiesFeatureToggleVersion(properties);\n    assertFalse(service.isEnhanced());\n    final var welcomeMessage = service.getWelcomeMessage(new User(\"Jamie No Code\"));\n    assertEquals(\"Welcome to the application.\", welcomeMessage);\n  }\n}\n"
  },
  {
    "path": "feature-toggle/src/test/java/com/iluwatar/featuretoggle/pattern/tieredversion/TieredFeatureToggleVersionTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.featuretoggle.pattern.tieredversion;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.featuretoggle.pattern.Service;\nimport com.iluwatar.featuretoggle.user.User;\nimport com.iluwatar.featuretoggle.user.UserGroup;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Test Tiered Feature Toggle */\nclass TieredFeatureToggleVersionTest {\n\n  final User paidUser = new User(\"Jamie Coder\");\n  final User freeUser = new User(\"Alan Defect\");\n  final Service service = new TieredFeatureToggleVersion();\n\n  @BeforeEach\n  void setUp() {\n    UserGroup.addUserToPaidGroup(paidUser);\n    UserGroup.addUserToFreeGroup(freeUser);\n  }\n\n  @Test\n  void testGetWelcomeMessageForPaidUser() {\n    final var welcomeMessage = service.getWelcomeMessage(paidUser);\n    final var expected = \"You're amazing Jamie Coder. Thanks for paying for this awesome software.\";\n    assertEquals(expected, welcomeMessage);\n  }\n\n  @Test\n  void testGetWelcomeMessageForFreeUser() {\n    final var welcomeMessage = service.getWelcomeMessage(freeUser);\n    final var expected = \"I suppose you can use this software.\";\n    assertEquals(expected, welcomeMessage);\n  }\n\n  @Test\n  void testIsEnhancedAlwaysTrueAsTiered() {\n    assertTrue(service.isEnhanced());\n  }\n}\n"
  },
  {
    "path": "feature-toggle/src/test/java/com/iluwatar/featuretoggle/user/UserGroupTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.featuretoggle.user;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test User Group specific feature */\nclass UserGroupTest {\n\n  @Test\n  void testAddUserToFreeGroup() {\n    var user = new User(\"Free User\");\n    UserGroup.addUserToFreeGroup(user);\n    assertFalse(UserGroup.isPaid(user));\n  }\n\n  @Test\n  void testAddUserToPaidGroup() {\n    var user = new User(\"Paid User\");\n    UserGroup.addUserToPaidGroup(user);\n    assertTrue(UserGroup.isPaid(user));\n  }\n\n  @Test\n  void testAddUserToPaidWhenOnFree() {\n    var user = new User(\"Paid User\");\n    UserGroup.addUserToFreeGroup(user);\n    assertThrows(IllegalArgumentException.class, () -> UserGroup.addUserToPaidGroup(user));\n  }\n\n  @Test\n  void testAddUserToFreeWhenOnPaid() {\n    var user = new User(\"Free User\");\n    UserGroup.addUserToPaidGroup(user);\n    assertThrows(IllegalArgumentException.class, () -> UserGroup.addUserToFreeGroup(user));\n  }\n}\n"
  },
  {
    "path": "filterer/README.md",
    "content": "---\ntitle: \"Filterer Pattern in Java: Streamlining Data Processing with Dynamic Filters\"\nshortTitle: Filterer\ndescription: \"Learn about the Filterer design pattern in Java, which enhances data processing flexibility by applying a series of filters to data objects. Ideal for dynamic and scalable filtering solutions.\"\nlanguage: en\ncategory: Behavioral\ntag:\n  - Data processing\n  - Data transformation\n  - Decoupling\n  - Functional decomposition\n  - Object composition\n  - Performance\n  - Runtime\n---\n\n## Also known as\n\n* Filters\n* Pipes and Filters\n\n## Intent of Filterer Design Pattern\n\nThe Filterer design pattern in Java is essential for creating dynamic and scalable filtering solutions. This pattern allows the application of a series of filters to data objects, enhancing data processing flexibility and scalability.\n\n## Detailed Explanation of Filterer Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a library system employing the Filterer pattern to dynamically combine filter criteria such as genre, author, and availability. This Java pattern makes the system more maintainable and scalable. Instead of writing separate methods for each possible combination of criteria, the library system employs the Filterer design pattern. Each filter criterion is encapsulated as an object, and these filter objects can be combined dynamically at runtime to create complex filtering logic. For example, a user can search for books that are both available and published after 2010 by combining the availability filter and the publication year filter. This approach makes the system more flexible and easier to maintain, as new filtering criteria can be added without modifying existing code.\n\nIn plain words\n\n> Filterer pattern is a design pattern that helps container-like objects return filtered versions of themselves.\n\nFlowchart\n\n![Filterer flowchart](./etc/filterer-flowchart.png)\n\n## Programmatic Example of Filterer Pattern in Java\n\nTo illustrate, we use the Filterer design pattern for a malware detection system in Java. This system can filter threats based on various criteria, showcasing the pattern’s flexibility and dynamic nature. In the design we have to take into consideration that new Threat types can be added later. Additionally, there is a requirement that the threat detection system can filter the detected threats based on different criteria (the target system acts as container-like object for threats).\n\nTo model the threat detection system, we introduce `Threat` and `ThreatAwareSystem` interfaces.\n\n```java\npublic interface Threat {\n    String name();\n    int id();\n    ThreatType type();\n}\n```\n\n```java\npublic interface ThreatAwareSystem {\n    String systemId();\n    List<? extends Threat> threats();\n    Filterer<? extends ThreatAwareSystem, ? extends Threat> filtered();\n}\n```\n\nNotice the `filtered` method that returns instance of `Filterer` interface which is defined as:\n\n```java\n@FunctionalInterface\npublic interface Filterer<G, E> {\n    G by(Predicate<? super E> predicate);\n}\n```\n\nA simple implementation of `ThreatAwareSystem`:\n\n```java\npublic class SimpleThreatAwareSystem implements ThreatAwareSystem {\n\n    private final String systemId;\n    private final ImmutableList<Threat> issues;\n\n    public SimpleThreatAwareSystem(final String systemId, final List<Threat> issues) {\n        this.systemId = systemId;\n        this.issues = ImmutableList.copyOf(issues);\n    }\n\n    @Override\n    public String systemId() {\n        return systemId;\n    }\n\n    @Override\n    public List<? extends Threat> threats() {\n        return new ArrayList<>(issues);\n    }\n\n    @Override\n    public Filterer<? extends ThreatAwareSystem, ? extends Threat> filtered() {\n        return this::filteredGroup;\n    }\n\n    private ThreatAwareSystem filteredGroup(Predicate<? super Threat> predicate) {\n        return new SimpleThreatAwareSystem(this.systemId, filteredItems(predicate));\n    }\n\n    private List<Threat> filteredItems(Predicate<? super Threat> predicate) {\n        return this.issues.stream()\n                .filter(predicate)\n                .collect(Collectors.toList());\n    }\n}\n```\n\nNow if we introduce a new subtype of `Threat` interface that adds probability with which given threat can appear:\n\n```java\npublic interface ProbableThreat extends Threat {\n    double probability();\n}\n```\n\nWe can also introduce a new interface that represents a system that is aware of threats with their probabilities:\n\n```java\npublic interface ProbabilisticThreatAwareSystem extends ThreatAwareSystem {\n    @Override\n    List<? extends ProbableThreat> threats();\n    @Override\n    Filterer<? extends ProbabilisticThreatAwareSystem, ? extends ProbableThreat> filtered();\n}\n```\n\nWe will be able to filter `ProbabilisticThreatAwareSystem` by `ProbableThreat` properties:\n\n```java\npublic class SimpleProbabilisticThreatAwareSystem implements ProbabilisticThreatAwareSystem {\n\n    private final String systemId;\n    private final ImmutableList<ProbableThreat> threats;\n\n    public SimpleProbabilisticThreatAwareSystem(final String systemId, final List<ProbableThreat> threats) {\n        this.systemId = systemId;\n        this.threats = ImmutableList.copyOf(threats);\n    }\n\n    @Override\n    public String systemId() {\n        return systemId;\n    }\n\n    @Override\n    public List<? extends ProbableThreat> threats() {\n        return threats;\n    }\n\n    @Override\n    public Filterer<? extends ProbabilisticThreatAwareSystem, ? extends ProbableThreat> filtered() {\n        return this::filteredGroup;\n    }\n\n    private ProbabilisticThreatAwareSystem filteredGroup(final Predicate<? super ProbableThreat> predicate) {\n        return new SimpleProbabilisticThreatAwareSystem(this.systemId, filteredItems(predicate));\n    }\n\n    private List<ProbableThreat> filteredItems(final Predicate<? super ProbableThreat> predicate) {\n        return this.threats.stream()\n                .filter(predicate)\n                .collect(Collectors.toList());\n    }\n}\n```\n\nNow let's see the full example in action showing how the filterer pattern works in practice.\n\n```java\n@Slf4j\npublic class App {\n\n  public static void main(String[] args) {\n    filteringSimpleThreats();\n    filteringSimpleProbableThreats();\n  }\n\n  private static void filteringSimpleProbableThreats() {\n    LOGGER.info(\"### Filtering ProbabilisticThreatAwareSystem by probability ###\");\n\n    var trojanArcBomb = new SimpleProbableThreat(\"Trojan-ArcBomb\", 1, ThreatType.TROJAN, 0.99);\n    var rootkit = new SimpleProbableThreat(\"Rootkit-Kernel\", 2, ThreatType.ROOTKIT, 0.8);\n\n    List<ProbableThreat> probableThreats = List.of(trojanArcBomb, rootkit);\n\n    var probabilisticThreatAwareSystem =\n        new SimpleProbabilisticThreatAwareSystem(\"Sys-1\", probableThreats);\n\n    LOGGER.info(\"Filtering ProbabilisticThreatAwareSystem. Initial : \"\n        + probabilisticThreatAwareSystem);\n\n    //Filtering using filterer\n    var filteredThreatAwareSystem = probabilisticThreatAwareSystem.filtered()\n        .by(probableThreat -> Double.compare(probableThreat.probability(), 0.99) == 0);\n\n    LOGGER.info(\"Filtered by probability = 0.99 : \" + filteredThreatAwareSystem);\n  }\n\n  private static void filteringSimpleThreats() {\n    LOGGER.info(\"### Filtering ThreatAwareSystem by ThreatType ###\");\n\n    var rootkit = new SimpleThreat(ThreatType.ROOTKIT, 1, \"Simple-Rootkit\");\n    var trojan = new SimpleThreat(ThreatType.TROJAN, 2, \"Simple-Trojan\");\n    List<Threat> threats = List.of(rootkit, trojan);\n\n    var threatAwareSystem = new SimpleThreatAwareSystem(\"Sys-1\", threats);\n\n    LOGGER.info(\"Filtering ThreatAwareSystem. Initial : \" + threatAwareSystem);\n\n    //Filtering using Filterer\n    var rootkitThreatAwareSystem = threatAwareSystem.filtered()\n        .by(threat -> threat.type() == ThreatType.ROOTKIT);\n\n    LOGGER.info(\"Filtered by threatType = ROOTKIT : \" + rootkitThreatAwareSystem);\n  }\n}\n```\n\nRunning the example produces the following console output.\n\n```\n08:33:23.568 [main] INFO com.iluwatar.filterer.App -- ### Filtering ThreatAwareSystem by ThreatType ###\n08:33:23.574 [main] INFO com.iluwatar.filterer.App -- Filtering ThreatAwareSystem. Initial : SimpleThreatAwareSystem(systemId=Sys-1, issues=[SimpleThreat(threatType=ROOTKIT, id=1, name=Simple-Rootkit), SimpleThreat(threatType=TROJAN, id=2, name=Simple-Trojan)])\n08:33:23.576 [main] INFO com.iluwatar.filterer.App -- Filtered by threatType = ROOTKIT : SimpleThreatAwareSystem(systemId=Sys-1, issues=[SimpleThreat(threatType=ROOTKIT, id=1, name=Simple-Rootkit)])\n08:33:23.576 [main] INFO com.iluwatar.filterer.App -- ### Filtering ProbabilisticThreatAwareSystem by probability ###\n08:33:23.581 [main] INFO com.iluwatar.filterer.App -- Filtering ProbabilisticThreatAwareSystem. Initial : SimpleProbabilisticThreatAwareSystem(systemId=Sys-1, threats=[SimpleProbableThreat{probability=0.99} SimpleThreat(threatType=TROJAN, id=1, name=Trojan-ArcBomb), SimpleProbableThreat{probability=0.8} SimpleThreat(threatType=ROOTKIT, id=2, name=Rootkit-Kernel)])\n08:33:23.581 [main] INFO com.iluwatar.filterer.App -- Filtered by probability = 0.99 : SimpleProbabilisticThreatAwareSystem(systemId=Sys-1, threats=[SimpleProbableThreat{probability=0.99} SimpleThreat(threatType=TROJAN, id=1, name=Trojan-ArcBomb)])\n```\n\n## When to Use the Filterer Pattern in Java\n\n* Use the Filterer pattern when dynamic and flexible filtering of a collection of objects is needed.\n* This Java design pattern is ideal for applications where filtering logic frequently changes or requires combination in various ways.\n* Ideal for scenarios requiring separation of filtering logic from the core business logic.\n\n## Filterer Pattern Java Tutorials\n\n* [Filterer Pattern (Tomasz Linkowski)](https://blog.tlinkowski.pl/2018/filterer-pattern/)\n* [Filterer Pattern in 10 Steps (Java Code Geeks)](https://www.javacodegeeks.com/2019/02/filterer-pattern-10-steps.html)\n\n## Real-World Applications of Filterer Pattern in Java\n\n* Stream processing libraries in Java, such as Apache Kafka Streams, utilize this pattern to build complex data processing pipelines.\n* Image processing software often uses filters to apply effects or transformations to images sequentially.\n\n## Benefits and Trade-offs of Filterer Pattern\n\nBenefits:\n\n* Increases flexibility by allowing different filters to be added or reorganized without affecting other parts of the system.\n* Enhances testability, as filters can be tested independently.\n* Promotes loose coupling between the stages of data processing.\n\nTrade-offs:\n\n* Potential performance overhead from continuous data passing between filters.\n* Complexity can increase with the number of filters, potentially affecting maintainability.\n\n## Related Java Design Patterns\n\n* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Filters can be seen as a specialized form of the Chain of Responsibility, where each filter decides if and how to process the input data and whether to pass it along the chain.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Similar to Decorator in that both modify behavior dynamically; however, filters focus more on data transformation than on adding responsibilities.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3W8sn2W)\n* [Kafka: The Definitive Guide: Real-Time Data and Stream Processing at Scale](https://amzn.to/49N3nRU)\n* [Java Performance: The Definitive Guide](https://amzn.to/3vRW3qj)\n"
  },
  {
    "path": "filterer/etc/filterer.urm.puml",
    "content": "@startuml\npackage com.iluwatar.filterer.domain {\n  interface Filterer<G, E> {\n    + by(Predicate<? super E>) : G {abstract}\n  }\n}\npackage com.iluwatar.filterer {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    - filteringSimpleProbableThreats() {static}\n    - filteringSimpleThreats() {static}\n    + main(args : String[]) {static}\n  }\n}\npackage com.iluwatar.filterer.threat {\n  interface ProbabilisticThreatAwareSystem {\n    + filtered() : Filterer<? extends ProbabilisticThreatAwareSystem, ? extends ProbableThreat> {abstract}\n    + threats() : List<? extends ProbableThreat> {abstract}\n  }\n  interface ProbableThreat {\n    + probability() : double {abstract}\n  }\n  class SimpleProbabilisticThreatAwareSystem {\n    - systemId : String\n    - threats : ImmutableList<ProbableThreat>\n    + SimpleProbabilisticThreatAwareSystem(systemId : String, threats : List<ProbableThreat>)\n    + equals(o : Object) : boolean\n    + filtered() : Filterer<? extends ProbabilisticThreatAwareSystem, ? extends ProbableThreat>\n    - filteredGroup(predicate : Predicate<? super ProbableThreat>) : ProbabilisticThreatAwareSystem\n    - filteredItems(predicate : Predicate<? super ProbableThreat>) : List<ProbableThreat>\n    + hashCode() : int\n    + systemId() : String\n    + threats() : List<? extends ProbableThreat>\n    + toString() : String\n  }\n  class SimpleProbableThreat {\n    - probability : double\n    + SimpleProbableThreat(name : String, id : int, threatType : ThreatType, probability : double)\n    + equals(o : Object) : boolean\n    + hashCode() : int\n    + probability() : double\n    + toString() : String\n  }\n  class SimpleThreat {\n    - id : int\n    - name : String\n    - threatType : ThreatType\n    + SimpleThreat(threatType : ThreatType, id : int, name : String)\n    + id() : int\n    + name() : String\n    + toString() : String\n    + type() : ThreatType\n  }\n  class SimpleThreatAwareSystem {\n    - issues : ImmutableList<Threat>\n    - systemId : String\n    + SimpleThreatAwareSystem(systemId : String, issues : List<Threat>)\n    + equals(o : Object) : boolean\n    + filtered() : Filterer<? extends ThreatAwareSystem, ? extends Threat>\n    - filteredGroup(predicate : Predicate<? super Threat>) : ThreatAwareSystem\n    - filteredItems(predicate : Predicate<? super Threat>) : List<Threat>\n    + hashCode() : int\n    + systemId() : String\n    + threats() : List<? extends Threat>\n    + toString() : String\n  }\n  interface Threat {\n    + id() : int {abstract}\n    + name() : String {abstract}\n    + type() : ThreatType {abstract}\n  }\n  interface ThreatAwareSystem {\n    + filtered() : Filterer<? extends ThreatAwareSystem, ? extends Threat> {abstract}\n    + systemId() : String {abstract}\n    + threats() : List<? extends Threat> {abstract}\n  }\n  enum ThreatType {\n    + ROOTKIT {static}\n    + TROJAN {static}\n    + WORM {static}\n    + valueOf(name : String) : ThreatType {static}\n    + values() : ThreatType[] {static}\n  }\n}\nSimpleThreatAwareSystem -->  \"-issues\" Threat\nSimpleThreat -->  \"-threatType\" ThreatType\nSimpleProbabilisticThreatAwareSystem -->  \"-threats\" ProbableThreat\nProbabilisticThreatAwareSystem --|> ThreatAwareSystem \nProbableThreat --|> Threat \nSimpleProbabilisticThreatAwareSystem ..|> ProbabilisticThreatAwareSystem \nSimpleProbableThreat ..|> ProbableThreat \nSimpleProbableThreat --|> SimpleThreat \nSimpleThreat ..|> Threat \nSimpleThreatAwareSystem ..|> ThreatAwareSystem \n@enduml"
  },
  {
    "path": "filterer/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>filterer</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.filterer.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "filterer/src/main/java/com/iluwatar/filterer/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer;\n\nimport com.iluwatar.filterer.threat.ProbableThreat;\nimport com.iluwatar.filterer.threat.SimpleProbabilisticThreatAwareSystem;\nimport com.iluwatar.filterer.threat.SimpleProbableThreat;\nimport com.iluwatar.filterer.threat.SimpleThreat;\nimport com.iluwatar.filterer.threat.SimpleThreatAwareSystem;\nimport com.iluwatar.filterer.threat.Threat;\nimport com.iluwatar.filterer.threat.ThreatAwareSystem;\nimport com.iluwatar.filterer.threat.ThreatType;\nimport java.util.List;\nimport java.util.function.Predicate;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This demo class represent how {@link com.iluwatar.filterer.domain.Filterer} pattern is used to\n * filter container-like objects to return filtered versions of themselves. The container like\n * objects are systems that are aware of threats that they can be vulnerable to. We would like to\n * have a way to create copy of different system objects but with filtered threats. The thing is to\n * keep it simple if we add new subtype of {@link Threat} (for example {@link ProbableThreat}) - we\n * still need to be able to filter by its properties.\n */\n@Slf4j\npublic class App {\n\n  public static void main(String[] args) {\n    filteringSimpleThreats();\n    filteringSimpleProbableThreats();\n  }\n\n  /**\n   * Demonstrates how to filter {@link com.iluwatar.filterer.threat.ProbabilisticThreatAwareSystem}\n   * based on probability property. The @{@link com.iluwatar.filterer.domain.Filterer#by(Predicate)}\n   * method is able to use {@link com.iluwatar.filterer.threat.ProbableThreat} as predicate\n   * argument.\n   */\n  private static void filteringSimpleProbableThreats() {\n    LOGGER.info(\"### Filtering ProbabilisticThreatAwareSystem by probability ###\");\n\n    var trojanArcBomb = new SimpleProbableThreat(\"Trojan-ArcBomb\", 1, ThreatType.TROJAN, 0.99);\n    var rootkit = new SimpleProbableThreat(\"Rootkit-Kernel\", 2, ThreatType.ROOTKIT, 0.8);\n\n    List<ProbableThreat> probableThreats = List.of(trojanArcBomb, rootkit);\n\n    var probabilisticThreatAwareSystem =\n        new SimpleProbabilisticThreatAwareSystem(\"Sys-1\", probableThreats);\n\n    LOGGER.info(\n        \"Filtering ProbabilisticThreatAwareSystem. Initial : \" + probabilisticThreatAwareSystem);\n\n    // Filtering using filterer\n    var filteredThreatAwareSystem =\n        probabilisticThreatAwareSystem\n            .filtered()\n            .by(probableThreat -> Double.compare(probableThreat.probability(), 0.99) == 0);\n\n    LOGGER.info(\"Filtered by probability = 0.99 : \" + filteredThreatAwareSystem);\n  }\n\n  /**\n   * Demonstrates how to filter {@link ThreatAwareSystem} based on startingOffset property of {@link\n   * SimpleThreat}. The @{@link com.iluwatar.filterer.domain.Filterer#by(Predicate)} method is able\n   * to use {@link Threat} as predicate argument.\n   */\n  private static void filteringSimpleThreats() {\n    LOGGER.info(\"### Filtering ThreatAwareSystem by ThreatType ###\");\n\n    var rootkit = new SimpleThreat(ThreatType.ROOTKIT, 1, \"Simple-Rootkit\");\n    var trojan = new SimpleThreat(ThreatType.TROJAN, 2, \"Simple-Trojan\");\n    List<Threat> threats = List.of(rootkit, trojan);\n\n    var threatAwareSystem = new SimpleThreatAwareSystem(\"Sys-1\", threats);\n\n    LOGGER.info(\"Filtering ThreatAwareSystem. Initial : \" + threatAwareSystem);\n\n    // Filtering using Filterer\n    var rootkitThreatAwareSystem =\n        threatAwareSystem.filtered().by(threat -> threat.type() == ThreatType.ROOTKIT);\n\n    LOGGER.info(\"Filtered by threatType = ROOTKIT : \" + rootkitThreatAwareSystem);\n  }\n}\n"
  },
  {
    "path": "filterer/src/main/java/com/iluwatar/filterer/domain/Filterer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer.domain;\n\nimport java.util.function.Predicate;\n\n/**\n * Filterer helper interface.\n *\n * @param <G> type of the container-like object.\n * @param <E> type of the elements contained within this container-like object.\n */\n@FunctionalInterface\npublic interface Filterer<G, E> {\n  G by(Predicate<? super E> predicate);\n}\n"
  },
  {
    "path": "filterer/src/main/java/com/iluwatar/filterer/threat/ProbabilisticThreatAwareSystem.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer.threat;\n\nimport com.iluwatar.filterer.domain.Filterer;\nimport java.util.List;\n\n/** Represents system that is aware of its threats with given probability of their occurrence. */\npublic interface ProbabilisticThreatAwareSystem extends ThreatAwareSystem {\n\n  /**\n   * {@inheritDoc}\n   *\n   * @return {@link ProbableThreat}\n   */\n  @Override\n  List<? extends ProbableThreat> threats();\n\n  /**\n   * {@inheritDoc}\n   *\n   * @return {@link Filterer}\n   */\n  @Override\n  Filterer<? extends ProbabilisticThreatAwareSystem, ? extends ProbableThreat> filtered();\n}\n"
  },
  {
    "path": "filterer/src/main/java/com/iluwatar/filterer/threat/ProbableThreat.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer.threat;\n\n/** Represents threat that might be a threat with given probability. */\npublic interface ProbableThreat extends Threat {\n  /**\n   * Returns probability of occurrence of given threat.\n   *\n   * @return probability of occurrence of given threat.\n   */\n  double probability();\n}\n"
  },
  {
    "path": "filterer/src/main/java/com/iluwatar/filterer/threat/SimpleProbabilisticThreatAwareSystem.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer.threat;\n\nimport com.iluwatar.filterer.domain.Filterer;\nimport java.util.List;\nimport java.util.function.Predicate;\nimport lombok.EqualsAndHashCode;\nimport lombok.RequiredArgsConstructor;\nimport lombok.ToString;\n\n/** {@inheritDoc} */\n@ToString\n@EqualsAndHashCode\n@RequiredArgsConstructor\npublic class SimpleProbabilisticThreatAwareSystem implements ProbabilisticThreatAwareSystem {\n\n  private final String systemId;\n  private final List<ProbableThreat> threats;\n\n  /** {@inheritDoc} */\n  @Override\n  public String systemId() {\n    return systemId;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public List<? extends ProbableThreat> threats() {\n    return threats;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public Filterer<? extends ProbabilisticThreatAwareSystem, ? extends ProbableThreat> filtered() {\n    return this::filteredGroup;\n  }\n\n  private ProbabilisticThreatAwareSystem filteredGroup(\n      final Predicate<? super ProbableThreat> predicate) {\n    return new SimpleProbabilisticThreatAwareSystem(this.systemId, filteredItems(predicate));\n  }\n\n  private List<ProbableThreat> filteredItems(final Predicate<? super ProbableThreat> predicate) {\n    return this.threats.stream().filter(predicate).toList();\n  }\n}\n"
  },
  {
    "path": "filterer/src/main/java/com/iluwatar/filterer/threat/SimpleProbableThreat.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer.threat;\n\nimport lombok.EqualsAndHashCode;\n\n/** {@inheritDoc} */\n@EqualsAndHashCode(callSuper = false)\npublic class SimpleProbableThreat extends SimpleThreat implements ProbableThreat {\n\n  private final double probability;\n\n  public SimpleProbableThreat(\n      final String name, final int id, final ThreatType threatType, final double probability) {\n    super(threatType, id, name);\n    this.probability = probability;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public double probability() {\n    return probability;\n  }\n\n  @Override\n  public String toString() {\n    return \"SimpleProbableThreat{\" + \"probability=\" + probability + \"} \" + super.toString();\n  }\n}\n"
  },
  {
    "path": "filterer/src/main/java/com/iluwatar/filterer/threat/SimpleThreat.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer.threat;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.RequiredArgsConstructor;\nimport lombok.ToString;\n\n/** Represents a simple threat. */\n@ToString\n@EqualsAndHashCode\n@RequiredArgsConstructor\npublic class SimpleThreat implements Threat {\n\n  private final ThreatType threatType;\n  private final int id;\n  private final String name;\n\n  /** {@inheritDoc} */\n  @Override\n  public String name() {\n    return name;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public int id() {\n    return id;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public ThreatType type() {\n    return threatType;\n  }\n}\n"
  },
  {
    "path": "filterer/src/main/java/com/iluwatar/filterer/threat/SimpleThreatAwareSystem.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer.threat;\n\nimport com.iluwatar.filterer.domain.Filterer;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.function.Predicate;\nimport lombok.EqualsAndHashCode;\nimport lombok.RequiredArgsConstructor;\nimport lombok.ToString;\n\n/** {@inheritDoc} */\n@ToString\n@EqualsAndHashCode\n@RequiredArgsConstructor\npublic class SimpleThreatAwareSystem implements ThreatAwareSystem {\n\n  private final String systemId;\n  private final List<Threat> issues;\n\n  /** {@inheritDoc} */\n  @Override\n  public String systemId() {\n    return systemId;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public List<? extends Threat> threats() {\n    return new ArrayList<>(issues);\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public Filterer<? extends ThreatAwareSystem, ? extends Threat> filtered() {\n    return this::filteredGroup;\n  }\n\n  private ThreatAwareSystem filteredGroup(Predicate<? super Threat> predicate) {\n    return new SimpleThreatAwareSystem(this.systemId, filteredItems(predicate));\n  }\n\n  private List<Threat> filteredItems(Predicate<? super Threat> predicate) {\n    return this.issues.stream().filter(predicate).toList();\n  }\n}\n"
  },
  {
    "path": "filterer/src/main/java/com/iluwatar/filterer/threat/Threat.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer.threat;\n\n/** Represents a threat that can be detected in given system. */\npublic interface Threat {\n  /**\n   * Returns name of the threat.\n   *\n   * @return value representing name of the threat.\n   */\n  String name();\n\n  /**\n   * Returns unique id of the threat.\n   *\n   * @return value representing threat id.\n   */\n  int id();\n\n  /**\n   * Returns threat type.\n   *\n   * @return {@link ThreatType}\n   */\n  ThreatType type();\n}\n"
  },
  {
    "path": "filterer/src/main/java/com/iluwatar/filterer/threat/ThreatAwareSystem.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer.threat;\n\nimport com.iluwatar.filterer.domain.Filterer;\nimport java.util.List;\n\n/** Represents system that is aware of threats that are present in it. */\npublic interface ThreatAwareSystem<T extends Threat> {\n\n  /**\n   * Returns the system id.\n   *\n   * @return system id.\n   */\n  String systemId();\n\n  /**\n   * Returns list of threats for this system.\n   *\n   * @return list of threats for this system.\n   */\n  List<T> threats();\n\n  /**\n   * Returns the instance of {@link Filterer} helper interface that allows to covariantly specify\n   * lower bound for predicate that we want to filter by.\n   *\n   * @return an instance of {@link Filterer} helper interface.\n   */\n  Filterer<ThreatAwareSystem<T>, T> filtered();\n}\n"
  },
  {
    "path": "filterer/src/main/java/com/iluwatar/filterer/threat/ThreatType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer.threat;\n\n/** Enum class representing Threat types. */\npublic enum ThreatType {\n  TROJAN,\n  WORM,\n  ROOTKIT\n}\n"
  },
  {
    "path": "filterer/src/test/java/com/iluwatar/filterer/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n\n  @Test\n  void shouldLaunchApp() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "filterer/src/test/java/com/iluwatar/filterer/threat/SimpleProbabilisticThreatAwareSystemTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer.threat;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\n\nclass SimpleProbabilisticThreatAwareSystemTest {\n\n  @Test\n  void shouldFilterByProbability() {\n    // given\n    var trojan = new SimpleProbableThreat(\"Troyan-ArcBomb\", 1, ThreatType.TROJAN, 0.99);\n    var rootkit = new SimpleProbableThreat(\"Rootkit-System\", 2, ThreatType.ROOTKIT, 0.8);\n    List<ProbableThreat> probableThreats = List.of(trojan, rootkit);\n\n    var simpleProbabilisticThreatAwareSystem =\n        new SimpleProbabilisticThreatAwareSystem(\"System-1\", probableThreats);\n\n    // when\n    var filtered =\n        simpleProbabilisticThreatAwareSystem\n            .filtered()\n            .by(probableThreat -> Double.compare(probableThreat.probability(), 0.99) == 0);\n\n    // then\n    assertEquals(filtered.threats().size(), 1);\n    assertEquals(filtered.threats().get(0), trojan);\n  }\n}\n"
  },
  {
    "path": "filterer/src/test/java/com/iluwatar/filterer/threat/SimpleThreatAwareSystemTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.filterer.threat;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\n\nclass SimpleThreatAwareSystemTest {\n  @Test\n  void shouldFilterByThreatType() {\n    // given\n    var rootkit = new SimpleThreat(ThreatType.ROOTKIT, 1, \"Simple-Rootkit\");\n    var trojan = new SimpleThreat(ThreatType.TROJAN, 2, \"Simple-Trojan\");\n    List<Threat> threats = List.of(rootkit, trojan);\n\n    var threatAwareSystem = new SimpleThreatAwareSystem(\"System-1\", threats);\n\n    // when\n    var rootkitThreatAwareSystem =\n        threatAwareSystem.filtered().by(threat -> threat.type() == ThreatType.ROOTKIT);\n\n    // then\n    assertEquals(rootkitThreatAwareSystem.threats().size(), 1);\n    assertEquals(rootkitThreatAwareSystem.threats().get(0), rootkit);\n  }\n}\n"
  },
  {
    "path": "fluent-interface/README.md",
    "content": "---\ntitle: \"Fluent Interface Pattern in Java: Enhancing Code Expressiveness with Fluent APIs\"\nshortTitle: Fluent Interface\ndescription: \"Learn how to implement the Fluent Interface design pattern in Java. Explore method chaining and Fluent API with practical examples and improve your code readability and maintainability.\"\ncategory: Behavioral\nlanguage: en\ntag: \n  - API design\n  - Code simplification\n  - Decoupling\n  - Object composition\n  - Reactive\n---\n\n## Also known as\n\n* Fluent API\n* Method Chaining\n\n## Intent of Fluent Interface Design Pattern\n\nThe primary goal of the Fluent Interface pattern is to provide an easily readable and flowing API by chaining method calls, often referred to as method chaining. This approach is ideal for building complex objects step-by-step and improving the overall developer experience.\n\n## Detailed Explanation of Fluent Interface Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine you are at a coffee shop customizing your order step-by-step. This approach is similar to how the Fluent Interface design pattern works in Java, allowing you to chain method calls to build and configure objects sequentially. Instead of telling the barista everything at once, you specify each customization step-by-step in a way that flows naturally. For instance, you might say, \"I'd like a large coffee, add two shots of espresso, no sugar, and top it with almond milk.\" This approach is similar to the Fluent Interface design pattern, where you chain together method calls to configure an object in a readable and intuitive manner. Just as you specify each part of your coffee order sequentially, a Fluent Interface allows you to chain method calls to build and configure objects step-by-step in code.\n\nIn plain words\n\n> Fluent Interface pattern provides easily readable flowing interface to code.\n\nWikipedia says\n\n> In software engineering, a fluent interface is an object-oriented API whose design relies extensively on method chaining. Its goal is to increase code legibility by creating a  domain-specific language (DSL).\n\nSequence diagram\n\n![Fluent Interface sequence diagram](./etc/fluent-interface-sequence-diagram.png)\n\n## Programmatic Example of Fluent Interface Pattern in Java\n\nWe need to select numbers based on different criteria from the list. It's a great chance to  utilize fluent interface pattern to provide readable easy-to-use developer experience.\n\nIn this example two implementations of a `FluentIterable` interface are given.\n\n```java\npublic interface FluentIterable<E> extends Iterable<E> {\n\n  FluentIterable<E> filter(Predicate<? super E> predicate);\n\n  Optional<E> first();\n\n  FluentIterable<E> first(int count);\n\n  Optional<E> last();\n\n  FluentIterable<E> last(int count);\n\n  <T> FluentIterable<T> map(Function<? super E, T> function);\n\n  List<E> asList();\n\n  static <E> List<E> copyToList(Iterable<E> iterable) {\n    var copy = new ArrayList<E>();\n    iterable.forEach(copy::add);\n    return copy;\n  }\n}\n```\n\nThe `SimpleFluentIterable` evaluates eagerly and would be too costly for real world applications.\n\n```java\npublic class SimpleFluentIterable<E> implements FluentIterable<E> {\n  // ...\n}\n```\n\nThe `LazyFluentIterable` is evaluated on termination.\n\n```java\npublic class LazyFluentIterable<E> implements FluentIterable<E> {\n  // ...\n}\n```\n\nTheir usage is demonstrated with a simple number list that is filtered, transformed and collected. The result is printed afterward.\n\n```java\npublic static void main(String[] args) {\n\n    var integerList = List.of(1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, -68);\n\n    prettyPrint(\"The initial list contains: \", integerList);\n\n    var firstFiveNegatives = SimpleFluentIterable\n            .fromCopyOf(integerList)\n            .filter(negatives())\n            .first(3)\n            .asList();\n    prettyPrint(\"The first three negative values are: \", firstFiveNegatives);\n\n\n    var lastTwoPositives = SimpleFluentIterable\n            .fromCopyOf(integerList)\n            .filter(positives())\n            .last(2)\n            .asList();\n    prettyPrint(\"The last two positive values are: \", lastTwoPositives);\n\n    SimpleFluentIterable\n            .fromCopyOf(integerList)\n            .filter(number -> number % 2 == 0)\n            .first()\n            .ifPresent(evenNumber -> LOGGER.info(\"The first even number is: {}\", evenNumber));\n\n\n    var transformedList = SimpleFluentIterable\n            .fromCopyOf(integerList)\n            .filter(negatives())\n            .map(transformToString())\n            .asList();\n    prettyPrint(\"A string-mapped list of negative numbers contains: \", transformedList);\n\n\n    var lastTwoOfFirstFourStringMapped = LazyFluentIterable\n            .from(integerList)\n            .filter(positives())\n            .first(4)\n            .last(2)\n            .map(number -> \"String[\" + number + \"]\")\n            .asList();\n    prettyPrint(\"The lazy list contains the last two of the first four positive numbers \"\n            + \"mapped to Strings: \", lastTwoOfFirstFourStringMapped);\n\n    LazyFluentIterable\n            .from(integerList)\n            .filter(negatives())\n            .first(2)\n            .last()\n            .ifPresent(number -> LOGGER.info(\"Last amongst first two negatives: {}\", number));\n}\n```\n\nProgram output:\n\n```\n08:50:08.260 [main] INFO com.iluwatar.fluentinterface.app.App -- The initial list contains: 1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, -68.\n08:50:08.265 [main] INFO com.iluwatar.fluentinterface.app.App -- The first three negative values are: -61, -22, -87.\n08:50:08.265 [main] INFO com.iluwatar.fluentinterface.app.App -- The last two positive values are: 23, 2.\n08:50:08.266 [main] INFO com.iluwatar.fluentinterface.app.App -- The first even number is: 14\n08:50:08.267 [main] INFO com.iluwatar.fluentinterface.app.App -- A string-mapped list of negative numbers contains: String[-61], String[-22], String[-87], String[-82], String[-98], String[-68].\n08:50:08.270 [main] INFO com.iluwatar.fluentinterface.app.App -- The lazy list contains the last two of the first four positive numbers mapped to Strings: String[18], String[6].\n08:50:08.270 [main] INFO com.iluwatar.fluentinterface.app.App -- Last amongst first two negatives: -22\n```\n\n## When to Use the Fluent Interface Pattern in Java\n\nUse the Fluent Interface Pattern in Java when\n\n* Designing APIs that are heavily used and where readability of client code is of high importance.\n* Building complex objects step-by-step, and there is a need to make the code more intuitive and less error-prone.\n* Enhancing code clarity and reducing the boilerplate code, especially in configurations and object-building scenarios.\n\n## Fluent Interface Pattern Java Tutorials\n\n* [An Approach to Internal Domain-Specific Languages in Java (InfoQ)](http://www.infoq.com/articles/internal-dsls-java)\n\n## Real-World Applications of Fluent Interface Pattern in Java\n\n* [Java 8 Stream API](http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html)\n* [Google Guava FluentIterable](https://github.com/google/guava/wiki/FunctionalExplained)\n* [JOOQ](http://www.jooq.org/doc/3.0/manual/getting-started/use-cases/jooq-as-a-standalone-sql-builder/)\n* [Mockito](http://mockito.org/)\n* [Java Hamcrest](http://code.google.com/p/hamcrest/wiki/Tutorial)\n* Builders in libraries like Apache Camel for integration workflows.\n\n## Benefits and Trade-offs of Fluent Interface Pattern\n\nBenefits:\n\n* Adopting the Fluent Interface pattern in your Java projects can significantly enhance code readability and maintainability.\n* Encourages building immutable objects since methods typically return new instances.\n* Reduces the need for variables as the context is maintained in the chain.\n\nTrade-offs:\n\n* Can lead to less intuitive code for those unfamiliar with the pattern.\n* Debugging can be challenging due to the chaining of method calls.\n* Overuse can lead to complex and hard-to-maintain code structures.\n\n## Related Java Design Patterns\n\n* [Builder](https://java-design-patterns.com/patterns/builder/): Often implemented using a Fluent Interface to construct objects step-by-step. The Builder Pattern focuses on constructing complex objects, while Fluent Interface emphasizes the method chaining mechanism.\n* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Fluent Interfaces can be seen as a specific utilization of the Chain of Responsibility, where each method in the chain handles a part of the task and then delegates to the next method.\n\n## References and Credits\n\n* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3UrXkh2)\n* [Domain Specific Languages](https://amzn.to/3R1UYDA)\n* [Effective Java](https://amzn.to/4d4azvL)\n* [Java Design Pattern Essentials](https://amzn.to/44bs6hG)\n* [Fluent Interface (Martin Fowler)](http://www.martinfowler.com/bliki/FluentInterface.html)\n"
  },
  {
    "path": "fluent-interface/etc/fluent-interface.urm.puml",
    "content": "@startuml\npackage com.iluwatar.fluentinterface.fluentiterable.simple {\n  class SimpleFluentIterable<E> {\n    - iterable : Iterable<E>\n    + SimpleFluentIterable<E>(iterable : Iterable<E>)\n    + asList() : List<E>\n    + filter(predicate : Predicate<? super E>) : FluentIterable<E>\n    + first() : Optional<E>\n    + first(count : int) : FluentIterable<E>\n    + forEach(action : Consumer<? super E>)\n    + from(iterable : Iterable<E>) : FluentIterable<E> {static}\n    + fromCopyOf(iterable : Iterable<E>) : FluentIterable<E> {static}\n    + getRemainingElementsCount() : int\n    + iterator() : Iterator<E>\n    + last() : Optional<E>\n    + last(count : int) : FluentIterable<E>\n    + map(function : Function<? super E, T>) : FluentIterable<T>\n    + spliterator() : Spliterator<E>\n    + toList(iterator : Iterator<E>) : List<E> {static}\n  }\n}\npackage com.iluwatar.fluentinterface.app {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n    - negatives() : Predicate<? super Integer> {static}\n    - positives() : Predicate<? super Integer> {static}\n    - prettyPrint(delimiter : String, prefix : String, iterable : Iterable<E>) {static}\n    - prettyPrint(prefix : String, iterable : Iterable<E>) {static}\n    - transformToString() : Function<Integer, String> {static}\n  }\n}\npackage com.iluwatar.fluentinterface.fluentiterable.lazy {\n  abstract class DecoratingIterator<E> {\n    # fromIterator : Iterator<E>\n    - next : E\n    + DecoratingIterator<E>(fromIterator : Iterator<E>)\n    + computeNext() : E {abstract}\n    + hasNext() : boolean\n    + next() : E\n  }\n  class LazyFluentIterable<E> {\n    - iterable : Iterable<E>\n    # LazyFluentIterable<E>()\n    + LazyFluentIterable<E>(iterable : Iterable<E>)\n    + asList() : List<E>\n    + filter(predicate : Predicate<? super E>) : FluentIterable<E>\n    + first() : Optional<E>\n    + first(count : int) : FluentIterable<E>\n    + from(iterable : Iterable<E>) : FluentIterable<E> {static}\n    + iterator() : Iterator<E>\n    + last() : Optional<E>\n    + last(count : int) : FluentIterable<E>\n    + map(function : Function<? super E, T>) : FluentIterable<T>\n  }\n}\npackage com.iluwatar.fluentinterface.fluentiterable {\n  interface FluentIterable<E> {\n    + asList() : List<E> {abstract}\n    + copyToList(iterable : Iterable<E>) : List<E> {static}\n    + filter(Predicate<? super E>) : FluentIterable<E> {abstract}\n    + first() : Optional<E> {abstract}\n    + first(int) : FluentIterable<E> {abstract}\n    + last() : Optional<E> {abstract}\n    + last(int) : FluentIterable<E> {abstract}\n    + map(Function<? super E, T>) : FluentIterable<T> {abstract}\n  }\n}\nLazyFluentIterable ..|> FluentIterable \nSimpleFluentIterable ..|> FluentIterable \n@enduml"
  },
  {
    "path": "fluent-interface/etc/fluentinterface.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.fluentinterface.app.App\" project=\"fluentinterface\" \n    file=\"/fluentinterface/src/main/java/com/iluwatar/fluentinterface/app/App.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"289\" y=\"-8\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"false\" protected=\"false\" private=\"false\" static=\"false\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.fluentinterface.fluentiterable.simple.SimpleFluentIterable\" \n    project=\"fluentinterface\" \n    file=\"/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"450\" y=\"430\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.fluentinterface.fluentiterable.lazy.LazyFluentIterable\" \n    project=\"fluentinterface\" \n    file=\"/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"860\" y=\"391\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"4\" language=\"java\" name=\"com.iluwatar.fluentinterface.fluentiterable.FluentIterable\" \n    project=\"fluentinterface\" \n    file=\"/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"794\" y=\"55\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.fluentinterface.fluentiterable.lazy.DecoratingIterator\" \n    project=\"fluentinterface\" \n    file=\"/fluentinterface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1245\" y=\"391\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"6\" language=\"java\" name=\"java.lang.Iterable\" project=\"fluentinterface\" \n    file=\"C:/Program Files/Java/jdk1.8.0_25/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"793\" y=\"-163\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <dependency id=\"7\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </dependency>  \n  <dependency id=\"8\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </dependency>  \n  <dependency id=\"9\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </dependency>  \n  <realization id=\"10\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <realization id=\"11\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <dependency id=\"12\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </dependency>  \n  <generalization id=\"13\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </generalization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"true\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "fluent-interface/etc/fluentinterface.urm.puml",
    "content": "@startuml\npackage com.iluwatar.fluentinterface.fluentiterable.simple {\n  class SimpleFluentIterable<E> {\n    - iterable : Iterable<E>\n    # SimpleFluentIterable<E>(iterable : Iterable<E>)\n    + asList() : List<E>\n    + filter(predicate : Predicate<? super E>) : FluentIterable<E>\n    + first() : Optional<E>\n    + first(count : int) : FluentIterable<E>\n    + forEach(action : Consumer<? super E>)\n    + from(iterable : Iterable<E>) : FluentIterable<E> {static}\n    + fromCopyOf(iterable : Iterable<E>) : FluentIterable<E> {static}\n    + getRemainingElementsCount() : int\n    + iterator() : Iterator<E>\n    + last() : Optional<E>\n    + last(count : int) : FluentIterable<E>\n    + map(function : Function<? super E, T>) : FluentIterable<T>\n    + spliterator() : Spliterator<E>\n    + toList(iterator : Iterator<E>) : List<E> {static}\n  }\n}\npackage com.iluwatar.fluentinterface.app {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n    - negatives() : Predicate<? super Integer> {static}\n    - positives() : Predicate<? super Integer> {static}\n    - prettyPrint(delimiter : String, prefix : String, iterable : Iterable<E>) {static}\n    - prettyPrint(prefix : String, iterable : Iterable<E>) {static}\n    - transformToString() : Function<Integer, String> {static}\n  }\n}\npackage com.iluwatar.fluentinterface.fluentiterable.lazy {\n  abstract class DecoratingIterator<E> {\n    # fromIterator : Iterator<E>\n    - next : E\n    + DecoratingIterator<E>(fromIterator : Iterator<E>)\n    + computeNext() : E {abstract}\n    + hasNext() : boolean\n    + next() : E\n  }\n  class LazyFluentIterable<E> {\n    - iterable : Iterable<E>\n    # LazyFluentIterable<E>()\n    # LazyFluentIterable<E>(iterable : Iterable<E>)\n    + asList() : List<E>\n    + filter(predicate : Predicate<? super E>) : FluentIterable<E>\n    + first() : Optional<E>\n    + first(count : int) : FluentIterable<E>\n    + from(iterable : Iterable<E>) : FluentIterable<E> {static}\n    + iterator() : Iterator<E>\n    + last() : Optional<E>\n    + last(count : int) : FluentIterable<E>\n    + map(function : Function<? super E, T>) : FluentIterable<T>\n  }\n}\npackage com.iluwatar.fluentinterface.fluentiterable {\n  interface FluentIterable<E> {\n    + asList() : List<E> {abstract}\n    + copyToList(iterable : Iterable<E>) : List<E> {static}\n    + filter(Predicate<? super E>) : FluentIterable<E> {abstract}\n    + first() : Optional<E> {abstract}\n    + first(int) : FluentIterable<E> {abstract}\n    + last() : Optional<E> {abstract}\n    + last(int) : FluentIterable<E> {abstract}\n    + map(Function<? super E, T>) : FluentIterable<T> {abstract}\n  }\n}\nLazyFluentIterable ..|> FluentIterable \nSimpleFluentIterable ..|> FluentIterable \n@enduml"
  },
  {
    "path": "fluent-interface/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>fluent-interface</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.fluentinterface.app.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "fluent-interface/src/main/java/com/iluwatar/fluentinterface/app/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fluentinterface.app;\n\nimport com.iluwatar.fluentinterface.fluentiterable.FluentIterable;\nimport com.iluwatar.fluentinterface.fluentiterable.lazy.LazyFluentIterable;\nimport com.iluwatar.fluentinterface.fluentiterable.simple.SimpleFluentIterable;\nimport java.util.List;\nimport java.util.StringJoiner;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Fluent Interface pattern is useful when you want to provide an easy readable, flowing API.\n * Those interfaces tend to mimic domain specific languages, so they can nearly be read as human\n * languages.\n *\n * <p>In this example two implementations of a {@link FluentIterable} interface are given. The\n * {@link SimpleFluentIterable} evaluates eagerly and would be too costly for real world\n * applications. The {@link LazyFluentIterable} is evaluated on termination. Their usage is\n * demonstrated with a simple number list that is filtered, transformed and collected. The result is\n * printed afterward.\n */\n@Slf4j\npublic class App {\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n\n    var integerList = List.of(1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, -68);\n\n    prettyPrint(\"The initial list contains: \", integerList);\n\n    var firstFiveNegatives =\n        SimpleFluentIterable.fromCopyOf(integerList).filter(negatives()).first(3).asList();\n    prettyPrint(\"The first three negative values are: \", firstFiveNegatives);\n\n    var lastTwoPositives =\n        SimpleFluentIterable.fromCopyOf(integerList).filter(positives()).last(2).asList();\n    prettyPrint(\"The last two positive values are: \", lastTwoPositives);\n\n    SimpleFluentIterable.fromCopyOf(integerList)\n        .filter(number -> number % 2 == 0)\n        .first()\n        .ifPresent(evenNumber -> LOGGER.info(\"The first even number is: {}\", evenNumber));\n\n    var transformedList =\n        SimpleFluentIterable.fromCopyOf(integerList)\n            .filter(negatives())\n            .map(transformToString())\n            .asList();\n    prettyPrint(\"A string-mapped list of negative numbers contains: \", transformedList);\n\n    var lastTwoOfFirstFourStringMapped =\n        LazyFluentIterable.from(integerList)\n            .filter(positives())\n            .first(4)\n            .last(2)\n            .map(number -> \"String[\" + number + \"]\")\n            .asList();\n    prettyPrint(\n        \"The lazy list contains the last two of the first four positive numbers \"\n            + \"mapped to Strings: \",\n        lastTwoOfFirstFourStringMapped);\n\n    LazyFluentIterable.from(integerList)\n        .filter(negatives())\n        .first(2)\n        .last()\n        .ifPresent(number -> LOGGER.info(\"Last amongst first two negatives: {}\", number));\n  }\n\n  private static Function<Integer, String> transformToString() {\n    return integer -> \"String[\" + integer + \"]\";\n  }\n\n  private static Predicate<? super Integer> negatives() {\n    return integer -> integer < 0;\n  }\n\n  private static Predicate<? super Integer> positives() {\n    return integer -> integer > 0;\n  }\n\n  private static <E> void prettyPrint(String prefix, Iterable<E> iterable) {\n    prettyPrint(\", \", prefix, iterable);\n  }\n\n  private static <E> void prettyPrint(String delimiter, String prefix, Iterable<E> iterable) {\n    var joiner = new StringJoiner(delimiter, prefix, \".\");\n    iterable.forEach(e -> joiner.add(e.toString()));\n    LOGGER.info(joiner.toString());\n  }\n}\n"
  },
  {
    "path": "fluent-interface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterable.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fluentinterface.fluentiterable;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\n\n/**\n * The FluentIterable is a more convenient implementation of the common iterable interface based on\n * the fluent interface design pattern. This interface defines common operations, but doesn't aim to\n * be complete. It was inspired by Guava's com.google.common.collect.FluentIterable.\n *\n * @param <E> is the class of objects the iterable contains\n */\npublic interface FluentIterable<E> extends Iterable<E> {\n\n  /**\n   * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy\n   * the predicate.\n   *\n   * @param predicate the condition to test with for the filtering. If the test is negative, the\n   *     tested object is removed by the iterator.\n   * @return a filtered FluentIterable\n   */\n  FluentIterable<E> filter(Predicate<? super E> predicate);\n\n  /**\n   * Returns an Optional containing the first element of this iterable if present, else returns\n   * Optional.empty().\n   *\n   * @return the first element after the iteration is evaluated\n   */\n  Optional<E> first();\n\n  /**\n   * Evaluates the iteration and leaves only the count first elements.\n   *\n   * @return the first count elements as an Iterable\n   */\n  FluentIterable<E> first(int count);\n\n  /**\n   * Evaluates the iteration and returns the last element. This is a terminating operation.\n   *\n   * @return the last element after the iteration is evaluated\n   */\n  Optional<E> last();\n\n  /**\n   * Evaluates the iteration and leaves only the count last elements.\n   *\n   * @return the last counts elements as an Iterable\n   */\n  FluentIterable<E> last(int count);\n\n  /**\n   * Transforms this FluentIterable into a new one containing objects of the type T.\n   *\n   * @param function a function that transforms an instance of E into an instance of T\n   * @param <T> the target type of the transformation\n   * @return a new FluentIterable of the new type\n   */\n  <T> FluentIterable<T> map(Function<? super E, T> function);\n\n  /**\n   * Returns the contents of this Iterable as a List.\n   *\n   * @return a List representation of this Iterable\n   */\n  List<E> asList();\n\n  /**\n   * Utility method that iterates over iterable and adds the contents to a list.\n   *\n   * @param iterable the iterable to collect\n   * @param <E> the type of the objects to iterate\n   * @return a list with all objects of the given iterator\n   */\n  static <E> List<E> copyToList(Iterable<E> iterable) {\n    var copy = new ArrayList<E>();\n    iterable.forEach(copy::add);\n    return copy;\n  }\n}\n"
  },
  {
    "path": "fluent-interface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/DecoratingIterator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fluentinterface.fluentiterable.lazy;\n\nimport java.util.Iterator;\n\n/**\n * This class is used to realize LazyFluentIterables. It decorates a given iterator. Does not\n * support consecutive hasNext() calls.\n *\n * @param <E> Iterable Collection of Elements of Type E\n */\npublic abstract class DecoratingIterator<E> implements Iterator<E> {\n\n  protected final Iterator<E> fromIterator;\n\n  private E next;\n\n  /** Creates an iterator that decorates the given iterator. */\n  public DecoratingIterator(Iterator<E> fromIterator) {\n    this.fromIterator = fromIterator;\n  }\n\n  /**\n   * Precomputes and saves the next element of the Iterable. null is considered as end of data.\n   *\n   * @return true if a next element is available\n   */\n  @Override\n  public final boolean hasNext() {\n    next = computeNext();\n    return next != null;\n  }\n\n  /**\n   * Returns the next element of the Iterable.\n   *\n   * @return the next element of the Iterable, or null if not present.\n   */\n  @Override\n  public final E next() {\n    if (next == null) {\n      return fromIterator.next();\n    } else {\n      final var result = next;\n      next = null;\n      return result;\n    }\n  }\n\n  /**\n   * Computes the next object of the Iterable. Can be implemented to realize custom behaviour for an\n   * iteration process. null is considered as end of data.\n   *\n   * @return the next element of the Iterable.\n   */\n  public abstract E computeNext();\n}\n"
  },
  {
    "path": "fluent-interface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterable.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fluentinterface.fluentiterable.lazy;\n\nimport com.iluwatar.fluentinterface.fluentiterable.FluentIterable;\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\nimport lombok.RequiredArgsConstructor;\n\n/**\n * This is a lazy implementation of the FluentIterable interface. It evaluates all chained\n * operations when a terminating operation is applied.\n *\n * @param <E> the type of the objects the iteration is about\n */\n@RequiredArgsConstructor\npublic class LazyFluentIterable<E> implements FluentIterable<E> {\n\n  private final Iterable<E> iterable;\n\n  /** This constructor can be used to implement anonymous subclasses of the LazyFluentIterable. */\n  protected LazyFluentIterable() {\n    iterable = this;\n  }\n\n  /**\n   * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy\n   * the predicate.\n   *\n   * @param predicate the condition to test with for the filtering. If the test is negative, the\n   *     tested object is removed by the iterator.\n   * @return a new FluentIterable object that decorates the source iterable\n   */\n  @Override\n  public FluentIterable<E> filter(Predicate<? super E> predicate) {\n    return new LazyFluentIterable<>() {\n      @Override\n      public Iterator<E> iterator() {\n        return new DecoratingIterator<>(iterable.iterator()) {\n          @Override\n          public E computeNext() {\n            while (fromIterator.hasNext()) {\n              var candidate = fromIterator.next();\n              if (predicate.test(candidate)) {\n                return candidate;\n              }\n            }\n\n            return null;\n          }\n        };\n      }\n    };\n  }\n\n  /**\n   * Can be used to collect objects from the iteration. Is a terminating operation.\n   *\n   * @return an Optional containing the first object of this Iterable\n   */\n  @Override\n  public Optional<E> first() {\n    var resultIterator = first(1).iterator();\n    return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty();\n  }\n\n  /**\n   * Can be used to collect objects from the iteration.\n   *\n   * @param count defines the number of objects to return\n   * @return the same FluentIterable with a collection decimated to a maximum of 'count' first\n   *     objects.\n   */\n  @Override\n  public FluentIterable<E> first(int count) {\n    return new LazyFluentIterable<>() {\n      @Override\n      public Iterator<E> iterator() {\n        return new DecoratingIterator<>(iterable.iterator()) {\n          int currentIndex;\n\n          @Override\n          public E computeNext() {\n            if (currentIndex < count && fromIterator.hasNext()) {\n              var candidate = fromIterator.next();\n              currentIndex++;\n              return candidate;\n            }\n            return null;\n          }\n        };\n      }\n    };\n  }\n\n  /**\n   * Can be used to collect objects from the iteration. Is a terminating operation.\n   *\n   * @return an Optional containing the last object of this Iterable\n   */\n  @Override\n  public Optional<E> last() {\n    var resultIterator = last(1).iterator();\n    return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty();\n  }\n\n  /**\n   * Can be used to collect objects from the Iterable. Is a terminating operation. This operation is\n   * memory intensive, because the contents of this Iterable are collected into a List, when the\n   * next object is requested.\n   *\n   * @param count defines the number of objects to return\n   * @return the same FluentIterable with a collection decimated to a maximum of 'count' last\n   *     objects\n   */\n  @Override\n  public FluentIterable<E> last(int count) {\n    return new LazyFluentIterable<>() {\n      @Override\n      public Iterator<E> iterator() {\n        return new DecoratingIterator<>(iterable.iterator()) {\n          private int stopIndex;\n          private int totalElementsCount;\n          private List<E> list;\n          private int currentIndex;\n\n          @Override\n          public E computeNext() {\n            initialize();\n\n            while (currentIndex < stopIndex && fromIterator.hasNext()) {\n              currentIndex++;\n              fromIterator.next();\n            }\n            if (currentIndex >= stopIndex && fromIterator.hasNext()) {\n              return fromIterator.next();\n            }\n            return null;\n          }\n\n          private void initialize() {\n            if (list == null) {\n              list = new ArrayList<>();\n              iterable.forEach(list::add);\n              totalElementsCount = list.size();\n              stopIndex = totalElementsCount - count;\n            }\n          }\n        };\n      }\n    };\n  }\n\n  /**\n   * Transforms this FluentIterable into a new one containing objects of the type T.\n   *\n   * @param function a function that transforms an instance of E into an instance of T\n   * @param <T> the target type of the transformation\n   * @return a new FluentIterable of the new type\n   */\n  @Override\n  public <T> FluentIterable<T> map(Function<? super E, T> function) {\n    return new LazyFluentIterable<>() {\n      @Override\n      public Iterator<T> iterator() {\n        return new DecoratingIterator<>(null) {\n          final Iterator<E> oldTypeIterator = iterable.iterator();\n\n          @Override\n          public T computeNext() {\n            if (oldTypeIterator.hasNext()) {\n              E candidate = oldTypeIterator.next();\n              return function.apply(candidate);\n            } else {\n              return null;\n            }\n          }\n        };\n      }\n    };\n  }\n\n  /**\n   * Collects all remaining objects of this iteration into a list.\n   *\n   * @return a list with all remaining objects of this iteration\n   */\n  @Override\n  public List<E> asList() {\n    return FluentIterable.copyToList(iterable);\n  }\n\n  @Override\n  public Iterator<E> iterator() {\n    return new DecoratingIterator<>(iterable.iterator()) {\n      @Override\n      public E computeNext() {\n        return fromIterator.hasNext() ? fromIterator.next() : null;\n      }\n    };\n  }\n\n  /**\n   * Constructors FluentIterable from given iterable.\n   *\n   * @return a FluentIterable from a given iterable. Calls the LazyFluentIterable constructor.\n   */\n  public static <E> FluentIterable<E> from(Iterable<E> iterable) {\n    return new LazyFluentIterable<>(iterable);\n  }\n}\n"
  },
  {
    "path": "fluent-interface/src/main/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterable.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fluentinterface.fluentiterable.simple;\n\nimport com.iluwatar.fluentinterface.fluentiterable.FluentIterable;\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.Spliterator;\nimport java.util.function.Consumer;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\nimport lombok.RequiredArgsConstructor;\n\n/**\n * This is a simple implementation of the FluentIterable interface. It evaluates all chained\n * operations eagerly. This implementation would be costly to be utilized in real applications.\n *\n * @param <E> the type of the objects the iteration is about\n */\n@RequiredArgsConstructor\npublic class SimpleFluentIterable<E> implements FluentIterable<E> {\n\n  private final Iterable<E> iterable;\n\n  /**\n   * Filters the contents of Iterable using the given predicate, leaving only the ones which satisfy\n   * the predicate.\n   *\n   * @param predicate the condition to test with for the filtering. If the test is negative, the\n   *     tested object is removed by the iterator.\n   * @return the same FluentIterable with a filtered collection\n   */\n  @Override\n  public final FluentIterable<E> filter(Predicate<? super E> predicate) {\n    var iterator = iterator();\n    while (iterator.hasNext()) {\n      var nextElement = iterator.next();\n      if (!predicate.test(nextElement)) {\n        iterator.remove();\n      }\n    }\n    return this;\n  }\n\n  /**\n   * Can be used to collect objects from the Iterable. Is a terminating operation.\n   *\n   * @return an option of the first object of the Iterable\n   */\n  @Override\n  public final Optional<E> first() {\n    var resultIterator = first(1).iterator();\n    return resultIterator.hasNext() ? Optional.of(resultIterator.next()) : Optional.empty();\n  }\n\n  /**\n   * Can be used to collect objects from the Iterable. Is a terminating operation.\n   *\n   * @param count defines the number of objects to return\n   * @return the same FluentIterable with a collection decimated to a maximum of 'count' first\n   *     objects.\n   */\n  @Override\n  public final FluentIterable<E> first(int count) {\n    var iterator = iterator();\n    var currentCount = 0;\n    while (iterator.hasNext()) {\n      iterator.next();\n      if (currentCount >= count) {\n        iterator.remove();\n      }\n      currentCount++;\n    }\n    return this;\n  }\n\n  /**\n   * Can be used to collect objects from the Iterable. Is a terminating operation.\n   *\n   * @return an option of the last object of the Iterable\n   */\n  @Override\n  public final Optional<E> last() {\n    var list = last(1).asList();\n    if (list.isEmpty()) {\n      return Optional.empty();\n    }\n    return Optional.of(list.get(0));\n  }\n\n  /**\n   * Can be used to collect objects from the Iterable. Is a terminating operation.\n   *\n   * @param count defines the number of objects to return\n   * @return the same FluentIterable with a collection decimated to a maximum of 'count' last\n   *     objects\n   */\n  @Override\n  public final FluentIterable<E> last(int count) {\n    var remainingElementsCount = getRemainingElementsCount();\n    var iterator = iterator();\n    var currentIndex = 0;\n    while (iterator.hasNext()) {\n      iterator.next();\n      if (currentIndex < remainingElementsCount - count) {\n        iterator.remove();\n      }\n      currentIndex++;\n    }\n\n    return this;\n  }\n\n  /**\n   * Transforms this FluentIterable into a new one containing objects of the type T.\n   *\n   * @param function a function that transforms an instance of E into an instance of T\n   * @param <T> the target type of the transformation\n   * @return a new FluentIterable of the new type\n   */\n  @Override\n  public final <T> FluentIterable<T> map(Function<? super E, T> function) {\n    var temporaryList = new ArrayList<T>();\n    this.forEach(e -> temporaryList.add(function.apply(e)));\n    return from(temporaryList);\n  }\n\n  /**\n   * Collects all remaining objects of this Iterable into a list.\n   *\n   * @return a list with all remaining objects of this Iterable\n   */\n  @Override\n  public List<E> asList() {\n    return toList(iterable.iterator());\n  }\n\n  /**\n   * Constructs FluentIterable from iterable.\n   *\n   * @return a FluentIterable from a given iterable. Calls the SimpleFluentIterable constructor.\n   */\n  public static <E> FluentIterable<E> from(Iterable<E> iterable) {\n    return new SimpleFluentIterable<>(iterable);\n  }\n\n  public static <E> FluentIterable<E> fromCopyOf(Iterable<E> iterable) {\n    var copy = FluentIterable.copyToList(iterable);\n    return new SimpleFluentIterable<>(copy);\n  }\n\n  @Override\n  public Iterator<E> iterator() {\n    return iterable.iterator();\n  }\n\n  @Override\n  public void forEach(Consumer<? super E> action) {\n    iterable.forEach(action);\n  }\n\n  @Override\n  public Spliterator<E> spliterator() {\n    return iterable.spliterator();\n  }\n\n  /**\n   * Find the count of remaining objects of current iterable.\n   *\n   * @return the count of remaining objects of the current Iterable\n   */\n  public final int getRemainingElementsCount() {\n    var counter = 0;\n    for (var ignored : this) {\n      counter++;\n    }\n    return counter;\n  }\n\n  /**\n   * Collects the remaining objects of the given iterator into a List.\n   *\n   * @return a new List with the remaining objects.\n   */\n  public static <E> List<E> toList(Iterator<E> iterator) {\n    var copy = new ArrayList<E>();\n    iterator.forEachRemaining(copy::add);\n    return copy;\n  }\n}\n"
  },
  {
    "path": "fluent-interface/src/test/java/com/iluwatar/fluentinterface/app/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fluentinterface.app;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application Test Entry */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "fluent-interface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/FluentIterableTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fluentinterface.fluentiterable;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.function.Consumer;\nimport org.junit.jupiter.api.Test;\n\n/** FluentIterableTest */\npublic abstract class FluentIterableTest {\n\n  /**\n   * Create a new {@link FluentIterable} from the given integers\n   *\n   * @param integers The integers\n   * @return The new iterable, use for testing\n   */\n  protected abstract FluentIterable<Integer> createFluentIterable(final Iterable<Integer> integers);\n\n  @Test\n  void testFirst() {\n    final var integers = List.of(1, 2, 3, 10, 9, 8);\n    final var first = createFluentIterable(integers).first();\n    assertNotNull(first);\n    assertTrue(first.isPresent());\n    assertEquals(integers.get(0), first.get());\n  }\n\n  @Test\n  void testFirstEmptyCollection() {\n    final var integers = Collections.<Integer>emptyList();\n    final var first = createFluentIterable(integers).first();\n    assertNotNull(first);\n    assertFalse(first.isPresent());\n  }\n\n  @Test\n  void testFirstCount() {\n    final var integers = List.of(1, 2, 3, 10, 9, 8);\n    final var first4 = createFluentIterable(integers).first(4).asList();\n\n    assertNotNull(first4);\n    assertEquals(4, first4.size());\n\n    assertEquals(integers.get(0), first4.get(0));\n    assertEquals(integers.get(1), first4.get(1));\n    assertEquals(integers.get(2), first4.get(2));\n    assertEquals(integers.get(3), first4.get(3));\n  }\n\n  @Test\n  void testFirstCountLessItems() {\n    final var integers = List.of(1, 2, 3);\n    final var first4 = createFluentIterable(integers).first(4).asList();\n\n    assertNotNull(first4);\n    assertEquals(3, first4.size());\n\n    assertEquals(integers.get(0), first4.get(0));\n    assertEquals(integers.get(1), first4.get(1));\n    assertEquals(integers.get(2), first4.get(2));\n  }\n\n  @Test\n  void testLast() {\n    final var integers = List.of(1, 2, 3, 10, 9, 8);\n    final var last = createFluentIterable(integers).last();\n    assertNotNull(last);\n    assertTrue(last.isPresent());\n    assertEquals(integers.get(integers.size() - 1), last.get());\n  }\n\n  @Test\n  void testLastEmptyCollection() {\n    final var integers = Collections.<Integer>emptyList();\n    final var last = createFluentIterable(integers).last();\n    assertNotNull(last);\n    assertFalse(last.isPresent());\n  }\n\n  @Test\n  void testLastCount() {\n    final var integers = List.of(1, 2, 3, 10, 9, 8);\n    final var last4 = createFluentIterable(integers).last(4).asList();\n\n    assertNotNull(last4);\n    assertEquals(4, last4.size());\n    assertEquals(Integer.valueOf(3), last4.get(0));\n    assertEquals(Integer.valueOf(10), last4.get(1));\n    assertEquals(Integer.valueOf(9), last4.get(2));\n    assertEquals(Integer.valueOf(8), last4.get(3));\n  }\n\n  @Test\n  void testLastCountLessItems() {\n    final var integers = List.of(1, 2, 3);\n    final var last4 = createFluentIterable(integers).last(4).asList();\n\n    assertNotNull(last4);\n    assertEquals(3, last4.size());\n\n    assertEquals(Integer.valueOf(1), last4.get(0));\n    assertEquals(Integer.valueOf(2), last4.get(1));\n    assertEquals(Integer.valueOf(3), last4.get(2));\n  }\n\n  @Test\n  void testFilter() {\n    final var integers = List.of(1, 2, 3, 10, 9, 8);\n    final var evenItems = createFluentIterable(integers).filter(i -> i % 2 == 0).asList();\n\n    assertNotNull(evenItems);\n    assertEquals(3, evenItems.size());\n    assertEquals(Integer.valueOf(2), evenItems.get(0));\n    assertEquals(Integer.valueOf(10), evenItems.get(1));\n    assertEquals(Integer.valueOf(8), evenItems.get(2));\n  }\n\n  @Test\n  void testMap() {\n    final var integers = List.of(1, 2, 3);\n    final var longs = createFluentIterable(integers).map(Integer::longValue).asList();\n\n    assertNotNull(longs);\n    assertEquals(integers.size(), longs.size());\n    assertEquals(Long.valueOf(1), longs.get(0));\n    assertEquals(Long.valueOf(2), longs.get(1));\n    assertEquals(Long.valueOf(3), longs.get(2));\n  }\n\n  @Test\n  void testForEach() {\n    final var integers = List.of(1, 2, 3);\n\n    final Consumer<Integer> consumer = mock(Consumer.class);\n    createFluentIterable(integers).forEach(consumer);\n\n    verify(consumer, times(1)).accept(1);\n    verify(consumer, times(1)).accept(2);\n    verify(consumer, times(1)).accept(3);\n    verifyNoMoreInteractions(consumer);\n  }\n\n  @Test\n  void testSpliterator() {\n    final var integers = List.of(1, 2, 3);\n    final var split = createFluentIterable(integers).spliterator();\n    assertNotNull(split);\n  }\n}\n"
  },
  {
    "path": "fluent-interface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/lazy/LazyFluentIterableTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fluentinterface.fluentiterable.lazy;\n\nimport com.iluwatar.fluentinterface.fluentiterable.FluentIterable;\nimport com.iluwatar.fluentinterface.fluentiterable.FluentIterableTest;\n\n/** LazyFluentIterableTest */\nclass LazyFluentIterableTest extends FluentIterableTest {\n\n  @Override\n  protected FluentIterable<Integer> createFluentIterable(Iterable<Integer> integers) {\n    return LazyFluentIterable.from(integers);\n  }\n}\n"
  },
  {
    "path": "fluent-interface/src/test/java/com/iluwatar/fluentinterface/fluentiterable/simple/SimpleFluentIterableTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.fluentinterface.fluentiterable.simple;\n\nimport com.iluwatar.fluentinterface.fluentiterable.FluentIterable;\nimport com.iluwatar.fluentinterface.fluentiterable.FluentIterableTest;\n\n/** SimpleFluentIterableTest */\nclass SimpleFluentIterableTest extends FluentIterableTest {\n\n  @Override\n  protected FluentIterable<Integer> createFluentIterable(Iterable<Integer> integers) {\n    return SimpleFluentIterable.fromCopyOf(integers);\n  }\n}\n"
  },
  {
    "path": "flux/README.md",
    "content": "---\ntitle: \"Flux Pattern in Java: Streamlining Complex UIs with Unidirectional Data Flow\"\nshortTitle: Flux\ndescription: \"Learn how the Flux design pattern simplifies data flow in Java applications through unidirectional architecture. Explore examples, benefits, and real-world applications.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - Client-server\n  - Decoupling\n  - Event-driven\n  - Publish/subscribe\n  - Reactive\n---\n\n## Intent of Flux Design Pattern\n\nThe Flux design pattern is intended to manage the flow of data in Java applications, particularly client-side web applications, by enforcing a unidirectional data flow. It aims to simplify the management of complex data interactions and promote a more predictable state behavior across components.\n\n## Detailed Explanation of Flux Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a busy restaurant kitchen as an analogy for the Flux design pattern. In this scenario, the kitchen operates based on customer orders (actions) received and processed through a single point of control (the dispatcher), which could be represented by the head chef. When an order arrives, the head chef assigns specific tasks to various sections of the kitchen (stores), such as the grill, the salad station, or the dessert team. Each section updates the progress of their tasks (state changes) back to the head chef, who ensures that all parts of the order are coordinated and completed in a synchronized manner before the dishes are sent out to the customer (the view).\n\nIn plain words\n\n> The Flux design pattern manages data flow in applications through a unidirectional architecture, coordinating actions, dispatchers, stores, and views to ensure stable and predictable state management. This pattern is particularly useful in Java design patterns for developing responsive client-side web applications.\n\nWikipedia says\n\n> To support React's concept of unidirectional data flow (which might be contrasted with AngularJS's bidirectional flow), the Flux architecture was developed as an alternative to the popular model–view–controller architecture. Flux features actions which are sent through a central dispatcher to a store, and changes to the store are propagated back to the view.\n\nArchitecture diagram\n\n![Flux Architecture Diagram](./etc/flux-architecture-diagram.png)\n\n## Programmatic Example of Flux Pattern in Java\n\nThe Flux design pattern is used for building client-side web applications. It advocates for a unidirectional data flow. When a user interacts with a view, the view propagates an action through a central dispatcher, to the various stores that hold the application's data and business logic, which updates all the views that are affected.\n\nIn the provided code, we can see an example of the Flux pattern in the `App` and `MenuStore` classes.\n\nThe `App` class is the entry point of the application. It initializes and wires the system, registers the stores with the dispatcher, registers the views with the stores, and triggers the initial rendering of the views. When a menu item is clicked, it triggers events through the dispatcher.\n\n```java\npublic class App {\n\n  public static void main(String[] args) {\n\n    var menuStore = new MenuStore();\n    Dispatcher.getInstance().registerStore(menuStore);\n    var contentStore = new ContentStore();\n    Dispatcher.getInstance().registerStore(contentStore);\n    var menuView = new MenuView();\n    menuStore.registerView(menuView);\n    var contentView = new ContentView();\n    contentStore.registerView(contentView);\n\n    menuView.render();\n    contentView.render();\n\n    menuView.itemClicked(MenuItem.COMPANY);\n  }\n}\n```\n\nThe `MenuStore` class is a concrete store that holds the state of the menu. It updates its state and notifies the views when it receives an action from the dispatcher.\n\n```java\npublic class MenuStore extends Store {\n\n  @Getter\n  private MenuItem selected = MenuItem.HOME;\n\n  @Override\n  public void onAction(Action action) {\n    if (action.getType().equals(ActionType.MENU_ITEM_SELECTED)) {\n      var menuAction = (MenuAction) action;\n      selected = menuAction.getMenuItem();\n      notifyChange();\n    }\n  }\n}\n```\n\nIn this example, when a menu item is clicked, the `MenuView` triggers a `MENU_ITEM_SELECTED` action. The `Dispatcher` forwards this action to all registered stores. The `MenuStore` handles this action by updating its state and notifying its views, causing them to rerender with the new state.\n\nThis is a basic example of the Flux pattern, where actions are dispatched from the views, handled by the stores, and cause the views to update.\n\n## When to Use the Flux Pattern in Java\n\nFlux is applicable in developing client-side Java applications, where maintaining consistent data across various components and managing complex state interactions are critical. It is especially suited for applications with dynamic user interfaces that react to frequent data updates.\n\n## Real-World Applications of Flux Pattern in Java\n\n* Facebook extensively uses the Flux design pattern in conjunction with React to build robust, scalable user interfaces that can handle complex data updates efficiently. \n* Many modern web applications adopt Flux or its variations (like Redux) to manage state in environments that demand high responsiveness and predictability.\n\n## Benefits and Trade-offs of Flux Pattern\n\nBenefits:\n\n* Ensures a unidirectional data flow that simplifies debugging and testing.\n* Enhances consistency across the application by centralizing the application state.\n* Improves the predictability of data flow and interaction in large applications.\n\nTrade-offs:\n\n* Can introduce boilerplate and complexity in smaller applications.\n* May require a learning curve to understand the pattern's architecture and its implementation nuances.\n\n## Related Java Design Patterns\n\n* [Observer](https://java-design-patterns.com/patterns/observer/): Flux's dispatcher component acts similarly to an observer, managing notifications about data changes to various stores.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Typically, the dispatcher in Flux is implemented as a singleton.\n* [Mediator](https://java-design-patterns.com/patterns/mediator/): Flux can be considered a variation of the mediator pattern where the dispatcher mediates the flow of data and ensures components do not update the state directly.\n\n## References and Credits\n\n* [Learning React: Modern Patterns for Developing React Apps](https://amzn.to/3Qdn9Pg)\n* [Pro React](https://amzn.to/3xNRttK)\n"
  },
  {
    "path": "flux/etc/flux.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <enumeration id=\"1\" language=\"java\" name=\"com.iluwatar.action.Content\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/action/Content.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1084\" y=\"564\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.view.MenuView\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/view/MenuView.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"142\" width=\"185\" x=\"789\" y=\"300\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.store.ContentStore\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/store/ContentStore.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1084\" y=\"364\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.dispatcher.Dispatcher\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/dispatcher/Dispatcher.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1084\" y=\"-9\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"5\" language=\"java\" name=\"com.iluwatar.view.View\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/view/View.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"171\" x=\"1204\" y=\"482\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.action.ContentAction\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/action/ContentAction.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"161\" x=\"588\" y=\"300\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.action.MenuAction\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/action/MenuAction.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"259\" y=\"353\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.store.MenuStore\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/store/MenuStore.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"164\" x=\"384\" y=\"300\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"9\" language=\"java\" name=\"com.iluwatar.action.Action\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/action/Action.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"258\" y=\"171\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"10\" language=\"java\" name=\"com.iluwatar.view.ContentView\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/view/ContentView.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"171\" x=\"1202\" y=\"300\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <enumeration id=\"11\" language=\"java\" name=\"com.iluwatar.action.ActionType\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/action/ActionType.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"247\" x=\"-113\" y=\"300\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <enumeration id=\"12\" language=\"java\" name=\"com.iluwatar.action.MenuItem\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/action/MenuItem.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"178\" width=\"162\" x=\"384\" y=\"482\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <class id=\"13\" language=\"java\" name=\"com.iluwatar.store.Store\" project=\"flux\" \n    file=\"/flux/src/main/java/com/iluwatar/store/Store.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1084\" y=\"191\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"14\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"15\" name=\"stores\"/>      \n      <multiplicity id=\"16\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"13\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"17\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </realization>  \n  <generalization id=\"18\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"9\"/>  \n  </generalization>  \n  <association id=\"19\">    \n    <end type=\"SOURCE\" refId=\"9\" navigable=\"false\">      \n      <attribute id=\"20\" name=\"type\"/>      \n      <multiplicity id=\"21\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"11\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"22\">    \n    <end type=\"SOURCE\" refId=\"7\" navigable=\"false\">      \n      <attribute id=\"23\" name=\"menuItem\"/>      \n      <multiplicity id=\"24\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"12\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"25\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"26\" name=\"selected\"/>      \n      <multiplicity id=\"27\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"12\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"28\">    \n    <bendpoint x=\"1403\" y=\"300\"/>    \n    <end type=\"SOURCE\" refId=\"13\" navigable=\"false\">      \n      <attribute id=\"29\" name=\"views\"/>      \n      <multiplicity id=\"30\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"31\">    \n    <end type=\"SOURCE\" refId=\"6\"/>    \n    <end type=\"TARGET\" refId=\"9\"/>  \n  </generalization>  \n  <association id=\"32\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"33\" name=\"content\"/>      \n      <multiplicity id=\"34\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"35\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"13\"/>  \n  </generalization>  \n  <generalization id=\"36\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"13\"/>  \n  </generalization>  \n  <realization id=\"37\">    \n    <end type=\"SOURCE\" refId=\"10\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </realization>  \n  <association id=\"38\">    \n    <end type=\"SOURCE\" refId=\"10\" navigable=\"false\">      \n      <attribute id=\"39\" name=\"content\"/>      \n      <multiplicity id=\"40\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"41\">    \n    <end type=\"SOURCE\" refId=\"8\" navigable=\"false\">      \n      <attribute id=\"42\" name=\"selected\"/>      \n      <multiplicity id=\"43\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"12\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"44\">    \n    <end type=\"SOURCE\" refId=\"6\" navigable=\"false\">      \n      <attribute id=\"45\" name=\"content\"/>      \n      <multiplicity id=\"46\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"47\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"48\" name=\"instance\"/>      \n      <multiplicity id=\"49\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "flux/etc/flux.urm.puml",
    "content": "@startuml\npackage com.iluwatar.flux.view {\n  class ContentView {\n    - LOGGER : Logger {static}\n    - content : Content\n    + ContentView()\n    + render()\n    + storeChanged(store : Store)\n  }\n  class MenuView {\n    - LOGGER : Logger {static}\n    - selected : MenuItem\n    + MenuView()\n    + itemClicked(item : MenuItem)\n    + render()\n    + storeChanged(store : Store)\n  }\n  interface View {\n    + render() {abstract}\n    + storeChanged(Store) {abstract}\n  }\n}\npackage com.iluwatar.flux.action {\n  abstract class Action {\n    - type : ActionType\n    + Action(type : ActionType)\n    + getType() : ActionType\n  }\n  enum ActionType {\n    + CONTENT_CHANGED {static}\n    + MENU_ITEM_SELECTED {static}\n    + valueOf(name : String) : ActionType {static}\n    + values() : ActionType[] {static}\n  }\n  enum Content {\n    + COMPANY {static}\n    + PRODUCTS {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Content {static}\n    + values() : Content[] {static}\n  }\n  class ContentAction {\n    - content : Content\n    + ContentAction(content : Content)\n    + getContent() : Content\n  }\n  class MenuAction {\n    - menuItem : MenuItem\n    + MenuAction(menuItem : MenuItem)\n    + getMenuItem() : MenuItem\n  }\n  enum MenuItem {\n    + COMPANY {static}\n    + HOME {static}\n    + PRODUCTS {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : MenuItem {static}\n    + values() : MenuItem[] {static}\n  }\n}\npackage com.iluwatar.flux.app {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n}\npackage com.iluwatar.flux.store {\n  class ContentStore {\n    - content : Content\n    + ContentStore()\n    + getContent() : Content\n    + onAction(action : Action)\n  }\n  class MenuStore {\n    - selected : MenuItem\n    + MenuStore()\n    + getSelected() : MenuItem\n    + onAction(action : Action)\n  }\n  abstract class Store {\n    - views : List<View>\n    + Store()\n    # notifyChange()\n    + onAction(Action) {abstract}\n    + registerView(view : View)\n  }\n}\npackage com.iluwatar.flux.dispatcher {\n  class Dispatcher {\n    - instance : Dispatcher {static}\n    - stores : List<Store>\n    - Dispatcher()\n    - dispatchAction(action : Action)\n    + getInstance() : Dispatcher {static}\n    + menuItemSelected(menuItem : MenuItem)\n    + registerStore(store : Store)\n  }\n}\nMenuAction -->  \"-menuItem\" MenuItem\nAction -->  \"-type\" ActionType\nMenuStore -->  \"-selected\" MenuItem\nDispatcher -->  \"-instance\" Dispatcher\nContentView -->  \"-content\" Content\nDispatcher -->  \"-stores\" Store\nMenuView -->  \"-selected\" MenuItem\nStore -->  \"-views\" View\nContentStore -->  \"-content\" Content\nContentAction -->  \"-content\" Content\nContentAction --|> Action \nMenuAction --|> Action \nContentStore --|> Store \nMenuStore --|> Store \nContentView ..|> View \nMenuView ..|> View \n@enduml"
  },
  {
    "path": "flux/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>flux</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.flux.app.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/action/Action.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.action;\n\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/** Action is the data payload dispatched to the stores when something happens. */\n@RequiredArgsConstructor\n@Getter\npublic abstract class Action {\n\n  private final ActionType type;\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/action/ActionType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.action;\n\n/** Types of actions. */\npublic enum ActionType {\n  MENU_ITEM_SELECTED,\n  CONTENT_CHANGED\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/action/Content.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.action;\n\nimport lombok.RequiredArgsConstructor;\n\n/** Content items. */\n@RequiredArgsConstructor\npublic enum Content {\n  PRODUCTS(\"Products - This page lists the company's products.\"),\n  COMPANY(\"Company - This page displays information about the company.\");\n\n  private final String title;\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/action/ContentAction.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.action;\n\nimport lombok.Getter;\n\n/** ContentAction is a concrete action. */\npublic class ContentAction extends Action {\n\n  @Getter private final Content content;\n\n  public ContentAction(Content content) {\n    super(ActionType.CONTENT_CHANGED);\n    this.content = content;\n  }\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/action/MenuAction.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.action;\n\nimport lombok.Getter;\n\n/** MenuAction is a concrete action. */\npublic class MenuAction extends Action {\n\n  @Getter private final MenuItem menuItem;\n\n  public MenuAction(MenuItem menuItem) {\n    super(ActionType.MENU_ITEM_SELECTED);\n    this.menuItem = menuItem;\n  }\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/action/MenuItem.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.action;\n\n/** Menu items. */\npublic enum MenuItem {\n  HOME(\"Home\"),\n  PRODUCTS(\"Products\"),\n  COMPANY(\"Company\");\n\n  private final String title;\n\n  MenuItem(String title) {\n    this.title = title;\n  }\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/app/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.app;\n\nimport com.iluwatar.flux.action.MenuItem;\nimport com.iluwatar.flux.dispatcher.Dispatcher;\nimport com.iluwatar.flux.store.ContentStore;\nimport com.iluwatar.flux.store.MenuStore;\nimport com.iluwatar.flux.view.ContentView;\nimport com.iluwatar.flux.view.MenuView;\n\n/**\n * Flux is the application architecture that Facebook uses for building client-side web\n * applications. Flux eschews MVC in favor of a unidirectional data flow. When a user interacts with\n * a React view, the view propagates an action through a central dispatcher, to the various stores\n * that hold the application's data and business logic, which updates all the views that are\n * affected.\n *\n * <p>This example has two views: menu and content. They represent typical main menu and content\n * area of a web page. When menu item is clicked it triggers events through the dispatcher. The\n * events are received and handled by the stores updating their data as needed. The stores then\n * notify the views that they should rerender themselves.\n *\n * <p>http://facebook.github.io/flux/docs/overview.html\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    // initialize and wire the system\n    var menuStore = new MenuStore();\n    Dispatcher.getInstance().registerStore(menuStore);\n    var contentStore = new ContentStore();\n    Dispatcher.getInstance().registerStore(contentStore);\n    var menuView = new MenuView();\n    menuStore.registerView(menuView);\n    var contentView = new ContentView();\n    contentStore.registerView(contentView);\n\n    // render initial view\n    menuView.render();\n    contentView.render();\n\n    // user clicks another menu item\n    // this triggers action dispatching and eventually causes views to render with new content\n    menuView.itemClicked(MenuItem.COMPANY);\n  }\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/dispatcher/Dispatcher.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.dispatcher;\n\nimport com.iluwatar.flux.action.Action;\nimport com.iluwatar.flux.action.Content;\nimport com.iluwatar.flux.action.ContentAction;\nimport com.iluwatar.flux.action.MenuAction;\nimport com.iluwatar.flux.action.MenuItem;\nimport com.iluwatar.flux.store.Store;\nimport java.util.LinkedList;\nimport java.util.List;\nimport lombok.Getter;\n\n/** Dispatcher sends Actions to registered Stores. */\npublic final class Dispatcher {\n\n  @Getter private static Dispatcher instance = new Dispatcher();\n\n  private final List<Store> stores = new LinkedList<>();\n\n  private Dispatcher() {}\n\n  public void registerStore(Store store) {\n    stores.add(store);\n  }\n\n  /** Menu item selected handler. */\n  public void menuItemSelected(MenuItem menuItem) {\n    dispatchAction(new MenuAction(menuItem));\n    if (menuItem == MenuItem.COMPANY) {\n      dispatchAction(new ContentAction(Content.COMPANY));\n    } else {\n      dispatchAction(new ContentAction(Content.PRODUCTS));\n    }\n  }\n\n  private void dispatchAction(Action action) {\n    stores.forEach(store -> store.onAction(action));\n  }\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/store/ContentStore.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.store;\n\nimport com.iluwatar.flux.action.Action;\nimport com.iluwatar.flux.action.ActionType;\nimport com.iluwatar.flux.action.Content;\nimport com.iluwatar.flux.action.ContentAction;\nimport lombok.Getter;\n\n/** ContentStore is a concrete store. */\npublic class ContentStore extends Store {\n\n  @Getter private Content content = Content.PRODUCTS;\n\n  @Override\n  public void onAction(Action action) {\n    if (action.getType().equals(ActionType.CONTENT_CHANGED)) {\n      var contentAction = (ContentAction) action;\n      content = contentAction.getContent();\n      notifyChange();\n    }\n  }\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/store/MenuStore.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.store;\n\nimport com.iluwatar.flux.action.Action;\nimport com.iluwatar.flux.action.ActionType;\nimport com.iluwatar.flux.action.MenuAction;\nimport com.iluwatar.flux.action.MenuItem;\nimport lombok.Getter;\n\n/** MenuStore is a concrete store. */\npublic class MenuStore extends Store {\n\n  @Getter private MenuItem selected = MenuItem.HOME;\n\n  @Override\n  public void onAction(Action action) {\n    if (action.getType().equals(ActionType.MENU_ITEM_SELECTED)) {\n      var menuAction = (MenuAction) action;\n      selected = menuAction.getMenuItem();\n      notifyChange();\n    }\n  }\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/store/Store.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.store;\n\nimport com.iluwatar.flux.action.Action;\nimport com.iluwatar.flux.view.View;\nimport java.util.LinkedList;\nimport java.util.List;\n\n/** Store is a data model. */\npublic abstract class Store {\n\n  private final List<View> views = new LinkedList<>();\n\n  public abstract void onAction(Action action);\n\n  public void registerView(View view) {\n    views.add(view);\n  }\n\n  protected void notifyChange() {\n    views.forEach(view -> view.storeChanged(this));\n  }\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/view/ContentView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.view;\n\nimport com.iluwatar.flux.action.Content;\nimport com.iluwatar.flux.store.ContentStore;\nimport com.iluwatar.flux.store.Store;\nimport lombok.extern.slf4j.Slf4j;\n\n/** ContentView is a concrete view. */\n@Slf4j\npublic class ContentView implements View {\n\n  private Content content = Content.PRODUCTS;\n\n  @Override\n  public void storeChanged(Store store) {\n    var contentStore = (ContentStore) store;\n    content = contentStore.getContent();\n    render();\n  }\n\n  @Override\n  public void render() {\n    LOGGER.info(content.toString());\n  }\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/view/MenuView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.view;\n\nimport com.iluwatar.flux.action.MenuItem;\nimport com.iluwatar.flux.dispatcher.Dispatcher;\nimport com.iluwatar.flux.store.MenuStore;\nimport com.iluwatar.flux.store.Store;\nimport lombok.extern.slf4j.Slf4j;\n\n/** MenuView is a concrete view. */\n@Slf4j\npublic class MenuView implements View {\n\n  private MenuItem selected = MenuItem.HOME;\n\n  @Override\n  public void storeChanged(Store store) {\n    var menuStore = (MenuStore) store;\n    selected = menuStore.getSelected();\n    render();\n  }\n\n  @Override\n  public void render() {\n    for (var item : MenuItem.values()) {\n      if (selected.equals(item)) {\n        LOGGER.info(\"* {}\", item);\n      } else {\n        LOGGER.info(item.toString());\n      }\n    }\n  }\n\n  public void itemClicked(MenuItem item) {\n    Dispatcher.getInstance().menuItemSelected(item);\n  }\n}\n"
  },
  {
    "path": "flux/src/main/java/com/iluwatar/flux/view/View.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.view;\n\nimport com.iluwatar.flux.store.Store;\n\n/** Views define the representation of data. */\npublic interface View {\n\n  void storeChanged(Store store);\n\n  void render();\n}\n"
  },
  {
    "path": "flux/src/test/java/com/iluwatar/flux/action/ContentTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.action;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport org.junit.jupiter.api.Test;\n\n/** ContentTest */\nclass ContentTest {\n\n  @Test\n  void testToString() {\n    for (final var content : Content.values()) {\n      final var toString = content.toString();\n      assertNotNull(toString);\n      assertFalse(toString.trim().isEmpty());\n    }\n  }\n}\n"
  },
  {
    "path": "flux/src/test/java/com/iluwatar/flux/action/MenuItemTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.action;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport org.junit.jupiter.api.Test;\n\n/** MenuItemTest */\nclass MenuItemTest {\n\n  @Test\n  void testToString() {\n    for (final var menuItem : MenuItem.values()) {\n      final var toString = menuItem.toString();\n      assertNotNull(toString);\n      assertFalse(toString.trim().isEmpty());\n    }\n  }\n}\n"
  },
  {
    "path": "flux/src/test/java/com/iluwatar/flux/app/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.app;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "flux/src/test/java/com/iluwatar/flux/dispatcher/DispatcherTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.dispatcher;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertSame;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport com.iluwatar.flux.action.Action;\nimport com.iluwatar.flux.action.ActionType;\nimport com.iluwatar.flux.action.Content;\nimport com.iluwatar.flux.action.ContentAction;\nimport com.iluwatar.flux.action.MenuAction;\nimport com.iluwatar.flux.action.MenuItem;\nimport com.iluwatar.flux.store.Store;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.ArgumentCaptor;\n\n/** DispatcherTest */\nclass DispatcherTest {\n\n  /**\n   * Dispatcher is a singleton with no way to reset it's internal state back to the beginning.\n   * Replace the instance with a fresh one before each test to make sure test cases have no\n   * influence on each other.\n   */\n  @BeforeEach\n  void setUp() throws Exception {\n    final var constructor = Dispatcher.class.getDeclaredConstructor();\n    constructor.setAccessible(true);\n\n    final var field = Dispatcher.class.getDeclaredField(\"instance\");\n    field.setAccessible(true);\n    field.set(Dispatcher.getInstance(), constructor.newInstance());\n  }\n\n  @Test\n  void testGetInstance() {\n    assertNotNull(Dispatcher.getInstance());\n    assertSame(Dispatcher.getInstance(), Dispatcher.getInstance());\n  }\n\n  @Test\n  void testMenuItemSelected() {\n    final var dispatcher = Dispatcher.getInstance();\n\n    final var store = mock(Store.class);\n    dispatcher.registerStore(store);\n    dispatcher.menuItemSelected(MenuItem.HOME);\n    dispatcher.menuItemSelected(MenuItem.COMPANY);\n\n    // We expect 4 events, 2 menu selections and 2 content change actions\n    final var actionCaptor = ArgumentCaptor.forClass(Action.class);\n    verify(store, times(4)).onAction(actionCaptor.capture());\n    verifyNoMoreInteractions(store);\n\n    final var actions = actionCaptor.getAllValues();\n    final var menuActions =\n        actions.stream()\n            .filter(a -> a.getType().equals(ActionType.MENU_ITEM_SELECTED))\n            .map(a -> (MenuAction) a)\n            .toList();\n\n    final var contentActions =\n        actions.stream()\n            .filter(a -> a.getType().equals(ActionType.CONTENT_CHANGED))\n            .map(a -> (ContentAction) a)\n            .toList();\n\n    assertEquals(2, menuActions.size());\n    assertEquals(\n        1, menuActions.stream().map(MenuAction::getMenuItem).filter(MenuItem.HOME::equals).count());\n    assertEquals(\n        1,\n        menuActions.stream().map(MenuAction::getMenuItem).filter(MenuItem.COMPANY::equals).count());\n\n    assertEquals(2, contentActions.size());\n    assertEquals(\n        1,\n        contentActions.stream()\n            .map(ContentAction::getContent)\n            .filter(Content.PRODUCTS::equals)\n            .count());\n    assertEquals(\n        1,\n        contentActions.stream()\n            .map(ContentAction::getContent)\n            .filter(Content.COMPANY::equals)\n            .count());\n  }\n}\n"
  },
  {
    "path": "flux/src/test/java/com/iluwatar/flux/store/ContentStoreTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.store;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport com.iluwatar.flux.action.Content;\nimport com.iluwatar.flux.action.ContentAction;\nimport com.iluwatar.flux.action.MenuAction;\nimport com.iluwatar.flux.action.MenuItem;\nimport com.iluwatar.flux.view.View;\nimport org.junit.jupiter.api.Test;\n\n/** ContentStoreTest */\nclass ContentStoreTest {\n\n  @Test\n  void testOnAction() {\n    final var contentStore = new ContentStore();\n\n    final var view = mock(View.class);\n    contentStore.registerView(view);\n\n    verifyNoMoreInteractions(view);\n\n    // Content should not react on menu action ...\n    contentStore.onAction(new MenuAction(MenuItem.PRODUCTS));\n    verifyNoMoreInteractions(view);\n\n    // ... but it should react on a content action\n    contentStore.onAction(new ContentAction(Content.COMPANY));\n    verify(view, times(1)).storeChanged(eq(contentStore));\n    verifyNoMoreInteractions(view);\n    assertEquals(Content.COMPANY, contentStore.getContent());\n  }\n}\n"
  },
  {
    "path": "flux/src/test/java/com/iluwatar/flux/store/MenuStoreTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.store;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport com.iluwatar.flux.action.Content;\nimport com.iluwatar.flux.action.ContentAction;\nimport com.iluwatar.flux.action.MenuAction;\nimport com.iluwatar.flux.action.MenuItem;\nimport com.iluwatar.flux.view.View;\nimport org.junit.jupiter.api.Test;\n\n/** MenuStoreTest */\nclass MenuStoreTest {\n\n  @Test\n  void testOnAction() {\n    final var menuStore = new MenuStore();\n\n    final var view = mock(View.class);\n    menuStore.registerView(view);\n\n    verifyNoMoreInteractions(view);\n\n    // Menu should not react on content action ...\n    menuStore.onAction(new ContentAction(Content.COMPANY));\n    verifyNoMoreInteractions(view);\n\n    // ... but it should react on a menu action\n    menuStore.onAction(new MenuAction(MenuItem.PRODUCTS));\n    verify(view, times(1)).storeChanged(eq(menuStore));\n    verifyNoMoreInteractions(view);\n    assertEquals(MenuItem.PRODUCTS, menuStore.getSelected());\n  }\n}\n"
  },
  {
    "path": "flux/src/test/java/com/iluwatar/flux/view/ContentViewTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.view;\n\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.flux.action.Content;\nimport com.iluwatar.flux.store.ContentStore;\nimport org.junit.jupiter.api.Test;\n\n/** ContentViewTest */\nclass ContentViewTest {\n\n  @Test\n  void testStoreChanged() {\n    final var store = mock(ContentStore.class);\n    when(store.getContent()).thenReturn(Content.PRODUCTS);\n\n    final var view = new ContentView();\n    view.storeChanged(store);\n\n    verify(store, times(1)).getContent();\n    verifyNoMoreInteractions(store);\n  }\n}\n"
  },
  {
    "path": "flux/src/test/java/com/iluwatar/flux/view/MenuViewTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flux.view;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.flux.action.Action;\nimport com.iluwatar.flux.action.MenuItem;\nimport com.iluwatar.flux.dispatcher.Dispatcher;\nimport com.iluwatar.flux.store.MenuStore;\nimport com.iluwatar.flux.store.Store;\nimport org.junit.jupiter.api.Test;\n\n/** MenuViewTest */\nclass MenuViewTest {\n\n  @Test\n  void testStoreChanged() {\n    final var store = mock(MenuStore.class);\n    when(store.getSelected()).thenReturn(MenuItem.HOME);\n\n    final var view = new MenuView();\n    view.storeChanged(store);\n\n    verify(store, times(1)).getSelected();\n    verifyNoMoreInteractions(store);\n  }\n\n  @Test\n  void testItemClicked() {\n    final var store = mock(Store.class);\n    Dispatcher.getInstance().registerStore(store);\n\n    final var view = new MenuView();\n    view.itemClicked(MenuItem.PRODUCTS);\n\n    // We should receive a menu click action and a content changed action\n    verify(store, times(2)).onAction(any(Action.class));\n  }\n}\n"
  },
  {
    "path": "flyweight/README.md",
    "content": "---\ntitle: \"Flyweight Pattern in Java: Maximizing Memory Efficiency with Shared Object Instances\"\nshortTitle: Flyweight\ndescription: \"Learn how the Flyweight design pattern optimizes memory usage in Java applications by sharing data among similar objects. Enhance performance and reduce memory footprint with practical examples and detailed explanations.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Gang of Four\n  - Memory management\n  - Object composition\n  - Optimization\n  - Performance\n---\n\n## Intent of Flyweight Design Pattern\n\nThe Flyweight design pattern in Java is crucial for optimizing memory usage and enhancing application performance. By minimizing the number of objects created, it significantly reduces the memory footprint. The primary goal of the Flyweight pattern is to share as much data as possible among similar objects, thereby improving efficiency and performance.\n\n## Detailed Explanation of Flyweight Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world application of the Flyweight pattern in Java can be seen in text editors like Microsoft Word or Google Docs. These applications use Flyweight to efficiently manage memory by sharing character objects, reducing the memory footprint significantly. In such applications, each character in a document could potentially be a separate object, which would be highly inefficient in terms of memory usage. Instead, the Flyweight pattern can be used to share character objects. For instance, all instances of the letter 'A' can share a single 'A' object with its intrinsic state (e.g., the shape of the character). The extrinsic state, such as the position, font, and color, can be stored separately and applied as needed. This way, the application efficiently manages memory by reusing existing objects for characters that appear multiple times.\n\nIn plain words\n\n> It is used to minimize memory usage or computational expenses by sharing as much as possible with similar objects.\n\nWikipedia says\n\n> In computer programming, flyweight is a software design pattern. A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory.\n\nSequence diagram\n\n![Flyweight sequence diagram](./etc/flyweight-sequence-diagram.png)\n\n## Programmatic Example of Flyweight Pattern in Java\n\nAlchemist's shop has shelves full of magic potions. Many of the potions are the same so there is no need to create a new object for each of them. Instead, one object instance can represent  multiple shelf items so the memory footprint remains small.\n\nFirst of all, we have different `Potion` types:\n\n```java\npublic interface Potion {\n  void drink();\n}\n```\n\n```java\n@Slf4j\npublic class HealingPotion implements Potion {\n  @Override\n  public void drink() {\n    LOGGER.info(\"You feel healed. (Potion={})\", System.identityHashCode(this));\n  }\n}\n```\n\n```java\n@Slf4j\npublic class HolyWaterPotion implements Potion {\n  @Override\n  public void drink() {\n    LOGGER.info(\"You feel blessed. (Potion={})\", System.identityHashCode(this));\n  }\n}\n```\n\n```java\n@Slf4j\npublic class InvisibilityPotion implements Potion {\n  @Override\n  public void drink() {\n    LOGGER.info(\"You become invisible. (Potion={})\", System.identityHashCode(this));\n  }\n}\n```\n\nThen the actual Flyweight class `PotionFactory`, which is the factory for creating potions.\n\n```java\npublic class PotionFactory {\n\n  private final Map<PotionType, Potion> potions;\n\n  public PotionFactory() {\n    potions = new EnumMap<>(PotionType.class);\n  }\n\n  Potion createPotion(PotionType type) {\n    var potion = potions.get(type);\n    if (potion == null) {\n      switch (type) {\n        case HEALING -> potion = new HealingPotion();\n        case HOLY_WATER -> potion = new HolyWaterPotion();\n        case INVISIBILITY -> potion = new InvisibilityPotion();\n        default -> {\n        }\n      }\n      potions.put(type, potion);\n    }\n    return potion;\n  }\n}\n```\n\n`AlchemistShop` contains two shelves of magic potions. The potions are created using the aforementioned `PotionFactory`.\n\n```java\n@Slf4j\npublic class AlchemistShop {\n\n  private final List<Potion> topShelf;\n  private final List<Potion> bottomShelf;\n\n  public AlchemistShop() {\n    var factory = new PotionFactory();\n    topShelf = List.of(\n        factory.createPotion(PotionType.INVISIBILITY),\n        factory.createPotion(PotionType.INVISIBILITY),\n        factory.createPotion(PotionType.STRENGTH),\n        factory.createPotion(PotionType.HEALING),\n        factory.createPotion(PotionType.INVISIBILITY),\n        factory.createPotion(PotionType.STRENGTH),\n        factory.createPotion(PotionType.HEALING),\n        factory.createPotion(PotionType.HEALING)\n    );\n    bottomShelf = List.of(\n        factory.createPotion(PotionType.POISON),\n        factory.createPotion(PotionType.POISON),\n        factory.createPotion(PotionType.POISON),\n        factory.createPotion(PotionType.HOLY_WATER),\n        factory.createPotion(PotionType.HOLY_WATER)\n    );\n  }\n\n  public final List<Potion> getTopShelf() {\n    return List.copyOf(this.topShelf);\n  }\n\n  public final List<Potion> getBottomShelf() {\n    return List.copyOf(this.bottomShelf);\n  }\n\n  public void drinkPotions() {\n    LOGGER.info(\"Drinking top shelf potions\\n\");\n    topShelf.forEach(Potion::drink);\n    LOGGER.info(\"Drinking bottom shelf potions\\n\");\n    bottomShelf.forEach(Potion::drink);\n  }\n}\n```\n\nIn our scenario, a brave visitor enters the alchemist shop and drinks all the potions.\n\n```java\npublic static void main(String[] args) {\n    // create the alchemist shop with the potions\n    var alchemistShop = new AlchemistShop();\n    // a brave visitor enters the alchemist shop and drinks all the potions\n    alchemistShop.drinkPotions();\n}\n```\n\nProgram output:\n\n```\n09:02:52.731 [main] INFO com.iluwatar.flyweight.AlchemistShop -- Drinking top shelf potions\n09:02:52.733 [main] INFO com.iluwatar.flyweight.InvisibilityPotion -- You become invisible. (Potion=1395089624)\n09:02:52.733 [main] INFO com.iluwatar.flyweight.InvisibilityPotion -- You become invisible. (Potion=1395089624)\n09:02:52.733 [main] INFO com.iluwatar.flyweight.StrengthPotion -- You feel strong. (Potion=1450821318)\n09:02:52.733 [main] INFO com.iluwatar.flyweight.HealingPotion -- You feel healed. (Potion=668849042)\n09:02:52.733 [main] INFO com.iluwatar.flyweight.InvisibilityPotion -- You become invisible. (Potion=1395089624)\n09:02:52.733 [main] INFO com.iluwatar.flyweight.StrengthPotion -- You feel strong. (Potion=1450821318)\n09:02:52.733 [main] INFO com.iluwatar.flyweight.HealingPotion -- You feel healed. (Potion=668849042)\n09:02:52.733 [main] INFO com.iluwatar.flyweight.HealingPotion -- You feel healed. (Potion=668849042)\n09:02:52.733 [main] INFO com.iluwatar.flyweight.AlchemistShop -- Drinking bottom shelf potions\n09:02:52.734 [main] INFO com.iluwatar.flyweight.PoisonPotion -- Urgh! This is poisonous. (Potion=2096057945)\n09:02:52.734 [main] INFO com.iluwatar.flyweight.PoisonPotion -- Urgh! This is poisonous. (Potion=2096057945)\n09:02:52.734 [main] INFO com.iluwatar.flyweight.PoisonPotion -- Urgh! This is poisonous. (Potion=2096057945)\n09:02:52.734 [main] INFO com.iluwatar.flyweight.HolyWaterPotion -- You feel blessed. (Potion=1689843956)\n09:02:52.734 [main] INFO com.iluwatar.flyweight.HolyWaterPotion -- You feel blessed. (Potion=1689843956)\n```\n\n## When to Use the Flyweight Pattern in Java\n\nThe Flyweight pattern's effectiveness depends heavily on how and where it's used. Apply the Flyweight pattern when all the following are true:\n\n* The Flyweight pattern is particularly effective in Java applications that use a large number of objects.\n* When storage costs are high due to the quantity of objects, Flyweight helps by sharing intrinsic data and managing extrinsic state separately.\n* Most of the object state can be made extrinsic.\n* Many groups of objects may be replaced by relatively few shared objects once the extrinsic state is removed.\n* The application doesn't depend on object identity. Since flyweight objects may be shared, identity tests will return true for conceptually distinct objects.\n\n## Real-World Applications of Flyweight Pattern in Java\n\n* [java.lang.Integer#valueOf(int)](http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#valueOf%28int%29) and similarly for Byte, Character and other wrapped types.\n* Java’s String class utilizes the Flyweight pattern to manage string literals efficiently.\n* GUI applications often use Flyweight for sharing objects like fonts or graphical components, thereby conserving memory and improving performance.\n\n## Benefits and Trade-offs of Flyweight Pattern\n\nBenefits:\n\n* Reduces the number of instances of an object, conserving memory.\n* Centralizes state management, reducing the risk of inconsistent state.\n\nTrade-offs:\n\n* Increases complexity by adding the management layer for shared objects.\n* Potential overhead in accessing shared objects if not well implemented.\n\n## Related Java Design Patterns\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): Often combined with Flyweight when the composites are shareable. Both are used to manage hierarchies and structures of objects.\n* [State](https://java-design-patterns.com/patterns/state/): Can be used to manage state in a shared Flyweight object, distinguishing internal state (invariant) from external state (context-specific).\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n"
  },
  {
    "path": "flyweight/etc/flyweight.urm.puml",
    "content": "@startuml\npackage com.iluwatar.flyweight {\n  class AlchemistShop {\n    - LOGGER : Logger {static}\n    - bottomShelf : List<Potion>\n    - topShelf : List<Potion>\n    + AlchemistShop()\n    + enumerate()\n    + getBottomShelf() : List<Potion>\n    + getTopShelf() : List<Potion>\n  }\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class HealingPotion {\n    - LOGGER : Logger {static}\n    + HealingPotion()\n    + drink()\n  }\n  class HolyWaterPotion {\n    - LOGGER : Logger {static}\n    + HolyWaterPotion()\n    + drink()\n  }\n  class InvisibilityPotion {\n    - LOGGER : Logger {static}\n    + InvisibilityPotion()\n    + drink()\n  }\n  class PoisonPotion {\n    - LOGGER : Logger {static}\n    + PoisonPotion()\n    + drink()\n  }\n  interface Potion {\n    + drink() {abstract}\n  }\n  class PotionFactory {\n    - potions : Map<PotionType, Potion>\n    + PotionFactory()\n    ~ createPotion(type : PotionType) : Potion\n  }\n  enum PotionType {\n    + HEALING {static}\n    + HOLY_WATER {static}\n    + INVISIBILITY {static}\n    + POISON {static}\n    + STRENGTH {static}\n    + valueOf(name : String) : PotionType {static}\n    + values() : PotionType[] {static}\n  }\n  class StrengthPotion {\n    - LOGGER : Logger {static}\n    + StrengthPotion()\n    + drink()\n  }\n}\nAlchemistShop -->  \"-topShelf\" Potion\nHealingPotion ..|> Potion \nHolyWaterPotion ..|> Potion \nInvisibilityPotion ..|> Potion \nPoisonPotion ..|> Potion \nStrengthPotion ..|> Potion \n@enduml"
  },
  {
    "path": "flyweight/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>flyweight</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.flyweight.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "flyweight/src/main/java/com/iluwatar/flyweight/AlchemistShop.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flyweight;\n\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/** AlchemistShop holds potions on its shelves. It uses PotionFactory to provide the potions. */\n@Slf4j\npublic class AlchemistShop {\n\n  private final List<Potion> topShelf;\n  private final List<Potion> bottomShelf;\n\n  /** Constructor. */\n  public AlchemistShop() {\n    var factory = new PotionFactory();\n    topShelf =\n        List.of(\n            factory.createPotion(PotionType.INVISIBILITY),\n            factory.createPotion(PotionType.INVISIBILITY),\n            factory.createPotion(PotionType.STRENGTH),\n            factory.createPotion(PotionType.HEALING),\n            factory.createPotion(PotionType.INVISIBILITY),\n            factory.createPotion(PotionType.STRENGTH),\n            factory.createPotion(PotionType.HEALING),\n            factory.createPotion(PotionType.HEALING));\n    bottomShelf =\n        List.of(\n            factory.createPotion(PotionType.POISON),\n            factory.createPotion(PotionType.POISON),\n            factory.createPotion(PotionType.POISON),\n            factory.createPotion(PotionType.HOLY_WATER),\n            factory.createPotion(PotionType.HOLY_WATER));\n  }\n\n  /**\n   * Get a read-only list of all the items on the top shelf.\n   *\n   * @return The top shelf potions\n   */\n  public final List<Potion> getTopShelf() {\n    return List.copyOf(this.topShelf);\n  }\n\n  /**\n   * Get a read-only list of all the items on the bottom shelf.\n   *\n   * @return The bottom shelf potions\n   */\n  public final List<Potion> getBottomShelf() {\n    return List.copyOf(this.bottomShelf);\n  }\n\n  /** Drink all the potions. */\n  public void drinkPotions() {\n    LOGGER.info(\"Drinking top shelf potions\");\n    topShelf.forEach(Potion::drink);\n    LOGGER.info(\"Drinking bottom shelf potions\");\n    bottomShelf.forEach(Potion::drink);\n  }\n}\n"
  },
  {
    "path": "flyweight/src/main/java/com/iluwatar/flyweight/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flyweight;\n\n/**\n * Flyweight pattern is useful when the program needs a huge amount of objects. It provides means to\n * decrease resource usage by sharing object instances.\n *\n * <p>In this example {@link AlchemistShop} has great amount of potions on its shelves. To fill the\n * shelves {@link AlchemistShop} uses {@link PotionFactory} (which represents the Flyweight in this\n * example). Internally {@link PotionFactory} holds a map of the potions and lazily creates new ones\n * when requested.\n *\n * <p>To enable safe sharing, between clients and threads, Flyweight objects must be immutable.\n * Flyweight objects are by definition value objects.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    // create the alchemist shop with the potions\n    var alchemistShop = new AlchemistShop();\n    // a brave visitor enters the alchemist shop and drinks all the potions\n    alchemistShop.drinkPotions();\n  }\n}\n"
  },
  {
    "path": "flyweight/src/main/java/com/iluwatar/flyweight/HealingPotion.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flyweight;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** HealingPotion. */\n@Slf4j\npublic class HealingPotion implements Potion {\n\n  @Override\n  public void drink() {\n    LOGGER.info(\"You feel healed. (Potion={})\", System.identityHashCode(this));\n  }\n}\n"
  },
  {
    "path": "flyweight/src/main/java/com/iluwatar/flyweight/HolyWaterPotion.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flyweight;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** HolyWaterPotion. */\n@Slf4j\npublic class HolyWaterPotion implements Potion {\n\n  @Override\n  public void drink() {\n    LOGGER.info(\"You feel blessed. (Potion={})\", System.identityHashCode(this));\n  }\n}\n"
  },
  {
    "path": "flyweight/src/main/java/com/iluwatar/flyweight/InvisibilityPotion.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flyweight;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** InvisibilityPotion. */\n@Slf4j\npublic class InvisibilityPotion implements Potion {\n\n  @Override\n  public void drink() {\n    LOGGER.info(\"You become invisible. (Potion={})\", System.identityHashCode(this));\n  }\n}\n"
  },
  {
    "path": "flyweight/src/main/java/com/iluwatar/flyweight/PoisonPotion.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flyweight;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** PoisonPotion. */\n@Slf4j\npublic class PoisonPotion implements Potion {\n\n  @Override\n  public void drink() {\n    LOGGER.info(\"Urgh! This is poisonous. (Potion={})\", System.identityHashCode(this));\n  }\n}\n"
  },
  {
    "path": "flyweight/src/main/java/com/iluwatar/flyweight/Potion.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flyweight;\n\n/** Interface for Potions. */\npublic interface Potion {\n\n  void drink();\n}\n"
  },
  {
    "path": "flyweight/src/main/java/com/iluwatar/flyweight/PotionFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flyweight;\n\nimport java.util.EnumMap;\nimport java.util.Map;\n\n/**\n * PotionFactory is the Flyweight in this example. It minimizes memory use by sharing object\n * instances. It holds a map of potion instances and new potions are created only when none of the\n * type already exists.\n */\npublic class PotionFactory {\n\n  private final Map<PotionType, Potion> potions;\n\n  public PotionFactory() {\n    potions = new EnumMap<>(PotionType.class);\n  }\n\n  Potion createPotion(PotionType type) {\n    var potion = potions.get(type);\n    if (potion == null) {\n      switch (type) {\n        case HEALING -> potion = new HealingPotion();\n        case HOLY_WATER -> potion = new HolyWaterPotion();\n        case INVISIBILITY -> potion = new InvisibilityPotion();\n        case POISON -> potion = new PoisonPotion();\n        case STRENGTH -> potion = new StrengthPotion();\n        default -> {}\n      }\n      if (potion != null) {\n        potions.put(type, potion);\n      }\n    }\n    return potion;\n  }\n}\n"
  },
  {
    "path": "flyweight/src/main/java/com/iluwatar/flyweight/PotionType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flyweight;\n\n/** Enumeration for potion types. */\npublic enum PotionType {\n  HEALING,\n  INVISIBILITY,\n  STRENGTH,\n  HOLY_WATER,\n  POISON\n}\n"
  },
  {
    "path": "flyweight/src/main/java/com/iluwatar/flyweight/StrengthPotion.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flyweight;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** StrengthPotion. */\n@Slf4j\npublic class StrengthPotion implements Potion {\n\n  @Override\n  public void drink() {\n    LOGGER.info(\"You feel strong. (Potion={})\", System.identityHashCode(this));\n  }\n}\n"
  },
  {
    "path": "flyweight/src/test/java/com/iluwatar/flyweight/AlchemistShopTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flyweight;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport org.junit.jupiter.api.Test;\n\n/** AlchemistShopTest */\nclass AlchemistShopTest {\n\n  @Test\n  void testShop() {\n    final var shop = new AlchemistShop();\n\n    final var bottomShelf = shop.getBottomShelf();\n    assertNotNull(bottomShelf);\n    assertEquals(5, bottomShelf.size());\n\n    final var topShelf = shop.getTopShelf();\n    assertNotNull(topShelf);\n    assertEquals(8, topShelf.size());\n\n    final var allPotions = new ArrayList<Potion>();\n    allPotions.addAll(topShelf);\n    allPotions.addAll(bottomShelf);\n\n    // There are 13 potion instances, but only 5 unique instance types\n    assertEquals(13, allPotions.size());\n    assertEquals(5, new HashSet<>(allPotions).size());\n  }\n}\n"
  },
  {
    "path": "flyweight/src/test/java/com/iluwatar/flyweight/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.flyweight;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "front-controller/README.md",
    "content": "---\ntitle: \"Front Controller Pattern in Java: Centralizing Web Request Handling\"\nshortTitle: Front Controller\ndescription: \"Explore the Front Controller design pattern in Java for centralized request handling. Learn how to improve web application efficiency and consistency with this architectural pattern.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - Architecture\n  - Decoupling\n  - Enterprise patterns\n  - Layered architecture\n  - Web development\n---\n\n## Also known as\n\n* Centralized Request Handling\n\n## Intent of Front Controller Design Pattern\n\nThe Front Controller design pattern aims to provide a centralized entry point for handling all incoming web requests. This pattern ensures consistent and efficient request routing and management across a Java web application.\n\n## Detailed Explanation of Front Controller Pattern with Real-World Examples\n\nReal-world example\n\n> In a real-world scenario, a front desk in a hotel serves as the centralized request handling point, similar to how the Front Controller design pattern functions in web application architecture. This desk acts as the \"front controller\" of the hotel, responsible for receiving all inquiries, from room service orders to maintenance requests. The receptionist assesses each request and routes it to the appropriate department—housekeeping, the kitchen, or maintenance. This system centralizes request handling, ensuring that guest needs are addressed efficiently and consistently, similar to how a Front Controller in a software application manages all incoming requests and delegates them to specific handlers.\n\nIn plain words\n\n> The Front Controller design pattern centralizes incoming web requests into a single handling point, allowing consistent processing and delegation across an application.\n\nWikipedia says\n\n> The front controller software design pattern is listed in several pattern catalogs and is related to the design of web applications. It is \"a controller that handles all requests for a website\", which is a useful structure for web application developers to achieve flexibility and reuse without code redundancy.\n\nArchitecture diagram\n\n![Front Controller Architecture Diagram](./etc/front-controller-architecture-diagram.png)\n\n## Programmatic Example of Front Controller Pattern in Java\n\nThe Front Controller design pattern is a pattern that provides a centralized entry point for handling all requests in a web application. It ensures that request handling is managed consistently and efficiently across an application.\n\nIn the provided code, we can see an example of the Front Controller pattern in the `App`, `FrontController` and `Dispatcher` classes.\n\nThe `App` class is the entry point of the application. It creates an instance of `FrontController` and uses it to handle various requests.\n\n```java\npublic class App {\n\n  public static void main(String[] args) {\n    var controller = new FrontController();\n    controller.handleRequest(\"Archer\");\n    controller.handleRequest(\"Catapult\");\n    controller.handleRequest(\"foobar\");\n  }\n}\n```\n\nThe `FrontController` class is the front controller in this example. It handles all requests and delegates them to the `Dispatcher`.\n\n```java\npublic class FrontController {\n\n    private final Dispatcher dispatcher;\n\n    public FrontController() {\n        this.dispatcher = new Dispatcher();\n    }\n\n    public void handleRequest(String request) {\n        dispatcher.dispatch(request);\n    }\n}\n```\n\nThe `Dispatcher` class is responsible for handling the dispatching of requests to the appropriate command. It retrieves the corresponding command based on the request and invokes the command's process method to handle the business logic.\n\n```java\npublic class Dispatcher {\n    \n  public void dispatch(String request) {\n    var command = getCommand(request);\n    command.process();\n  }\n\n  Command getCommand(String request) {\n    var commandClass = getCommandClass(request);\n    try {\n      return (Command) commandClass.getDeclaredConstructor().newInstance();\n    } catch (Exception e) {\n      throw new ApplicationException(e);\n    }\n  }\n\n  static Class<?> getCommandClass(String request) {\n    try {\n      return Class.forName(\"com.iluwatar.front.controller.\" + request + \"Command\");\n    } catch (ClassNotFoundException e) {\n      return UnknownCommand.class;\n    }\n  }\n}\n```\n\nIn this example, when a request is received, the `FrontController` delegates the request to the `Dispatcher`, which creates a command object based on the request and calls its `process` method. The command object is responsible for handling the request and rendering the appropriate view.\n\nThis is a basic example of the Front Controller pattern, where all requests are handled by a single controller and dispatcher, ensuring consistent and efficient request handling.\n\n## When to Use the Front Controller Pattern in Java\n\n* The Front Controller design pattern is particularly useful for Java web applications that require a centralized mechanism for request handling.\n* Systems that need a common processing point for all requests to perform tasks such as authentication, logging, and routing.\n\n## Real-World Applications of Front Controller Pattern in Java\n\n* [Apache Struts](https://struts.apache.org/)\n* Java web frameworks like Spring MVC and JavaServer Faces (JSF) implement the Front Controller pattern through their central dispatcher servlet, which manages web requests and delegates responsibilities.\n\n## Benefits and Trade-offs of Front Controller Pattern\n\nBenefits:\n\n* The main benefit of the Front Controller design pattern is the centralization of request handling, which simplifies maintenance and ensures consistent behavior across the application.\n* Eases the integration of services like security and user session management.\n* Facilitates common behavior like routing, logging, and authentication across requests.\n\nTrade-offs:\n\n* Can become a bottleneck if not properly managed.\n* Increases complexity in the dispatcher controller, requiring careful design to avoid tight coupling.\n\n## Related Java Design Patterns\n\n* [Page Controller](https://java-design-patterns.com/patterns/page-controller/): Front Controller can delegate requests to Page Controllers, which handle specific page requests. This division supports the Single Responsibility Principle.\n* [Model-View-Controller (MVC)](https://java-design-patterns.com/patterns/model-view-controller/): Front Controller acts as the controller, managing the flow between model and view.\n* [Command](https://java-design-patterns.com/patterns/command/): Can be used to encapsulate a request as an object, which the Front Controller can manipulate and delegate.\n\n## References and Credits\n\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "front-controller/etc/front-controller.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.front.controller.ArcherCommand\" project=\"front-controller\" \n    file=\"/front-controller/src/main/java/com/iluwatar/front/controller/ArcherCommand.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"748\" y=\"378\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.front.controller.CatapultView\" project=\"front-controller\" \n    file=\"/front-controller/src/main/java/com/iluwatar/front/controller/CatapultView.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"545\" y=\"201\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.front.controller.ArcherView\" project=\"front-controller\" \n    file=\"/front-controller/src/main/java/com/iluwatar/front/controller/ArcherView.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"748\" y=\"201\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.front.controller.UnknownCommand\" project=\"front-controller\" \n    file=\"/front-controller/src/main/java/com/iluwatar/front/controller/UnknownCommand.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"365\" y=\"378\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.front.controller.CatapultCommand\" project=\"front-controller\" \n    file=\"/front-controller/src/main/java/com/iluwatar/front/controller/CatapultCommand.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"544\" y=\"378\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"6\" language=\"java\" name=\"com.iluwatar.front.controller.Command\" project=\"front-controller\" \n    file=\"/front-controller/src/main/java/com/iluwatar/front/controller/Command.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"545\" y=\"551\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.front.controller.FrontController\" project=\"front-controller\" \n    file=\"/front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"137\" y=\"378\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"8\" language=\"java\" name=\"com.iluwatar.front.controller.View\" project=\"front-controller\" \n    file=\"/front-controller/src/main/java/com/iluwatar/front/controller/View.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"545\" y=\"66\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"9\" language=\"java\" name=\"com.iluwatar.front.controller.ErrorView\" project=\"front-controller\" \n    file=\"/front-controller/src/main/java/com/iluwatar/front/controller/ErrorView.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"365\" y=\"201\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <dependency id=\"10\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </dependency>  \n  <realization id=\"11\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </realization>  \n  <realization id=\"12\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </realization>  \n  <realization id=\"13\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </realization>  \n  <realization id=\"14\">    \n    <end type=\"SOURCE\" refId=\"9\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </realization>  \n  <dependency id=\"15\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </dependency>  \n  <realization id=\"16\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </realization>  \n  <dependency id=\"17\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"9\"/>  \n  </dependency>  \n  <dependency id=\"18\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </dependency>  \n  <dependency id=\"19\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </dependency>  \n  <realization id=\"20\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "front-controller/etc/front-controller.urm.puml",
    "content": "@startuml\npackage com.iluwatar.front.controller {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class ArcherCommand {\n    + ArcherCommand()\n    + process()\n  }\n  class ArcherView {\n    - LOGGER : Logger {static}\n    + ArcherView()\n    + display()\n  }\n  class CatapultCommand {\n    + CatapultCommand()\n    + process()\n  }\n  class CatapultView {\n    - LOGGER : Logger {static}\n    + CatapultView()\n    + display()\n  }\n  interface Command {\n    + process() {abstract}\n  }\n  class ErrorView {\n    - LOGGER : Logger {static}\n    + ErrorView()\n    + display()\n  }\n  class FrontController {\n    + FrontController()\n    - getCommand(request : String) : Command\n    - getCommandClass(request : String) : Class<?> {static}\n    + handleRequest(request : String)\n  }\n  class UnknownCommand {\n    + UnknownCommand()\n    + process()\n  }\n  interface View {\n    + display() {abstract}\n  }\n}\nArcherCommand ..|> Command \nArcherView ..|> View \nCatapultCommand ..|> Command \nCatapultView ..|> View \nErrorView ..|> View \nUnknownCommand ..|> Command \n@enduml"
  },
  {
    "path": "front-controller/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>front-controller</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-params</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.front.controller.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "front-controller/src/main/java/com/iluwatar/front/controller/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\n/**\n * The Front Controller is a presentation tier pattern. Essentially, it defines a controller that\n * handles all requests for a website.\n *\n * <p>The Front Controller pattern consolidates request handling through a single handler object (\n * {@link FrontController}). This object can carry out common behavior such as authorization,\n * request logging and routing requests to corresponding views.\n *\n * <p>Typically, the requests are mapped to command objects ({@link Command}) which then display the\n * correct view ({@link View}).\n *\n * <p>In this example we have implemented two views: {@link ArcherView} and {@link CatapultView}.\n * These are displayed by sending correct request to the {@link FrontController} object. For\n * example, the {@link ArcherView} gets displayed when {@link FrontController} receives request\n * \"Archer\". When the request is unknown, we display the error view ({@link ErrorView}).\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var controller = new FrontController();\n    controller.handleRequest(\"Archer\");\n    controller.handleRequest(\"Catapult\");\n    controller.handleRequest(\"foobar\");\n  }\n}\n"
  },
  {
    "path": "front-controller/src/main/java/com/iluwatar/front/controller/ApplicationException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\nimport java.io.Serial;\n\n/** Custom exception type. */\npublic class ApplicationException extends RuntimeException {\n\n  @Serial private static final long serialVersionUID = 1L;\n\n  public ApplicationException(Throwable cause) {\n    super(cause);\n  }\n}\n"
  },
  {
    "path": "front-controller/src/main/java/com/iluwatar/front/controller/ArcherCommand.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\n/** Command for archers. */\npublic class ArcherCommand implements Command {\n\n  @Override\n  public void process() {\n    new ArcherView().display();\n  }\n}\n"
  },
  {
    "path": "front-controller/src/main/java/com/iluwatar/front/controller/ArcherView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** View for archers. */\n@Slf4j\npublic class ArcherView implements View {\n\n  @Override\n  public void display() {\n    LOGGER.info(\"Displaying archers\");\n  }\n}\n"
  },
  {
    "path": "front-controller/src/main/java/com/iluwatar/front/controller/CatapultCommand.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\n/** Command for catapults. */\npublic class CatapultCommand implements Command {\n\n  @Override\n  public void process() {\n    new CatapultView().display();\n  }\n}\n"
  },
  {
    "path": "front-controller/src/main/java/com/iluwatar/front/controller/CatapultView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** View for catapults. */\n@Slf4j\npublic class CatapultView implements View {\n\n  @Override\n  public void display() {\n    LOGGER.info(\"Displaying catapults\");\n  }\n}\n"
  },
  {
    "path": "front-controller/src/main/java/com/iluwatar/front/controller/Command.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\n/** Commands are the intermediary between requests and views. */\npublic interface Command {\n\n  void process();\n}\n"
  },
  {
    "path": "front-controller/src/main/java/com/iluwatar/front/controller/Dispatcher.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\n/**\n * The Dispatcher class is responsible for handling the dispatching of requests to the appropriate\n * command. It retrieves the corresponding command based on the request and invokes the command's\n * process method to handle the business logic.\n */\npublic class Dispatcher {\n\n  /**\n   * Dispatches the request to the appropriate command.\n   *\n   * @param request the request to be handled\n   */\n  public void dispatch(String request) {\n    var command = getCommand(request);\n    command.process();\n  }\n\n  /**\n   * Retrieves the appropriate command instance for the given request.\n   *\n   * @param request the request to be handled\n   * @return the command instance corresponding to the request\n   */\n  Command getCommand(String request) {\n    var commandClass = getCommandClass(request);\n    try {\n      return (Command) commandClass.getDeclaredConstructor().newInstance();\n    } catch (Exception e) {\n      throw new ApplicationException(e);\n    }\n  }\n\n  /**\n   * Retrieves the Class object for the command corresponding to the given request.\n   *\n   * @param request the request to be handled\n   * @return the Class object of the command corresponding to the request\n   */\n  static Class<?> getCommandClass(String request) {\n    try {\n      return Class.forName(\"com.iluwatar.front.controller.\" + request + \"Command\");\n    } catch (ClassNotFoundException e) {\n      return UnknownCommand.class;\n    }\n  }\n}\n"
  },
  {
    "path": "front-controller/src/main/java/com/iluwatar/front/controller/ErrorView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** View for errors. */\n@Slf4j\npublic class ErrorView implements View {\n\n  @Override\n  public void display() {\n    LOGGER.error(\"Error 500\");\n  }\n}\n"
  },
  {
    "path": "front-controller/src/main/java/com/iluwatar/front/controller/FrontController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\n/**\n * The FrontController is responsible for handling all incoming requests. It delegates the\n * processing of requests to the Dispatcher, which then determines the appropriate command and view\n * to render the correct response.\n */\npublic class FrontController {\n\n  private final Dispatcher dispatcher;\n\n  public FrontController() {\n    this.dispatcher = new Dispatcher();\n  }\n\n  public void handleRequest(String request) {\n    dispatcher.dispatch(request);\n  }\n}\n"
  },
  {
    "path": "front-controller/src/main/java/com/iluwatar/front/controller/UnknownCommand.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\n/** Default command in case the mapping is not successful. */\npublic class UnknownCommand implements Command {\n\n  @Override\n  public void process() {\n    new ErrorView().display();\n  }\n}\n"
  },
  {
    "path": "front-controller/src/main/java/com/iluwatar/front/controller/View.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\n/** Views are the representations rendered for the user. */\npublic interface View {\n\n  void display();\n}\n"
  },
  {
    "path": "front-controller/src/test/java/com/iluwatar/front/controller/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "front-controller/src/test/java/com/iluwatar/front/controller/ApplicationExceptionTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\nimport static org.junit.jupiter.api.Assertions.assertSame;\n\nimport org.junit.jupiter.api.Test;\n\n/** ApplicationExceptionTest */\nclass ApplicationExceptionTest {\n\n  @Test\n  void testCause() {\n    final var cause = new Exception();\n    assertSame(cause, new ApplicationException(cause).getCause());\n  }\n}\n"
  },
  {
    "path": "front-controller/src/test/java/com/iluwatar/front/controller/CommandTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.front.controller.utils.InMemoryAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\n/** CommandTest */\nclass CommandTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  static List<Object[]> dataProvider() {\n    return List.of(\n        new Object[] {\"Archer\", \"Displaying archers\"},\n        new Object[] {\"Catapult\", \"Displaying catapults\"},\n        new Object[] {\"NonExistentCommand\", \"Error 500\"});\n  }\n\n  /**\n   * @param request The request that's been tested\n   * @param displayMessage The expected display message\n   */\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testDisplay(String request, String displayMessage) {\n    final var frontController = new FrontController();\n    assertEquals(0, appender.getLogSize());\n    frontController.handleRequest(request);\n    assertEquals(displayMessage, appender.getLastMessage());\n    assertEquals(1, appender.getLogSize());\n  }\n}\n"
  },
  {
    "path": "front-controller/src/test/java/com/iluwatar/front/controller/DispatcherTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\nimport static org.junit.jupiter.api.Assertions.*;\nimport static org.mockito.Mockito.*;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass DispatcherTest {\n\n  private Dispatcher dispatcher;\n\n  @BeforeEach\n  public void setUp() {\n    dispatcher = new Dispatcher();\n  }\n\n  @Test\n  void testDispatchKnownCommand() {\n    Command mockCommand = mock(ArcherCommand.class);\n    dispatcher = spy(dispatcher);\n    doReturn(mockCommand).when(dispatcher).getCommand(\"Archer\");\n\n    dispatcher.dispatch(\"Archer\");\n\n    verify(mockCommand, times(1)).process();\n  }\n\n  @Test\n  void testDispatchUnknownCommand() {\n    Command mockCommand = mock(UnknownCommand.class);\n    dispatcher = spy(dispatcher);\n    doReturn(mockCommand).when(dispatcher).getCommand(\"Unknown\");\n\n    dispatcher.dispatch(\"Unknown\");\n\n    verify(mockCommand, times(1)).process();\n  }\n\n  @Test\n  void testGetCommandKnown() {\n    Command command = dispatcher.getCommand(\"Archer\");\n    assertNotNull(command);\n    assertTrue(command instanceof ArcherCommand);\n  }\n\n  @Test\n  void testGetCommandUnknown() {\n    Command command = dispatcher.getCommand(\"Unknown\");\n    assertNotNull(command);\n    assertTrue(command instanceof UnknownCommand);\n  }\n\n  @Test\n  void testGetCommandClassKnown() {\n    Class<?> commandClass = Dispatcher.getCommandClass(\"Archer\");\n    assertNotNull(commandClass);\n    assertEquals(ArcherCommand.class, commandClass);\n  }\n\n  @Test\n  void testGetCommandClassUnknown() {\n    Class<?> commandClass = Dispatcher.getCommandClass(\"Unknown\");\n    assertNotNull(commandClass);\n    assertEquals(UnknownCommand.class, commandClass);\n  }\n}\n"
  },
  {
    "path": "front-controller/src/test/java/com/iluwatar/front/controller/FrontControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.front.controller.utils.InMemoryAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\n/** FrontControllerTest */\nclass FrontControllerTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  static List<Object[]> dataProvider() {\n    return List.of(\n        new Object[] {new ArcherCommand(), \"Displaying archers\"},\n        new Object[] {new CatapultCommand(), \"Displaying catapults\"},\n        new Object[] {new UnknownCommand(), \"Error 500\"});\n  }\n\n  /**\n   * @param command The command that's been tested\n   * @param displayMessage The expected display message\n   */\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testDisplay(Command command, String displayMessage) {\n    assertEquals(0, appender.getLogSize());\n    command.process();\n    assertEquals(displayMessage, appender.getLastMessage());\n    assertEquals(1, appender.getLogSize());\n  }\n}\n"
  },
  {
    "path": "front-controller/src/test/java/com/iluwatar/front/controller/ViewTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.front.controller.utils.InMemoryAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\n/** ViewTest */\nclass ViewTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  static List<Object[]> dataProvider() {\n    return List.of(\n        new Object[] {new ArcherView(), \"Displaying archers\"},\n        new Object[] {new CatapultView(), \"Displaying catapults\"},\n        new Object[] {new ErrorView(), \"Error 500\"});\n  }\n\n  /**\n   * @param view The view that's been tested\n   * @param displayMessage The expected display message\n   */\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testDisplay(View view, String displayMessage) {\n    assertEquals(0, appender.getLogSize());\n    view.display();\n    assertEquals(displayMessage, appender.getLastMessage());\n    assertEquals(1, appender.getLogSize());\n  }\n}\n"
  },
  {
    "path": "front-controller/src/test/java/com/iluwatar/front/controller/utils/InMemoryAppender.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.front.controller.utils;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.slf4j.LoggerFactory;\n\n/** InMemory Log Appender Util. */\npublic class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n\n  private final List<ILoggingEvent> log = new LinkedList<>();\n\n  public InMemoryAppender() {\n    ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n    start();\n  }\n\n  @Override\n  protected void append(ILoggingEvent eventObject) {\n    log.add(eventObject);\n  }\n\n  public String getLastMessage() {\n    return log.get(log.size() - 1).getFormattedMessage();\n  }\n\n  public int getLogSize() {\n    return log.size();\n  }\n}\n"
  },
  {
    "path": "function-composition/.gitignore",
    "content": "################## Eclipse ######################\ntarget\n.metadata\n.settings\n.classpath\n.project\n*.class\ntmp/\n*.tmp\n*.bak\n*~.nib\nlocal.properties\n.loadpath\n.recommenders\n.DS_Store\n\n#######  Java annotation processor (APT) ########\n.factorypath\n\n################ Package Files ##################\n*.jar\n*.war\n*.ear\n*.swp\ndatanucleus.log\n/bin/\n*.log\nevent-sourcing/Journal.json\n\n################## Checkstyle ###################\n.checkstyle\n\n##################### STS #######################\n.apt_generated\n.springBeans\n.sts4-cache\n\n################# IntelliJ IDEA #################\n.idea\n*.iws\n*.iml\n*.ipr\n\n################### NetBeans ####################\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\nbuild/\n!**/src/main/**/build/\n!**/src/test/**/build/\n\n#################### VS Code ####################\n.vscode/\n\n#################### Java Design Patterns #######\netc/Java Design Patterns.urm.puml\nserialized-entity/output.txt\n"
  },
  {
    "path": "function-composition/README.md",
    "content": "---\ntitle: \"Function Composition Pattern in Java: Crafting Elegant Functional Pipelines\"\nshortTitle: Function Composition\ndescription: \"Learn about the Function Composition design pattern in Java. Discover how to create complex functions by combining simpler ones, enhancing code modularity and reusability. Explore real-world examples, benefits, and applications.\"\ncategory: Functional\nlanguage: en\ntag:\n  - Code simplification\n  - Composition\n  - Functional decomposition\n  - Reusability\n---\n\n## Also known as\n\n* Function Chaining\n* Higher-Order Function Wrapping\n\n## Intent of Function Composition Design Pattern\n\nCombine multiple small functions into a single operation that executes them in a sequence, producing a new function as the result.\n\n## Detailed Explanation of Function Composition Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a fast-food restaurant where the process of making a burger is broken down into several steps: grilling the patty, toasting the bun, adding condiments, and assembling the burger. Each of these steps can be seen as a function.\n>\n> In the Functional Composition design pattern, these individual steps (functions) can be composed into a complete burger-making process. Each step remains simple and reusable. For instance, the grilling function could be reused for making sandwiches or other dishes that require a grilled patty. This modular approach allows the restaurant to efficiently create various menu items by reusing and combining simple, predefined steps.\n\nIn plain words\n\n> The Function Composition pattern allows building complex functions by combining simpler ones, making it easier to manage, test, and reuse individual pieces of functionality.\n\nWikipedia says\n\n> Function composition is an act or mechanism to combine simple functions to build more complicated ones. Like the usual composition of functions in mathematics, the result of each function is passed as the argument of the next, and the result of the last one is the result of the whole.\n\nSequence diagram\n\n![Function Composition sequence diagram](./etc/function-composition-sequence-diagram.png)\n\n## Programmatic Example of Function Composition Pattern in Java\n\nIn the functional programming paradigm, function composition is a powerful technique. For instance, in Java, you can use higher-order functions to combine operations like multiplying and squaring numbers.\n\nUsing Java's functional interfaces, we can define simple functions and compose them. Here's how function composition works in Java.\n\nLet's start with defining two simple functions. In this case, we have a function `timesTwo` that multiplies its input by 2, and a function `square` that squares its input:\n\n```java\nFunction<Integer, Integer> timesTwo = x -> x * 2;\nFunction<Integer, Integer> square = x -> x * x;\n```\n\nNext, we use the `FunctionComposer` class to compose these two functions into a new function. The `composeFunctions` method takes two functions as arguments and returns a new function that is the composition of the input functions:\n\n```java\nFunction<Integer, Integer> composedFunction = FunctionComposer.composeFunctions(timesTwo, square);\n```\n\nFinally, we apply the composed function to an input value. In this case, we apply it to the number 3. The result is the square of the number 3 multiplied by 2, which is 36:\n\n```java\npublic static void main(String[] args) {\n    final var logger = LoggerFactory.getLogger(App.class);\n    Function<Integer, Integer> timesTwo = x -> x * 2;\n    Function<Integer, Integer> square = x -> x * x;\n\n    Function<Integer, Integer> composedFunction = FunctionComposer.composeFunctions(timesTwo, square);\n\n    int result = composedFunction.apply(3);\n    logger.info(\"Result of composing 'timesTwo' and 'square' functions applied to 3 is: \" + result);\n}\n```\n\nThis will output:\n\n```\nResult of composing 'timesTwo' and 'square' functions applied to 3 is: 36\n```\n\nThis example demonstrates how the Function Composition pattern can be used to create complex functions by composing simpler ones, enhancing modularity and reusability of function-based logic.\n\n## When to Use the Function Composition Pattern in Java\n\nUse the Function Composition pattern when:\n\n* When you want to build complex transformations by chaining smaller, reusable functions in Java.\n* When the logic is best expressed through a series of operations that naturally feed one into another.\n* When you want to reduce code duplication and improve readability by isolating each operation in its own function.\n\n## Function Composition Pattern Java Tutorials\n\n* [Function Composition in Java (Medium)](https://functionalprogramming.medium.com/function-composition-in-java-beaf39426f52)\n* [Functional Programming in Java (Baeldung)](https://www.baeldung.com/java-functional-programming)\n\n## Real-World Applications of Function Composition Pattern in Java\n\n* Java’s Stream API, where map and filter are composed for data transformations.\n* Google Guava’s Function utilities.\n* Apache Commons libraries that provide utilities for chaining functions.\n\n## Benefits and Trade-offs of Function Composition Pattern\n\nBenefits:\n\n* Encourages highly modular and reusable code.\n* Simplifies complex logic by breaking it down into smaller, testable units.\n* Makes the code more expressive and easier to maintain.\n\nTrade-offs:\n\n* Excessive chaining can reduce readability if taken too far.\n* May introduce performance overhead due to multiple function calls.\n* Errors can be harder to trace in a deeply composed function pipeline.\n\n## Related Java Design Patterns\n\n* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/) - Both patterns allow processing to be broken down into a series of steps, but Functional Composition focuses on function composition rather than responsibility delegation.\n* [Composite](https://java-design-patterns.com/patterns/composite/): Also deals with combining smaller components, though it is typically about object structure rather than function operations.\n\n## References and Credits\n\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Functional Programming in Java](https://amzn.to/3JUIc5Q)\n* [Java 8 in Action: Lambdas, Streams, and functional-style programming](https://amzn.to/3QCmGXs)\n"
  },
  {
    "path": "function-composition/etc/function-composition.urm.puml",
    "content": "@startuml\npackage com.iluwatar.function.composition {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class FunctionComposer {\n    + FunctionComposer()\n    + composeFunctions(f1 : Function<Integer, Integer>, f2 : Function<Integer, Integer>) : Function<Integer, Integer> {static}\n  }\n}\n@enduml"
  },
  {
    "path": "function-composition/etc/function.composition.urm.puml",
    "content": "@startuml\nskinparam monochrome true\n\nparticipant \"App\" as App\nparticipant \"FunctionComposer\" as Composer\nparticipant \"Function<Integer, Integer>\" as F1\n\ncreate F1\nApp -> F1 : func1 = x -> x * 2\ncreate F1\nApp -> F1 : func2 = x -> x * x\n\nApp -> Composer : func1, func2\nactivate Composer\nComposer -> F1 : func1.andThen(func2)\ndeactivate Composer\nactivate F1\nF1 -> App : composedFunction\ndeactivate F1\n\n@enduml"
  },
  {
    "path": "function-composition/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>function-composition</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>"
  },
  {
    "path": "function-composition/src/main/java/com/iluwatar/function/composition/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.function.composition;\n\nimport java.util.function.Function;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Main application class to demonstrate the use of function composition. */\n@Slf4j\npublic class App {\n\n  /**\n   * Main method to demonstrate function composition using FunctionComposer.\n   *\n   * @param args command line arguments (not used)\n   */\n  public static void main(String[] args) {\n    Function<Integer, Integer> timesTwo = x -> x * 2;\n    Function<Integer, Integer> square = x -> x * x;\n\n    Function<Integer, Integer> composedFunction =\n        FunctionComposer.composeFunctions(timesTwo, square);\n\n    int result = composedFunction.apply(3);\n    LOGGER.info(\"Result of composing 'timesTwo' and 'square' functions applied to 3 is: \" + result);\n  }\n}\n"
  },
  {
    "path": "function-composition/src/main/java/com/iluwatar/function/composition/FunctionComposer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.function.composition;\n\nimport java.util.function.Function;\n\n/**\n * Class for composing functions using the Function Composition pattern. Provides a static method to\n * compose two functions using the 'andThen' method.\n */\npublic class FunctionComposer {\n\n  private FunctionComposer() {}\n\n  /**\n   * Composes two functions where the output of the first function becomes the input of the second\n   * function.\n   *\n   * @param f1 the first function to apply\n   * @param f2 the second function to apply after the first\n   * @return a composed function that applies f1 and then f2\n   */\n  public static Function<Integer, Integer> composeFunctions(\n      Function<Integer, Integer> f1, Function<Integer, Integer> f2) {\n    return f1.andThen(f2);\n  }\n}\n"
  },
  {
    "path": "function-composition/src/test/java/com/iluwatar/function/composition/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.function.composition;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "function-composition/src/test/java/com/iluwatar/function/composition/FunctionComposerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.function.composition;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.function.Function;\nimport org.junit.jupiter.api.Test;\n\n/** Test class for FunctionComposer. */\nclass FunctionComposerTest {\n\n  /** Tests the composition of two functions. */\n  @Test\n  void testComposeFunctions() {\n    Function<Integer, Integer> timesTwo = x -> x * 2;\n    Function<Integer, Integer> square = x -> x * x;\n\n    Function<Integer, Integer> composed = FunctionComposer.composeFunctions(timesTwo, square);\n\n    assertEquals(36, composed.apply(3), \"Expected output of composed functions is 36\");\n  }\n\n  /** Tests function composition with identity function. */\n  @Test\n  void testComposeWithIdentity() {\n    Function<Integer, Integer> identity = Function.identity();\n    Function<Integer, Integer> timesThree = x -> x * 3;\n\n    Function<Integer, Integer> composedLeft =\n        FunctionComposer.composeFunctions(identity, timesThree);\n    Function<Integer, Integer> composedRight =\n        FunctionComposer.composeFunctions(timesThree, identity);\n\n    assertEquals(\n        9, composedLeft.apply(3), \"Composition with identity on the left should be the same\");\n    assertEquals(\n        9, composedRight.apply(3), \"Composition with identity on the right should be the same\");\n  }\n\n  /** Tests function composition resulting in zero. */\n  @Test\n  void testComposeToZero() {\n    Function<Integer, Integer> multiply = x -> x * 10;\n    Function<Integer, Integer> toZero = x -> 0;\n\n    Function<Integer, Integer> composed = FunctionComposer.composeFunctions(multiply, toZero);\n\n    assertEquals(\n        0, composed.apply(5), \"Expected output of function composition leading to zero is 0\");\n  }\n\n  /** Tests the composition with a negative function. */\n  @Test\n  void testComposeNegative() {\n    Function<Integer, Integer> negate = x -> -x;\n    Function<Integer, Integer> square = x -> x * x;\n\n    Function<Integer, Integer> composed = FunctionComposer.composeFunctions(negate, square);\n\n    assertEquals(9, composed.apply(3), \"Expected square of negative number to be positive\");\n  }\n\n  /** Tests the composition of functions that cancel each other out. */\n  @Test\n  void testComposeInverseFunctions() {\n    Function<Integer, Integer> timesTwo = x -> x * 2;\n    Function<Integer, Integer> half = x -> x / 2;\n\n    Function<Integer, Integer> composed = FunctionComposer.composeFunctions(timesTwo, half);\n\n    assertEquals(5, composed.apply(5), \"Expect the functions to cancel each other out\");\n  }\n}\n"
  },
  {
    "path": "game-loop/README.md",
    "content": "---\ntitle: \"Game Loop Pattern in Java: Mastering Smooth Game Mechanics\"\nshortTitle: Game Loop\ndescription: \"Learn about the Game Loop design pattern, its implementation in Java, and how it ensures smooth gameplay by continuously updating game state, processing inputs, and rendering. Ideal for real-time simulations and gaming.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Concurrency\n  - Event-driven\n  - Game programming\n  - Performance\n---\n\n## Also known as\n\n* Game Cycle\n* Main Game Loop\n\n## Intent of Game Loop Design Pattern\n\nThe Game Loop design pattern is essential for creating smooth and interactive gaming experiences by facilitating continuous game execution. Each loop cycle processes input, updates the game state, and renders the game state to the screen, ensuring consistent performance across all hardware setups.\n\n## Detailed Explanation of Game Loop Pattern with Real-World Examples\n\nReal-world example\n\n> A practical analogy of the Game Loop can be seen in an amusement park ride, like a roller coaster. Similar to how the ride operates in a loop, updating its state and ensuring smooth operation, the Game Loop continuously processes inputs and updates the game state for a seamless gaming experience. The roller coaster operates in a continuous loop, where the state of the ride (the position and speed of the coaster) is continuously updated while the ride is running. The control system of the roller coaster ensures that the cars move smoothly along the track, adjusting speeds, and handling the ride's safety systems in real-time. Just like the game loop, this control system repeatedly processes inputs (such as the current speed and position), updates the state, and triggers outputs (like adjusting the brakes or accelerating the cars) to maintain the desired operation throughout the duration of the ride.\n\nIn plain words\n\n> Game Loop pattern ensures that game time progresses in equal speed in all different hardware setups. \n\nWikipedia says\n\n> The central component of any game, from a programming standpoint, is the game loop. The game loop allows the game to run smoothly regardless of a user's input, or lack thereof.\n\nFlowchart\n\n![Game Loop flowchart](./etc/game-loop-flowchart.png)\n\n## Programmatic Example of Game Loop Pattern in Java\n\nIn our Java example, we illustrate a simple game loop controlling a bullet's movement, updating its position, ensuring smooth rendering, and responding to user inputs. The Game Loop is the main process driving all game rendering threads, present in all modern games. It handles input processing, internal status updates, rendering, AI, and other processes. Starting with a simple `Bullet` class, we demonstrate the movement of bullets in our game, focusing on their 1-dimensional position for demonstration purposes.\n\n```java\npublic class Bullet {\n\n  private float position;\n\n  public Bullet() {\n    position = 0.0f;\n  }\n\n  public float getPosition() {\n    return position;\n  }\n\n  public void setPosition(float position) {\n    this.position = position;\n  }\n}\n```\n\n`GameController` is responsible for moving objects in the game, including the aforementioned bullet.\n\n```java\npublic class GameController {\n\n  protected final Bullet bullet;\n\n  public GameController() {\n    bullet = new Bullet();\n  }\n\n  public void moveBullet(float offset) {\n    var currentPosition = bullet.getPosition();\n    bullet.setPosition(currentPosition + offset);\n  }\n\n  public float getBulletPosition() {\n    return bullet.getPosition();\n  }\n}\n```\n\nNow we introduce the game loop. Actually, in this demo we have 3 different game loops. Let's see the base class `GameLoop` first.\n\n```java\npublic enum GameStatus {\n\n  RUNNING, STOPPED\n}\n\npublic abstract class GameLoop {\n\n  protected final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n  protected volatile GameStatus status;\n\n  protected GameController controller;\n\n  private Thread gameThread;\n\n  public GameLoop() {\n    controller = new GameController();\n    status = GameStatus.STOPPED;\n  }\n\n  public void run() {\n    status = GameStatus.RUNNING;\n    gameThread = new Thread(this::processGameLoop);\n    gameThread.start();\n  }\n\n  public void stop() {\n    status = GameStatus.STOPPED;\n  }\n\n  public boolean isGameRunning() {\n    return status == GameStatus.RUNNING;\n  }\n\n  protected void processInput() {\n    try {\n      var lag = new Random().nextInt(200) + 50;\n      Thread.sleep(lag);\n    } catch (InterruptedException e) {\n      logger.error(e.getMessage());\n    }\n  }\n\n  protected void render() {\n    var position = controller.getBulletPosition();\n    logger.info(\"Current bullet position: \" + position);\n  }\n\n  protected abstract void processGameLoop();\n}\n```\n\nHere's the first game loop implementation, `FrameBasedGameLoop`:\n\n```java\npublic class FrameBasedGameLoop extends GameLoop {\n\n  @Override\n  protected void processGameLoop() {\n    while (isGameRunning()) {\n      processInput();\n      update();\n      render();\n    }\n  }\n\n  protected void update() {\n    controller.moveBullet(0.5f);\n  }\n}\n```\n\nHere's the second game loop implementation, `FixedStepGameLoop`:\n\n```java\npublic class FixedStepGameLoop extends GameLoop {\n\n  /**\n   * 20 ms per frame = 50 FPS.\n   */\n  private static final long MS_PER_FRAME = 20;\n\n  @Override\n  protected void processGameLoop() {\n    var previousTime = System.currentTimeMillis();\n    var lag = 0L;\n    while (isGameRunning()) {\n      var currentTime = System.currentTimeMillis();\n      var elapsedTime = currentTime - previousTime;\n      previousTime = currentTime;\n      lag += elapsedTime;\n\n      processInput();\n\n      while (lag >= MS_PER_FRAME) {\n        update();\n        lag -= MS_PER_FRAME;\n      }\n\n      render();\n    }\n  }\n\n  protected void update() {\n    controller.moveBullet(0.5f * MS_PER_FRAME / 1000);\n  }\n}\n```\n\nAnd the third game loop implementation, `VariableStepGameLoop`:\n\n```java\npublic class VariableStepGameLoop extends GameLoop {\n\n  @Override\n  protected void processGameLoop() {\n    var lastFrameTime = System.currentTimeMillis();\n    while (isGameRunning()) {\n      processInput();\n      var currentFrameTime = System.currentTimeMillis();\n      var elapsedTime = currentFrameTime - lastFrameTime;\n      update(elapsedTime);\n      lastFrameTime = currentFrameTime;\n      render();\n    }\n  }\n\n  protected void update(Long elapsedTime) {\n    controller.moveBullet(0.5f * elapsedTime / 1000);\n  }\n\n}\n```\n\nFinally, we show all the game loops in action.\n\n```java\npublic static void main(String[] args) {\n\n    try {\n        LOGGER.info(\"Start frame-based game loop:\");\n        var frameBasedGameLoop = new FrameBasedGameLoop();\n        frameBasedGameLoop.run();\n        Thread.sleep(GAME_LOOP_DURATION_TIME);\n        frameBasedGameLoop.stop();\n        LOGGER.info(\"Stop frame-based game loop.\");\n\n        LOGGER.info(\"Start variable-step game loop:\");\n        var variableStepGameLoop = new VariableStepGameLoop();\n        variableStepGameLoop.run();\n        Thread.sleep(GAME_LOOP_DURATION_TIME);\n        variableStepGameLoop.stop();\n        LOGGER.info(\"Stop variable-step game loop.\");\n\n        LOGGER.info(\"Start fixed-step game loop:\");\n        var fixedStepGameLoop = new FixedStepGameLoop();\n        fixedStepGameLoop.run();\n        Thread.sleep(GAME_LOOP_DURATION_TIME);\n        fixedStepGameLoop.stop();\n        LOGGER.info(\"Stop variable-step game loop.\");\n\n    } catch (InterruptedException e) {\n        LOGGER.error(e.getMessage());\n    }\n}\n```\n\nProgram output:\n\n```java\nStart frame-based game loop:\nCurrent bullet position: 0.5\nCurrent bullet position: 1.0\nCurrent bullet position: 1.5\nCurrent bullet position: 2.0\nCurrent bullet position: 2.5\nCurrent bullet position: 3.0\nCurrent bullet position: 3.5\nCurrent bullet position: 4.0\nCurrent bullet position: 4.5\nCurrent bullet position: 5.0\nCurrent bullet position: 5.5\nCurrent bullet position: 6.0\nStop frame-based game loop.\nStart variable-step game loop:\nCurrent bullet position: 6.5\nCurrent bullet position: 0.038\nCurrent bullet position: 0.084\nCurrent bullet position: 0.145\nCurrent bullet position: 0.1805\nCurrent bullet position: 0.28\nCurrent bullet position: 0.32\nCurrent bullet position: 0.42549998\nCurrent bullet position: 0.52849996\nCurrent bullet position: 0.57799995\nCurrent bullet position: 0.63199997\nCurrent bullet position: 0.672\nCurrent bullet position: 0.778\nCurrent bullet position: 0.848\nCurrent bullet position: 0.8955\nCurrent bullet position: 0.9635\nStop variable-step game loop.\nStart fixed-step game loop:\nCurrent bullet position: 0.0\nCurrent bullet position: 1.086\nCurrent bullet position: 0.059999995\nCurrent bullet position: 0.12999998\nCurrent bullet position: 0.24000004\nCurrent bullet position: 0.33999994\nCurrent bullet position: 0.36999992\nCurrent bullet position: 0.43999985\nCurrent bullet position: 0.5399998\nCurrent bullet position: 0.65999967\nCurrent bullet position: 0.68999964\nCurrent bullet position: 0.7299996\nCurrent bullet position: 0.79999954\nCurrent bullet position: 0.89999944\nCurrent bullet position: 0.98999935\nStop variable-step game loop.\n```\n\n## When to Use the Game Loop Pattern in Java\n\nThe Game Loop pattern is perfect for real-time simulations and gaming where continuous state updates and smooth frame rates are critical.\n\n## Real-World Applications of Game Loop Pattern in Java\n\n* Video games, both 2D and 3D, across various platforms.\n* Real-time simulations that require a steady frame rate for updating logic and rendering.\n\n## Benefits and Trade-offs of Game Loop Pattern\n\nBenefits:\n\n* Ensures the game progresses smoothly and deterministically.\n* Facilitates synchronization between the game state, user input, and screen rendering.\n* Provides a clear structure for the game developers to manage game dynamics and timing.\n\nTrade-offs:\n\n* Can lead to performance issues if the loop is not well-managed, especially in resource-intensive updates or rendering.\n* Difficulty in managing varying frame rates across different hardware.\n\n## Related Java Design Patterns\n\n* [State](https://java-design-patterns.com/patterns/state/): Often used within a game loop to manage different states of the game (e.g., menu, playing, paused). The relationship lies in managing the state-specific behavior and transitions smoothly within the game loop.\n* [Observer](https://java-design-patterns.com/patterns/observer/): Useful in a game loop for event handling, where game entities can subscribe to and react to events (e.g., collision, scoring).\n\n## References and Credits\n\n* [Game Programming Patterns](https://amzn.to/3K96fOn)\n* [Game Engine Architecture, Third Edition](https://amzn.to/3VgB4av)\n* [Real-Time Collision Detection](https://amzn.to/3W9Jj8T)\n* [Game Programming Patterns - Game Loop](http://gameprogrammingpatterns.com/game-loop.html)\n"
  },
  {
    "path": "game-loop/etc/game-loop.urm.puml",
    "content": "@startuml\npackage com.iluwatar.gameloop {\n  class App {\n    - GAME_LOOP_DURATION_TIME : int {static}\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Bullet {\n    - position : float\n    + Bullet()\n    + getPosition() : float\n    + setPosition(position : float)\n  }\n  class FixedStepGameLoop {\n    - MS_PER_FRAME : long {static}\n    + FixedStepGameLoop()\n    # processGameLoop()\n    # update()\n  }\n  class FrameBasedGameLoop {\n    + FrameBasedGameLoop()\n    # processGameLoop()\n    # update()\n  }\n  class GameController {\n    # bullet : Bullet\n    + GameController()\n    + getBulletPosition() : float\n    + moveBullet(offset : float)\n  }\n  abstract class GameLoop {\n    # controller : GameController\n    - gameThread : Thread\n    # logger : Logger\n    # status : GameStatus\n    + GameLoop()\n    + isGameRunning() : boolean\n    # processGameLoop() {abstract}\n    # processInput()\n    # render()\n    + run()\n    + stop()\n  }\n  enum GameStatus {\n    + RUNNING {static}\n    + STOPPED {static}\n    + valueOf(name : String) : GameStatus {static}\n    + values() : GameStatus[] {static}\n  }\n  class VariableStepGameLoop {\n    + VariableStepGameLoop()\n    # processGameLoop()\n    # update(elapsedTime : Long)\n  }\n}\nGameLoop -->  \"-status\" GameStatus\nGameController -->  \"-bullet\" Bullet\nGameLoop -->  \"-controller\" GameController\nFixedStepGameLoop --|> GameLoop \nFrameBasedGameLoop --|> GameLoop \nVariableStepGameLoop --|> GameLoop \n@enduml"
  },
  {
    "path": "game-loop/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>game-loop</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.gameloop.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "game-loop/src/main/java/com/iluwatar/gameloop/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * A game loop runs continuously during gameplay. Each turn of the loop, it processes user input\n * without blocking, updates the game state, and renders the game. It tracks the passage of time to\n * control the rate of gameplay.\n */\n@Slf4j\npublic class App {\n\n  /** Each type of game loop will run for 2 seconds. */\n  private static final int GAME_LOOP_DURATION_TIME = 2000;\n\n  /**\n   * Program entry point.\n   *\n   * @param args runtime arguments\n   */\n  public static void main(String[] args) {\n\n    try {\n      LOGGER.info(\"Start frame-based game loop:\");\n      var frameBasedGameLoop = new FrameBasedGameLoop();\n      frameBasedGameLoop.run();\n      Thread.sleep(GAME_LOOP_DURATION_TIME);\n      frameBasedGameLoop.stop();\n      LOGGER.info(\"Stop frame-based game loop.\");\n\n      LOGGER.info(\"Start variable-step game loop:\");\n      var variableStepGameLoop = new VariableStepGameLoop();\n      variableStepGameLoop.run();\n      Thread.sleep(GAME_LOOP_DURATION_TIME);\n      variableStepGameLoop.stop();\n      LOGGER.info(\"Stop variable-step game loop.\");\n\n      LOGGER.info(\"Start fixed-step game loop:\");\n      var fixedStepGameLoop = new FixedStepGameLoop();\n      fixedStepGameLoop.run();\n      Thread.sleep(GAME_LOOP_DURATION_TIME);\n      fixedStepGameLoop.stop();\n      LOGGER.info(\"Stop variable-step game loop.\");\n\n    } catch (InterruptedException e) {\n      LOGGER.error(e.getMessage());\n    }\n  }\n}\n"
  },
  {
    "path": "game-loop/src/main/java/com/iluwatar/gameloop/Bullet.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Bullet object class. */\npublic class Bullet {\n\n  @Getter @Setter private float position;\n\n  public Bullet() {\n    position = 0.0f;\n  }\n}\n"
  },
  {
    "path": "game-loop/src/main/java/com/iluwatar/gameloop/FixedStepGameLoop.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\n/**\n * For fixed-step game loop, a certain amount of real time has elapsed since the last turn of the\n * game loop. This is how much game time need to be simulated for the game’s “now” to catch up with\n * the player’s.\n */\npublic class FixedStepGameLoop extends GameLoop {\n\n  /** 20 ms per frame = 50 FPS. */\n  private static final long MS_PER_FRAME = 20;\n\n  @Override\n  protected void processGameLoop() {\n    var previousTime = System.currentTimeMillis();\n    var lag = 0L;\n    while (isGameRunning()) {\n      var currentTime = System.currentTimeMillis();\n      var elapsedTime = currentTime - previousTime;\n      previousTime = currentTime;\n      lag += elapsedTime;\n\n      processInput();\n\n      while (lag >= MS_PER_FRAME) {\n        update();\n        lag -= MS_PER_FRAME;\n      }\n\n      render();\n    }\n  }\n\n  protected void update() {\n    controller.moveBullet(0.5f * MS_PER_FRAME / 1000);\n  }\n}\n"
  },
  {
    "path": "game-loop/src/main/java/com/iluwatar/gameloop/FrameBasedGameLoop.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\n/**\n * Frame-based game loop is the easiest implementation. The loop always keeps spinning for the\n * following three processes: processInput, update and render. The problem with it is you have no\n * control over how fast the game runs. On a fast machine, that loop will spin so fast users won’t\n * be able to see what’s going on. On a slow machine, the game will crawl. If you have a part of the\n * game that’s content-heavy or does more AI or physics, the game will actually play slower there.\n */\npublic class FrameBasedGameLoop extends GameLoop {\n\n  @Override\n  protected void processGameLoop() {\n    while (isGameRunning()) {\n      processInput();\n      update();\n      render();\n    }\n  }\n\n  /**\n   * Each time when update() is invoked, a new frame is created, and the bullet will be moved 0.5f\n   * away from the current position.\n   */\n  protected void update() {\n    controller.moveBullet(0.5f);\n  }\n}\n"
  },
  {
    "path": "game-loop/src/main/java/com/iluwatar/gameloop/GameController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\n/**\n * Update and render objects in the game. Here we add a Bullet object to the game system to show how\n * the game loop works.\n */\npublic class GameController {\n\n  protected final Bullet bullet;\n\n  /** Initialize Bullet instance. */\n  public GameController() {\n    bullet = new Bullet();\n  }\n\n  /**\n   * Move bullet position by the provided offset.\n   *\n   * @param offset moving offset\n   */\n  public void moveBullet(float offset) {\n    var currentPosition = bullet.getPosition();\n    bullet.setPosition(currentPosition + offset);\n  }\n\n  /**\n   * Get current position of the bullet.\n   *\n   * @return position of bullet\n   */\n  public float getBulletPosition() {\n    return bullet.getPosition();\n  }\n}\n"
  },
  {
    "path": "game-loop/src/main/java/com/iluwatar/gameloop/GameLoop.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\nimport java.security.SecureRandom;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** Abstract class for GameLoop implementation class. */\npublic abstract class GameLoop {\n\n  protected final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n  protected volatile GameStatus status;\n\n  protected final GameController controller;\n\n  /** Initialize game status to be stopped. */\n  protected GameLoop() {\n    controller = new GameController();\n    status = GameStatus.STOPPED;\n  }\n\n  /** Run game loop. */\n  public void run() {\n    status = GameStatus.RUNNING;\n    Thread gameThread = new Thread(this::processGameLoop);\n    gameThread.start();\n  }\n\n  /** Stop game loop. */\n  public void stop() {\n    status = GameStatus.STOPPED;\n  }\n\n  /**\n   * Check if game is running or not.\n   *\n   * @return {@code true} if the game is running.\n   */\n  public boolean isGameRunning() {\n    return status == GameStatus.RUNNING;\n  }\n\n  /**\n   * Handle any user input that has happened since the last call. In order to simulate the situation\n   * in real-life game, here we add a random time lag. The time lag ranges from 50 ms to 250 ms.\n   */\n  protected void processInput() {\n    try {\n      var lag = new SecureRandom().nextInt(200) + 50;\n      Thread.sleep(lag);\n    } catch (InterruptedException e) {\n      logger.error(e.getMessage());\n      /* Clean up whatever needs to be handled before interrupting  */\n      Thread.currentThread().interrupt();\n    }\n  }\n\n  /** Render game frames to screen. Here we print bullet position to simulate this process. */\n  protected void render() {\n    var position = controller.getBulletPosition();\n    logger.info(\"Current bullet position: {}\", position);\n  }\n\n  /** execute game loop logic. */\n  protected abstract void processGameLoop();\n}\n"
  },
  {
    "path": "game-loop/src/main/java/com/iluwatar/gameloop/GameStatus.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\n/** Enum class for game status. */\npublic enum GameStatus {\n  RUNNING,\n  STOPPED\n}\n"
  },
  {
    "path": "game-loop/src/main/java/com/iluwatar/gameloop/VariableStepGameLoop.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\n/**\n * The variable-step game loop chooses a time step to advance based on how much real time passed\n * since the last frame. The longer the frame takes, the bigger steps the game takes. It always\n * keeps up with real time because it will take bigger and bigger steps to get there.\n */\npublic class VariableStepGameLoop extends GameLoop {\n\n  @Override\n  protected void processGameLoop() {\n    var lastFrameTime = System.currentTimeMillis();\n    while (isGameRunning()) {\n      processInput();\n      var currentFrameTime = System.currentTimeMillis();\n      var elapsedTime = currentFrameTime - lastFrameTime;\n      update(elapsedTime);\n      lastFrameTime = currentFrameTime;\n      render();\n    }\n  }\n\n  protected void update(Long elapsedTime) {\n    controller.moveBullet(0.5f * elapsedTime / 1000);\n  }\n}\n"
  },
  {
    "path": "game-loop/src/test/java/com/iluwatar/gameloop/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** App unit test class. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "game-loop/src/test/java/com/iluwatar/gameloop/FixedStepGameLoopTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** FixedStepGameLoop unit test class. */\nclass FixedStepGameLoopTest {\n\n  private FixedStepGameLoop gameLoop;\n\n  @BeforeEach\n  void setup() {\n    gameLoop = new FixedStepGameLoop();\n  }\n\n  @AfterEach\n  void tearDown() {\n    gameLoop = null;\n  }\n\n  @Test\n  void testUpdate() {\n    gameLoop.update();\n    assertEquals(0.01f, gameLoop.controller.getBulletPosition(), 0);\n  }\n}\n"
  },
  {
    "path": "game-loop/src/test/java/com/iluwatar/gameloop/FrameBasedGameLoopTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** FrameBasedGameLoop unit test class. */\nclass FrameBasedGameLoopTest {\n\n  private FrameBasedGameLoop gameLoop;\n\n  @BeforeEach\n  void setup() {\n    gameLoop = new FrameBasedGameLoop();\n  }\n\n  @AfterEach\n  void tearDown() {\n    gameLoop = null;\n  }\n\n  @Test\n  void testUpdate() {\n    gameLoop.update();\n    assertEquals(0.5f, gameLoop.controller.getBulletPosition(), 0);\n  }\n}\n"
  },
  {
    "path": "game-loop/src/test/java/com/iluwatar/gameloop/GameControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass GameControllerTest {\n\n  private GameController controller;\n\n  @BeforeEach\n  void setup() {\n    controller = new GameController();\n  }\n\n  @AfterEach\n  void tearDown() {\n    controller = null;\n  }\n\n  @Test\n  void testMoveBullet() {\n    controller.moveBullet(1.5f);\n    assertEquals(1.5f, controller.bullet.getPosition(), 0);\n  }\n\n  @Test\n  void testGetBulletPosition() {\n    assertEquals(controller.bullet.getPosition(), controller.getBulletPosition(), 0);\n  }\n}\n"
  },
  {
    "path": "game-loop/src/test/java/com/iluwatar/gameloop/GameLoopTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** GameLoop unit test class. */\nclass GameLoopTest {\n\n  private GameLoop gameLoop;\n\n  /** Create mock implementation of GameLoop. */\n  @BeforeEach\n  void setup() {\n    gameLoop =\n        new GameLoop() {\n          @Override\n          protected void processGameLoop() {\n            throw new UnsupportedOperationException(\"Not supported yet.\");\n          }\n        };\n  }\n\n  @AfterEach\n  void tearDown() {\n    gameLoop = null;\n  }\n\n  @Test\n  void testRun() {\n    gameLoop.run();\n    Assertions.assertEquals(GameStatus.RUNNING, gameLoop.status);\n  }\n\n  @Test\n  void testStop() {\n    gameLoop.stop();\n    Assertions.assertEquals(GameStatus.STOPPED, gameLoop.status);\n  }\n\n  @Test\n  void testIsGameRunning() {\n    assertFalse(gameLoop.isGameRunning());\n  }\n}\n"
  },
  {
    "path": "game-loop/src/test/java/com/iluwatar/gameloop/VariableStepGameLoopTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gameloop;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** VariableStepGameLoop unit test class. */\nclass VariableStepGameLoopTest {\n\n  private VariableStepGameLoop gameLoop;\n\n  @BeforeEach\n  void setup() {\n    gameLoop = new VariableStepGameLoop();\n  }\n\n  @AfterEach\n  void tearDown() {\n    gameLoop = null;\n  }\n\n  @Test\n  void testUpdate() {\n    gameLoop.update(20L);\n    Assertions.assertEquals(0.01f, gameLoop.controller.getBulletPosition(), 0);\n  }\n}\n"
  },
  {
    "path": "gateway/README.md",
    "content": "---\ntitle: \"Gateway Pattern in Java: Simplifying External System Integration\"\nshortTitle: Gateway\ndescription: \"Discover the Gateway design pattern in Java, a powerful technique for integrating remote services and APIs. Learn how to encapsulate interactions and simplify your application architecture with practical examples and real-world use cases.\"\ncategory: Integration\nlanguage: en\ntag:\n  - API design\n  - Data access\n  - Decoupling\n  - Enterprise patterns\n---\n\n## Also known as\n\n* Service Gateway\n\n## Intent of Gateway Design Pattern\n\nThe Gateway design pattern is a crucial concept in Java design patterns for simplifying API integration and interactions with remote services. It provides a unified and simplified interface to external systems, enhancing the maintainability and architecture of applications. By encapsulating these interactions, the Gateway pattern ensures loose coupling and promotes a more modular and scalable software design, making it essential for robust and efficient application development.\n\n## Detailed Explanation of Gateway Pattern with Real-World Examples\n\nReal-world example\n\n> In real-world applications, companies often need to interact with multiple external systems. The Gateway design pattern provides a unified interface for such interactions, handling protocol translation and data transformation, thereby ensuring loose coupling between the internal and external components. '\n> \n> Consider a logistics company that uses multiple third-party services for various operations, such as shipping, inventory management, and customer notifications. Each of these services has its own API with different protocols and data formats. To simplify the interaction, the company implements a Gateway design pattern. This gateway acts as a unified interface for all third-party service interactions, allowing the company's internal systems to communicate with these services seamlessly. The gateway handles the translation of protocols, data transformation, and routing of requests, ensuring that the internal systems remain decoupled from the specifics of each external service. This setup improves maintainability and scalability while providing a single point of control for external communications.\n\nIn plain words\n\n> Gateway can provide an interface which lets internal system to utilize external service.\n\nWikipedia says\n\n> A server that acts as an API front-end, receives API requests, enforces throttling and security policies, passes requests to the back-end service and then passes the response back to the requester.\n\nSequence diagram\n\n![Gateway sequence diagram](./etc/gateway-sequence-diagram.png)\n\n## Programmatic Example of Gateway Pattern in Java\n\nFirst, we define a `Gateway` interface. This interface represents the contract for our external services. Each service that we want to interact with will implement this interface.\n\n```java\npublic interface Gateway {\n  void execute();\n}\n```\n\nNext, we create our external services. These are the services that our application needs to interact with. Each service implements the `Gateway` interface and provides its own implementation of the `execute` method.\n\n```java\npublic class ExternalServiceA implements Gateway {\n  @Override\n  public void execute() {\n    // Implementation for ExternalServiceA\n  }\n}\n```\n\n```java\npublic class ExternalServiceB implements Gateway {\n  @Override\n  public void execute() {\n    // Implementation for ExternalServiceB\n  }\n}\n```\n\n```java\npublic class ExternalServiceC implements Gateway {\n  @Override\n  public void execute() {\n    // Implementation for ExternalServiceC\n  }\n}\n```\n\nWe then create a `GatewayFactory` class. This class maintains a registry of all available gateways. It provides methods to register a new gateway and to retrieve a gateway by its key.\n\n```java\npublic class GatewayFactory {\n  private Map<String, Gateway> gateways = new HashMap<>();\n\n  public void registerGateway(String key, Gateway gateway) {\n    gateways.put(key, gateway);\n  }\n\n  public Gateway getGateway(String key) {\n    return gateways.get(key);\n  }\n}\n```\n\nFinally, we have our main application. The application uses the `GatewayFactory` to register and retrieve gateways. It then uses these gateways to interact with the external services.\n\n```java\npublic class App {\n  public static void main(String[] args) throws Exception {\n    GatewayFactory gatewayFactory = new GatewayFactory();\n\n    // Register different gateways\n    gatewayFactory.registerGateway(\"ServiceA\", new ExternalServiceA());\n    gatewayFactory.registerGateway(\"ServiceB\", new ExternalServiceB());\n    gatewayFactory.registerGateway(\"ServiceC\", new ExternalServiceC());\n\n    // Use an executor service for execution\n    Gateway serviceA = gatewayFactory.getGateway(\"ServiceA\");\n    Gateway serviceB = gatewayFactory.getGateway(\"ServiceB\");\n    Gateway serviceC = gatewayFactory.getGateway(\"ServiceC\");\n\n    // Execute external services\n    try {\n      serviceA.execute();\n      serviceB.execute();\n      serviceC.execute();\n    } catch (ThreadDeath e) {\n      LOGGER.info(\"Interrupted!\" + e);\n      throw e;\n    }\n  }\n}\n```\n\nRunning the example produces the following output.\n\n```\n09:24:44.030 [main] INFO com.iluwatar.gateway.ExternalServiceA -- Executing Service A\n09:24:45.038 [main] INFO com.iluwatar.gateway.ExternalServiceB -- Executing Service B\n09:24:46.043 [main] INFO com.iluwatar.gateway.ExternalServiceC -- Executing Service C\n```\n\nThis example demonstrates how the Gateway design pattern can be used to simplify the interaction with multiple external services. Each service is encapsulated behind a common interface, and the application interacts with this interface rather than directly with the services. This reduces coupling and makes the application easier to maintain and extend.\n\n## When to Use the Gateway Pattern in Java\n\nUse the Gateway pattern when integrating with remote services or APIs. It is particularly beneficial in microservices architecture to manage communication through well-defined interfaces.\n\n## Real-World Applications of Gateway Pattern in Java\n\n* API Gateways in Microservices: Acts as an intermediary that processes incoming requests from clients, directing them to appropriate services within a microservices architecture.\n* Database Gateways: Provides a unified interface to access data from various database systems, hiding the specifics of database querying and data retrieval.\n\n## Benefits and Trade-offs of Gateway Pattern\n\nBenefits:\n\n* The Gateway design pattern reduces complexity by abstracting the details of external APIs and services behind a simpler interface.\n* Promotes loose coupling between the application and its dependencies on external systems.\n* Makes the system easier to test and maintain.\n\nTrade-offs:\n\n* Introduces an additional layer that could potentially impact performance.\n* Requires careful design to avoid creating a monolithic gateway that becomes a bottleneck.\n\n## Related Java Design Patterns\n\n* [Facade](https://java-design-patterns.com/patterns/facade/): Similar to Gateway in abstracting complex subsystems, but Gateway specifically targets external or remote interfaces.\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): While both patterns provide a different interface to a subsystem, Gateway focuses more on networked data sources and services.\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): Often used together, as both can control and manage access to another object, but Gateway specifically deals with external services.\n* [API Gateway](https://java-design-patterns.com/patterns/microservices-api-gateway/): Often considered a specialization of the Gateway pattern, it specifically manages API requests and routes them to the appropriate services within a backend system.\n\n## References and Credits\n\n* [Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions](https://amzn.to/3WcFVui)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Gateway (Martin Fowler)](https://martinfowler.com/articles/gateway-pattern.html)\n"
  },
  {
    "path": "gateway/etc/gateway.urm.puml",
    "content": "@startuml GatewayPattern\npackage com.iluwatar.gateway{\nclass App {\n  +main(args: String[]): void\n}\n\nclass GatewayFactory {\n  -gateways: Map<String, Gateway>\n  +registerGateway(key: String, gateway: Gateway): void\n  +getGateway(key: String): Gateway\n}\n\ninterface Gateway {\n  {abstract} +execute(): void\n}\n\nclass ExternalServiceA {\n  +execute(): void\n}\n\nclass ExternalServiceB {\n  +execute(): void\n}\n\nclass ExternalServiceC {\n  +execute(): void\n  +error(): void\n}\n\nApp --> GatewayFactory : Uses\n\n\nGatewayFactory --> Gateway : Creates\n\nGatewayFactory --> ExternalServiceA : Registers\nGatewayFactory --> ExternalServiceB : Registers\nGatewayFactory --> ExternalServiceC : Registers\n\nExternalServiceA --> Gateway : Implements\nExternalServiceB --> Gateway : Implements\nExternalServiceC --> Gateway : Implements\n\n@enduml\n"
  },
  {
    "path": "gateway/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <packaging>jar</packaging>\n    <artifactId>gateway</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.gateway.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "gateway/src/main/java/com/iluwatar/gateway/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gateway;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * the Gateway design pattern is a structural design pattern that provides a unified interface to a\n * set of interfaces in a subsystem. It involves creating a Gateway interface that serves as a\n * common entry point for interacting with various services, and concrete implementations of this\n * interface for different external services.\n *\n * <p>In this example, GateFactory is the factory class, and it provides a method to create\n * different kinds of external services. ExternalServiceA, B, and C are virtual implementations of\n * the external services. Each service provides its own implementation of the execute() method. The\n * Gateway interface is the common interface for all external services. The App class serves as the\n * main entry point for the application implementing the Gateway design pattern. Through the Gateway\n * interface, the App class could call each service with much less complexity.\n */\n@Slf4j\npublic class App {\n  /** Simulate an application calling external services. */\n  public static void main(String[] args) throws Exception {\n    GatewayFactory gatewayFactory = new GatewayFactory();\n\n    // Register different gateways\n    gatewayFactory.registerGateway(\"ServiceA\", new ExternalServiceA());\n    gatewayFactory.registerGateway(\"ServiceB\", new ExternalServiceB());\n    gatewayFactory.registerGateway(\"ServiceC\", new ExternalServiceC());\n\n    // Use an executor service for execution\n    Gateway serviceA = gatewayFactory.getGateway(\"ServiceA\");\n    Gateway serviceB = gatewayFactory.getGateway(\"ServiceB\");\n    Gateway serviceC = gatewayFactory.getGateway(\"ServiceC\");\n\n    // Execute external services\n    try {\n      serviceA.execute();\n      serviceB.execute();\n      serviceC.execute();\n    } catch (ThreadDeath e) {\n      LOGGER.info(\"Interrupted!\" + e);\n      throw e;\n    }\n  }\n}\n"
  },
  {
    "path": "gateway/src/main/java/com/iluwatar/gateway/ExternalServiceA.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gateway;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** ExternalServiceA is one of external services. */\n@Slf4j\nclass ExternalServiceA implements Gateway {\n  @Override\n  public void execute() throws Exception {\n    LOGGER.info(\"Executing Service A\");\n    // Simulate a time-consuming task\n    Thread.sleep(1000);\n  }\n}\n"
  },
  {
    "path": "gateway/src/main/java/com/iluwatar/gateway/ExternalServiceB.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gateway;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** ExternalServiceB is one of external services. */\n@Slf4j\nclass ExternalServiceB implements Gateway {\n  @Override\n  public void execute() throws Exception {\n    LOGGER.info(\"Executing Service B\");\n    // Simulate a time-consuming task\n    Thread.sleep(1000);\n  }\n}\n"
  },
  {
    "path": "gateway/src/main/java/com/iluwatar/gateway/ExternalServiceC.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gateway;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** ExternalServiceC is one of external services. */\n@Slf4j\nclass ExternalServiceC implements Gateway {\n  @Override\n  public void execute() throws Exception {\n    LOGGER.info(\"Executing Service C\");\n    // Simulate a time-consuming task\n    Thread.sleep(1000);\n  }\n\n  public void error() {\n    // Simulate an exception\n    throw new RuntimeException(\"Service C encountered an error\");\n  }\n}\n"
  },
  {
    "path": "gateway/src/main/java/com/iluwatar/gateway/Gateway.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gateway;\n\n/** Service interface. */\ninterface Gateway {\n  void execute() throws Exception;\n}\n"
  },
  {
    "path": "gateway/src/main/java/com/iluwatar/gateway/GatewayFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gateway;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * The \"GatewayFactory\" class is responsible for providing different external services in this\n * Gateway design pattern example. It allows clients to register and retrieve specific gateways\n * based on unique keys.\n */\npublic class GatewayFactory {\n  private Map<String, Gateway> gateways = new HashMap<>();\n\n  public void registerGateway(String key, Gateway gateway) {\n    gateways.put(key, gateway);\n  }\n\n  public Gateway getGateway(String key) {\n    return gateways.get(key);\n  }\n}\n"
  },
  {
    "path": "gateway/src/test/java/com/iluwatar/gateway/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gateway;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.concurrent.*;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\npublic class AppTest {\n\n  private GatewayFactory gatewayFactory;\n  private ExecutorService executorService;\n\n  @BeforeEach\n  void setUp() {\n    gatewayFactory = new GatewayFactory();\n    executorService = Executors.newFixedThreadPool(2);\n    gatewayFactory.registerGateway(\"ServiceA\", new ExternalServiceA());\n    gatewayFactory.registerGateway(\"ServiceB\", new ExternalServiceB());\n    gatewayFactory.registerGateway(\"ServiceC\", new ExternalServiceC());\n  }\n\n  @Test\n  void testServiceAExecution() throws InterruptedException, ExecutionException {\n    // Test Service A execution\n    Future<?> serviceAFuture =\n        executorService.submit(\n            () -> {\n              try {\n                Gateway serviceA = gatewayFactory.getGateway(\"ServiceA\");\n                serviceA.execute();\n              } catch (Exception e) {\n                fail(\"Service A should not throw an exception.\");\n              }\n            });\n\n    // Wait for Service A to complete\n    serviceAFuture.get();\n  }\n\n  @Test\n  void testServiceCExecutionWithException() throws InterruptedException, ExecutionException {\n    // Test Service B execution with an exception\n    Future<?> serviceBFuture =\n        executorService.submit(\n            () -> {\n              try {\n                Gateway serviceB = gatewayFactory.getGateway(\"ServiceB\");\n                serviceB.execute();\n              } catch (Exception e) {\n                fail(\"Service B should not throw an exception.\");\n              }\n            });\n\n    // Wait for Service B to complete\n    serviceBFuture.get();\n  }\n\n  @Test\n  void testServiceCExecution() throws InterruptedException, ExecutionException {\n    // Test Service C execution\n    Future<?> serviceCFuture =\n        executorService.submit(\n            () -> {\n              try {\n                Gateway serviceC = gatewayFactory.getGateway(\"ServiceC\");\n                serviceC.execute();\n              } catch (Exception e) {\n                fail(\"Service C should not throw an exception.\");\n              }\n            });\n\n    // Wait for Service C to complete\n    serviceCFuture.get();\n  }\n\n  @Test\n  void testServiceCError() {\n    try {\n      ExternalServiceC serviceC = (ExternalServiceC) gatewayFactory.getGateway(\"ServiceC\");\n      serviceC.error();\n      fail(\"Service C should throw an exception.\");\n    } catch (Exception e) {\n      assertEquals(\"Service C encountered an error\", e.getMessage());\n    }\n  }\n}\n"
  },
  {
    "path": "gateway/src/test/java/com/iluwatar/gateway/ServiceFactoryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.gateway;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\npublic class ServiceFactoryTest {\n\n  private GatewayFactory gatewayFactory;\n  private ExecutorService executorService;\n\n  @BeforeEach\n  void setUp() {\n    gatewayFactory = new GatewayFactory();\n    executorService = Executors.newFixedThreadPool(2);\n    gatewayFactory.registerGateway(\"ServiceA\", new ExternalServiceA());\n    gatewayFactory.registerGateway(\"ServiceB\", new ExternalServiceB());\n    gatewayFactory.registerGateway(\"ServiceC\", new ExternalServiceC());\n  }\n\n  @Test\n  void testGatewayFactoryRegistrationAndRetrieval() {\n    Gateway serviceA = gatewayFactory.getGateway(\"ServiceA\");\n    Gateway serviceB = gatewayFactory.getGateway(\"ServiceB\");\n    Gateway serviceC = gatewayFactory.getGateway(\"ServiceC\");\n\n    // Check if the retrieved instances match their expected types\n    assertTrue(\n        serviceA instanceof ExternalServiceA, \"ServiceA should be an instance of ExternalServiceA\");\n    assertTrue(\n        serviceB instanceof ExternalServiceB, \"ServiceB should be an instance of ExternalServiceB\");\n    assertTrue(\n        serviceC instanceof ExternalServiceC, \"ServiceC should be an instance of ExternalServiceC\");\n  }\n\n  @Test\n  void testGatewayFactoryRegistrationWithNonExistingKey() {\n    Gateway nonExistingService = gatewayFactory.getGateway(\"NonExistingService\");\n    assertNull(nonExistingService);\n  }\n\n  @Test\n  void testGatewayFactoryConcurrency() throws InterruptedException {\n    int numThreads = 10;\n    CountDownLatch latch = new CountDownLatch(numThreads);\n    AtomicBoolean failed = new AtomicBoolean(false);\n\n    for (int i = 0; i < numThreads; i++) {\n      executorService.submit(\n          () -> {\n            try {\n              Gateway serviceA = gatewayFactory.getGateway(\"ServiceA\");\n              serviceA.execute();\n            } catch (Exception e) {\n              failed.set(true);\n            } finally {\n              latch.countDown();\n            }\n          });\n    }\n\n    latch.await();\n    assertFalse(failed.get(), \"This should not fail\");\n  }\n}\n"
  },
  {
    "path": "guarded-suspension/README.md",
    "content": "---\ntitle: \"Guarded Suspension Pattern in Java: Ensuring Safe Concurrency in Critical Sections\"\nshortTitle: Guarded Suspension\ndescription: \"Learn about the Guarded Suspension design pattern in Java. Understand its implementation for efficient concurrency control, with real-world examples and code snippets.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Asynchronous\n  - Decoupling\n  - Resource management\n  - Synchronization\n  - Thread management\n---\n\n## Also known as\n\n* Conditional Block\n* Suspended Execution\n\n## Intent of Guarded Suspension Design Pattern\n\nThe Guarded Suspension pattern is crucial in Java design patterns for managing operations that require both a lock and a condition to proceed. It optimizes concurrency control by allowing a thread to wait for the right condition efficiently.\n\n## Detailed Explanation of Guarded Suspension Pattern with Real-World Examples\n\nReal-world example\n\n> A practical example of the Guarded Suspension pattern can be seen in a ride-sharing service. In this system, passengers wait for a car to become available, ensuring efficient resource use without continuous checking. When a passenger requests a ride, the request is suspended until a driver becomes available. The system monitors the availability of drivers, and once a driver is ready to take a new passenger, the system notifies the waiting passenger and resumes the ride request process. This ensures that passengers are not continuously checking for available drivers and that drivers are efficiently matched with passengers based on their availability.\n\nIn plain words\n\n> Guarded Suspension pattern is used when one thread waits for the result of another thread's execution.\n\nWikipedia says\n\n> In concurrent programming, Guarded Suspension manages operations requiring a lock and a precondition, delaying execution until the precondition is met.\n\nSequence diagram\n\n![Guarded Suspension sequence diagram](./etc/guarded-suspension-sequence-diagram.png)\n\n## Programmatic Example of Guarded Suspension Pattern in Java\n\nThe `GuardedQueue` class in Java showcases concurrent programming using the Guarded Suspension pattern. It includes synchronized methods that manage thread management and synchronization, demonstrating how threads wait for the right conditions to execute.\n\nThe `GuardedQueue` class demonstrates the Guarded Suspension pattern by encapsulating a queue and providing two synchronized methods, `get` and `put`. The `get` method waits if the queue is empty, while the `put` method adds an item to the queue and notifies any waiting threads.\n\n```java\n@Slf4j\npublic class GuardedQueue {\n    private final Queue<Integer> sourceList = new LinkedList<>();\n\n    // Synchronized get method waits until the queue is not empty\n    public synchronized Integer get() {\n        while (sourceList.isEmpty()) {\n            try {\n                wait();\n            } catch (InterruptedException e) {\n                LOGGER.error(\"Error occurred: \", e);\n            }\n        }\n        return sourceList.poll();\n    }\n\n    // Synchronized put method adds an item to the queue and notifies waiting threads\n    public synchronized void put(Integer e) {\n        sourceList.add(e);\n        notify();\n    }\n}\n```\n\n* `get`: This method waits while the `sourceList` is empty. When an item is added and `notify` is called, the waiting thread is awakened to continue execution and retrieve the item.\n* `put`: This method adds an item to the queue and calls `notify` to wake up any waiting thread that is suspended in the `get` method.\n\nHere is the `App` class driving the example:\n\n```java\npublic class App {\n    public static void main(String[] args) {\n        GuardedQueue guardedQueue = new GuardedQueue();\n        ExecutorService executorService = Executors.newFixedThreadPool(3);\n\n        // Thread to get from the guardedQueue\n        executorService.execute(() -> {\n            Integer item = guardedQueue.get();\n            LOGGER.info(\"Retrieved: \" + item);\n        });\n\n        // Simulating some delay before putting an item\n        try {\n            Thread.sleep(2000);\n        } catch (InterruptedException e) {\n            LOGGER.error(\"Error occurred: \", e);\n        }\n\n        // Thread to put an item into the guardedQueue\n        executorService.execute(() -> {\n            guardedQueue.put(20);\n            LOGGER.info(\"Item added to queue\");\n        });\n\n        executorService.shutdown();\n        try {\n            executorService.awaitTermination(30, TimeUnit.SECONDS);\n        } catch (InterruptedException e) {\n            LOGGER.error(\"Error occurred: \", e);\n        }\n    }\n}\n```\n\n* `ExecutorService` is used to manage a pool of threads.\n* The first thread attempts to retrieve an item from the `GuardedQueue` and waits since the queue is initially empty.\n* After a 2-second delay, the second thread adds an item to the queue, waking up the first thread.\n* The first thread then retrieves the item and logs it.\n\nExecution yields:\n\n```\n19:22:58.984 [pool-1-thread-1] INFO com.iluwatar.guarded.suspension.GuardedQueue -- waiting\n19:23:00.993 [pool-1-thread-2] INFO com.iluwatar.guarded.suspension.GuardedQueue -- putting\n19:23:00.994 [pool-1-thread-2] INFO com.iluwatar.guarded.suspension.GuardedQueue -- notifying\n19:23:00.994 [pool-1-thread-1] INFO com.iluwatar.guarded.suspension.GuardedQueue -- getting\n19:23:00.994 [pool-1-thread-1] INFO com.iluwatar.guarded.suspension.GuardedQueue -- Retrieved: 20\n```\n\n* The log output shows the sequence of events: the first thread waits, the second thread puts an item, and the first thread then retrieves the item. This demonstrates the Guarded Suspension pattern in action.\n\n## When to Use the Guarded Suspension Pattern in Java\n\nThis pattern is ideal for scenarios requiring a thread to wait for specific conditions, promoting efficient concurrency control and reducing busy waiting overhead.\n\n## Real-World Applications of Guarded Suspension Pattern in Java\n\n* Network servers waiting for client requests.\n* Producer-consumer scenarios where the consumer must wait for the producer to provide data.\n* Event-driven applications where actions are triggered only after specific events have occurred.\n\n## Benefits and Trade-offs of Guarded Suspension Pattern\n\nBenefits:\n\n* Reduces CPU consumption by preventing busy waiting.\n* Increases system responsiveness by synchronizing actions to the availability of necessary conditions or resources.\n\nTrade-offs:\n\n* Complexity in implementation, especially when multiple conditions need to be managed.\n* Potential for deadlocks if not carefully managed.\n\n## Related Java Design Patterns\n\n* [Monitor](https://java-design-patterns.com/patterns/monitor/): Both patterns manage the synchronization of threads based on conditions. Guarded Suspension specifically deals with suspending threads until conditions are met, while Monitor Object encapsulates condition and mutual exclusion handling.\n* [Producer-Consumer](https://java-design-patterns.com/patterns/producer-consumer/): Often implemented using Guarded Suspension to handle waiting consumers and producers efficiently.\n* [Balking](https://java-design-patterns.com/patterns/balking/): Similar to Guarded Suspension, Balking is used when a thread checks a condition and only proceeds if the condition is favorable; if not, it immediately returns or bails out. This pattern complements Guarded Suspension by managing actions based on immediate condition checks without waiting.\n\n## References and Credits\n\n* [Concurrent Programming in Java : Design Principles and Patterns](https://amzn.to/4dIBqxL)\n* [Java Concurrency in Practice](https://amzn.to/3JxnXek)\n* [Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects](https://amzn.to/49Ke1c9)\n"
  },
  {
    "path": "guarded-suspension/etc/guarded-suspension.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.13\" icons=\"true\" automaticImage=\"JPEG\" always-add-relationships=\"false\" \n  generalizations=\"true\" realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" \n  router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.guarded.suspension.GuardedQueue\" \n    project=\"java-design-patterns_guarded-suspension\" \n    file=\"/java-design-patterns_guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"277\" width=\"326\" x=\"301\" y=\"172\"/>    \n    <display autosize=\"false\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "guarded-suspension/etc/guarded-suspension.urm.puml",
    "content": "@startuml\npackage com.iluwatar.guarded.suspension {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class GuardedQueue {\n    - LOGGER : Logger {static}\n    - sourceList : Queue<Integer>\n    + GuardedQueue()\n    + get() : Integer\n    + put(e : Integer)\n  }\n}\n@enduml"
  },
  {
    "path": "guarded-suspension/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <packaging>jar</packaging>\n  <artifactId>guarded-suspension</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.guarded.suspension.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.guarded.suspension;\n\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Guarded-suspension is a concurrent design pattern for handling situation when to execute some\n * action we need condition to be satisfied. The implementation utilizes a GuardedQueue, which\n * features two primary methods: `get` and `put`. The key condition governing these operations is\n * that elements cannot be retrieved (`get`) from an empty queue. When a thread attempts to retrieve\n * an element under this condition, it triggers the invocation of the `wait` method from the Object\n * class, causing the thread to pause. Conversely, when an element is added (`put`) to the queue by\n * another thread, it invokes the `notify` method. This notifies the waiting thread that it can now\n * successfully retrieve an element from the queue.\n */\n@Slf4j\npublic class App {\n  /**\n   * Example pattern execution.\n   *\n   * @param args - command line args\n   */\n  public static void main(String[] args) {\n    var guardedQueue = new GuardedQueue();\n    var executorService = Executors.newFixedThreadPool(3);\n\n    // here we create first thread which is supposed to get from guardedQueue\n    executorService.execute(guardedQueue::get);\n\n    // here we wait two seconds to show that the thread which is trying\n    // to get from guardedQueue will be waiting\n    try {\n      Thread.sleep(2000);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Error occurred: \", e);\n    }\n    // now we execute second thread which will put number to guardedQueue\n    // and notify first thread that it could get\n    executorService.execute(() -> guardedQueue.put(20));\n    executorService.shutdown();\n    try {\n      executorService.awaitTermination(30, TimeUnit.SECONDS);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Error occurred: \", e);\n    }\n  }\n}\n"
  },
  {
    "path": "guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.guarded.suspension;\n\nimport java.util.LinkedList;\nimport java.util.Queue;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Guarded Queue is an implementation for Guarded Suspension Pattern Guarded suspension pattern is\n * used to handle a situation when you want to execute a method on an object which is not in a\n * proper state.\n *\n * @see <a\n *     href=\"http://java-design-patterns.com/patterns/guarded-suspension/\">http://java-design-patterns.com/patterns/guarded-suspension/</a>\n */\n@Slf4j\npublic class GuardedQueue {\n  private final Queue<Integer> sourceList;\n\n  public GuardedQueue() {\n    this.sourceList = new LinkedList<>();\n  }\n\n  /**\n   * Get the last element of the queue if exists.\n   *\n   * @return last element of a queue if queue is not empty\n   */\n  public synchronized Integer get() {\n    while (sourceList.isEmpty()) {\n      try {\n        LOGGER.info(\"waiting\");\n        wait();\n      } catch (InterruptedException e) {\n        LOGGER.error(\"Error occurred: \", e);\n      }\n    }\n    LOGGER.info(\"getting\");\n    return sourceList.peek();\n  }\n\n  /**\n   * Put a value in the queue.\n   *\n   * @param e number which we want to put to our queue\n   */\n  public synchronized void put(Integer e) {\n    LOGGER.info(\"putting\");\n    sourceList.add(e);\n    LOGGER.info(\"notifying\");\n    notify();\n  }\n}\n"
  },
  {
    "path": "guarded-suspension/src/test/java/com/iluwatar/guarded/suspension/GuardedQueueTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.guarded.suspension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\n\n/** Test for Guarded Queue. */\n@Slf4j\nclass GuardedQueueTest {\n  private volatile Integer value;\n\n  @Test\n  void testGet() {\n    var g = new GuardedQueue();\n    var executorService = Executors.newFixedThreadPool(2);\n    executorService.submit(() -> value = g.get());\n    executorService.submit(() -> g.put(10));\n    executorService.shutdown();\n    try {\n      executorService.awaitTermination(30, TimeUnit.SECONDS);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Error occurred: \", e);\n    }\n    assertEquals(Integer.valueOf(10), value);\n  }\n\n  @Test\n  void testPut() {\n    var g = new GuardedQueue();\n    g.put(12);\n    assertEquals(Integer.valueOf(12), g.get());\n  }\n}\n"
  },
  {
    "path": "half-sync-half-async/README.md",
    "content": "---\ntitle: \"Half-Sync/Half-Async Pattern in Java: Enhancing System Performance with Dual Processing\"\nshortTitle: Half-Sync/Half-Async\ndescription: \"Learn how the Half-Sync/Half-Async design pattern in Java improves concurrency and system efficiency by decoupling asynchronous and synchronous processing. Explore real-world examples, programmatic implementations, and key use cases.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Asynchronous\n  - Decoupling\n  - Synchronization\n  - Thread management\n---\n\n## Also known as\n\n* Async-Sync Bridge\n* Half-Synchronous/Half-Asynchronous\n\n## Intent of Half-Sync/Half-Async Design Pattern\n\nThe Half-Sync/Half-Async pattern in Java aims to decouple asynchronous and synchronous processing in concurrent systems, enhancing efficiency and performance. This pattern is particularly useful for managing complex concurrent operations in software systems.\n\n## Detailed Explanation of Half-Sync/Half-Async Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a busy restaurant kitchen where order taking is asynchronous, allowing waiters to keep working while chefs cook each dish synchronously. Similarly, the Half-Sync/Half-Async pattern handles multiple asynchronous tasks and synchronous processing in Java applications efficiently. Meanwhile, the cooking (synchronous part) follows a specific sequence and requires waiting for each dish to be prepared before starting the next. This setup enables the restaurant to handle multiple customer orders efficiently, while ensuring each dish is cooked with the required attention and timing, much like the Half-Sync/Half-Async pattern manages asynchronous tasks and synchronous processing in software systems.\n\nIn plain words\n\n> The Half-Sync/Half-Async pattern separates operations into asynchronous tasks that handle events without waiting, and synchronous tasks that process these events in an orderly and blocking manner.\n\nWikipedia says\n\n> The Half-Sync/Half-Async design pattern is used to solve situations where one part of the application runs synchronously while another runs asynchronously, and the two modules need to communicate with each other.\n\nSequence diagram\n\n![Half-Sync/Half-Async sequence diagram](./etc/half-sync-half-async-sequence-diagram.png)\n\n## Programmatic Example of Half-Sync/Half-Async Pattern in Java\n\nThe Half-Sync/Half-Async design pattern is a concurrency pattern that separates synchronous and asynchronous processing in a system, simplifying the programming model without affecting performance. It's particularly useful in scenarios where you have a mix of short, mid, and long duration tasks.\n\nIn the provided Java implementation, we can see an example of the Half-Sync/Half-Async pattern in the `App`, `AsynchronousService`, and `ArithmeticSumTask` classes.\n\nThe `App` class is the entry point of the application. It creates an instance of `AsynchronousService` and uses it to handle various tasks asynchronously.\n\n```java\npublic class App {\n\n  public static void main(String[] args) {\n    var service = new AsynchronousService(new LinkedBlockingQueue<>());\n    service.execute(new ArithmeticSumTask(1000));\n    service.execute(new ArithmeticSumTask(500));\n    service.execute(new ArithmeticSumTask(2000));\n    service.execute(new ArithmeticSumTask(1));\n    service.close();\n  }\n}\n```\n\nThe `AsynchronousService` class is the asynchronous part of the system. It manages a queue of tasks and processes them in a separate thread.\n\n```java\npublic class AsynchronousService {\n  // Implementation details...\n}\n```\n\nThe `ArithmeticSumTask` class represents a task that can be processed asynchronously. It implements the `AsyncTask` interface, which defines methods for pre-processing, post-processing, and error handling.\n\n```java\nstatic class ArithmeticSumTask implements AsyncTask<Long> {\n  private final long numberOfElements;\n\n  public ArithmeticSumTask(long numberOfElements) {\n    this.numberOfElements = numberOfElements;\n  }\n\n  @Override\n  public Long call() throws Exception {\n    return ap(numberOfElements);\n  }\n\n  @Override\n  public void onPreCall() {\n    if (numberOfElements < 0) {\n      throw new IllegalArgumentException(\"n is less than 0\");\n    }\n  }\n\n  @Override\n  public void onPostCall(Long result) {\n    LOGGER.info(result.toString());\n  }\n\n  @Override\n  public void onError(Throwable throwable) {\n    throw new IllegalStateException(\"Should not occur\");\n  }\n}\n```\n\nThis is the `main` function in the `App` class.\n\n```java\npublic static void main(String[] args) {\n    \n    var service = new AsynchronousService(new LinkedBlockingQueue<>());\n\n    service.execute(new ArithmeticSumTask(1000));\n\n    service.execute(new ArithmeticSumTask(500));\n    service.execute(new ArithmeticSumTask(2000));\n    service.execute(new ArithmeticSumTask(1));\n\n    service.close();\n}\n```\n\nIn this example, the `App` class enqueues tasks to the `AsynchronousService`, which processes them asynchronously. The `ArithmeticSumTask` class defines the task to be processed, including pre-processing, the actual processing, and post-processing steps. \n\nRunning the code produces:\n\n```\n10:56:33.922 [pool-1-thread-4] INFO com.iluwatar.halfsynchalfasync.App -- 1\n10:56:34.425 [pool-1-thread-2] INFO com.iluwatar.halfsynchalfasync.App -- 125250\n10:56:34.925 [pool-1-thread-1] INFO com.iluwatar.halfsynchalfasync.App -- 500500\n10:56:35.925 [pool-1-thread-3] INFO com.iluwatar.halfsynchalfasync.App -- 2001000\n```\n\nThis is a basic example of the Half-Sync/Half-Async pattern, where tasks are enqueued and processed asynchronously, while the main thread continues to handle other tasks.\n\n## When to Use the Half-Sync/Half-Async Pattern in Java\n\nUse the Half-Sync/Half-Async pattern in scenarios where:\n\n* High performance and efficient concurrency are crucial, such as in Java's standard libraries and network servers managing concurrent connections.\n* The system needs to effectively utilize multicore architectures to balance tasks between asynchronous and synchronous processing.\n* Decoupling of asynchronous tasks from synchronous processing is necessary to simplify the design and implementation.\n\n## Real-World Applications of Half-Sync/Half-Async Pattern in Java\n\n* The Half-Sync/Half-Async pattern is utilized in various frameworks and systems, including BSD Unix networking, Real-Time CORBA, and Android's AsyncTask framework.\n* Java's standard libraries utilize this pattern with thread pools and execution queues in the concurrency utilities (e.g., java.util.concurrent).\n* Network servers handling concurrent connections where IO operations are handled asynchronously and processing of requests is done synchronously.\n\n## Benefits and Trade-offs of Half-Sync/Half-Async Pattern\n\nBenefits:\n\n* This pattern improves system responsiveness and throughput by isolating blocking operations from non-blocking ones, making it a valuable design pattern in Java concurrency.\n* Simplifies programming model by isolating asynchronous and synchronous processing layers.\n\nTrade-offs:\n\n* Adds complexity in managing two different processing modes.\n* Requires careful design to avoid bottlenecks between the synchronous and asynchronous parts.\n\n## Related Java Design Patterns\n\n* [Leader/Followers](https://java-design-patterns.com/patterns/leader-followers/): Both patterns manage thread assignments and concurrency, but Leader/Followers uses a single thread to handle all I/O events, dispatching work to others.\n* [Producer/Consumer](https://java-design-patterns.com/patterns/producer-consumer/): Can be integrated with Half-Sync/Half-Async to manage work queues between the async and sync parts.\n* [Reactor](https://java-design-patterns.com/patterns/reactor/): Often used with Half-Sync/Half-Async to handle multiple service requests delivered to a service handler without blocking the handler.\n\n## References and Credits\n\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n* [Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects](https://amzn.to/3UgC24V)\n* [Half-Sync/Half-Async (Douglas C. Schmidt and Charles D. Cranor)](https://www.dre.vanderbilt.edu/~schmidt/PDF/PLoP-95.pdf)\n"
  },
  {
    "path": "half-sync-half-async/etc/half-sync-half-async.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.halfsynchalfasync.AsynchronousService\" project=\"half-sync-half-async\" \n    file=\"/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"115\" width=\"265\" x=\"41\" y=\"37\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"2\" language=\"java\" name=\"com.iluwatar.halfsynchalfasync.AsyncTask\" project=\"half-sync-half-async\" \n    file=\"/half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsyncTask.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"776\" y=\"223\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"3\" language=\"java\" name=\"java.util.concurrent.BlockingQueue\" project=\"async-method-invocation\" \n    file=\"/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"494\" y=\"310\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"false\" package=\"false\" protected=\"false\" private=\"false\" static=\"true\"/>      \n      <operations public=\"false\" package=\"false\" protected=\"false\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"4\" language=\"java\" name=\"java.util.concurrent.ThreadPoolExecutor\" project=\"async-method-invocation\" \n    file=\"/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"174\" y=\"343\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"false\" package=\"false\" protected=\"false\" private=\"false\" static=\"false\"/>    \n    </display>  \n  </class>  \n  <interface id=\"5\" language=\"java\" name=\"java.util.concurrent.Callable\" project=\"async-method-invocation\" \n    file=\"/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"772\" y=\"47\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <generalization id=\"6\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </generalization>  \n  <association id=\"7\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"8\" name=\"workQueue\"/>      \n      <multiplicity id=\"9\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <dependency id=\"10\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </dependency>  \n  <dependency id=\"11\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </dependency>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "half-sync-half-async/etc/half-sync-half-async.urm.puml",
    "content": "@startuml\npackage com.iluwatar.halfsynchalfasync {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    - ap(i : long) : long {static}\n    + main(args : String[]) {static}\n  }\n  ~class ArithmeticSumTask {\n    - numberOfElements : long\n    + ArithmeticSumTask(numberOfElements : long)\n    + call() : Long\n    + onError(throwable : Throwable)\n    + onPostCall(result : Long)\n    + onPreCall()\n  }\n  interface AsyncTask<O> {\n    + call() : O {abstract}\n    + onError(Throwable) {abstract}\n    + onPostCall(O) {abstract}\n    + onPreCall() {abstract}\n  }\n  class AsynchronousService {\n    - LOGGER : Logger {static}\n    - service : ExecutorService\n    + AsynchronousService(workQueue : BlockingQueue<Runnable>)\n    + close()\n    + execute(task : AsyncTask<T>)\n  }\n}\nArithmeticSumTask ..+ App\nArithmeticSumTask ..|> AsyncTask \n@enduml"
  },
  {
    "path": "half-sync-half-async/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>half-sync-half-async</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.halfsynchalfasync.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.halfsynchalfasync;\n\nimport java.util.concurrent.LinkedBlockingQueue;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This application demonstrates Half-Sync/Half-Async pattern. Key parts of the pattern are {@link\n * AsyncTask} and {@link AsynchronousService}.\n *\n * <p><i>PROBLEM</i> <br>\n * A concurrent system have a mixture of short duration, mid-duration and long duration tasks. Mid\n * or long duration tasks should be performed asynchronously to meet quality of service\n * requirements.\n *\n * <p><i>INTENT</i> <br>\n * The intent of this pattern is to separate the synchronous and asynchronous processing in the\n * concurrent application by introducing two intercommunicating layers - one for sync and one for\n * async. This simplifies the programming without unduly affecting the performance.\n *\n * <p><i>APPLICABILITY</i> <br>\n * UNIX network subsystems - In operating systems network operations are carried out asynchronously\n * with help of hardware level interrupts.<br>\n * CORBA - At the asynchronous layer one thread is associated with each socket that is connected to\n * the client. Thread blocks waiting for CORBA requests from the client. On receiving request it is\n * inserted in the queuing layer which is then picked up by synchronous layer which processes the\n * request and sends response back to the client.<br>\n * Android AsyncTask framework - Framework provides a way to execute long-running blocking calls,\n * such as downloading a file, in background threads so that the UI thread remains free to respond\n * to user inputs.<br>\n *\n * <p><i>IMPLEMENTATION</i> <br>\n * The main method creates an asynchronous service which does not block the main thread while the\n * task is being performed. The main thread continues its work which is similar to Async Method\n * Invocation pattern. The difference between them is that there is a queuing layer between\n * Asynchronous layer and synchronous layer, which allows for different communication patterns\n * between both layers. Such as Priority Queue can be used as queuing layer to prioritize the way\n * tasks are executed. Our implementation is just one simple way of implementing this pattern, there\n * are many variants possible as described in its applications.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var service = new AsynchronousService(new LinkedBlockingQueue<>());\n    /*\n     * A new task to calculate sum is received but as this is main thread, it should not block. So\n     * it passes it to the asynchronous task layer to compute and proceeds with handling other\n     * incoming requests. This is particularly useful when main thread is waiting on Socket to\n     * receive new incoming requests and does not wait for particular request to be completed before\n     * responding to new request.\n     */\n    service.execute(new ArithmeticSumTask(1000));\n\n    /*\n     * New task received, lets pass that to async layer for computation. So both requests will be\n     * executed in parallel.\n     */\n    service.execute(new ArithmeticSumTask(500));\n    service.execute(new ArithmeticSumTask(2000));\n    service.execute(new ArithmeticSumTask(1));\n\n    service.close();\n  }\n\n  /** ArithmeticSumTask. */\n  static class ArithmeticSumTask implements AsyncTask<Long> {\n    private final long numberOfElements;\n\n    public ArithmeticSumTask(long numberOfElements) {\n      this.numberOfElements = numberOfElements;\n    }\n\n    /*\n     * This is the long-running task that is performed in background. In our example the long-running\n     * task is calculating arithmetic sum with artificial delay.\n     */\n    @Override\n    public Long call() {\n      return ap(numberOfElements);\n    }\n\n    /*\n     * This will be called in context of the main thread where some validations can be done\n     * regarding the inputs. Such as it must be greater than 0. It's a small computation which can\n     * be performed in main thread. If we did validate the input in background thread then we pay\n     * the cost of context switching which is much more than validating it in main thread.\n     */\n    @Override\n    public void onPreCall() {\n      if (numberOfElements < 0) {\n        throw new IllegalArgumentException(\"n is less than 0\");\n      }\n    }\n\n    @Override\n    public void onPostCall(Long result) {\n      // Handle the result of computation\n      LOGGER.info(result.toString());\n    }\n\n    @Override\n    public void onError(Throwable throwable) {\n      throw new IllegalStateException(\"Should not occur\");\n    }\n  }\n\n  private static long ap(long i) {\n    try {\n      Thread.sleep(i);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Exception caught.\", e);\n    }\n    return i * (i + 1) / 2;\n  }\n}\n"
  },
  {
    "path": "half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsyncTask.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.halfsynchalfasync;\n\nimport java.util.concurrent.Callable;\n\n/**\n * Represents some computation that is performed asynchronously and its result. The computation is\n * typically done is background threads and the result is posted back in form of callback. The\n * callback does not implement {@code isComplete}, {@code cancel} as it is out of scope of this\n * pattern.\n *\n * @param <O> type of result\n */\npublic interface AsyncTask<O> extends Callable<O> {\n  /**\n   * Is called in context of caller thread before call to {@link #call()}. Large tasks should not be\n   * performed in this method as it will block the caller thread. Small tasks such as validations\n   * can be performed here so that the performance penalty of context switching is not incurred in\n   * case of invalid requests.\n   */\n  void onPreCall();\n\n  /**\n   * A callback called after the result is successfully computed by {@link #call()}. In our\n   * implementation this method is called in context of background thread but in some variants, such\n   * as Android where only UI thread can change the state of UI widgets, this method is called in\n   * context of UI thread.\n   */\n  void onPostCall(O result);\n\n  /**\n   * A callback called if computing the task resulted in some exception. This method is called when\n   * either of {@link #call()} or {@link #onPreCall()} throw any exception.\n   *\n   * @param throwable error cause\n   */\n  void onError(Throwable throwable);\n\n  /**\n   * This is where the computation of task should reside. This method is called in context of\n   * background thread.\n   */\n  @Override\n  O call() throws Exception;\n}\n"
  },
  {
    "path": "half-sync-half-async/src/main/java/com/iluwatar/halfsynchalfasync/AsynchronousService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.halfsynchalfasync;\n\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.FutureTask;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This is the asynchronous layer which does not block when a new request arrives. It just passes\n * the request to the synchronous layer which consists of a queue i.e. a {@link BlockingQueue} and a\n * pool of threads i.e. {@link ThreadPoolExecutor}. Out of this pool of worker threads one of the\n * thread picks up the task and executes it synchronously in background and the result is posted\n * back to the caller via callback.\n */\n@Slf4j\npublic class AsynchronousService {\n  /*\n   * This represents the queuing layer as well as synchronous layer of the pattern. The thread pool\n   * contains worker threads which execute the tasks in blocking/synchronous manner. Long-running\n   * tasks should be performed in the background which does not affect the performance of main\n   * thread.\n   */\n  private final ExecutorService service;\n\n  /**\n   * Creates an asynchronous service using {@code workQueue} as communication channel between\n   * asynchronous layer and synchronous layer. Different types of queues such as Priority queue, can\n   * be used to control the pattern of communication between the layers.\n   */\n  public AsynchronousService(BlockingQueue<Runnable> workQueue) {\n    service = new ThreadPoolExecutor(10, 10, 10, TimeUnit.SECONDS, workQueue);\n  }\n\n  /**\n   * A non-blocking method which performs the task provided in background and returns immediately.\n   *\n   * <p>On successful completion of task the result is posted back using callback method {@link\n   * AsyncTask#onPostCall(Object)}, if task execution is unable to complete normally due to some\n   * exception then the reason for error is posted back using callback method {@link\n   * AsyncTask#onError(Throwable)}.\n   *\n   * <p>NOTE: The results are posted back in the context of background thread in this\n   * implementation.\n   */\n  public <T> void execute(final AsyncTask<T> task) {\n    try {\n      // some small tasks such as validation can be performed here.\n      task.onPreCall();\n    } catch (Exception e) {\n      task.onError(e);\n      return;\n    }\n\n    service.submit(\n        new FutureTask<>(task) {\n          @Override\n          protected void done() {\n            super.done();\n            try {\n              /*\n               * called in context of background thread. There is other variant possible where result is\n               * posted back and sits in the queue of caller thread which then picks it up for\n               * processing. An example of such a system is Android OS, where the UI elements can only\n               * be updated using UI thread. So result must be posted back in UI thread.\n               */\n              task.onPostCall(get());\n            } catch (InterruptedException e) {\n              // should not occur\n            } catch (ExecutionException e) {\n              task.onError(e.getCause());\n            }\n          }\n        });\n  }\n\n  /** Stops the pool of workers. This is a blocking call to wait for all tasks to be completed. */\n  public void close() {\n    service.shutdown();\n    try {\n      service.awaitTermination(10, TimeUnit.SECONDS);\n    } catch (InterruptedException ie) {\n      LOGGER.error(\"Error waiting for executor service shutdown!\");\n    }\n  }\n}\n"
  },
  {
    "path": "half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.halfsynchalfasync;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(null));\n  }\n}\n"
  },
  {
    "path": "half-sync-half-async/src/test/java/com/iluwatar/halfsynchalfasync/AsynchronousServiceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.halfsynchalfasync;\n\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.inOrder;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.timeout;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\nimport static org.mockito.Mockito.when;\n\nimport java.io.IOException;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** AsynchronousServiceTest */\nclass AsynchronousServiceTest {\n  private AsynchronousService service;\n  private AsyncTask<Object> task;\n\n  @BeforeEach\n  void setUp() {\n    service = new AsynchronousService(new LinkedBlockingQueue<>());\n    task = mock(AsyncTask.class);\n  }\n\n  @Test\n  void testPerfectExecution() throws Exception {\n    final var result = new Object();\n    when(task.call()).thenReturn(result);\n    service.execute(task);\n\n    verify(task, timeout(2000)).onPostCall(eq(result));\n\n    final var inOrder = inOrder(task);\n    inOrder.verify(task, times(1)).onPreCall();\n    inOrder.verify(task, times(1)).call();\n    inOrder.verify(task, times(1)).onPostCall(eq(result));\n\n    verifyNoMoreInteractions(task);\n  }\n\n  @Test\n  void testCallException() throws Exception {\n    final var exception = new IOException();\n    when(task.call()).thenThrow(exception);\n    service.execute(task);\n\n    verify(task, timeout(2000)).onError(eq(exception));\n\n    final var inOrder = inOrder(task);\n    inOrder.verify(task, times(1)).onPreCall();\n    inOrder.verify(task, times(1)).call();\n    inOrder.verify(task, times(1)).onError(exception);\n\n    verifyNoMoreInteractions(task);\n  }\n\n  @Test\n  void testPreCallException() {\n    final var exception = new IllegalStateException();\n    doThrow(exception).when(task).onPreCall();\n    service.execute(task);\n\n    verify(task, timeout(2000)).onError(eq(exception));\n\n    final var inOrder = inOrder(task);\n    inOrder.verify(task, times(1)).onPreCall();\n    inOrder.verify(task, times(1)).onError(exception);\n\n    verifyNoMoreInteractions(task);\n  }\n}\n"
  },
  {
    "path": "health-check/README.md",
    "content": "---\ntitle: \"Health Check Pattern in Java: Monitoring System Health for Optimal Operation\"\nshortTitle: Health Check\ndescription: \"Learn about the Health Check pattern in Java, a vital design for monitoring system health and ensuring reliability in microservices and distributed systems. Discover examples, applications, and benefits.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Fault tolerance\n  - Microservices\n  - Monitoring\n  - System health\n---\n\n## Also known as\n\n* Health Monitoring\n* Service Health Check\n\n## Intent of Health Check Design Pattern\n\nThe Health Check pattern in Java is designed to proactively monitor the health of individual software components or services, allowing for quick identification and remediation of issues that may affect overall system functionality in microservices architectures.\n\n## Detailed Explanation of Health Check Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a hospital where patient monitoring systems are used to ensure the health of patients. Each monitoring device periodically checks the vital signs of a patient and reports back to a central system. Similarly, in Java-based software systems, a Health Check pattern allows each service to periodically report its status to a central monitoring system. If any device detects abnormal vital signs, it triggers an alert for immediate medical attention. Similarly, in software, a Health Check pattern allows each service to periodically report its status to a central monitoring system. If a service is found to be unhealthy, the system can take corrective actions such as alerting administrators, restarting the service, or redirecting traffic to healthy instances, thereby ensuring continuous and reliable operation.\n\nIn plain words\n\n> The Health Check Pattern is like a regular doctor's visit for services in a microservices architecture. It helps in early detection of issues and ensures that services are healthy and available.\n\nSequence diagram\n\n![Health Check sequence diagram](./etc/health-check-sequence-diagram.png)\n\n## Programmatic Example of Health Check Pattern in Java\n\nThe Health Check design pattern is particularly useful in distributed systems where the health of individual components can affect the overall health of the system. Using Spring Boot Actuator, developers can easily implement health checks in Java applications.\n\nIn the provided code, we can see an example of the Health Check pattern in the `App` class and the use of Spring Boot's Actuator.\n\nThe `App` class is the entry point of the application. It starts a Spring Boot application which has health check capabilities built-in through the use of Spring Boot Actuator.\n\n```java\n@EnableCaching\n@EnableScheduling\n@SpringBootApplication\npublic class App {\n  public static void main(String[] args) {\n    SpringApplication.run(App.class, args);\n  }\n}\n```\n\nSpring Boot Actuator provides several built-in health checks through its `/actuator/health` endpoint. For example, it can check the status of the database connection, disk space, and other important system parameters. You can also add custom health checks as needed.\n\nTo add a custom health check, you can create a class that implements the `HealthIndicator` interface and override its `health` method. Here is an example:\n\n```java\n@Component\npublic class CustomHealthCheck implements HealthIndicator {\n    @Override\n    public Health health() {\n        int errorCode = check(); // perform some specific health check\n        if (errorCode != 0) {\n            return Health.down()\n              .withDetail(\"Error Code\", errorCode).build();\n        }\n        return Health.up().build();\n    }\n     \n    public int check() {\n        // Our logic to check health\n        return 0;\n    }\n}\n```\n\nIn this example, the `check` method contains the logic for the health check. If the health check fails, it returns a non-zero error code, and the `health` method builds a `DOWN` health status with the error code. If the health check passes, it returns a `UP` health status.\n\nThis is a basic example of the Health Check pattern, where health checks are built into the system and can be easily accessed and monitored.\n\n## When to Use the Health Check Pattern in Java\n\n* Use when building Java microservices or distributed systems where it is crucial to monitor the health of each service.\n* Suitable for scenarios where automated systems need to determine the operational status of services to perform load balancing, failover, or recovery operations.\n\n## Real-World Applications of Health Check Pattern in Java\n\nKnown uses of the Health Check pattern in Java include\n\n* Kubernetes liveness and readiness probes\n* AWS elastic load balancing health checks\n* Spring Boot Actuator integrations\n\n## Benefits and Trade-offs of Health Check Pattern\n\nBenefits:\n\n* Improved system reliability through early detection of failures.\n* Enhanced system availability by allowing for automatic or manual recovery processes.\n* Simplifies maintenance and operations by providing clear visibility into system health.\n\nTrade-offs:\n\n* Additional overhead for implementing and maintaining health check mechanisms.\n* May introduce complexity in handling false positives and negatives in health status reporting.\n\n## Related Java Design Patterns\n\n* [Circuit Breaker](https://java-design-patterns.com/patterns/circuit-breaker/): Both patterns enhance system resilience; while Health Check monitors health status, Circuit Breaker protects a system from repeated failures.\n* [Observer](https://java-design-patterns.com/patterns/observer/): Health Check can be seen as a specific use case of the Observer pattern, where the subject being observed is the system’s health.\n\n## References and Credits\n\n* [Microservices Patterns: With examples in Java](https://amzn.to/3UyWD5O)\n* [Release It! Design and Deploy Production-Ready Software](https://amzn.to/3Uul4kF)\n* [Pattern: Health Check API (Microservices.io)](https://microservices.io/patterns/observability/health-check-api.html)\n"
  },
  {
    "path": "health-check/etc/health-check.puml",
    "content": "@startuml\n\n!theme plain\ntop to bottom direction\nskinparam linetype ortho\n\nclass App {\n  + App(): \n  + main(String[]): void\n}\nclass AsynchronousHealthChecker {\n  + AsynchronousHealthChecker(): \n  + performCheck(Supplier<Health>, long): CompletableFuture<Health>\n  - awaitTerminationWithTimeout(): boolean\n  + shutdown(): void\n}\nclass CpuHealthIndicator {\n  + CpuHealthIndicator(): \n  - processCpuLoadThreshold: double\n  - systemCpuLoadThreshold: double\n  - loadAverageThreshold: double\n  - osBean: OperatingSystemMXBean\n  - defaultWarningMessage: String\n  + init(): void\n  + health(): Health\n   defaultWarningMessage: String\n   osBean: OperatingSystemMXBean\n   loadAverageThreshold: double\n   processCpuLoadThreshold: double\n   systemCpuLoadThreshold: double\n}\nclass CustomHealthIndicator {\n  + CustomHealthIndicator(AsynchronousHealthChecker, CacheManager, HealthCheckRepository): \n  + evictHealthCache(): void\n  - check(): Health\n  + health(): Health\n}\nclass DatabaseTransactionHealthIndicator {\n  + DatabaseTransactionHealthIndicator(HealthCheckRepository, AsynchronousHealthChecker, RetryTemplate): \n  - retryTemplate: RetryTemplate\n  - healthCheckRepository: HealthCheckRepository\n  - timeoutInSeconds: long\n  - asynchronousHealthChecker: AsynchronousHealthChecker\n  + health(): Health\n   timeoutInSeconds: long\n   retryTemplate: RetryTemplate\n   healthCheckRepository: HealthCheckRepository\n   asynchronousHealthChecker: AsynchronousHealthChecker\n}\nclass GarbageCollectionHealthIndicator {\n  + GarbageCollectionHealthIndicator(): \n  - memoryUsageThreshold: double\n  + health(): Health\n   memoryPoolMxBeans: List<MemoryPoolMXBean>\n   garbageCollectorMxBeans: List<GarbageCollectorMXBean>\n   memoryUsageThreshold: double\n}\nclass HealthCheck {\n  + HealthCheck(): \n  - status: String\n  - id: Integer\n  + equals(Object): boolean\n  # canEqual(Object): boolean\n  + hashCode(): int\n  + toString(): String\n   id: Integer\n   status: String\n}\nclass HealthCheckRepository {\n  + HealthCheckRepository(): \n  + performTestTransaction(): void\n  + checkHealth(): Integer\n}\nclass MemoryHealthIndicator {\n  + MemoryHealthIndicator(AsynchronousHealthChecker): \n  + checkMemory(): Health\n  + health(): Health\n}\nclass RetryConfig {\n  + RetryConfig(): \n  + retryTemplate(): RetryTemplate\n}\n\nCustomHealthIndicator              \"1\" *-[#595959,plain]-> \"healthChecker\\n1\" AsynchronousHealthChecker          \nCustomHealthIndicator              \"1\" *-[#595959,plain]-> \"healthCheckRepository\\n1\" HealthCheckRepository              \nDatabaseTransactionHealthIndicator \"1\" *-[#595959,plain]-> \"asynchronousHealthChecker\\n1\" AsynchronousHealthChecker          \nDatabaseTransactionHealthIndicator \"1\" *-[#595959,plain]-> \"healthCheckRepository\\n1\" HealthCheckRepository              \nHealthCheckRepository               -[#595959,dashed]->  HealthCheck                        : \"«create»\"\nMemoryHealthIndicator              \"1\" *-[#595959,plain]-> \"asynchronousHealthChecker\\n1\" AsynchronousHealthChecker          \n@enduml\n"
  },
  {
    "path": "health-check/etc/health-check.urm.puml",
    "content": "@startuml\npackage com.iluwatar.health.check {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class AsynchronousHealthChecker {\n    - HEALTH_CHECK_FAILED_MESSAGE : String {static}\n    - HEALTH_CHECK_TIMEOUT_MESSAGE : String {static}\n    - LOGGER : Logger {static}\n    - healthCheckExecutor : ScheduledExecutorService\n    + AsynchronousHealthChecker()\n    - awaitTerminationWithTimeout() : boolean\n    + performCheck(healthCheck : Supplier<Health>, timeoutInSeconds : long) : CompletableFuture<Health>\n    + shutdown()\n  }\n  class CpuHealthIndicator {\n    - ERROR_MESSAGE : String {static}\n    - HIGH_LOAD_AVERAGE_MESSAGE : String {static}\n    - HIGH_LOAD_AVERAGE_MESSAGE_WITHOUT_PARAM : String {static}\n    - HIGH_PROCESS_CPU_LOAD_MESSAGE : String {static}\n    - HIGH_PROCESS_CPU_LOAD_MESSAGE_WITHOUT_PARAM : String {static}\n    - HIGH_SYSTEM_CPU_LOAD_MESSAGE : String {static}\n    - HIGH_SYSTEM_CPU_LOAD_MESSAGE_WITHOUT_PARAM : String {static}\n    - LOGGER : Logger {static}\n    - defaultWarningMessage : String\n    - loadAverageThreshold : double\n    - osBean : OperatingSystemMXBean\n    - processCpuLoadThreshold : double\n    - systemCpuLoadThreshold : double\n    + CpuHealthIndicator()\n    + getDefaultWarningMessage() : String\n    + getLoadAverageThreshold() : double\n    + getOsBean() : OperatingSystemMXBean\n    + getProcessCpuLoadThreshold() : double\n    + getSystemCpuLoadThreshold() : double\n    + health() : Health\n    + init()\n    + setDefaultWarningMessage(defaultWarningMessage : String)\n    + setLoadAverageThreshold(loadAverageThreshold : double)\n    + setOsBean(osBean : OperatingSystemMXBean)\n    + setProcessCpuLoadThreshold(processCpuLoadThreshold : double)\n    + setSystemCpuLoadThreshold(systemCpuLoadThreshold : double)\n  }\n  class CustomHealthIndicator {\n    - LOGGER : Logger {static}\n    - cacheManager : CacheManager\n    - healthCheckRepository : HealthCheckRepository\n    - healthChecker : AsynchronousHealthChecker\n    - timeoutInSeconds : long\n    + CustomHealthIndicator(healthChecker : AsynchronousHealthChecker, cacheManager : CacheManager, healthCheckRepository : HealthCheckRepository)\n    - check() : Health\n    + evictHealthCache()\n    + health() : Health\n  }\n  class DatabaseTransactionHealthIndicator {\n    - LOGGER : Logger {static}\n    - asynchronousHealthChecker : AsynchronousHealthChecker\n    - healthCheckRepository : HealthCheckRepository\n    - retryTemplate : RetryTemplate\n    - timeoutInSeconds : long\n    + DatabaseTransactionHealthIndicator(healthCheckRepository : HealthCheckRepository, asynchronousHealthChecker : AsynchronousHealthChecker, retryTemplate : RetryTemplate)\n    + getAsynchronousHealthChecker() : AsynchronousHealthChecker\n    + getHealthCheckRepository() : HealthCheckRepository\n    + getRetryTemplate() : RetryTemplate\n    + getTimeoutInSeconds() : long\n    + health() : Health\n    + setTimeoutInSeconds(timeoutInSeconds : long)\n  }\n  class GarbageCollectionHealthIndicator {\n    - LOGGER : Logger {static}\n    - memoryUsageThreshold : double\n    + GarbageCollectionHealthIndicator()\n    - addMemoryPoolDetails(collectorDetails : Map<String, String>, memoryPoolMxBeans : List<MemoryPoolMXBean>, memoryPoolNamesList : List<String>)\n    - createCollectorDetails(gcBean : GarbageCollectorMXBean, memoryPoolMxBeans : List<MemoryPoolMXBean>) : Map<String, String>\n    # getGarbageCollectorMxBeans() : List<GarbageCollectorMXBean>\n    # getMemoryPoolMxBeans() : List<MemoryPoolMXBean>\n    + getMemoryUsageThreshold() : double\n    + health() : Health\n    + setMemoryUsageThreshold(memoryUsageThreshold : double)\n  }\n  class HealthCheck {\n    - id : Integer\n    - status : String\n    + HealthCheck()\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getId() : Integer\n    + getStatus() : String\n    + hashCode() : int\n    + setId(id : Integer)\n    + setStatus(status : String)\n    + toString() : String\n  }\n  class HealthCheckRepository {\n    - HEALTH_CHECK_OK : String {static}\n    - LOGGER : Logger {static}\n    - entityManager : EntityManager\n    + HealthCheckRepository()\n    + checkHealth() : Integer\n    + performTestTransaction()\n  }\n  class MemoryHealthIndicator {\n    - LOGGER : Logger {static}\n    - asynchronousHealthChecker : AsynchronousHealthChecker\n    - memoryThreshold : double\n    - timeoutInSeconds : long\n    + MemoryHealthIndicator(asynchronousHealthChecker : AsynchronousHealthChecker)\n    + checkMemory() : Health\n    + health() : Health\n  }\n  class RetryConfig {\n    - backOffPeriod : long\n    - maxAttempts : int\n    + RetryConfig()\n    + retryTemplate() : RetryTemplate\n  }\n}\nDatabaseTransactionHealthIndicator -->  \"-asynchronousHealthChecker\" AsynchronousHealthChecker\nDatabaseTransactionHealthIndicator -->  \"-healthCheckRepository\" HealthCheckRepository\nCustomHealthIndicator -->  \"-healthCheckRepository\" HealthCheckRepository\nCustomHealthIndicator -->  \"-healthChecker\" AsynchronousHealthChecker\nMemoryHealthIndicator -->  \"-asynchronousHealthChecker\" AsynchronousHealthChecker\n@enduml"
  },
  {
    "path": "health-check/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>health-check</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-data-jpa</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.hibernate</groupId>\n            <artifactId>hibernate-core</artifactId>\n            <version>6.4.4.Final</version>\n        </dependency>\n        <dependency>\n            <groupId>jakarta.xml.bind</groupId>\n            <artifactId>jakarta.xml.bind-api</artifactId>\n            <version>4.0.2</version>\n        </dependency>\n\n        <!-- Testing Dependencies -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <!-- Spring Retry for retrying failed database operations -->\n        <dependency>\n            <groupId>org.springframework.retry</groupId>\n            <artifactId>spring-retry</artifactId>\n            <version>2.0.11</version>\n        </dependency>\n\n        <!-- H2 for mocking database -->\n        <dependency>\n            <groupId>com.h2database</groupId>\n            <artifactId>h2</artifactId>\n            <scope>runtime</scope>\n        </dependency>\n\n        <!-- https://mvnrepository.com/artifact/org.assertj/assertj-core -->\n        <dependency>\n            <groupId>org.assertj</groupId>\n            <artifactId>assertj-core</artifactId>\n            <version>3.27.3</version>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>io.rest-assured</groupId>\n            <artifactId>rest-assured</artifactId>\n            <version>5.5.1</version>\n            <scope>test</scope>\n        </dependency>\n\n    </dependencies>\n\n\n    <build>\n        <plugins>\n            <!-- Maven Assembly Plugin for creating a single distributable JAR -->\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <phase>package</phase>\n                        <goals>\n                            <goal>single</goal>\n                        </goals>\n                        <configuration>\n                            <descriptorRefs>\n                                <descriptorRef>jar-with-dependencies</descriptorRef>\n                            </descriptorRefs>\n                            <archive>\n                                <manifest>\n                                    <!-- Define the main class for the executable JAR -->\n                                    <mainClass>com.iluwatar.healthcheck.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n\n            <!-- Other plugins as needed -->\n\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "health-check/src/main/java/com/iluwatar/health/check/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.health.check;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cache.annotation.EnableCaching;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\n/**\n * This application provides health check APIs for various aspects of the microservice architecture,\n * including database transactions, garbage collection, and overall system health. These health\n * checks are essential for monitoring the health and performance of the microservices and ensuring\n * their availability and responsiveness. For more information about health checks and their role in\n * microservice architectures, please refer to: [Microservices Health Checks\n * API]('https://microservices.io/patterns/observability/health-check-api.html').\n */\n@EnableCaching\n@EnableScheduling\n@SpringBootApplication\npublic class App {\n  /** Program entry point. */\n  public static void main(String[] args) {\n    SpringApplication.run(App.class, args);\n  }\n}\n"
  },
  {
    "path": "health-check/src/main/java/com/iluwatar/health/check/AsynchronousHealthChecker.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.health.check;\n\nimport jakarta.annotation.PreDestroy;\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.CompletionException;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\nimport java.util.function.Supplier;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.stereotype.Component;\n\n/** An asynchronous health checker component that executes health checks in a separate thread. */\n@Slf4j\n@Component\n@RequiredArgsConstructor\npublic class AsynchronousHealthChecker {\n\n  /** A scheduled executor service used to execute health checks in a separate thread. */\n  private final ScheduledExecutorService healthCheckExecutor =\n      Executors.newSingleThreadScheduledExecutor();\n\n  private static final String HEALTH_CHECK_TIMEOUT_MESSAGE = \"Health check timed out\";\n  private static final String HEALTH_CHECK_FAILED_MESSAGE = \"Health check failed\";\n\n  /**\n   * Performs a health check asynchronously using the provided health check logic with a specified\n   * timeout.\n   *\n   * @param healthCheck the health check logic supplied as a {@code Supplier<Health>}\n   * @param timeoutInSeconds the maximum time to wait for the health check to complete, in seconds\n   * @return a {@code CompletableFuture<Health>} object that represents the result of the health\n   *     check\n   */\n  public CompletableFuture<Health> performCheck(\n      Supplier<Health> healthCheck, long timeoutInSeconds) {\n    CompletableFuture<Health> future =\n        CompletableFuture.supplyAsync(healthCheck, healthCheckExecutor);\n\n    // Schedule a task to enforce the timeout\n    healthCheckExecutor.schedule(\n        () -> {\n          if (!future.isDone()) {\n            LOGGER.error(HEALTH_CHECK_TIMEOUT_MESSAGE);\n            future.completeExceptionally(new TimeoutException(HEALTH_CHECK_TIMEOUT_MESSAGE));\n          }\n        },\n        timeoutInSeconds,\n        TimeUnit.SECONDS);\n\n    return future.handle(\n        (result, throwable) -> {\n          if (throwable != null) {\n            LOGGER.error(HEALTH_CHECK_FAILED_MESSAGE, throwable);\n            // Check if the throwable is a TimeoutException or caused by a TimeoutException\n            Throwable rootCause =\n                throwable instanceof CompletionException ? throwable.getCause() : throwable;\n            if (!(rootCause instanceof TimeoutException)) {\n              LOGGER.error(HEALTH_CHECK_FAILED_MESSAGE, rootCause);\n              return Health.down().withException(rootCause).build();\n            } else {\n              LOGGER.error(HEALTH_CHECK_TIMEOUT_MESSAGE, rootCause);\n              // If it is a TimeoutException, rethrow it wrapped in a CompletionException\n              throw new CompletionException(rootCause);\n            }\n          } else {\n            return result;\n          }\n        });\n  }\n\n  /**\n   * Checks whether the health check executor service has terminated completely. This method waits\n   * for the executor service to finish all its tasks within a specified timeout. If the timeout is\n   * reached before all tasks are completed, the method returns `true`; otherwise, it returns\n   * `false`.\n   *\n   * @throws InterruptedException if the current thread is interrupted while waiting for the\n   *     executor service to terminate\n   */\n  private boolean awaitTerminationWithTimeout() throws InterruptedException {\n    boolean isTerminationIncomplete = !healthCheckExecutor.awaitTermination(5, TimeUnit.SECONDS);\n    LOGGER.info(\"Termination status: {}\", isTerminationIncomplete);\n    // Await termination and return true if termination is incomplete (timeout elapsed)\n    return isTerminationIncomplete;\n  }\n\n  /** Shuts down the executor service, allowing in-flight tasks to complete. */\n  @PreDestroy\n  public void shutdown() {\n    try {\n      // Wait a while for existing tasks to terminate\n      if (awaitTerminationWithTimeout()) {\n        LOGGER.info(\"Health check executor did not terminate in time\");\n        // Attempt to cancel currently executing tasks\n        healthCheckExecutor.shutdownNow();\n        // Wait again for tasks to respond to being cancelled\n        if (awaitTerminationWithTimeout()) {\n          LOGGER.error(\"Health check executor did not terminate\");\n        }\n      }\n    } catch (InterruptedException ie) {\n      // Preserve interrupt status\n      Thread.currentThread().interrupt();\n      // (Re-)Cancel if current thread also interrupted\n      healthCheckExecutor.shutdownNow();\n      // Log the stack trace for interrupted exception\n      LOGGER.error(\"Shutdown of the health check executor was interrupted\", ie);\n    }\n  }\n}\n"
  },
  {
    "path": "health-check/src/main/java/com/iluwatar/health/check/CpuHealthIndicator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.health.check;\n\nimport jakarta.annotation.PostConstruct;\nimport java.lang.management.ManagementFactory;\nimport java.lang.management.OperatingSystemMXBean;\nimport java.time.Instant;\nimport java.util.HashMap;\nimport java.util.Map;\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.HealthIndicator;\nimport org.springframework.stereotype.Component;\n\n/** A health indicator that checks the health of the system's CPU. */\n@Getter\n@Setter\n@Slf4j\n@Component\npublic class CpuHealthIndicator implements HealthIndicator {\n\n  /** The operating system MXBean used to gather CPU health information. */\n  private OperatingSystemMXBean osBean;\n\n  /** Initializes the {@link OperatingSystemMXBean} instance. */\n  @PostConstruct\n  public void init() {\n    this.osBean = ManagementFactory.getOperatingSystemMXBean();\n  }\n\n  /**\n   * The system CPU load threshold. If the system CPU load is above this threshold, the health\n   * indicator will return a `down` health status.\n   */\n  @Value(\"${cpu.system.load.threshold:80.0}\")\n  private double systemCpuLoadThreshold;\n\n  /**\n   * The process CPU load threshold. If the process CPU load is above this threshold, the health\n   * indicator will return a `down` health status.\n   */\n  @Value(\"${cpu.process.load.threshold:50.0}\")\n  private double processCpuLoadThreshold;\n\n  /**\n   * The load average threshold. If the load average is above this threshold, the health indicator\n   * will return an `up` health status with a warning message.\n   */\n  @Value(\"${cpu.load.average.threshold:0.75}\")\n  private double loadAverageThreshold;\n\n  private static final String ERROR_MESSAGE = \"error\";\n\n  private static final String HIGH_SYSTEM_CPU_LOAD_MESSAGE = \"High system CPU load: {}\";\n  private static final String HIGH_PROCESS_CPU_LOAD_MESSAGE = \"High process CPU load: {}\";\n  private static final String HIGH_LOAD_AVERAGE_MESSAGE = \"High load average: {}\";\n  private static final String HIGH_PROCESS_CPU_LOAD_MESSAGE_WITHOUT_PARAM = \"High process CPU load\";\n  private static final String HIGH_SYSTEM_CPU_LOAD_MESSAGE_WITHOUT_PARAM = \"High system CPU load\";\n  private static final String HIGH_LOAD_AVERAGE_MESSAGE_WITHOUT_PARAM = \"High load average\";\n\n  /**\n   * Checks the health of the system's CPU and returns a health indicator object.\n   *\n   * @return a health indicator object\n   */\n  @Override\n  public Health health() {\n\n    if (!(osBean instanceof com.sun.management.OperatingSystemMXBean sunOsBean)) {\n      LOGGER.error(\"Unsupported operating system MXBean: {}\", osBean.getClass().getName());\n      return Health.unknown()\n          .withDetail(ERROR_MESSAGE, \"Unsupported operating system MXBean\")\n          .build();\n    }\n\n    double systemCpuLoad = sunOsBean.getCpuLoad() * 100;\n    double processCpuLoad = sunOsBean.getProcessCpuLoad() * 100;\n    int availableProcessors = sunOsBean.getAvailableProcessors();\n    double loadAverage = sunOsBean.getSystemLoadAverage();\n\n    Map<String, Object> details = new HashMap<>();\n    details.put(\"timestamp\", Instant.now());\n    details.put(\"systemCpuLoad\", String.format(\"%.2f%%\", systemCpuLoad));\n    details.put(\"processCpuLoad\", String.format(\"%.2f%%\", processCpuLoad));\n    details.put(\"availableProcessors\", availableProcessors);\n    details.put(\"loadAverage\", loadAverage);\n\n    if (systemCpuLoad > systemCpuLoadThreshold) {\n      LOGGER.error(HIGH_SYSTEM_CPU_LOAD_MESSAGE, systemCpuLoad);\n      return Health.down()\n          .withDetails(details)\n          .withDetail(ERROR_MESSAGE, HIGH_SYSTEM_CPU_LOAD_MESSAGE_WITHOUT_PARAM)\n          .build();\n    } else if (processCpuLoad > processCpuLoadThreshold) {\n      LOGGER.error(HIGH_PROCESS_CPU_LOAD_MESSAGE, processCpuLoad);\n      return Health.down()\n          .withDetails(details)\n          .withDetail(ERROR_MESSAGE, HIGH_PROCESS_CPU_LOAD_MESSAGE_WITHOUT_PARAM)\n          .build();\n    } else if (loadAverage > (availableProcessors * loadAverageThreshold)) {\n      LOGGER.error(HIGH_LOAD_AVERAGE_MESSAGE, loadAverage);\n      return Health.up()\n          .withDetails(details)\n          .withDetail(ERROR_MESSAGE, HIGH_LOAD_AVERAGE_MESSAGE_WITHOUT_PARAM)\n          .build();\n    } else {\n      return Health.up().withDetails(details).build();\n    }\n  }\n}\n"
  },
  {
    "path": "health-check/src/main/java/com/iluwatar/health/check/CustomHealthIndicator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.health.check;\n\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.TimeUnit;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.HealthIndicator;\nimport org.springframework.cache.Cache;\nimport org.springframework.cache.CacheManager;\nimport org.springframework.cache.annotation.Cacheable;\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Component;\n\n/**\n * A custom health indicator that periodically checks the health of a database and caches the\n * result. It leverages an asynchronous health checker to perform the health checks.\n */\n@Slf4j\n@Component\n@RequiredArgsConstructor\npublic class CustomHealthIndicator implements HealthIndicator {\n\n  private final AsynchronousHealthChecker healthChecker;\n  private final CacheManager cacheManager;\n  private final HealthCheckRepository healthCheckRepository;\n\n  @Value(\"${health.check.timeout:10}\")\n  private long timeoutInSeconds;\n\n  /**\n   * Perform a health check and cache the result.\n   *\n   * @return the health status of the application\n   * @throws HealthCheckInterruptedException if the health check is interrupted\n   */\n  @Override\n  @Cacheable(value = \"health-check\", unless = \"#result.status == 'DOWN'\")\n  public Health health() {\n    LOGGER.info(\"Performing health check\");\n    CompletableFuture<Health> healthFuture =\n        healthChecker.performCheck(this::check, timeoutInSeconds);\n    try {\n      return healthFuture.get(timeoutInSeconds, TimeUnit.SECONDS);\n    } catch (InterruptedException e) {\n      Thread.currentThread().interrupt();\n      LOGGER.error(\"Health check interrupted\", e);\n      throw new HealthCheckInterruptedException(e);\n    } catch (Exception e) {\n      LOGGER.error(\"Health check failed\", e);\n      return Health.down(e).build();\n    }\n  }\n\n  /**\n   * Checks the health of the database by querying for a simple constant value expected from the\n   * database.\n   *\n   * @return Health indicating UP if the database returns the constant correctly, otherwise DOWN.\n   */\n  private Health check() {\n    Integer result = healthCheckRepository.checkHealth();\n    boolean databaseIsUp = result != null && result == 1;\n    LOGGER.info(\"Health check result: {}\", databaseIsUp);\n    return databaseIsUp\n        ? Health.up().withDetail(\"database\", \"reachable\").build()\n        : Health.down().withDetail(\"database\", \"unreachable\").build();\n  }\n\n  /**\n   * Evicts all entries from the health check cache. This is scheduled to run at a fixed rate\n   * defined in the application properties.\n   */\n  @Scheduled(fixedRateString = \"${health.check.cache.evict.interval:60000}\")\n  public void evictHealthCache() {\n    LOGGER.info(\"Evicting health check cache\");\n    try {\n      Cache healthCheckCache = cacheManager.getCache(\"health-check\");\n      LOGGER.info(\"Health check cache: {}\", healthCheckCache);\n      if (healthCheckCache != null) {\n        healthCheckCache.clear();\n      }\n    } catch (Exception e) {\n      LOGGER.error(\"Failed to evict health check cache\", e);\n    }\n  }\n}\n"
  },
  {
    "path": "health-check/src/main/java/com/iluwatar/health/check/DatabaseTransactionHealthIndicator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.health.check;\n\nimport java.util.concurrent.ExecutionException;\nimport java.util.function.Supplier;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.HealthIndicator;\nimport org.springframework.retry.support.RetryTemplate;\nimport org.springframework.stereotype.Component;\n\n/**\n * A health indicator that checks the health of database transactions by attempting to perform a\n * test transaction using a retry mechanism. If the transaction succeeds after multiple attempts,\n * the health indicator returns {@link Health#up()} and logs a success message. If all retry\n * attempts fail, the health indicator returns {@link Health#down()} and logs an error message.\n */\n@Slf4j\n@Component\n@RequiredArgsConstructor\n@Setter\n@Getter\npublic class DatabaseTransactionHealthIndicator implements HealthIndicator {\n\n  /** A repository for performing health checks on the database. */\n  private final HealthCheckRepository healthCheckRepository;\n\n  /** An asynchronous health checker used to execute health checks in a separate thread. */\n  private final AsynchronousHealthChecker asynchronousHealthChecker;\n\n  /** A retry template used to retry the test transaction if it fails due to a transient error. */\n  private final RetryTemplate retryTemplate;\n\n  /**\n   * The timeout in seconds for the health check. If the health check does not complete within this\n   * timeout, it will be considered timed out and will return {@link Health#down()}.\n   */\n  @Value(\"${health.check.timeout:10}\")\n  private long timeoutInSeconds;\n\n  /**\n   * Performs a health check by attempting to perform a test transaction with retry support.\n   *\n   * @return the health status of the database transactions\n   */\n  @Override\n  public Health health() {\n    LOGGER.info(\"Calling performCheck with timeout {}\", timeoutInSeconds);\n    Supplier<Health> dbTransactionCheck =\n        () -> {\n          try {\n            healthCheckRepository.performTestTransaction();\n            return Health.up().build();\n          } catch (Exception e) {\n            LOGGER.error(\"Database transaction health check failed\", e);\n            return Health.down(e).build();\n          }\n        };\n    try {\n      return asynchronousHealthChecker.performCheck(dbTransactionCheck, timeoutInSeconds).get();\n    } catch (InterruptedException | ExecutionException e) {\n      LOGGER.error(\"Database transaction health check timed out or was interrupted\", e);\n      Thread.currentThread().interrupt();\n      return Health.down(e).build();\n    }\n  }\n}\n"
  },
  {
    "path": "health-check/src/main/java/com/iluwatar/health/check/GarbageCollectionHealthIndicator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.health.check;\n\nimport java.lang.management.GarbageCollectorMXBean;\nimport java.lang.management.ManagementFactory;\nimport java.lang.management.MemoryPoolMXBean;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.HealthIndicator;\nimport org.springframework.stereotype.Component;\n\n/**\n * A custom health indicator that checks the garbage collection status of the application and\n * reports the health status accordingly. It gathers information about the collection count,\n * collection time, memory pool name, and garbage collector algorithm for each garbage collector and\n * presents the details in a structured manner.\n */\n@Slf4j\n@Component\n@Getter\n@Setter\npublic class GarbageCollectionHealthIndicator implements HealthIndicator {\n\n  /**\n   * The memory usage threshold above which a warning message is included in the health check\n   * report.\n   */\n  @Value(\"${memory.usage.threshold:0.8}\")\n  private double memoryUsageThreshold;\n\n  /**\n   * Performs a health check by gathering garbage collection metrics and evaluating the overall\n   * health of the garbage collection system.\n   *\n   * @return a {@link Health} object representing the health status of the garbage collection system\n   */\n  @Override\n  public Health health() {\n    List<GarbageCollectorMXBean> gcBeans = getGarbageCollectorMxBeans();\n    List<MemoryPoolMXBean> memoryPoolMxBeans = getMemoryPoolMxBeans();\n    Map<String, Map<String, String>> gcDetails = new HashMap<>();\n\n    for (GarbageCollectorMXBean gcBean : gcBeans) {\n      Map<String, String> collectorDetails = createCollectorDetails(gcBean, memoryPoolMxBeans);\n      gcDetails.put(gcBean.getName(), collectorDetails);\n    }\n\n    return Health.up().withDetails(gcDetails).build();\n  }\n\n  /**\n   * Creates details for the given garbage collector, including collection count, collection time,\n   * and memory pool information.\n   *\n   * @param gcBean The garbage collector MXBean\n   * @param memoryPoolMxBeans List of memory pool MXBeans\n   * @return Map containing details for the garbage collector\n   */\n  private Map<String, String> createCollectorDetails(\n      GarbageCollectorMXBean gcBean, List<MemoryPoolMXBean> memoryPoolMxBeans) {\n    Map<String, String> collectorDetails = new HashMap<>();\n    long count = gcBean.getCollectionCount();\n    long time = gcBean.getCollectionTime();\n    collectorDetails.put(\"count\", String.format(\"%d\", count));\n    collectorDetails.put(\"time\", String.format(\"%dms\", time));\n\n    String[] memoryPoolNames = gcBean.getMemoryPoolNames();\n    List<String> memoryPoolNamesList = Arrays.asList(memoryPoolNames);\n    if (!memoryPoolNamesList.isEmpty()) {\n      addMemoryPoolDetails(collectorDetails, memoryPoolMxBeans, memoryPoolNamesList);\n    } else {\n      LOGGER.error(\"Garbage collector '{}' does not have any memory pools\", gcBean.getName());\n    }\n\n    return collectorDetails;\n  }\n\n  /**\n   * Adds memory pool details to the collector details.\n   *\n   * @param collectorDetails Map containing details for the garbage collector\n   * @param memoryPoolMxBeans List of memory pool MXBeans\n   * @param memoryPoolNamesList List of memory pool names associated with the garbage collector\n   */\n  private void addMemoryPoolDetails(\n      Map<String, String> collectorDetails,\n      List<MemoryPoolMXBean> memoryPoolMxBeans,\n      List<String> memoryPoolNamesList) {\n    for (MemoryPoolMXBean memoryPoolmxbean : memoryPoolMxBeans) {\n      if (memoryPoolNamesList.contains(memoryPoolmxbean.getName())) {\n        double memoryUsage =\n            memoryPoolmxbean.getUsage().getUsed() / (double) memoryPoolmxbean.getUsage().getMax();\n        if (memoryUsage > memoryUsageThreshold) {\n          collectorDetails.put(\n              \"warning\",\n              String.format(\n                  \"Memory pool '%s' usage is high (%2f%%)\",\n                  memoryPoolmxbean.getName(), memoryUsage));\n        }\n\n        collectorDetails.put(\n            \"memoryPools\", String.format(\"%s: %s%%\", memoryPoolmxbean.getName(), memoryUsage));\n      }\n    }\n  }\n\n  /**\n   * Retrieves the list of garbage collector MXBeans using ManagementFactory.\n   *\n   * @return a list of {@link GarbageCollectorMXBean} objects representing the garbage collectors\n   */\n  protected List<GarbageCollectorMXBean> getGarbageCollectorMxBeans() {\n    return ManagementFactory.getGarbageCollectorMXBeans();\n  }\n\n  /**\n   * Retrieves the list of memory pool MXBeans using ManagementFactory.\n   *\n   * @return a list of {@link MemoryPoolMXBean} objects representing the memory pools\n   */\n  protected List<MemoryPoolMXBean> getMemoryPoolMxBeans() {\n    return ManagementFactory.getMemoryPoolMXBeans();\n  }\n}\n"
  },
  {
    "path": "health-check/src/main/java/com/iluwatar/health/check/HealthCheck.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.health.check;\n\nimport jakarta.persistence.Column;\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.GenerationType;\nimport jakarta.persistence.Id;\nimport lombok.Data;\n\n/**\n * An entity class that represents a health check record in the database. This class is used to\n * persist the results of health checks performed by the `DatabaseTransactionHealthIndicator`.\n */\n@Entity\n@Data\npublic class HealthCheck {\n\n  /** The unique identifier of the health check record. */\n  @Id\n  @GeneratedValue(strategy = GenerationType.IDENTITY)\n  private Integer id;\n\n  /** The status of the health check. Possible values are \"UP\" and \"DOWN\". */\n  @Column(name = \"status\")\n  private String status;\n}\n"
  },
  {
    "path": "health-check/src/main/java/com/iluwatar/health/check/HealthCheckInterruptedException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.health.check;\n\n/**\n * Exception thrown when the health check is interrupted during execution. This exception is a\n * runtime exception that wraps the original cause.\n */\npublic class HealthCheckInterruptedException extends RuntimeException {\n  /**\n   * Constructs a new HealthCheckInterruptedException with the specified cause.\n   *\n   * @param cause the cause of the exception\n   */\n  public HealthCheckInterruptedException(Throwable cause) {\n    super(\"Health check interrupted\", cause);\n  }\n}\n"
  },
  {
    "path": "health-check/src/main/java/com/iluwatar/health/check/HealthCheckRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.health.check;\n\nimport jakarta.persistence.EntityManager;\nimport jakarta.persistence.PersistenceContext;\nimport jakarta.transaction.Transactional;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.stereotype.Repository;\n\n/**\n * A repository class for managing health check records in the database. This class provides methods\n * for checking the health of the database connection and performing test transactions.\n */\n@Slf4j\n@Repository\npublic class HealthCheckRepository {\n\n  private static final String HEALTH_CHECK_OK = \"OK\";\n\n  @PersistenceContext private EntityManager entityManager;\n\n  /**\n   * Checks the health of the database connection by executing a simple query that should always\n   * return 1 if the connection is healthy.\n   *\n   * @return 1 if the database connection is healthy, or null otherwise\n   */\n  public Integer checkHealth() {\n    try {\n      return (Integer) entityManager.createNativeQuery(\"SELECT 1\").getSingleResult();\n    } catch (Exception e) {\n      LOGGER.error(\"Health check query failed\", e);\n      throw e;\n    }\n  }\n\n  /**\n   * Performs a test transaction by writing a record to the `health_check` table, reading it back,\n   * and then deleting it. If any of these operations fail, an exception is thrown.\n   *\n   * @throws Exception if the test transaction fails\n   */\n  @Transactional\n  public void performTestTransaction() throws Exception {\n    try {\n      HealthCheck healthCheck = new HealthCheck();\n      healthCheck.setStatus(HEALTH_CHECK_OK);\n      entityManager.persist(healthCheck);\n      entityManager.flush();\n      HealthCheck retrievedHealthCheck = entityManager.find(HealthCheck.class, healthCheck.getId());\n      entityManager.remove(retrievedHealthCheck);\n    } catch (Exception e) {\n      LOGGER.error(\"Test transaction failed\", e);\n      throw e;\n    }\n  }\n}\n"
  },
  {
    "path": "health-check/src/main/java/com/iluwatar/health/check/MemoryHealthIndicator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.health.check;\n\nimport java.lang.management.ManagementFactory;\nimport java.lang.management.MemoryMXBean;\nimport java.lang.management.MemoryUsage;\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.ExecutionException;\nimport java.util.function.Supplier;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.HealthIndicator;\nimport org.springframework.stereotype.Component;\n\n/**\n * A custom health indicator that checks the memory usage of the application and reports the health\n * status accordingly. It uses an asynchronous health checker to perform the health check and a\n * configurable memory usage threshold to determine the health status.\n */\n@Slf4j\n@Component\n@RequiredArgsConstructor\npublic class MemoryHealthIndicator implements HealthIndicator {\n\n  private final AsynchronousHealthChecker asynchronousHealthChecker;\n\n  /** The timeout in seconds for the health check. */\n  @Value(\"${health.check.timeout:10}\")\n  private long timeoutInSeconds;\n\n  /**\n   * The memory usage threshold in percentage. If the memory usage is less than this threshold, the\n   * health status is reported as UP. Otherwise, the health status is reported as DOWN.\n   */\n  @Value(\"${health.check.memory.threshold:0.9}\")\n  private double memoryThreshold;\n\n  /**\n   * Performs a health check by checking the memory usage of the application.\n   *\n   * @return the health status of the application\n   */\n  public Health checkMemory() {\n    Supplier<Health> memoryCheck =\n        () -> {\n          MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean();\n          MemoryUsage heapMemoryUsage = memoryMxBean.getHeapMemoryUsage();\n          long maxMemory = heapMemoryUsage.getMax();\n          long usedMemory = heapMemoryUsage.getUsed();\n\n          double memoryUsage = (double) usedMemory / maxMemory;\n          String format = String.format(\"%.2f%% of %d max\", memoryUsage * 100, maxMemory);\n\n          if (memoryUsage < memoryThreshold) {\n            LOGGER.info(\"Memory usage is below threshold: {}\", format);\n            return Health.up().withDetail(\"memory usage\", format).build();\n          } else {\n            return Health.down().withDetail(\"memory usage\", format).build();\n          }\n        };\n\n    try {\n      CompletableFuture<Health> future =\n          asynchronousHealthChecker.performCheck(memoryCheck, timeoutInSeconds);\n      return future.get();\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Health check interrupted\", e);\n      Thread.currentThread().interrupt();\n      return Health.down().withDetail(\"error\", \"Health check interrupted\").build();\n    } catch (ExecutionException e) {\n      LOGGER.error(\"Health check failed\", e);\n      Throwable cause = e.getCause() == null ? e : e.getCause();\n      return Health.down().withDetail(\"error\", cause.toString()).build();\n    }\n  }\n\n  /**\n   * Retrieves the health status of the application by checking the memory usage.\n   *\n   * @return the health status of the application\n   */\n  @Override\n  public Health health() {\n    return checkMemory();\n  }\n}\n"
  },
  {
    "path": "health-check/src/main/java/com/iluwatar/health/check/RetryConfig.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.health.check;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.retry.backoff.FixedBackOffPolicy;\nimport org.springframework.retry.policy.SimpleRetryPolicy;\nimport org.springframework.retry.support.RetryTemplate;\nimport org.springframework.stereotype.Component;\n\n/** Configuration class for retry policies used in health check operations. */\n@Configuration\n@Component\npublic class RetryConfig {\n\n  /** The backoff period in milliseconds to wait between retry attempts. */\n  @Value(\"${retry.backoff.period:2000}\")\n  private long backOffPeriod;\n\n  /** The maximum number of retry attempts for health check operations. */\n  @Value(\"${retry.max.attempts:3}\")\n  private int maxAttempts;\n\n  /**\n   * Creates a retry template with the configured backoff period and maximum number of attempts.\n   *\n   * @return a retry template\n   */\n  @Bean\n  public RetryTemplate retryTemplate() {\n    RetryTemplate retryTemplate = new RetryTemplate();\n\n    FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();\n    fixedBackOffPolicy.setBackOffPeriod(backOffPeriod); // wait 2 seconds between retries\n    retryTemplate.setBackOffPolicy(fixedBackOffPolicy);\n\n    SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();\n    retryPolicy.setMaxAttempts(maxAttempts); // retry a max of 3 attempts\n    retryTemplate.setRetryPolicy(retryPolicy);\n\n    return retryTemplate;\n  }\n}\n"
  },
  {
    "path": "health-check/src/main/resources/application.properties",
    "content": "server.port=6161\nmanagement.endpoints.web.base-path=/actuator\nmanagement.endpoint.health.probes.enabled=true\nmanagement.health.livenessState.enabled=true\nmanagement.health.readinessState.enabled=true\nmanagement.endpoints.web.exposure.include=health,info\n\nmanagement.endpoint.health.show-details=always\n\n# Enable health check logging\nlogging.level.com.iluwatar.health.check=DEBUG\n\n# H2 Database configuration\nspring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE\nspring.datasource.driverClassName=org.h2.Driver\nspring.datasource.username=sa\nspring.datasource.password=\nspring.jpa.database-platform=org.hibernate.dialect.H2Dialect\n\n# H2 console available at /h2-console\nspring.h2.console.enabled=true\nspring.h2.console.path=/h2-console\n\n# JPA Hibernate ddl auto (none, update, create, create-drop, validate)\nspring.jpa.hibernate.ddl-auto=create\nspring.jpa.properties.hibernate.format_sql=true\nspring.jpa.properties.hibernate.use_sql_comments=true\n\n# Show SQL statements\nspring.jpa.show-sql=true\n\n# Custom health check configuration\nhealth.check.timeout=10\nhealth.check.cache.evict.interval=60000\n\n# CPU health check configuration\ncpu.system.load.threshold=95.0\ncpu.process.load.threshold=70.0\ncpu.load.average.threshold=10.0\ncpu.warning.message=CPU usage is high\n\n# Retry configuration\nretry.backoff.period=2000\nretry.max.attempts=3\n\n# Memory health check configuration\nmemory.usage.threshold = 0.8"
  },
  {
    "path": "health-check/src/test/java/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport com.iluwatar.health.check.App;\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /** Entry point */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "health-check/src/test/java/AsynchronousHealthCheckerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport static org.junit.jupiter.api.Assertions.*;\nimport static org.mockito.Mockito.when;\n\nimport ch.qos.logback.classic.LoggerContext;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.read.ListAppender;\nimport com.iluwatar.health.check.AsynchronousHealthChecker;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.List;\nimport java.util.concurrent.*;\nimport java.util.function.Supplier;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.Status;\n\n/** Tests for {@link AsynchronousHealthChecker}. */\n@Slf4j\nclass AsynchronousHealthCheckerTest {\n\n  /** The {@link AsynchronousHealthChecker} instance to be tested. */\n  private AsynchronousHealthChecker healthChecker;\n\n  private ListAppender<ILoggingEvent> listAppender;\n\n  @Mock private ScheduledExecutorService executorService;\n\n  public AsynchronousHealthCheckerTest() {\n    MockitoAnnotations.openMocks(this);\n  }\n\n  /**\n   * Sets up the test environment before each test method.\n   *\n   * <p>Creates a new {@link AsynchronousHealthChecker} instance.\n   */\n  @BeforeEach\n  void setUp() {\n    healthChecker = new AsynchronousHealthChecker();\n    // Replace the logger with the root logger of logback\n    LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);\n\n    // Create and start a ListAppender\n    LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();\n    listAppender = new ListAppender<>();\n    listAppender.start();\n\n    // Add the appender to the root logger context\n    loggerContext.getLogger(Logger.ROOT_LOGGER_NAME).addAppender(listAppender);\n  }\n\n  /**\n   * Tears down the test environment after each test method.\n   *\n   * <p>Shuts down the {@link AsynchronousHealthChecker} instance to prevent resource leaks.\n   */\n  @AfterEach\n  void tearDown() {\n    healthChecker.shutdown();\n    ((LoggerContext) LoggerFactory.getILoggerFactory()).reset();\n  }\n\n  /**\n   * Tests that the {@link performCheck()} method completes normally when the health supplier\n   * returns a successful health check.\n   *\n   * <p>Given a health supplier that returns a healthy status, the test verifies that the {@link\n   * performCheck()} method completes normally and returns the expected health object.\n   */\n  @Test\n  void whenPerformCheck_thenCompletesNormally() throws ExecutionException, InterruptedException {\n    // Given\n    Supplier<Health> healthSupplier = () -> Health.up().build();\n\n    // When\n    CompletableFuture<Health> healthFuture = healthChecker.performCheck(healthSupplier, 3);\n\n    // Then\n    Health health = healthFuture.get();\n    assertEquals(Health.up().build(), health);\n  }\n\n  /**\n   * Tests that the {@link performCheck()} method returns a healthy health status when the health\n   * supplier returns a healthy status.\n   *\n   * <p>Given a health supplier that returns a healthy status, the test verifies that the {@link\n   * performCheck()} method returns a health object with a status of UP.\n   */\n  @Test\n  void whenHealthCheckIsSuccessful_ReturnsHealthy()\n      throws ExecutionException, InterruptedException {\n    // Arrange\n    Supplier<Health> healthSupplier = () -> Health.up().build();\n\n    // Act\n    CompletableFuture<Health> healthFuture = healthChecker.performCheck(healthSupplier, 4);\n\n    // Assert\n    assertEquals(Status.UP, healthFuture.get().getStatus());\n  }\n\n  /**\n   * Tests that the {@link performCheck()} method rejects new tasks after the {@link shutdown()}\n   * method is called.\n   *\n   * <p>Given the {@link AsynchronousHealthChecker} instance is shut down, the test verifies that\n   * the {@link performCheck()} method throws a {@link RejectedExecutionException} when attempting\n   * to submit a new health check task.\n   */\n  @Test\n  void whenShutdown_thenRejectsNewTasks() {\n    // Given\n    healthChecker.shutdown();\n\n    // When/Then\n    assertThrows(\n        RejectedExecutionException.class,\n        () -> healthChecker.performCheck(() -> Health.up().build(), 2),\n        \"Expected to throw RejectedExecutionException but did not\");\n  }\n\n  /**\n   * Tests that the {@link performCheck()} method returns a healthy health status when the health\n   * supplier returns a healthy status.\n   *\n   * <p>Given a health supplier that throws a RuntimeException, the test verifies that the {@link\n   * performCheck()} method returns a health object with a status of DOWN and an error message\n   * containing the exception message.\n   */\n  @Test\n  void whenHealthCheckThrowsException_thenReturnsDown() {\n    // Arrange\n    Supplier<Health> healthSupplier =\n        () -> {\n          throw new RuntimeException(\"Health check failed\");\n        };\n    // Act\n    CompletableFuture<Health> healthFuture = healthChecker.performCheck(healthSupplier, 10);\n    // Assert\n    Health health = healthFuture.join();\n    assertEquals(Status.DOWN, health.getStatus());\n    String errorMessage = health.getDetails().get(\"error\").toString();\n    assertTrue(errorMessage.contains(\"Health check failed\"));\n  }\n\n  /**\n   * Helper method to check if the log contains a specific message.\n   *\n   * @param action The action that triggers the log statement.\n   * @return True if the log contains the message after the action is performed, false otherwise.\n   */\n  private boolean doesLogContainMessage(Runnable action) {\n    action.run();\n    List<ILoggingEvent> events = listAppender.list;\n    return events.stream()\n        .anyMatch(event -> event.getMessage().contains(\"Health check executor did not terminate\"));\n  }\n\n  /**\n   * Tests that the {@link AsynchronousHealthChecker#shutdown()} method logs an error message when\n   * the executor does not terminate after attempting to cancel tasks.\n   */\n  @Test\n  void whenShutdownExecutorDoesNotTerminateAfterCanceling_LogsErrorMessage() {\n    // Given\n    healthChecker.shutdown(); // To trigger the scenario\n\n    // When/Then\n    boolean containsMessage = doesLogContainMessage(healthChecker::shutdown);\n    if (!containsMessage) {\n      List<ch.qos.logback.classic.spi.ILoggingEvent> events = listAppender.list;\n      LOGGER.info(\"Logged events:\");\n      for (ch.qos.logback.classic.spi.ILoggingEvent event : events) {\n        LOGGER.info(event.getMessage());\n      }\n    }\n    assertTrue(containsMessage, \"Expected log message not found\");\n  }\n\n  /**\n   * Verifies that {@link AsynchronousHealthChecker#awaitTerminationWithTimeout} returns true even\n   * if the executor service does not terminate completely within the specified timeout.\n   *\n   * @throws NoSuchMethodException if the private method cannot be accessed.\n   * @throws InvocationTargetException if the private method throws an exception.\n   * @throws IllegalAccessException if the private method is not accessible.\n   * @throws InterruptedException if the thread is interrupted while waiting for the executor\n   *     service to terminate.\n   */\n  @Test\n  void awaitTerminationWithTimeout_IncompleteTermination_ReturnsTrue()\n      throws NoSuchMethodException,\n          InvocationTargetException,\n          IllegalAccessException,\n          InterruptedException {\n\n    // Mock executor service to return false (incomplete termination)\n    when(executorService.awaitTermination(5, TimeUnit.SECONDS)).thenReturn(false);\n\n    // Use reflection to access the private method for code coverage.\n    Method privateMethod =\n        AsynchronousHealthChecker.class.getDeclaredMethod(\"awaitTerminationWithTimeout\");\n    privateMethod.setAccessible(true);\n\n    // When\n    boolean result = (boolean) privateMethod.invoke(healthChecker);\n\n    // Then\n    assertTrue(result, \"Termination should be incomplete\");\n  }\n}\n"
  },
  {
    "path": "health-check/src/test/java/CpuHealthIndicatorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.health.check.CpuHealthIndicator;\nimport com.sun.management.OperatingSystemMXBean;\nimport java.lang.reflect.Field;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.Status;\n\n/** Test class for the {@link CpuHealthIndicator} class. */\nclass CpuHealthIndicatorTest {\n\n  /** The CPU health indicator to be tested. */\n  private CpuHealthIndicator cpuHealthIndicator;\n\n  /** The mocked operating system MXBean used to simulate CPU health information. */\n  private OperatingSystemMXBean mockOsBean;\n\n  /**\n   * Sets up the test environment before each test method.\n   *\n   * <p>Mocks the {@link OperatingSystemMXBean} and sets it in the {@link CpuHealthIndicator}\n   * instance.\n   */\n  @BeforeEach\n  void setUp() {\n    // Mock the com.sun.management.OperatingSystemMXBean\n    mockOsBean = Mockito.mock(com.sun.management.OperatingSystemMXBean.class);\n    cpuHealthIndicator = new CpuHealthIndicator();\n    setOperatingSystemMXBean(cpuHealthIndicator, mockOsBean);\n  }\n\n  /**\n   * Reflection method to set the private osBean in CpuHealthIndicator.\n   *\n   * @param indicator The CpuHealthIndicator instance to set the osBean for.\n   * @param osBean The OperatingSystemMXBean to set.\n   */\n  private void setOperatingSystemMXBean(\n      CpuHealthIndicator indicator, OperatingSystemMXBean osBean) {\n    try {\n      Field osBeanField = CpuHealthIndicator.class.getDeclaredField(\"osBean\");\n      osBeanField.setAccessible(true);\n      osBeanField.set(indicator, osBean);\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      throw new RuntimeException(e);\n    }\n  }\n\n  /**\n   * Tests that the health status is DOWN when the system CPU load is high.\n   *\n   * <p>Sets the system CPU load to 90% and mocks the other getters to return appropriate values.\n   * Executes the health check and asserts that the health status is DOWN and the error message\n   * indicates high system CPU load.\n   */\n  @Test\n  void whenSystemCpuLoadIsHigh_thenHealthIsDown() {\n    // Set thresholds for testing within the test method to avoid issues with Spring's @Value\n    cpuHealthIndicator.setSystemCpuLoadThreshold(80.0);\n    cpuHealthIndicator.setProcessCpuLoadThreshold(50.0);\n    cpuHealthIndicator.setLoadAverageThreshold(0.75);\n\n    // Mock the getters to return your desired values\n    when(mockOsBean.getCpuLoad()).thenReturn(0.9); // Simulate 90% system CPU load\n    when(mockOsBean.getAvailableProcessors()).thenReturn(8);\n    when(mockOsBean.getSystemLoadAverage()).thenReturn(9.0);\n\n    // Execute the health check\n    Health health = cpuHealthIndicator.health();\n\n    // Assertions\n    assertEquals(\n        Status.DOWN,\n        health.getStatus(),\n        \"Health status should be DOWN when system CPU load is high\");\n    assertEquals(\n        \"High system CPU load\",\n        health.getDetails().get(\"error\"),\n        \"Error message should indicate high system CPU load\");\n  }\n\n  /**\n   * Tests that the health status is DOWN when the process CPU load is high.\n   *\n   * <p>Sets the process CPU load to 80% and mocks the other getters to return appropriate values.\n   * Executes the health check and asserts that the health status is DOWN and the error message\n   * indicates high process CPU load.\n   */\n  @Test\n  void whenProcessCpuLoadIsHigh_thenHealthIsDown() {\n    // Set thresholds for testing within the test method to avoid issues with Spring's @Value\n    cpuHealthIndicator.setSystemCpuLoadThreshold(80.0);\n    cpuHealthIndicator.setProcessCpuLoadThreshold(50.0);\n    cpuHealthIndicator.setLoadAverageThreshold(0.75);\n\n    // Mock the getters to return your desired values\n    when(mockOsBean.getCpuLoad()).thenReturn(0.5); // Simulate 50% system CPU load\n    when(mockOsBean.getProcessCpuLoad()).thenReturn(0.8); // Simulate 80% process CPU load\n    when(mockOsBean.getAvailableProcessors()).thenReturn(8);\n    when(mockOsBean.getSystemLoadAverage()).thenReturn(5.0);\n\n    // Execute the health check\n    Health health = cpuHealthIndicator.health();\n\n    // Assertions\n    assertEquals(\n        Status.DOWN,\n        health.getStatus(),\n        \"Health status should be DOWN when process CPU load is high\");\n    assertEquals(\n        \"High process CPU load\",\n        health.getDetails().get(\"error\"),\n        \"Error message should indicate high process CPU load\");\n  }\n}\n"
  },
  {
    "path": "health-check/src/test/java/CustomHealthIndicatorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.Mockito.any;\nimport static org.mockito.Mockito.doNothing;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.health.check.AsynchronousHealthChecker;\nimport com.iluwatar.health.check.CustomHealthIndicator;\nimport com.iluwatar.health.check.HealthCheckRepository;\nimport java.util.concurrent.CompletableFuture;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.Status;\nimport org.springframework.cache.Cache;\nimport org.springframework.cache.CacheManager;\nimport org.springframework.cache.concurrent.ConcurrentMapCacheManager;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/** Tests class< for {@link CustomHealthIndicator}. * */\nclass CustomHealthIndicatorTest {\n\n  /** Mocked AsynchronousHealthChecker instance. */\n  @Mock private AsynchronousHealthChecker healthChecker;\n\n  /** Mocked CacheManager instance. */\n  @Mock private CacheManager cacheManager;\n\n  /** Mocked HealthCheckRepository instance. */\n  @Mock private HealthCheckRepository healthCheckRepository;\n\n  /** Mocked Cache instance. */\n  @Mock private Cache cache;\n\n  /** `CustomHealthIndicator` instance to be tested. */\n  private CustomHealthIndicator customHealthIndicator;\n\n  /** Sets up the test environment. */\n  @BeforeEach\n  void setUp() {\n    MockitoAnnotations.openMocks(this);\n    when(cacheManager.getCache(\"health-check\")).thenReturn(cache);\n    customHealthIndicator =\n        new CustomHealthIndicator(healthChecker, cacheManager, healthCheckRepository);\n  }\n\n  /**\n   * Test case for the `health()` method when the database is up.\n   *\n   * <p>Asserts that when the `health()` method is called and the database is up, it returns a\n   * Health object with Status.UP.\n   */\n  @Test\n  void whenDatabaseIsUp_thenHealthIsUp() {\n    CompletableFuture<Health> future =\n        CompletableFuture.completedFuture(Health.up().withDetail(\"database\", \"reachable\").build());\n    when(healthChecker.performCheck(any(), anyLong())).thenReturn(future);\n    when(healthCheckRepository.checkHealth()).thenReturn(1);\n\n    Health health = customHealthIndicator.health();\n\n    assertEquals(Status.UP, health.getStatus());\n  }\n\n  /**\n   * Test case for the `health()` method when the database is down.\n   *\n   * <p>Asserts that when the `health()` method is called and the database is down, it returns a\n   * Health object with Status.DOWN.\n   */\n  @Test\n  void whenDatabaseIsDown_thenHealthIsDown() {\n    CompletableFuture<Health> future =\n        CompletableFuture.completedFuture(\n            Health.down().withDetail(\"database\", \"unreachable\").build());\n    when(healthChecker.performCheck(any(), anyLong())).thenReturn(future);\n    when(healthCheckRepository.checkHealth()).thenReturn(null);\n\n    Health health = customHealthIndicator.health();\n\n    assertEquals(Status.DOWN, health.getStatus());\n  }\n\n  /**\n   * Test case for the `health()` method when the health check times out.\n   *\n   * <p>Asserts that when the `health()` method is called and the health check times out, it returns\n   * a Health object with Status.DOWN.\n   */\n  @Test\n  void whenHealthCheckTimesOut_thenHealthIsDown() {\n    CompletableFuture<Health> future = new CompletableFuture<>();\n    when(healthChecker.performCheck(any(), anyLong())).thenReturn(future);\n\n    Health health = customHealthIndicator.health();\n\n    assertEquals(Status.DOWN, health.getStatus());\n  }\n\n  /**\n   * Test case for the `evictHealthCache()` method.\n   *\n   * <p>Asserts that when the `evictHealthCache()` method is called, the health cache is cleared.\n   */\n  @Test\n  void whenEvictHealthCache_thenCacheIsCleared() {\n    doNothing().when(cache).clear();\n\n    customHealthIndicator.evictHealthCache();\n\n    verify(cache, times(1)).clear();\n    verify(cacheManager, times(1)).getCache(\"health-check\");\n  }\n\n  /** Configuration static class for the health check cache. */\n  @Configuration\n  static class CacheConfig {\n    /**\n     * Creates a concurrent map cache manager named \"health-check\".\n     *\n     * @return a new ConcurrentMapCacheManager instance\n     */\n    @Bean\n    public CacheManager cacheManager() {\n      return new ConcurrentMapCacheManager(\"health-check\");\n    }\n  }\n}\n"
  },
  {
    "path": "health-check/src/test/java/DatabaseTransactionHealthIndicatorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.doNothing;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.eq;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.health.check.AsynchronousHealthChecker;\nimport com.iluwatar.health.check.DatabaseTransactionHealthIndicator;\nimport com.iluwatar.health.check.HealthCheckRepository;\nimport java.util.concurrent.CompletableFuture;\nimport java.util.function.Supplier;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.Status;\nimport org.springframework.retry.support.RetryTemplate;\n\n/** Unit tests for the {@link DatabaseTransactionHealthIndicator} class. */\nclass DatabaseTransactionHealthIndicatorTest {\n\n  /** Timeout value in seconds for the health check. */\n  private final long timeoutInSeconds = 4;\n\n  /** Mocked HealthCheckRepository instance. */\n  @Mock private HealthCheckRepository healthCheckRepository;\n\n  /** Mocked AsynchronousHealthChecker instance. */\n  @Mock private AsynchronousHealthChecker asynchronousHealthChecker;\n\n  /** Mocked RetryTemplate instance. */\n  @Mock private RetryTemplate retryTemplate;\n\n  /** `DatabaseTransactionHealthIndicator` instance to be tested. */\n  private DatabaseTransactionHealthIndicator healthIndicator;\n\n  /** Performs initialization before each test method. */\n  @BeforeEach\n  void setUp() {\n    MockitoAnnotations.openMocks(this);\n    healthIndicator =\n        new DatabaseTransactionHealthIndicator(\n            healthCheckRepository, asynchronousHealthChecker, retryTemplate);\n    healthIndicator.setTimeoutInSeconds(timeoutInSeconds);\n  }\n\n  /**\n   * Test case for the `health()` method when the database transaction succeeds.\n   *\n   * <p>Asserts that when the `health()` method is called and the database transaction succeeds, it\n   * returns a Health object with Status.UP.\n   */\n  @Test\n  void whenDatabaseTransactionSucceeds_thenHealthIsUp() throws Exception {\n    CompletableFuture<Health> future = CompletableFuture.completedFuture(Health.up().build());\n    when(asynchronousHealthChecker.performCheck(any(Supplier.class), eq(timeoutInSeconds)))\n        .thenReturn(future);\n\n    // Simulate the health check repository behavior\n    doNothing().when(healthCheckRepository).performTestTransaction();\n\n    // Now call the actual method\n    Health health = healthIndicator.health();\n\n    // Check that the health status is UP\n    assertEquals(Status.UP, health.getStatus());\n  }\n\n  /**\n   * Test case for the `health()` method when the database transaction fails.\n   *\n   * <p>Asserts that when the `health()` method is called and the database transaction fails, it\n   * returns a Health object with Status.DOWN.\n   */\n  @Test\n  void whenDatabaseTransactionFails_thenHealthIsDown() throws Exception {\n    CompletableFuture<Health> future = new CompletableFuture<>();\n    when(asynchronousHealthChecker.performCheck(any(Supplier.class), eq(timeoutInSeconds)))\n        .thenReturn(future);\n\n    // Simulate a database exception during the transaction\n    doThrow(new RuntimeException(\"DB exception\"))\n        .when(healthCheckRepository)\n        .performTestTransaction();\n\n    // Complete the future exceptionally to simulate a failure in the health check\n    future.completeExceptionally(new RuntimeException(\"DB exception\"));\n\n    Health health = healthIndicator.health();\n\n    // Check that the health status is DOWN\n    assertEquals(Status.DOWN, health.getStatus());\n  }\n\n  /**\n   * Test case for the `health()` method when the health check times out.\n   *\n   * <p>Asserts that when the `health()` method is called and the health check times out, it returns\n   * a Health object with Status.DOWN.\n   */\n  @Test\n  void whenHealthCheckTimesOut_thenHealthIsDown() {\n    CompletableFuture<Health> future = new CompletableFuture<>();\n    when(asynchronousHealthChecker.performCheck(any(Supplier.class), eq(timeoutInSeconds)))\n        .thenReturn(future);\n\n    // Complete the future exceptionally to simulate a timeout\n    future.completeExceptionally(new RuntimeException(\"Simulated timeout\"));\n\n    Health health = healthIndicator.health();\n\n    // Check that the health status is DOWN due to timeout\n    assertEquals(Status.DOWN, health.getStatus());\n  }\n}\n"
  },
  {
    "path": "health-check/src/test/java/GarbageCollectionHealthIndicatorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport static org.junit.jupiter.api.Assertions.*;\nimport static org.mockito.Mockito.*;\n\nimport com.iluwatar.health.check.GarbageCollectionHealthIndicator;\nimport java.lang.management.GarbageCollectorMXBean;\nimport java.lang.management.MemoryPoolMXBean;\nimport java.lang.management.MemoryUsage;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.Status;\n\n/** Test class for {@link GarbageCollectionHealthIndicator}. */\nclass GarbageCollectionHealthIndicatorTest {\n\n  /** Mocked garbage collector MXBean. */\n  @Mock private GarbageCollectorMXBean garbageCollectorMXBean;\n\n  /** Mocked memory pool MXBean. */\n  @Mock private MemoryPoolMXBean memoryPoolMXBean;\n\n  /** Garbage collection health indicator instance to be tested. */\n  private GarbageCollectionHealthIndicator healthIndicator;\n\n  /** Set up the test environment before each test case. */\n  @BeforeEach\n  void setUp() {\n    MockitoAnnotations.openMocks(this);\n    healthIndicator =\n        spy(\n            new GarbageCollectionHealthIndicator() {\n              @Override\n              protected List<GarbageCollectorMXBean> getGarbageCollectorMxBeans() {\n                return Collections.singletonList(garbageCollectorMXBean);\n              }\n\n              @Override\n              protected List<MemoryPoolMXBean> getMemoryPoolMxBeans() {\n                return Collections.singletonList(memoryPoolMXBean);\n              }\n            });\n    healthIndicator.setMemoryUsageThreshold(0.8);\n    Locale.setDefault(Locale.US);\n  }\n\n  /** Test case to verify that the health status is up when memory usage is low. */\n  @Test\n  void whenMemoryUsageIsLow_thenHealthIsUp() {\n    when(garbageCollectorMXBean.getCollectionCount()).thenReturn(100L);\n    when(garbageCollectorMXBean.getCollectionTime()).thenReturn(1000L);\n    when(garbageCollectorMXBean.getMemoryPoolNames()).thenReturn(new String[] {\"Eden Space\"});\n\n    when(memoryPoolMXBean.getUsage()).thenReturn(new MemoryUsage(0, 100, 500, 1000));\n    when(memoryPoolMXBean.getName()).thenReturn(\"Eden Space\");\n\n    var health = healthIndicator.health();\n    assertEquals(Status.UP, health.getStatus());\n  }\n\n  /** Test case to verify that the health status contains a warning when memory usage is high. */\n  @Test\n  void whenMemoryUsageIsHigh_thenHealthContainsWarning() {\n    // Arrange\n    double threshold = 0.8; // 80% threshold for test\n    healthIndicator.setMemoryUsageThreshold(threshold);\n\n    String poolName = \"CodeCache\";\n    when(garbageCollectorMXBean.getName()).thenReturn(\"G1 Young Generation\");\n    when(garbageCollectorMXBean.getMemoryPoolNames()).thenReturn(new String[] {poolName});\n\n    long maxMemory = 1000L; // e.g., 1000 bytes\n    long usedMemory = (long) (threshold * maxMemory) + 1; // e.g., 801 bytes to exceed 80% threshold\n    when(memoryPoolMXBean.getUsage())\n        .thenReturn(new MemoryUsage(0, usedMemory, usedMemory, maxMemory));\n    when(memoryPoolMXBean.getName()).thenReturn(poolName);\n\n    // Act\n    Health health = healthIndicator.health();\n\n    // Assert\n    Map<String, Object> gcDetails =\n        (Map<String, Object>) health.getDetails().get(\"G1 Young Generation\");\n    assertNotNull(gcDetails, \"Expected details for 'G1 Young Generation', but none were found.\");\n\n    String memoryPoolsDetail = (String) gcDetails.get(\"memoryPools\");\n    assertNotNull(\n        memoryPoolsDetail, \"Expected memory pool details for 'CodeCache', but none were found.\");\n\n    // Extracting the actual usage reported in the details for comparison\n    String memoryUsageReported = memoryPoolsDetail.split(\": \")[1].trim().replace(\"%\", \"\");\n    double memoryUsagePercentage = Double.parseDouble(memoryUsageReported);\n\n    assertTrue(\n        memoryUsagePercentage > threshold,\n        \"Memory usage percentage should be above the threshold.\");\n\n    String warning = (String) gcDetails.get(\"warning\");\n    assertNotNull(warning, \"Expected a warning for high memory usage, but none was found.\");\n\n    // Check that the warning message is as expected\n    String expectedWarningRegex =\n        String.format(\"Memory pool '%s' usage is high \\\\(\\\\d+\\\\.\\\\d+%%\\\\)\", poolName);\n    assertTrue(\n        warning.matches(expectedWarningRegex),\n        \"Expected a high usage warning, but format is incorrect: \" + warning);\n  }\n\n  /** Test case to verify that the health status is up when there are no garbage collections. */\n  @Test\n  void whenNoGarbageCollections_thenHealthIsUp() {\n    // Arrange: Mock the garbage collector to simulate no collections\n    when(garbageCollectorMXBean.getCollectionCount()).thenReturn(0L);\n    when(garbageCollectorMXBean.getCollectionTime()).thenReturn(0L);\n    when(garbageCollectorMXBean.getName()).thenReturn(\"G1 Young Generation\");\n    when(garbageCollectorMXBean.getMemoryPoolNames()).thenReturn(new String[] {});\n\n    // Act: Perform the health check\n    Health health = healthIndicator.health();\n\n    // Assert: Ensure the health is up and there are no warnings\n    assertEquals(Status.UP, health.getStatus());\n    Map<String, Object> gcDetails =\n        (Map<String, Object>) health.getDetails().get(\"G1 Young Generation\");\n    assertNotNull(gcDetails, \"Expected details for 'G1 Young Generation', but none were found.\");\n    assertNull(\n        gcDetails.get(\"warning\"),\n        \"Expected no warning for 'G1 Young Generation' as there are no collections.\");\n  }\n}\n"
  },
  {
    "path": "health-check/src/test/java/HealthCheckRepositoryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport static org.junit.jupiter.api.Assertions.*;\nimport static org.mockito.Mockito.*;\n\nimport com.iluwatar.health.check.HealthCheck;\nimport com.iluwatar.health.check.HealthCheckRepository;\nimport jakarta.persistence.EntityManager;\nimport jakarta.persistence.Query;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\n/** Tests class for {@link HealthCheckRepository}. */\n@ExtendWith(MockitoExtension.class)\nclass HealthCheckRepositoryTest {\n\n  /** Mocked EntityManager instance. */\n  @Mock private EntityManager entityManager;\n\n  /** `HealthCheckRepository` instance to be tested. */\n  @InjectMocks private HealthCheckRepository healthCheckRepository;\n\n  /**\n   * Test case for the `performTestTransaction()` method.\n   *\n   * <p>Asserts that when the `performTestTransaction()` method is called, it successfully executes\n   * a test transaction.\n   */\n  @Test\n  void whenCheckHealth_thenReturnsOne() {\n    // Arrange\n    Query mockedQuery = mock(Query.class);\n    when(entityManager.createNativeQuery(\"SELECT 1\")).thenReturn(mockedQuery);\n    when(mockedQuery.getSingleResult()).thenReturn(1);\n\n    // Act\n    Integer healthCheckResult = healthCheckRepository.checkHealth();\n\n    // Assert\n    assertNotNull(healthCheckResult);\n    assertEquals(1, healthCheckResult);\n  }\n\n  /**\n   * Test case for the `performTestTransaction()` method.\n   *\n   * <p>Asserts that when the `performTestTransaction()` method is called, it successfully executes\n   * a test transaction.\n   */\n  @Test\n  void whenPerformTestTransaction_thenSucceeds() {\n    // Arrange\n    HealthCheck healthCheck = new HealthCheck();\n    healthCheck.setStatus(\"OK\");\n\n    // Mocking the necessary EntityManager behaviors\n    when(entityManager.find(eq(HealthCheck.class), any())).thenReturn(healthCheck);\n\n    // Act & Assert\n    assertDoesNotThrow(() -> healthCheckRepository.performTestTransaction());\n\n    // Verify the interactions\n    verify(entityManager).persist(any(HealthCheck.class));\n    verify(entityManager).flush();\n    verify(entityManager).remove(any(HealthCheck.class));\n  }\n\n  /**\n   * Test case for the `checkHealth()` method when the database is down.\n   *\n   * <p>Asserts that when the `checkHealth()` method is called and the database is down, it throws a\n   * RuntimeException.\n   */\n  @Test\n  void whenCheckHealth_andDatabaseIsDown_thenThrowsException() {\n    // Arrange\n    when(entityManager.createNativeQuery(\"SELECT 1\")).thenThrow(RuntimeException.class);\n\n    // Act & Assert\n    assertThrows(RuntimeException.class, () -> healthCheckRepository.checkHealth());\n  }\n\n  /**\n   * Test case for the `performTestTransaction()` method when the persist operation fails.\n   *\n   * <p>Asserts that when the `performTestTransaction()` method is called and the persist operation\n   * fails, it throws a RuntimeException.\n   */\n  @Test\n  void whenPerformTestTransaction_andPersistFails_thenThrowsException() {\n    // Arrange\n    doThrow(new RuntimeException()).when(entityManager).persist(any(HealthCheck.class));\n\n    // Act & Assert\n    assertThrows(RuntimeException.class, () -> healthCheckRepository.performTestTransaction());\n\n    // Verify that remove is not called if persist fails\n    verify(entityManager, never()).remove(any(HealthCheck.class));\n  }\n}\n"
  },
  {
    "path": "health-check/src/test/java/HealthEndpointIntegrationTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport static io.restassured.RestAssured.given;\nimport static org.hamcrest.Matchers.equalTo;\n\nimport com.iluwatar.health.check.App;\nimport io.restassured.builder.RequestSpecBuilder;\nimport io.restassured.filter.log.LogDetail;\nimport io.restassured.response.Response;\nimport io.restassured.specification.RequestSpecification;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.context.SpringBootTest.WebEnvironment;\nimport org.springframework.boot.test.web.client.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\n\n/**\n * Integration tests for the health endpoint.\n *\n * <p>* * Log statement for the test case response in case of \"DOWN\" status with high CPU load\n * during pipeline execution. * Note: During pipeline execution, if the health check shows \"DOWN\"\n * status with high CPU load, it is expected behavior. The service checks CPU usage, and if it's not\n * under 90%, it returns this error, example return value:\n * {\"status\":\"DOWN\",\"components\":{\"cpu\":{\"status\":\"DOWN\",\"details\":{\"processCpuLoad\":\"100.00%\", *\n * \"availableProcessors\":2,\"systemCpuLoad\":\"100.00%\",\"loadAverage\":1.97,\"timestamp\":\"2023-11-09T08:34:15.974557865Z\",\n * * \"error\":\"High system CPU load\"}}} *\n */\n@Slf4j\n@SpringBootTest(\n    classes = {App.class},\n    webEnvironment = WebEnvironment.RANDOM_PORT)\nclass HealthEndpointIntegrationTest {\n\n  /** Autowired TestRestTemplate instance for making HTTP requests. */\n  @Autowired private TestRestTemplate restTemplate;\n\n  // Create a RequestSpecification that logs the request details\n  private final RequestSpecification requestSpec =\n      new RequestSpecBuilder().log(LogDetail.ALL).build();\n\n  private String getEndpointBasePath() {\n    return restTemplate.getRootUri() + \"/actuator/health\";\n  }\n\n  // Common method to log response details\n  private void logResponseDetails(Response response) {\n    LOGGER.info(\"Request URI: \" + response.getDetailedCookies());\n    LOGGER.info(\"Response Time: \" + response.getTime() + \"ms\");\n    LOGGER.info(\"Response Status: \" + response.getStatusCode());\n    LOGGER.info(\"Response: \" + response.getBody().asString());\n  }\n\n  /** Test that the health endpoint returns the UP status. */\n  @Test\n  void healthEndpointReturnsUpStatus() {\n    Response response = given(requestSpec).get(getEndpointBasePath()).andReturn();\n    logResponseDetails(response);\n\n    if (response.getStatusCode() == HttpStatus.SERVICE_UNAVAILABLE.value()) {\n      LOGGER.warn(\n          \"Health endpoint returned 503 Service Unavailable. This may be due to pipeline \"\n              + \"configuration. Please check the pipeline logs.\");\n      response.then().assertThat().statusCode(HttpStatus.SERVICE_UNAVAILABLE.value());\n      return;\n    }\n\n    if (response.getStatusCode() != HttpStatus.OK.value()\n        || !\"UP\".equals(response.path(\"status\"))) {\n      LOGGER.error(\"Health endpoint response: \" + response.getBody().asString());\n      LOGGER.error(\"Health endpoint status: \" + response.getStatusCode());\n    }\n\n    response.then().assertThat().statusCode(HttpStatus.OK.value()).body(\"status\", equalTo(\"UP\"));\n  }\n\n  /**\n   * Test that the health endpoint returns complete details about the application's health. If the\n   * status is 503, the test passes without further checks. If the status is 200, additional checks\n   * are performed on various components. In case of a \"DOWN\" status, the test logs the entire\n   * response for visibility.\n   */\n  @Test\n  void healthEndpointReturnsCompleteDetails() {\n    // Make the HTTP request to the health endpoint\n    Response response = given(requestSpec).get(getEndpointBasePath()).andReturn();\n\n    // Log the response details\n    logResponseDetails(response);\n\n    // Check if the status is 503 (SERVICE_UNAVAILABLE)\n    if (response.getStatusCode() == HttpStatus.SERVICE_UNAVAILABLE.value()) {\n      LOGGER.warn(\n          \"Health endpoint returned 503 Service Unavailable. This may be due to CI pipeline \"\n              + \"configuration. Please check the CI pipeline logs.\");\n      response\n          .then()\n          .assertThat()\n          .statusCode(HttpStatus.SERVICE_UNAVAILABLE.value())\n          .log()\n          .all(); // Log the entire response for visibility\n      return;\n    }\n\n    // If status is 200, proceed with additional checks\n    response\n        .then()\n        .assertThat()\n        .statusCode(HttpStatus.OK.value()) // Check that the status is UP\n        .body(\"status\", equalTo(\"UP\")) // Verify the status body is UP\n        .body(\"components.cpu.status\", equalTo(\"UP\")) // Check CPU status\n        .body(\"components.db.status\", equalTo(\"UP\")) // Check DB status\n        .body(\"components.diskSpace.status\", equalTo(\"UP\")) // Check disk space status\n        .body(\"components.ping.status\", equalTo(\"UP\")) // Check ping status\n        .body(\"components.custom.status\", equalTo(\"UP\")); // Check custom component status\n\n    // Check for \"DOWN\" status and high CPU load\n    if (\"DOWN\".equals(response.path(\"status\"))) {\n      LOGGER.error(\"Health endpoint response: \" + response.getBody().asString());\n      LOGGER.error(\"Health endpoint status: \" + response.path(\"status\"));\n      LOGGER.error(\n          \"High CPU load detected: \" + response.path(\"components.cpu.details.processCpuLoad\"));\n    }\n  }\n\n  /**\n   * Test that the liveness endpoint returns the UP status.\n   *\n   * <p>The liveness endpoint is used to indicate whether the application is still running and\n   * responsive.\n   */\n  @Test\n  void livenessEndpointShouldReturnUpStatus() {\n    // Make the HTTP request to the liveness endpoint\n    Response response = given(requestSpec).get(getEndpointBasePath() + \"/liveness\").andReturn();\n\n    // Log the response details\n    logResponseDetails(response);\n\n    // Check if the status is 503 (SERVICE_UNAVAILABLE)\n    if (response.getStatusCode() == HttpStatus.SERVICE_UNAVAILABLE.value()) {\n      LOGGER.warn(\n          \"Liveness endpoint returned 503 Service Unavailable. This may be due to CI pipeline \"\n              + \"configuration. Please check the CI pipeline logs.\");\n      // If status is 503, the test passes without further checks\n      response\n          .then()\n          .assertThat()\n          .statusCode(HttpStatus.SERVICE_UNAVAILABLE.value())\n          .log()\n          .all(); // Log the entire response for visibility\n      return;\n    }\n\n    // If status is 200, proceed with additional checks\n    response.then().assertThat().statusCode(HttpStatus.OK.value()).body(\"status\", equalTo(\"UP\"));\n\n    // Check for \"DOWN\" status and high CPU load\n    if (\"DOWN\".equals(response.path(\"status\"))) {\n      LOGGER.error(\"Liveness endpoint response: \" + response.getBody().asString());\n      LOGGER.error(\"Liveness endpoint status: \" + response.path(\"status\"));\n      LOGGER.error(\n          \"High CPU load detected: \" + response.path(\"components.cpu.details.processCpuLoad\"));\n    }\n  }\n\n  /**\n   * Test that the custom health indicator returns the UP status and additional details.\n   *\n   * <p>The custom health indicator is used to provide more specific information about the health of\n   * a particular component or aspect of the application.\n   */\n  @Test\n  void customHealthIndicatorShouldReturnUpStatusAndDetails() {\n    // Make the HTTP request to the health endpoint\n    Response response = given(requestSpec).get(getEndpointBasePath()).andReturn();\n\n    // Log the response details\n    logResponseDetails(response);\n\n    // Check if the status is 503 (SERVICE_UNAVAILABLE)\n    if (response.getStatusCode() == HttpStatus.SERVICE_UNAVAILABLE.value()) {\n      LOGGER.warn(\n          \"Custom health indicator returned 503 Service Unavailable. This may be due to CI pipeline \"\n              + \"configuration. Please check the CI pipeline logs.\");\n      // If status is 503, the test passes without further checks\n      response\n          .then()\n          .assertThat()\n          .statusCode(HttpStatus.SERVICE_UNAVAILABLE.value())\n          .log()\n          .all(); // Log the entire response for visibility\n      return;\n    }\n\n    // If status is 200, proceed with additional checks\n    response\n        .then()\n        .assertThat()\n        .statusCode(HttpStatus.OK.value()) // Check that the status is UP\n        .body(\"components.custom.status\", equalTo(\"UP\")) // Verify the custom component status\n        .body(\"components.custom.details.database\", equalTo(\"reachable\")); // Verify custom details\n\n    // Check for \"DOWN\" status and high CPU load\n    if (\"DOWN\".equals(response.path(\"status\"))) {\n      LOGGER.error(\"Custom health indicator response: \" + response.getBody().asString());\n      LOGGER.error(\"Custom health indicator status: \" + response.path(\"status\"));\n      LOGGER.error(\n          \"High CPU load detected: \" + response.path(\"components.cpu.details.processCpuLoad\"));\n    }\n  }\n}\n"
  },
  {
    "path": "health-check/src/test/java/MemoryHealthIndicatorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport static org.junit.jupiter.api.Assertions.*;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.health.check.AsynchronousHealthChecker;\nimport com.iluwatar.health.check.MemoryHealthIndicator;\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.ExecutionException;\nimport java.util.function.Supplier;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.Status;\n\n/** Unit tests for {@link MemoryHealthIndicator}. */\n@ExtendWith(MockitoExtension.class)\nclass MemoryHealthIndicatorTest {\n\n  /** Mocked AsynchronousHealthChecker instance. */\n  @Mock private AsynchronousHealthChecker asynchronousHealthChecker;\n\n  /** `MemoryHealthIndicator` instance to be tested. */\n  @InjectMocks private MemoryHealthIndicator memoryHealthIndicator;\n\n  /**\n   * Test case for the `health()` method when memory usage is below the threshold.\n   *\n   * <p>Asserts that when the `health()` method is called and memory usage is below the threshold,\n   * it returns a Health object with Status.UP.\n   */\n  @Test\n  void whenMemoryUsageIsBelowThreshold_thenHealthIsUp() {\n    // Arrange\n    CompletableFuture<Health> future =\n        CompletableFuture.completedFuture(\n            Health.up().withDetail(\"memory usage\", \"50% of max\").build());\n    when(asynchronousHealthChecker.performCheck(any(Supplier.class), anyLong())).thenReturn(future);\n\n    // Act\n    Health health = memoryHealthIndicator.health();\n\n    // Assert\n    assertEquals(Status.UP, health.getStatus());\n    assertEquals(\"50% of max\", health.getDetails().get(\"memory usage\"));\n  }\n\n  /**\n   * Test case for the `health()` method when memory usage is above the threshold.\n   *\n   * <p>Asserts that when the `health()` method is called and memory usage is above the threshold,\n   * it returns a Health object with Status.DOWN.\n   */\n  @Test\n  void whenMemoryUsageIsAboveThreshold_thenHealthIsDown() {\n    // Arrange\n    CompletableFuture<Health> future =\n        CompletableFuture.completedFuture(\n            Health.down().withDetail(\"memory usage\", \"95% of max\").build());\n    when(asynchronousHealthChecker.performCheck(any(Supplier.class), anyLong())).thenReturn(future);\n\n    // Act\n    Health health = memoryHealthIndicator.health();\n\n    // Assert\n    assertEquals(Status.DOWN, health.getStatus());\n    assertEquals(\"95% of max\", health.getDetails().get(\"memory usage\"));\n  }\n\n  /**\n   * Test case for the `health()` method when the health check is interrupted.\n   *\n   * <p>Asserts that when the `health()` method is called and the health check is interrupted, it\n   * returns a Health object with Status DOWN and an error detail indicating the interruption.\n   *\n   * @throws ExecutionException if the future fails to complete\n   * @throws InterruptedException if the thread is interrupted while waiting for the future to\n   *     complete\n   */\n  @Test\n  void whenHealthCheckIsInterrupted_thenHealthIsDown()\n      throws ExecutionException, InterruptedException {\n    // Arrange\n    CompletableFuture<Health> future = mock(CompletableFuture.class);\n    when(asynchronousHealthChecker.performCheck(any(Supplier.class), anyLong())).thenReturn(future);\n    // Simulate InterruptedException when future.get() is called\n    when(future.get()).thenThrow(new InterruptedException(\"Health check interrupted\"));\n\n    // Act\n    Health health = memoryHealthIndicator.health();\n\n    // Assert\n    assertEquals(Status.DOWN, health.getStatus());\n    String errorDetail = (String) health.getDetails().get(\"error\");\n    assertNotNull(errorDetail);\n    assertTrue(errorDetail.contains(\"Health check interrupted\"));\n  }\n\n  /**\n   * Test case for the `health()` method when the health check execution fails.\n   *\n   * <p>Asserts that when the `health()` method is called and the health check execution fails, it\n   * returns a Health object with Status DOWN and an error detail indicating the failure.\n   */\n  @Test\n  void whenHealthCheckExecutionFails_thenHealthIsDown() {\n    // Arrange\n    CompletableFuture<Health> future = new CompletableFuture<>();\n    future.completeExceptionally(\n        new ExecutionException(new RuntimeException(\"Service unavailable\")));\n    when(asynchronousHealthChecker.performCheck(any(Supplier.class), anyLong())).thenReturn(future);\n\n    // Act\n    Health health = memoryHealthIndicator.health();\n\n    // Assert\n    assertEquals(Status.DOWN, health.getStatus());\n    assertTrue(health.getDetails().get(\"error\").toString().contains(\"Service unavailable\"));\n  }\n}\n"
  },
  {
    "path": "health-check/src/test/java/RetryConfigTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.health.check.RetryConfig;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.retry.support.RetryTemplate;\n\n/** Unit tests for the {@link RetryConfig} class. */\n@SpringBootTest(classes = RetryConfig.class)\nclass RetryConfigTest {\n\n  /** Injected RetryTemplate instance. */\n  @Autowired private RetryTemplate retryTemplate;\n\n  /**\n   * Tests that the retry template retries three times with a two-second delay.\n   *\n   * <p>Verifies that the retryable operation is executed three times before throwing an exception,\n   * and that the total elapsed time for the retries is at least four seconds.\n   */\n  @Test\n  void shouldRetryThreeTimesWithTwoSecondDelay() {\n    AtomicInteger attempts = new AtomicInteger();\n    Runnable retryableOperation =\n        () -> {\n          attempts.incrementAndGet();\n          throw new RuntimeException(\"Test exception for retry\");\n        };\n\n    long startTime = System.currentTimeMillis();\n    try {\n      retryTemplate.execute(\n          context -> {\n            retryableOperation.run();\n            return null;\n          });\n    } catch (Exception e) {\n      // Expected exception\n    }\n    long endTime = System.currentTimeMillis();\n\n    assertEquals(3, attempts.get(), \"Should have retried three times\");\n    assertTrue(\n        (endTime - startTime) >= 4000,\n        \"Should have waited at least 4 seconds in total for backoff\");\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/README.md",
    "content": "---\ntitle: \"Hexagonal Architecture Pattern in Java: Decoupling Core Logic for Enhanced Flexibility\"\nshortTitle: Hexagonal Architecture\ndescription: \"Explore the Hexagonal Architecture pattern in Java. Learn how it decouples core logic from external interfaces, enhances maintainability, and improves testability with practical examples.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - Decoupling\n  - Layered architecture\n---\n\n## Also known as\n\n* Ports and Adapters\n\n## Intent of Hexagonal Architecture Design Pattern\n\nHexagonal Architecture, also known as Ports and Adapters, is a design pattern in Java that promotes decoupling of core business logic from external interfaces like databases and user interfaces. This architectural approach enhances maintainability and testability of software systems.\n\n## Detailed Explanation of Hexagonal Architecture Pattern with Real-World Examples\n\nReal-world example\n\n> In online banking systems, Hexagonal Architecture allows core banking logic to remain unaffected by changes in user interfaces or third-party services. This decoupling ensures the system's maintainability and flexibility. In such systems, the core banking logic (like processing transactions, managing accounts, and calculating interest) represents the application's core. This core is then surrounded by various adapters that allow the system to interact with different external interfaces without affecting the business logic. For instance, customers might access their accounts through a web interface, a mobile app, or even through ATM services. Meanwhile, the banking system also needs to interface with external services for credit checks, fraud detection, and interbank transactions. Each of these interfaces interacts with the core banking logic through specific adapters designed to translate the external calls to and from the application's internal APIs. This setup allows the bank to modify or extend its external interfaces without having to alter the core business logic, enhancing flexibility and maintainability.\n\nIn plain words\n\n> Hexagonal Architecture organizes an application into a central core of business logic surrounded by ports and adapters that manage interactions with external systems like user interfaces and databases, allowing the core to remain independent of external concerns.\n\nWikipedia says\n\n> The hexagonal architecture, or ports and adapters architecture, is an architectural pattern used in software design. It aims at creating loosely coupled application components that can be easily connected to their software environment by means of ports and adapters. This makes components exchangeable at any level and facilitates test automation.\n\nArchitecture diagram\n\n![Hexagonal Architecture Diagram](./etc/hexagonal-architecture-diagram.png)\n\n\n## Programmatic Example of Hexagonal Architecture Pattern in Java\n\nThe Hexagonal Architecture, also known as Ports and Adapters, is a design pattern that aims to create a loosely coupled application where the core business logic is isolated from external interfaces like databases, user interfaces, or third-party services. This allows the core application to be independent and easily testable.\n\nThe Java code example below illustrates how Hexagonal Architecture isolates core business logic using dependency injection, making the application highly testable and independent from external components.\n\nIn the provided code, we can see an example of the Hexagonal Architecture pattern in the `App` class and the use of Google's Guice for dependency injection.\n\nThe `App` class is the entry point of the application. It creates an instance of `LotteryAdministration` and `LotteryService` through dependency injection and uses them to handle various tasks.\n\n```java\npublic class App {\n\n  public static void main(String[] args) {\n\n    var injector = Guice.createInjector(new LotteryTestingModule());\n\n    // start new lottery round\n    var administration = injector.getInstance(LotteryAdministration.class);\n    administration.resetLottery();\n\n    // submit some lottery tickets\n    var service = injector.getInstance(LotteryService.class);\n    SampleData.submitTickets(service, 20);\n\n    // perform lottery\n    administration.performLottery();\n  }\n}\n```\n\nThe `LotteryAdministration` class is responsible for managing the lottery rounds. It has methods to start a new round, perform the lottery, and reset the lottery.\n\n```java\npublic class LotteryAdministration {\n\n  private final LotteryTicketRepository repository;\n  private final LotteryEventLog notifications;\n  private final WireTransfers wireTransfers;\n\n  @Inject\n  public LotteryAdministration(LotteryTicketRepository repository, LotteryEventLog notifications,\n                               WireTransfers wireTransfers) {\n    this.repository = repository;\n    this.notifications = notifications;\n    this.wireTransfers = wireTransfers;\n  }\n\n  public Map<LotteryTicketId, LotteryTicket> getAllSubmittedTickets() {\n    return repository.findAll();\n  }\n\n  public LotteryNumbers performLottery() {\n    // Implementation details...\n  }\n\n  public void resetLottery() {\n    repository.deleteAll();\n  }\n}\n```\n\nThe `LotteryService` class is responsible for managing the lottery tickets. It has methods to submit a ticket, check a ticket's status, and get the winning ticket.\n\n```java\npublic class LotteryService {\n\n  private final LotteryTicketRepository repository;\n  private final LotteryEventLog notifications;\n  private final WireTransfers wireTransfers;\n\n  @Inject\n  public LotteryService(LotteryTicketRepository repository, LotteryEventLog notifications,\n                        WireTransfers wireTransfers) {\n    this.repository = repository;\n    this.notifications = notifications;\n    this.wireTransfers = wireTransfers;\n  }\n\n  public Optional<LotteryTicketId> submitTicket(LotteryTicket ticket) {\n    // Implementation details...\n  }\n\n  public LotteryTicketCheckResult checkTicketForPrize(\n      LotteryTicketId id,\n      LotteryNumbers winningNumbers\n  ) {\n    // Implementation details...\n  }\n}\n```\n\nRunning the main function of App class produces the following output:\n\n```\n11:06:58.357 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for calvin@google.com was submitted. Bank account 334-746 was charged for 3 credits.\n11:06:58.359 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for arnold@google.com was submitted. Bank account 114-988 was charged for 3 credits.\n11:06:58.359 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for ollie@google.com was submitted. Bank account 190-045 was charged for 3 credits.\n11:06:58.359 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for peter@google.com was submitted. Bank account 335-886 was charged for 3 credits.\n11:06:58.359 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for ray@google.com was submitted. Bank account 843-073 was charged for 3 credits.\n11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for calvin@google.com was submitted. Bank account 334-746 was charged for 3 credits.\n11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for lisa@google.com was submitted. Bank account 024-653 was charged for 3 credits.\n11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for harriet@google.com was submitted. Bank account 842-404 was charged for 3 credits.\n11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for larry@google.com was submitted. Bank account 734-853 was charged for 3 credits.\n11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for lars@google.com was submitted. Bank account 746-936 was charged for 3 credits.\n11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for tyron@google.com was submitted. Bank account 310-992 was charged for 3 credits.\n11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for xavier@google.com was submitted. Bank account 143-947 was charged for 3 credits.\n11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for kevin@google.com was submitted. Bank account 453-936 was charged for 3 credits.\n11:06:58.360 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for yngwie@google.com was submitted. Bank account 241-465 was charged for 3 credits.\n11:06:58.361 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for calvin@google.com was submitted. Bank account 334-746 was charged for 3 credits.\n11:06:58.361 [main] ERROR com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for larry@google.com could not be submitted because the credit transfer of 3 credits failed.\n11:06:58.362 [main] ERROR com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for larry@google.com could not be submitted because the credit transfer of 3 credits failed.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for mary@google.com was submitted. Bank account 234-987 was charged for 3 credits.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for edwin@google.com was submitted. Bank account 895-345 was charged for 3 credits.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for jacob@google.com was submitted. Bank account 444-766 was charged for 3 credits.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for ollie@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for jacob@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for peter@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for ray@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for calvin@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for lisa@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for harriet@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for larry@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for lars@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for tyron@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for xavier@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for kevin@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for yngwie@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for calvin@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for calvin@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for mary@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for arnold@google.com was checked and unfortunately did not win this time.\n11:06:58.362 [main] INFO com.iluwatar.hexagonal.eventlog.StdOutEventLog -- Lottery ticket for edwin@google.com was checked and unfortunately did not win this time.\n```\n\nIn this example, the `LotteryAdministration` and `LotteryService` classes are the core of the application. They interact with external interfaces like `LotteryTicketRepository`, `LotteryEventLog`, and `WireTransfers` through dependency injection, keeping the core business logic decoupled from external concerns. This is a basic example of the Hexagonal Architecture pattern, where the core application is at the center of input/output systems.\n\n## When to Use the Hexagonal Architecture Pattern in Java\n\nHexagonal Architecture is particularly beneficial in scenarios:\n\n* The application needs to interact with multiple external systems.\n* There is a requirement for high testability and maintainability.\n* The application should remain unaffected by changes in external interfaces.\n\n## Real-World Applications of Hexagonal Architecture Pattern in Java\n\n* Implemented extensively within enterprise applications that leverage frameworks like Spring.\n* Used in microservices architectures to maintain clear boundaries and protocols between services.\n* Adopted in systems that require integration with various databases or external APIs without impacting the business logic.\n\n## Benefits and Trade-offs of Hexagonal Architecture Pattern\n\nBenefits:\n\n* Improved Testability: Allows the core functionality to be tested independently of external components.\n* Flexibility: Facilitates the addition or replacement of components that interact with the application without modifying the core business logic.\n* Maintainability: Reduces dependencies on external interfaces, simplifying upgrades and maintenance.\n\nTrade-offs:\n\n* Complexity: Introduces more abstractions and layers, which can complicate the system design and understanding.\n* Overhead: Might be an over-engineering for simple applications, where simpler architectural patterns could suffice.\n\n## Related Java Design Patterns\n\n* [Layered Architecture](https://java-design-patterns.com/patterns/layers/): Shares the concept of organizing code into responsibilities; however, Hexagonal emphasizes port-based interaction with external elements.\n* Microservices: Often used in conjunction with Hexagonal Architecture to define clear boundaries and protocols between services.\n\n## References and Credits\n\n* [Implementing Domain-Driven Design](https://amzn.to/4dmBjrB)\n* [Building Microservices](https://amzn.to/3UACtrU)\n"
  },
  {
    "path": "hexagonal-architecture/etc/hexagonal-architecture.urm.puml",
    "content": "@startuml\npackage com.iluwatar.hexagonal.sampledata {\n  class SampleData {\n    - PLAYERS : List<PlayerDetails> {static}\n    - RANDOM : SecureRandom {static}\n    + SampleData()\n    - getRandomPlayerDetails() : PlayerDetails {static}\n    + submitTickets(lotteryService : LotteryService, numTickets : int) {static}\n  }\n}\npackage com.iluwatar.hexagonal.service {\n  class ConsoleLottery {\n    - LOGGER : Logger {static}\n    + ConsoleLottery()\n    + main(args : String[]) {static}\n    - printMainMenu() {static}\n    - readString(scanner : Scanner) : String {static}\n  }\n  interface LotteryConsoleService {\n    + addFundsToLotteryAccount(WireTransfers, Scanner) {abstract}\n    + checkTicket(LotteryService, Scanner) {abstract}\n    + queryLotteryAccountFunds(WireTransfers, Scanner) {abstract}\n    + submitTicket(LotteryService, Scanner) {abstract}\n  }\n  class LotteryConsoleServiceImpl {\n    - logger : Logger\n    + LotteryConsoleServiceImpl(logger : Logger)\n    + addFundsToLotteryAccount(bank : WireTransfers, scanner : Scanner)\n    + checkTicket(service : LotteryService, scanner : Scanner)\n    + queryLotteryAccountFunds(bank : WireTransfers, scanner : Scanner)\n    - readString(scanner : Scanner) : String\n    + submitTicket(service : LotteryService, scanner : Scanner)\n  }\n}\npackage com.iluwatar.hexagonal.mongo {\n  class MongoConnectionPropertiesLoader {\n    - DEFAULT_HOST : String {static}\n    - DEFAULT_PORT : int {static}\n    - LOGGER : Logger {static}\n    + MongoConnectionPropertiesLoader()\n    + load() {static}\n  }\n}\npackage com.iluwatar.hexagonal.domain {\n  class LotteryAdministration {\n    - notifications : LotteryEventLog\n    - repository : LotteryTicketRepository\n    - wireTransfers : WireTransfers\n    + LotteryAdministration(repository : LotteryTicketRepository, notifications : LotteryEventLog, wireTransfers : WireTransfers)\n    + getAllSubmittedTickets() : Map<LotteryTicketId, LotteryTicket>\n    + performLottery() : LotteryNumbers\n    + resetLottery()\n  }\n  class LotteryConstants {\n    + PLAYER_MAX_BALANCE : int {static}\n    + PRIZE_AMOUNT : int {static}\n    + SERVICE_BANK_ACCOUNT : String {static}\n    + SERVICE_BANK_ACCOUNT_BALANCE : int {static}\n    + TICKET_PRIZE : int {static}\n    - LotteryConstants()\n  }\n  class LotteryNumbers {\n    + MAX_NUMBER : int {static}\n    + MIN_NUMBER : int {static}\n    + NUM_NUMBERS : int {static}\n    - numbers : Set<Integer>\n    - LotteryNumbers()\n    - LotteryNumbers(givenNumbers : Set<Integer>)\n    # canEqual(other : Object) : boolean\n    + create(givenNumbers : Set<Integer>) : LotteryNumbers {static}\n    + createRandom() : LotteryNumbers {static}\n    + equals(o : Object) : boolean\n    - generateRandomNumbers()\n    + getNumbers() : Set<Integer>\n    + getNumbersAsString() : String\n    + hashCode() : int\n    + toString() : String\n  }\n  -class RandomNumberGenerator {\n    - randomIterator : OfInt\n    + RandomNumberGenerator(min : int, max : int)\n    + nextInt() : int\n  }\n  class LotteryService {\n    - notifications : LotteryEventLog\n    - repository : LotteryTicketRepository\n    - wireTransfers : WireTransfers\n    + LotteryService(repository : LotteryTicketRepository, notifications : LotteryEventLog, wireTransfers : WireTransfers)\n    + checkTicketForPrize(id : LotteryTicketId, winningNumbers : LotteryNumbers) : LotteryTicketCheckResult\n    + submitTicket(ticket : LotteryTicket) : Optional<LotteryTicketId>\n  }\n  class LotteryTicketCheckResult {\n    - prizeAmount : int\n    - result : CheckResult\n    + LotteryTicketCheckResult(result : CheckResult)\n    + LotteryTicketCheckResult(result : CheckResult, prizeAmount : int)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getPrizeAmount() : int\n    + getResult() : CheckResult\n    + hashCode() : int\n  }\n  enum CheckResult {\n    + NO_PRIZE {static}\n    + TICKET_NOT_SUBMITTED {static}\n    + WIN_PRIZE {static}\n    + valueOf(name : String) : CheckResult {static}\n    + values() : CheckResult[] {static}\n  }\n  class LotteryTicketId {\n    - id : int\n    - numAllocated : AtomicInteger {static}\n    + LotteryTicketId()\n    + LotteryTicketId(id : int)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getId() : int\n    + hashCode() : int\n    + toString() : String\n  }\n  class LotteryUtils {\n    - LotteryUtils()\n    + checkTicketForPrize(repository : LotteryTicketRepository, id : LotteryTicketId, winningNumbers : LotteryNumbers) : LotteryTicketCheckResult {static}\n  }\n}\npackage com.iluwatar.hexagonal.banking {\n  class InMemoryBank {\n    - accounts : Map<String, Integer> {static}\n    + InMemoryBank()\n    + getFunds(bankAccount : String) : int\n    + setFunds(bankAccount : String, amount : int)\n    + transferFunds(amount : int, sourceAccount : String, destinationAccount : String) : boolean\n  }\n  class MongoBank {\n    - DEFAULT_ACCOUNTS_COLLECTION : String {static}\n    - DEFAULT_DB : String {static}\n    - accountsCollection : MongoCollection<Document>\n    - database : MongoDatabase\n    - mongoClient : MongoClient\n    + MongoBank()\n    + MongoBank(dbName : String, accountsCollectionName : String)\n    + connect()\n    + connect(dbName : String, accountsCollectionName : String)\n    + getAccountsCollection() : MongoCollection<Document>\n    + getDatabase() : MongoDatabase\n    + getFunds(bankAccount : String) : int\n    + getMongoClient() : MongoClient\n    + setFunds(bankAccount : String, amount : int)\n    + transferFunds(amount : int, sourceAccount : String, destinationAccount : String) : boolean\n  }\n  interface WireTransfers {\n    + getFunds(String) : int {abstract}\n    + setFunds(String, int) {abstract}\n    + transferFunds(int, String, String) : boolean {abstract}\n  }\n}\npackage com.iluwatar.hexagonal.database {\n  class InMemoryTicketRepository {\n    - tickets : Map<LotteryTicketId, LotteryTicket> {static}\n    + InMemoryTicketRepository()\n    + deleteAll()\n    + findAll() : Map<LotteryTicketId, LotteryTicket>\n    + findById(id : LotteryTicketId) : Optional<LotteryTicket>\n    + save(ticket : LotteryTicket) : Optional<LotteryTicketId>\n  }\n  interface LotteryTicketRepository {\n    + deleteAll() {abstract}\n    + findAll() : Map<LotteryTicketId, LotteryTicket> {abstract}\n    + findById(LotteryTicketId) : Optional<LotteryTicket> {abstract}\n    + save(LotteryTicket) : Optional<LotteryTicketId> {abstract}\n  }\n  class MongoTicketRepository {\n    - DEFAULT_COUNTERS_COLLECTION : String {static}\n    - DEFAULT_DB : String {static}\n    - DEFAULT_TICKETS_COLLECTION : String {static}\n    - TICKET_ID : String {static}\n    - countersCollection : MongoCollection<Document>\n    - database : MongoDatabase\n    - mongoClient : MongoClient\n    - ticketsCollection : MongoCollection<Document>\n    + MongoTicketRepository()\n    + MongoTicketRepository(dbName : String, ticketsCollectionName : String, countersCollectionName : String)\n    + connect()\n    + connect(dbName : String, ticketsCollectionName : String, countersCollectionName : String)\n    + deleteAll()\n    - docToTicket(doc : Document) : LotteryTicket\n    + findAll() : Map<LotteryTicketId, LotteryTicket>\n    + findById(id : LotteryTicketId) : Optional<LotteryTicket>\n    + getCountersCollection() : MongoCollection<Document>\n    + getNextId() : int\n    + getTicketsCollection() : MongoCollection<Document>\n    - initCounters()\n    + save(ticket : LotteryTicket) : Optional<LotteryTicketId>\n  }\n}\npackage com.iluwatar.hexagonal {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n}\npackage com.iluwatar.hexagonal.administration {\n  class ConsoleAdministration {\n    - LOGGER : Logger {static}\n    + ConsoleAdministration()\n    + main(args : String[]) {static}\n    - printMainMenu() {static}\n    - readString(scanner : Scanner) : String {static}\n  }\n  interface ConsoleAdministrationSrv {\n    + getAllSubmittedTickets() {abstract}\n    + performLottery() {abstract}\n    + resetLottery() {abstract}\n  }\n  class ConsoleAdministrationSrvImpl {\n    - administration : LotteryAdministration\n    - logger : Logger\n    + ConsoleAdministrationSrvImpl(administration : LotteryAdministration, logger : Logger)\n    + getAllSubmittedTickets()\n    + performLottery()\n    + resetLottery()\n  }\n}\npackage com.iluwatar.hexagonal.eventlog {\n  interface LotteryEventLog {\n    + prizeError(PlayerDetails, int) {abstract}\n    + ticketDidNotWin(PlayerDetails) {abstract}\n    + ticketSubmitError(PlayerDetails) {abstract}\n    + ticketSubmitted(PlayerDetails) {abstract}\n    + ticketWon(PlayerDetails, int) {abstract}\n  }\n  class MongoEventLog {\n    - DEFAULT_DB : String {static}\n    - DEFAULT_EVENTS_COLLECTION : String {static}\n    - EMAIL : String {static}\n    + MESSAGE : String {static}\n    - PHONE : String {static}\n    - database : MongoDatabase\n    - eventsCollection : MongoCollection<Document>\n    - mongoClient : MongoClient\n    - stdOutEventLog : StdOutEventLog\n    + MongoEventLog()\n    + MongoEventLog(dbName : String, eventsCollectionName : String)\n    + connect()\n    + connect(dbName : String, eventsCollectionName : String)\n    + getDatabase() : MongoDatabase\n    + getEventsCollection() : MongoCollection<Document>\n    + getMongoClient() : MongoClient\n    + prizeError(details : PlayerDetails, prizeAmount : int)\n    + ticketDidNotWin(details : PlayerDetails)\n    + ticketSubmitError(details : PlayerDetails)\n    + ticketSubmitted(details : PlayerDetails)\n    + ticketWon(details : PlayerDetails, prizeAmount : int)\n  }\n  class StdOutEventLog {\n    - LOGGER : Logger {static}\n    + StdOutEventLog()\n    + prizeError(details : PlayerDetails, prizeAmount : int)\n    + ticketDidNotWin(details : PlayerDetails)\n    + ticketSubmitError(details : PlayerDetails)\n    + ticketSubmitted(details : PlayerDetails)\n    + ticketWon(details : PlayerDetails, prizeAmount : int)\n  }\n}\nLotteryAdministration -->  \"-wireTransfers\" WireTransfers\nLotteryService -->  \"-notifications\" LotteryEventLog\nLotteryAdministration -->  \"-repository\" LotteryTicketRepository\nMongoEventLog -->  \"-stdOutEventLog\" StdOutEventLog\nLotteryService -->  \"-wireTransfers\" WireTransfers\nLotteryAdministration -->  \"-notifications\" LotteryEventLog\nConsoleAdministrationSrvImpl -->  \"-administration\" LotteryAdministration\nLotteryService -->  \"-repository\" LotteryTicketRepository\nLotteryTicketCheckResult -->  \"-result\" CheckResult\nConsoleAdministrationSrvImpl ..|> ConsoleAdministrationSrv \nInMemoryBank ..|> WireTransfers \nMongoBank ..|> WireTransfers \nInMemoryTicketRepository ..|> LotteryTicketRepository \nMongoTicketRepository ..|> LotteryTicketRepository \nMongoEventLog ..|> LotteryEventLog \nStdOutEventLog ..|> LotteryEventLog \nLotteryConsoleServiceImpl ..|> LotteryConsoleService \n@enduml"
  },
  {
    "path": "hexagonal-architecture/etc/hexagonal.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.10\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" \n  generalizations=\"true\" realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" \n  router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.hexagonal.eventlog.StdOutEventLog\" project=\"hexagonal\"\n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/notifications/StdOutNotifications.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"167\" width=\"235\" x=\"731\" y=\"122\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.hexagonal.banking.InMemoryBank\" project=\"hexagonal\" \n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/InMemoryBank.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"149\" width=\"217\" x=\"1006\" y=\"122\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.hexagonal.domain.LotterySystem\" project=\"hexagonal\"\n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotterySystemImpl.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"167\" width=\"421\" x=\"1263\" y=\"122\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.hexagonal.domain.LotteryTicket\" project=\"hexagonal\" \n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"167\" width=\"278\" x=\"1568\" y=\"347\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.hexagonal.database.InMemoryTicketRepository\" project=\"hexagonal\" \n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/database/InMemoryTicketRepository.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"149\" width=\"265\" x=\"1724\" y=\"122\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"6\" language=\"java\" name=\"com.iluwatar.hexagonal.banking.WireTransfers\" project=\"hexagonal\" \n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/banking/WireTransfers.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"113\" width=\"217\" x=\"1006\" y=\"347\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.hexagonal.domain.LotteryService\" project=\"hexagonal\"\n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/service/ConsoleService.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"113\" width=\"421\" x=\"2029\" y=\"122\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"8\" language=\"java\" name=\"com.iluwatar.hexagonal.database.LotteryTicketRepository\" project=\"hexagonal\" \n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/database/LotteryTicketRepository.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"131\" width=\"265\" x=\"1263\" y=\"347\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"9\" language=\"java\" name=\"com.iluwatar.hexagonal.domain.LotterySystem\" project=\"hexagonal\" \n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotterySystem.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"149\" width=\"421\" x=\"1886\" y=\"347\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"10\" language=\"java\" name=\"com.iluwatar.hexagonal.domain.LotteryNumbers\" project=\"hexagonal\" \n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryNumbers.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"275\" width=\"209\" x=\"1568\" y=\"554\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"11\" language=\"java\" name=\"com.iluwatar.hexagonal.domain.LotteryAdministration\"\n    project=\"hexagonal\" file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/LotteryAdministration.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"113\" width=\"320\" x=\"2808\" y=\"347\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"12\" language=\"java\" name=\"com.iluwatar.hexagonal.domain.LotteryNumbers.RandomNumberGenerator\" \n    project=\"hexagonal\" file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/LotteryNumbers.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"113\" width=\"189\" x=\"1568\" y=\"869\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"13\" language=\"java\" name=\"com.iluwatar.hexagonal.domain.LotteryAdministration\" project=\"hexagonal\"\n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"131\" width=\"320\" x=\"2490\" y=\"122\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"14\" language=\"java\" name=\"com.iluwatar.hexagonal.domain.PlayerDetails\" project=\"hexagonal\" \n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"239\" width=\"222\" x=\"1019\" y=\"554\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"15\" language=\"java\" name=\"com.iluwatar.hexagonal.domain.LotteryService\" project=\"hexagonal\"\n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/service/LotteryService.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"95\" width=\"421\" x=\"2347\" y=\"347\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"16\" language=\"java\" name=\"com.iluwatar.hexagonal.App\" project=\"hexagonal\" \n    file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/App.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"131\" width=\"221\" x=\"470\" y=\"347\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"17\" language=\"java\" name=\"com.iluwatar.hexagonal.eventlog.LotteryEventLog\"\n    project=\"hexagonal\" file=\"/hexagonal/src/main/java/com/iluwatar/hexagonal/notifications/LotteryNotifications.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"149\" width=\"235\" x=\"731\" y=\"347\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <association id=\"18\">    \n    <end type=\"SOURCE\" refId=\"16\" navigable=\"false\">      \n      <attribute id=\"19\" name=\"PLAYERS\"/>      \n      <multiplicity id=\"20\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"14\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"21\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"22\" name=\"wireTransfers\"/>      \n      <multiplicity id=\"23\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"6\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"24\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </realization>  \n  <nesting id=\"25\">    \n    <end type=\"SOURCE\" refId=\"10\"/>    \n    <end type=\"TARGET\" refId=\"12\"/>  \n  </nesting>  \n  <association id=\"26\">    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"27\" name=\"tickets\"/>      \n      <multiplicity id=\"28\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"29\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"17\"/>  \n  </realization>  \n  <realization id=\"30\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"9\"/>  \n  </realization>  \n  <realization id=\"31\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"15\"/>  \n  </realization>  \n  <association id=\"32\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"33\" name=\"lotteryNumbers\"/>      \n      <multiplicity id=\"34\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"10\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"35\">    \n    <end type=\"SOURCE\" refId=\"13\"/>    \n    <end type=\"TARGET\" refId=\"11\"/>  \n  </realization>  \n  <association id=\"36\">    \n    <end type=\"SOURCE\" refId=\"13\" navigable=\"false\">      \n      <attribute id=\"37\" name=\"lotterySystem\"/>      \n      <multiplicity id=\"38\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"9\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"39\">    \n    <end type=\"SOURCE\" refId=\"7\" navigable=\"false\">      \n      <attribute id=\"40\" name=\"lotterySystem\"/>      \n      <multiplicity id=\"41\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"9\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"42\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"43\" name=\"repository\"/>      \n      <multiplicity id=\"44\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"8\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"45\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </realization>  \n  <association id=\"46\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"47\" name=\"notifications\"/>      \n      <multiplicity id=\"48\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"17\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"49\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"50\" name=\"playerDetails\"/>      \n      <multiplicity id=\"51\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"14\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "hexagonal-architecture/etc/hexagonal.urm.puml",
    "content": "@startuml\npackage com.iluwatar.hexagonal.sampledata {\n  class SampleData {\n    - PLAYERS : List<PlayerDetails> {static}\n    - RANDOM : Random {static}\n    + SampleData()\n    - getRandomPlayerDetails() : PlayerDetails {static}\n    + submitTickets(lotteryService : LotteryService, numTickets : int) {static}\n  }\n}\npackage com.iluwatar.hexagonal.service {\n  class ConsoleLottery {\n    - LOGGER : Logger {static}\n    + ConsoleLottery()\n    + main(args : String[]) {static}\n    - printMainMenu() {static}\n    - readString(scanner : Scanner) : String {static}\n  }\n  interface LotteryConsoleService {\n    + addFundsToLotteryAccount(WireTransfers, Scanner) {abstract}\n    + checkTicket(LotteryService, Scanner) {abstract}\n    + queryLotteryAccountFunds(WireTransfers, Scanner) {abstract}\n    + submitTicket(LotteryService, Scanner) {abstract}\n  }\n  class LotteryConsoleServiceImpl {\n    - logger : Logger\n    + LotteryConsoleServiceImpl(logger : Logger)\n    + addFundsToLotteryAccount(bank : WireTransfers, scanner : Scanner)\n    + checkTicket(service : LotteryService, scanner : Scanner)\n    + queryLotteryAccountFunds(bank : WireTransfers, scanner : Scanner)\n    - readString(scanner : Scanner) : String\n    + submitTicket(service : LotteryService, scanner : Scanner)\n  }\n}\npackage com.iluwatar.hexagonal.mongo {\n  class MongoConnectionPropertiesLoader {\n    - DEFAULT_HOST : String {static}\n    - DEFAULT_PORT : int {static}\n    + MongoConnectionPropertiesLoader()\n    + load() {static}\n  }\n}\npackage com.iluwatar.hexagonal.domain {\n  class LotteryAdministration {\n    - notifications : LotteryEventLog\n    - repository : LotteryTicketRepository\n    - wireTransfers : WireTransfers\n    + LotteryAdministration(repository : LotteryTicketRepository, notifications : LotteryEventLog, wireTransfers : WireTransfers)\n    + getAllSubmittedTickets() : Map<LotteryTicketId, LotteryTicket>\n    + performLottery() : LotteryNumbers\n    + resetLottery()\n  }\n  class LotteryConstants {\n    + PLAYER_MAX_BALANCE : int {static}\n    + PRIZE_AMOUNT : int {static}\n    + SERVICE_BANK_ACCOUNT : String {static}\n    + SERVICE_BANK_ACCOUNT_BALANCE : int {static}\n    + TICKET_PRIZE : int {static}\n    - LotteryConstants()\n  }\n  class LotteryNumbers {\n    + MAX_NUMBER : int {static}\n    + MIN_NUMBER : int {static}\n    + NUM_NUMBERS : int {static}\n    - numbers : Set<Integer>\n    - LotteryNumbers()\n    - LotteryNumbers(givenNumbers : Set<Integer>)\n    + create(givenNumbers : Set<Integer>) : LotteryNumbers {static}\n    + createRandom() : LotteryNumbers {static}\n    + equals(obj : Object) : boolean\n    - generateRandomNumbers()\n    + getNumbers() : Set<Integer>\n    + getNumbersAsString() : String\n    + hashCode() : int\n    + toString() : String\n  }\n  -class RandomNumberGenerator {\n    - randomIterator : OfInt\n    + RandomNumberGenerator(min : int, max : int)\n    + nextInt() : int\n  }\n  class LotteryService {\n    - notifications : LotteryEventLog\n    - repository : LotteryTicketRepository\n    - wireTransfers : WireTransfers\n    + LotteryService(repository : LotteryTicketRepository, notifications : LotteryEventLog, wireTransfers : WireTransfers)\n    + checkTicketForPrize(id : LotteryTicketId, winningNumbers : LotteryNumbers) : LotteryTicketCheckResult\n    + submitTicket(ticket : LotteryTicket) : Optional<LotteryTicketId>\n  }\n  class LotteryTicket {\n    - id : LotteryTicketId\n    - lotteryNumbers : LotteryNumbers\n    - playerDetails : PlayerDetails\n    + LotteryTicket(id : LotteryTicketId, details : PlayerDetails, numbers : LotteryNumbers)\n    + equals(obj : Object) : boolean\n    + getId() : LotteryTicketId\n    + getNumbers() : LotteryNumbers\n    + getPlayerDetails() : PlayerDetails\n    + hashCode() : int\n    + setId(id : LotteryTicketId)\n    + toString() : String\n  }\n  class LotteryTicketCheckResult {\n    - checkResult : CheckResult\n    - prizeAmount : int\n    + LotteryTicketCheckResult(result : CheckResult)\n    + LotteryTicketCheckResult(result : CheckResult, amount : int)\n    + equals(obj : Object) : boolean\n    + getPrizeAmount() : int\n    + getResult() : CheckResult\n    + hashCode() : int\n  }\n  enum CheckResult {\n    + NO_PRIZE {static}\n    + TICKET_NOT_SUBMITTED {static}\n    + WIN_PRIZE {static}\n    + valueOf(name : String) : CheckResult {static}\n    + values() : CheckResult[] {static}\n  }\n  class LotteryTicketId {\n    - id : int\n    - numAllocated : AtomicInteger {static}\n    + LotteryTicketId()\n    + LotteryTicketId(id : int)\n    + equals(o : Object) : boolean\n    + getId() : int\n    + hashCode() : int\n    + toString() : String\n  }\n  class LotteryUtils {\n    - LotteryUtils()\n    + checkTicketForPrize(repository : LotteryTicketRepository, id : LotteryTicketId, winningNumbers : LotteryNumbers) : LotteryTicketCheckResult {static}\n  }\n  class PlayerDetails {\n    - bankAccountNumber : String\n    - emailAddress : String\n    - phoneNumber : String\n    + PlayerDetails(email : String, bankAccount : String, phone : String)\n    + equals(obj : Object) : boolean\n    + getBankAccount() : String\n    + getEmail() : String\n    + getPhoneNumber() : String\n    + hashCode() : int\n    + toString() : String\n  }\n}\npackage com.iluwatar.hexagonal.banking {\n  class InMemoryBank {\n    - accounts : Map<String, Integer> {static}\n    + InMemoryBank()\n    + getFunds(bankAccount : String) : int\n    + setFunds(bankAccount : String, amount : int)\n    + transferFunds(amount : int, sourceAccount : String, destinationAccount : String) : boolean\n  }\n  class MongoBank {\n    - DEFAULT_ACCOUNTS_COLLECTION : String {static}\n    - DEFAULT_DB : String {static}\n    - accountsCollection : MongoCollection<Document>\n    - database : MongoDatabase\n    - mongoClient : MongoClient\n    + MongoBank()\n    + MongoBank(dbName : String, accountsCollectionName : String)\n    + connect()\n    + connect(dbName : String, accountsCollectionName : String)\n    + getAccountsCollection() : MongoCollection<Document>\n    + getFunds(bankAccount : String) : int\n    + getMongoClient() : MongoClient\n    + getMongoDatabase() : MongoDatabase\n    + setFunds(bankAccount : String, amount : int)\n    + transferFunds(amount : int, sourceAccount : String, destinationAccount : String) : boolean\n  }\n  interface WireTransfers {\n    + getFunds(String) : int {abstract}\n    + setFunds(String, int) {abstract}\n    + transferFunds(int, String, String) : boolean {abstract}\n  }\n}\npackage com.iluwatar.hexagonal.database {\n  class InMemoryTicketRepository {\n    - tickets : Map<LotteryTicketId, LotteryTicket> {static}\n    + InMemoryTicketRepository()\n    + deleteAll()\n    + findAll() : Map<LotteryTicketId, LotteryTicket>\n    + findById(id : LotteryTicketId) : Optional<LotteryTicket>\n    + save(ticket : LotteryTicket) : Optional<LotteryTicketId>\n  }\n  interface LotteryTicketRepository {\n    + deleteAll() {abstract}\n    + findAll() : Map<LotteryTicketId, LotteryTicket> {abstract}\n    + findById(LotteryTicketId) : Optional<LotteryTicket> {abstract}\n    + save(LotteryTicket) : Optional<LotteryTicketId> {abstract}\n  }\n  class MongoTicketRepository {\n    - DEFAULT_COUNTERS_COLLECTION : String {static}\n    - DEFAULT_DB : String {static}\n    - DEFAULT_TICKETS_COLLECTION : String {static}\n    - countersCollection : MongoCollection<Document>\n    - database : MongoDatabase\n    - mongoClient : MongoClient\n    - ticketsCollection : MongoCollection<Document>\n    + MongoTicketRepository()\n    + MongoTicketRepository(dbName : String, ticketsCollectionName : String, countersCollectionName : String)\n    + connect()\n    + connect(dbName : String, ticketsCollectionName : String, countersCollectionName : String)\n    + deleteAll()\n    - docToTicket(doc : Document) : LotteryTicket\n    + findAll() : Map<LotteryTicketId, LotteryTicket>\n    + findById(id : LotteryTicketId) : Optional<LotteryTicket>\n    + getCountersCollection() : MongoCollection<Document>\n    + getNextId() : int\n    + getTicketsCollection() : MongoCollection<Document>\n    - initCounters()\n    + save(ticket : LotteryTicket) : Optional<LotteryTicketId>\n  }\n}\npackage com.iluwatar.hexagonal {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n}\npackage com.iluwatar.hexagonal.administration {\n  class ConsoleAdministration {\n    - LOGGER : Logger {static}\n    + ConsoleAdministration()\n    + main(args : String[]) {static}\n    - printMainMenu() {static}\n    - readString(scanner : Scanner) : String {static}\n  }\n  interface ConsoleAdministrationSrv {\n    + getAllSubmittedTickets() {abstract}\n    + performLottery() {abstract}\n    + resetLottery() {abstract}\n  }\n  class ConsoleAdministrationSrvImpl {\n    - administration : LotteryAdministration\n    - logger : Logger\n    + ConsoleAdministrationSrvImpl(administration : LotteryAdministration, logger : Logger)\n    + getAllSubmittedTickets()\n    + performLottery()\n    + resetLottery()\n  }\n}\npackage com.iluwatar.hexagonal.eventlog {\n  interface LotteryEventLog {\n    + prizeError(PlayerDetails, int) {abstract}\n    + ticketDidNotWin(PlayerDetails) {abstract}\n    + ticketSubmitError(PlayerDetails) {abstract}\n    + ticketSubmitted(PlayerDetails) {abstract}\n    + ticketWon(PlayerDetails, int) {abstract}\n  }\n  class MongoEventLog {\n    - DEFAULT_DB : String {static}\n    - DEFAULT_EVENTS_COLLECTION : String {static}\n    - database : MongoDatabase\n    - eventsCollection : MongoCollection<Document>\n    - mongoClient : MongoClient\n    - stdOutEventLog : StdOutEventLog\n    + MongoEventLog()\n    + MongoEventLog(dbName : String, eventsCollectionName : String)\n    + connect()\n    + connect(dbName : String, eventsCollectionName : String)\n    + getEventsCollection() : MongoCollection<Document>\n    + getMongoClient() : MongoClient\n    + getMongoDatabase() : MongoDatabase\n    + prizeError(details : PlayerDetails, prizeAmount : int)\n    + ticketDidNotWin(details : PlayerDetails)\n    + ticketSubmitError(details : PlayerDetails)\n    + ticketSubmitted(details : PlayerDetails)\n    + ticketWon(details : PlayerDetails, prizeAmount : int)\n  }\n  class StdOutEventLog {\n    - LOGGER : Logger {static}\n    + StdOutEventLog()\n    + prizeError(details : PlayerDetails, prizeAmount : int)\n    + ticketDidNotWin(details : PlayerDetails)\n    + ticketSubmitError(details : PlayerDetails)\n    + ticketSubmitted(details : PlayerDetails)\n    + ticketWon(details : PlayerDetails, prizeAmount : int)\n  }\n}\nLotteryTicket -->  \"-playerDetails\" PlayerDetails\nMongoEventLog -->  \"-stdOutEventLog\" StdOutEventLog\nLotteryService -->  \"-wireTransfers\" WireTransfers\nLotteryAdministration -->  \"-notifications\" LotteryEventLog\nLotteryAdministration -->  \"-wireTransfers\" WireTransfers\nLotteryTicket -->  \"-id\" LotteryTicketId\nLotteryAdministration -->  \"-repository\" LotteryTicketRepository\nLotteryService -->  \"-notifications\" LotteryEventLog\nLotteryTicket -->  \"-lotteryNumbers\" LotteryNumbers\nSampleData -->  \"-PLAYERS\" PlayerDetails\nConsoleAdministrationSrvImpl -->  \"-administration\" LotteryAdministration\nRandomNumberGenerator ..+ LotteryNumbers\nLotteryService -->  \"-repository\" LotteryTicketRepository\nCheckResult ..+ LotteryTicketCheckResult\nLotteryTicketCheckResult -->  \"-checkResult\" CheckResult\nConsoleAdministrationSrvImpl ..|> ConsoleAdministrationSrv \nInMemoryBank ..|> WireTransfers \nMongoBank ..|> WireTransfers \nInMemoryTicketRepository ..|> LotteryTicketRepository \nMongoTicketRepository ..|> LotteryTicketRepository \nMongoEventLog ..|> LotteryEventLog \nStdOutEventLog ..|> LotteryEventLog \nLotteryConsoleServiceImpl ..|> LotteryConsoleService \n@enduml"
  },
  {
    "path": "hexagonal-architecture/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>hexagonal-architecture</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>com.google.inject</groupId>\n      <artifactId>guice</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>de.flapdoodle.embed</groupId>\n      <artifactId>de.flapdoodle.embed.mongo</artifactId>\n      <version>4.20.0</version>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mongodb</groupId>\n      <artifactId>bson</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.mongodb</groupId>\n      <artifactId>mongodb-driver-legacy</artifactId>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.hexagonal.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal;\n\nimport com.google.inject.Guice;\nimport com.iluwatar.hexagonal.domain.LotteryAdministration;\nimport com.iluwatar.hexagonal.domain.LotteryService;\nimport com.iluwatar.hexagonal.module.LotteryTestingModule;\nimport com.iluwatar.hexagonal.sampledata.SampleData;\n\n/**\n * Hexagonal Architecture pattern decouples the application core from the services it uses. This\n * allows the services to be plugged in and the application will run with or without the services.\n *\n * <p>The core logic, or business logic, of an application consists of the algorithms that are\n * essential to its purpose. They implement the use cases that are the heart of the application.\n * When you change them, you change the essence of the application.\n *\n * <p>The services are not essential. They can be replaced without changing the purpose of the\n * application. Examples: database access and other types of storage, user interface components,\n * e-mail and other communication components, hardware devices.\n *\n * <p>This example demonstrates Hexagonal Architecture with a lottery system. The application core\n * is separate from the services that drive it and from the services it uses.\n *\n * <p>The primary ports for the application are console interfaces {@link\n * com.iluwatar.hexagonal.administration.ConsoleAdministration} through which the lottery round is\n * initiated and run and {@link com.iluwatar.hexagonal.service.ConsoleLottery} that allows players\n * to submit lottery tickets for the draw.\n *\n * <p>The secondary ports that application core uses are{@link\n * com.iluwatar.hexagonal.banking.WireTransfers} which is a banking service, {@link\n * com.iluwatar.hexagonal.eventlog.LotteryEventLog} that delivers eventlog as lottery events occur\n * and {@link com.iluwatar.hexagonal.database.LotteryTicketRepository} that is the storage for the\n * lottery tickets.\n */\npublic class App {\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n\n    var injector = Guice.createInjector(new LotteryTestingModule());\n\n    // start new lottery round\n    var administration = injector.getInstance(LotteryAdministration.class);\n    administration.resetLottery();\n\n    // submit some lottery tickets\n    var service = injector.getInstance(LotteryService.class);\n    SampleData.submitTickets(service, 20);\n\n    // perform lottery\n    administration.performLottery();\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministration.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.administration;\n\nimport com.google.inject.Guice;\nimport com.iluwatar.hexagonal.domain.LotteryAdministration;\nimport com.iluwatar.hexagonal.domain.LotteryService;\nimport com.iluwatar.hexagonal.module.LotteryModule;\nimport com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader;\nimport com.iluwatar.hexagonal.sampledata.SampleData;\nimport java.util.Scanner;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Console interface for lottery administration. */\n@Slf4j\npublic class ConsoleAdministration {\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n    MongoConnectionPropertiesLoader.load();\n    var injector = Guice.createInjector(new LotteryModule());\n    var administration = injector.getInstance(LotteryAdministration.class);\n    var service = injector.getInstance(LotteryService.class);\n    SampleData.submitTickets(service, 20);\n    var consoleAdministration = new ConsoleAdministrationSrvImpl(administration, LOGGER);\n    try (var scanner = new Scanner(System.in)) {\n      var exit = false;\n      while (!exit) {\n        printMainMenu();\n        var cmd = readString(scanner);\n        if (\"1\".equals(cmd)) {\n          consoleAdministration.getAllSubmittedTickets();\n        } else if (\"2\".equals(cmd)) {\n          consoleAdministration.performLottery();\n        } else if (\"3\".equals(cmd)) {\n          consoleAdministration.resetLottery();\n        } else if (\"4\".equals(cmd)) {\n          exit = true;\n        } else {\n          LOGGER.info(\"Unknown command: {}\", cmd);\n        }\n      }\n    }\n  }\n\n  private static void printMainMenu() {\n    LOGGER.info(\"\");\n    LOGGER.info(\"### Lottery Administration Console ###\");\n    LOGGER.info(\"(1) Show all submitted tickets\");\n    LOGGER.info(\"(2) Perform lottery draw\");\n    LOGGER.info(\"(3) Reset lottery ticket database\");\n    LOGGER.info(\"(4) Exit\");\n  }\n\n  private static String readString(Scanner scanner) {\n    LOGGER.info(\"> \");\n    return scanner.next();\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministrationSrv.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.administration;\n\n/** Console interface for lottery administration. */\npublic interface ConsoleAdministrationSrv {\n\n  /** Get all submitted tickets. */\n  void getAllSubmittedTickets();\n\n  /** Draw lottery numbers. */\n  void performLottery();\n\n  /** Begin new lottery round. */\n  void resetLottery();\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/administration/ConsoleAdministrationSrvImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.administration;\n\nimport com.iluwatar.hexagonal.domain.LotteryAdministration;\nimport org.slf4j.Logger;\n\n/** Console implementation for lottery administration. */\npublic class ConsoleAdministrationSrvImpl implements ConsoleAdministrationSrv {\n  private final LotteryAdministration administration;\n  private final Logger logger;\n\n  /** Constructor. */\n  public ConsoleAdministrationSrvImpl(LotteryAdministration administration, Logger logger) {\n    this.administration = administration;\n    this.logger = logger;\n  }\n\n  @Override\n  public void getAllSubmittedTickets() {\n    administration\n        .getAllSubmittedTickets()\n        .forEach((k, v) -> logger.info(\"Key: {}, Value: {}\", k, v));\n  }\n\n  @Override\n  public void performLottery() {\n    var numbers = administration.performLottery();\n    logger.info(\"The winning numbers: {}\", numbers.getNumbersAsString());\n    logger.info(\"Time to reset the database for next round, eh?\");\n  }\n\n  @Override\n  public void resetLottery() {\n    administration.resetLottery();\n    logger.info(\"The lottery ticket database was cleared.\");\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/banking/InMemoryBank.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.banking;\n\nimport com.iluwatar.hexagonal.domain.LotteryConstants;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/** Banking implementation. */\npublic class InMemoryBank implements WireTransfers {\n\n  private static final Map<String, Integer> accounts = new HashMap<>();\n\n  static {\n    accounts.put(\n        LotteryConstants.SERVICE_BANK_ACCOUNT, LotteryConstants.SERVICE_BANK_ACCOUNT_BALANCE);\n  }\n\n  @Override\n  public void setFunds(String bankAccount, int amount) {\n    accounts.put(bankAccount, amount);\n  }\n\n  @Override\n  public int getFunds(String bankAccount) {\n    return accounts.getOrDefault(bankAccount, 0);\n  }\n\n  @Override\n  public boolean transferFunds(int amount, String sourceAccount, String destinationAccount) {\n    if (accounts.getOrDefault(sourceAccount, 0) >= amount) {\n      accounts.put(sourceAccount, accounts.get(sourceAccount) - amount);\n      accounts.put(destinationAccount, accounts.get(destinationAccount) + amount);\n      return true;\n    } else {\n      return false;\n    }\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/banking/MongoBank.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.banking;\n\nimport com.mongodb.MongoClient;\nimport com.mongodb.client.MongoCollection;\nimport com.mongodb.client.MongoDatabase;\nimport com.mongodb.client.model.UpdateOptions;\nimport java.util.ArrayList;\nimport lombok.Getter;\nimport org.bson.Document;\n\n/** Mongo based banking adapter. */\npublic class MongoBank implements WireTransfers {\n\n  private static final String DEFAULT_DB = \"lotteryDB\";\n  private static final String DEFAULT_ACCOUNTS_COLLECTION = \"accounts\";\n\n  @Getter private MongoClient mongoClient;\n  @Getter private MongoDatabase database;\n  @Getter private MongoCollection<Document> accountsCollection;\n\n  /** Constructor. */\n  public MongoBank() {\n    connect();\n  }\n\n  /** Constructor accepting parameters. */\n  public MongoBank(String dbName, String accountsCollectionName) {\n    connect(dbName, accountsCollectionName);\n  }\n\n  /** Connect to database with default parameters. */\n  public void connect() {\n    connect(DEFAULT_DB, DEFAULT_ACCOUNTS_COLLECTION);\n  }\n\n  /** Connect to database with given parameters. */\n  public void connect(String dbName, String accountsCollectionName) {\n    if (mongoClient != null) {\n      mongoClient.close();\n    }\n    mongoClient =\n        new MongoClient(\n            System.getProperty(\"mongo-host\"), Integer.parseInt(System.getProperty(\"mongo-port\")));\n    database = mongoClient.getDatabase(dbName);\n    accountsCollection = database.getCollection(accountsCollectionName);\n  }\n\n  @Override\n  public void setFunds(String bankAccount, int amount) {\n    var search = new Document(\"_id\", bankAccount);\n    var update = new Document(\"_id\", bankAccount).append(\"funds\", amount);\n    var updateOptions = new UpdateOptions().upsert(true);\n    accountsCollection.updateOne(search, new Document(\"$set\", update), updateOptions);\n  }\n\n  @Override\n  public int getFunds(String bankAccount) {\n    return accountsCollection\n        .find(new Document(\"_id\", bankAccount))\n        .limit(1)\n        .into(new ArrayList<>())\n        .stream()\n        .findFirst()\n        .map(x -> x.getInteger(\"funds\"))\n        .orElse(0);\n  }\n\n  @Override\n  public boolean transferFunds(int amount, String sourceAccount, String destinationAccount) {\n    var sourceFunds = getFunds(sourceAccount);\n    if (sourceFunds < amount) {\n      return false;\n    } else {\n      var destFunds = getFunds(destinationAccount);\n      setFunds(sourceAccount, sourceFunds - amount);\n      setFunds(destinationAccount, destFunds + amount);\n      return true;\n    }\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/banking/WireTransfers.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.banking;\n\n/** Interface to bank accounts. */\npublic interface WireTransfers {\n\n  /** Set amount of funds for bank account. */\n  void setFunds(String bankAccount, int amount);\n\n  /** Get amount of funds for bank account. */\n  int getFunds(String bankAccount);\n\n  /** Transfer funds from one bank account to another. */\n  boolean transferFunds(int amount, String sourceBackAccount, String destinationBankAccount);\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/database/InMemoryTicketRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.database;\n\nimport com.iluwatar.hexagonal.domain.LotteryTicket;\nimport com.iluwatar.hexagonal.domain.LotteryTicketId;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Optional;\n\n/** Mock database for lottery tickets. */\npublic class InMemoryTicketRepository implements LotteryTicketRepository {\n\n  private static final Map<LotteryTicketId, LotteryTicket> tickets = new HashMap<>();\n\n  @Override\n  public Optional<LotteryTicket> findById(LotteryTicketId id) {\n    return Optional.ofNullable(tickets.get(id));\n  }\n\n  @Override\n  public Optional<LotteryTicketId> save(LotteryTicket ticket) {\n    var id = new LotteryTicketId();\n    tickets.put(id, ticket);\n    return Optional.of(id);\n  }\n\n  @Override\n  public Map<LotteryTicketId, LotteryTicket> findAll() {\n    return tickets;\n  }\n\n  @Override\n  public void deleteAll() {\n    tickets.clear();\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/database/LotteryTicketRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.database;\n\nimport com.iluwatar.hexagonal.domain.LotteryTicket;\nimport com.iluwatar.hexagonal.domain.LotteryTicketId;\nimport java.util.Map;\nimport java.util.Optional;\n\n/** Interface for accessing lottery tickets in database. */\npublic interface LotteryTicketRepository {\n\n  /** Find lottery ticket by id. */\n  Optional<LotteryTicket> findById(LotteryTicketId id);\n\n  /** Save lottery ticket. */\n  Optional<LotteryTicketId> save(LotteryTicket ticket);\n\n  /** Get all lottery tickets. */\n  Map<LotteryTicketId, LotteryTicket> findAll();\n\n  /** Delete all lottery tickets. */\n  void deleteAll();\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/database/MongoTicketRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.database;\n\nimport com.iluwatar.hexagonal.domain.LotteryNumbers;\nimport com.iluwatar.hexagonal.domain.LotteryTicket;\nimport com.iluwatar.hexagonal.domain.LotteryTicketId;\nimport com.iluwatar.hexagonal.domain.PlayerDetails;\nimport com.mongodb.MongoClient;\nimport com.mongodb.client.MongoCollection;\nimport com.mongodb.client.MongoDatabase;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\nimport lombok.Getter;\nimport org.bson.Document;\n\n/** Mongo lottery ticket database. */\npublic class MongoTicketRepository implements LotteryTicketRepository {\n\n  private static final String DEFAULT_DB = \"lotteryDB\";\n  private static final String DEFAULT_TICKETS_COLLECTION = \"lotteryTickets\";\n  private static final String DEFAULT_COUNTERS_COLLECTION = \"counters\";\n  private static final String TICKET_ID = \"ticketId\";\n\n  private MongoClient mongoClient;\n  private MongoDatabase database;\n  @Getter private MongoCollection<Document> ticketsCollection;\n  @Getter private MongoCollection<Document> countersCollection;\n\n  /** Constructor. */\n  public MongoTicketRepository() {\n    connect();\n  }\n\n  /** Constructor accepting parameters. */\n  public MongoTicketRepository(\n      String dbName, String ticketsCollectionName, String countersCollectionName) {\n    connect(dbName, ticketsCollectionName, countersCollectionName);\n  }\n\n  /** Connect to database with default parameters. */\n  public void connect() {\n    connect(DEFAULT_DB, DEFAULT_TICKETS_COLLECTION, DEFAULT_COUNTERS_COLLECTION);\n  }\n\n  /** Connect to database with given parameters. */\n  public void connect(String dbName, String ticketsCollectionName, String countersCollectionName) {\n    if (mongoClient != null) {\n      mongoClient.close();\n    }\n    mongoClient =\n        new MongoClient(\n            System.getProperty(\"mongo-host\"), Integer.parseInt(System.getProperty(\"mongo-port\")));\n    database = mongoClient.getDatabase(dbName);\n    ticketsCollection = database.getCollection(ticketsCollectionName);\n    countersCollection = database.getCollection(countersCollectionName);\n    if (countersCollection.countDocuments() <= 0) {\n      initCounters();\n    }\n  }\n\n  private void initCounters() {\n    var doc = new Document(\"_id\", TICKET_ID).append(\"seq\", 1);\n    countersCollection.insertOne(doc);\n  }\n\n  /**\n   * Get next ticket id.\n   *\n   * @return next ticket id\n   */\n  public int getNextId() {\n    var find = new Document(\"_id\", TICKET_ID);\n    var increase = new Document(\"seq\", 1);\n    var update = new Document(\"$inc\", increase);\n    var result = countersCollection.findOneAndUpdate(find, update);\n    return result.getInteger(\"seq\");\n  }\n\n  @Override\n  public Optional<LotteryTicket> findById(LotteryTicketId id) {\n    return ticketsCollection\n        .find(new Document(TICKET_ID, id.getId()))\n        .limit(1)\n        .into(new ArrayList<>())\n        .stream()\n        .findFirst()\n        .map(this::docToTicket);\n  }\n\n  @Override\n  public Optional<LotteryTicketId> save(LotteryTicket ticket) {\n    var ticketId = getNextId();\n    var doc = new Document(TICKET_ID, ticketId);\n    doc.put(\"email\", ticket.playerDetails().email());\n    doc.put(\"bank\", ticket.playerDetails().bankAccount());\n    doc.put(\"phone\", ticket.playerDetails().phoneNumber());\n    doc.put(\"numbers\", ticket.lotteryNumbers().getNumbersAsString());\n    ticketsCollection.insertOne(doc);\n    return Optional.of(new LotteryTicketId(ticketId));\n  }\n\n  @Override\n  public Map<LotteryTicketId, LotteryTicket> findAll() {\n    return ticketsCollection.find(new Document()).into(new ArrayList<>()).stream()\n        .map(this::docToTicket)\n        .collect(Collectors.toMap(LotteryTicket::id, Function.identity()));\n  }\n\n  @Override\n  public void deleteAll() {\n    ticketsCollection.deleteMany(new Document());\n  }\n\n  private LotteryTicket docToTicket(Document doc) {\n    var playerDetails =\n        new PlayerDetails(doc.getString(\"email\"), doc.getString(\"bank\"), doc.getString(\"phone\"));\n    var numbers =\n        Arrays.stream(doc.getString(\"numbers\").split(\",\"))\n            .map(Integer::parseInt)\n            .collect(Collectors.toSet());\n    var lotteryNumbers = LotteryNumbers.create(numbers);\n    var ticketId = new LotteryTicketId(doc.getInteger(TICKET_ID));\n    return new LotteryTicket(ticketId, playerDetails, lotteryNumbers);\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/domain/LotteryAdministration.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\nimport static com.iluwatar.hexagonal.domain.LotteryConstants.PRIZE_AMOUNT;\nimport static com.iluwatar.hexagonal.domain.LotteryConstants.SERVICE_BANK_ACCOUNT;\n\nimport com.google.inject.Inject;\nimport com.iluwatar.hexagonal.banking.WireTransfers;\nimport com.iluwatar.hexagonal.database.LotteryTicketRepository;\nimport com.iluwatar.hexagonal.eventlog.LotteryEventLog;\nimport java.util.Map;\n\n/** Lottery administration implementation. */\npublic class LotteryAdministration {\n\n  private final LotteryTicketRepository repository;\n  private final LotteryEventLog notifications;\n  private final WireTransfers wireTransfers;\n\n  /** Constructor. */\n  @Inject\n  public LotteryAdministration(\n      LotteryTicketRepository repository,\n      LotteryEventLog notifications,\n      WireTransfers wireTransfers) {\n    this.repository = repository;\n    this.notifications = notifications;\n    this.wireTransfers = wireTransfers;\n  }\n\n  /** Get all the lottery tickets submitted for lottery. */\n  public Map<LotteryTicketId, LotteryTicket> getAllSubmittedTickets() {\n    return repository.findAll();\n  }\n\n  /** Draw lottery numbers. */\n  public LotteryNumbers performLottery() {\n    var numbers = LotteryNumbers.createRandom();\n    var tickets = getAllSubmittedTickets();\n    for (var id : tickets.keySet()) {\n      var lotteryTicket = tickets.get(id);\n      var playerDetails = lotteryTicket.playerDetails();\n      var playerAccount = playerDetails.bankAccount();\n      var result = LotteryUtils.checkTicketForPrize(repository, id, numbers).getResult();\n      if (result == LotteryTicketCheckResult.CheckResult.WIN_PRIZE) {\n        if (wireTransfers.transferFunds(PRIZE_AMOUNT, SERVICE_BANK_ACCOUNT, playerAccount)) {\n          notifications.ticketWon(playerDetails, PRIZE_AMOUNT);\n        } else {\n          notifications.prizeError(playerDetails, PRIZE_AMOUNT);\n        }\n      } else if (result == LotteryTicketCheckResult.CheckResult.NO_PRIZE) {\n        notifications.ticketDidNotWin(playerDetails);\n      }\n    }\n    return numbers;\n  }\n\n  /** Begin new lottery round. */\n  public void resetLottery() {\n    repository.deleteAll();\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/domain/LotteryConstants.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\n/** Lottery domain constants. */\npublic class LotteryConstants {\n\n  private LotteryConstants() {}\n\n  public static final int PRIZE_AMOUNT = 100000;\n  public static final String SERVICE_BANK_ACCOUNT = \"123-123\";\n  public static final int TICKET_PRIZE = 3;\n  public static final int SERVICE_BANK_ACCOUNT_BALANCE = 150000;\n  public static final int PLAYER_MAX_BALANCE = 100;\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/domain/LotteryNumbers.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\nimport com.google.common.base.Joiner;\nimport java.security.SecureRandom;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.PrimitiveIterator;\nimport java.util.Set;\nimport lombok.EqualsAndHashCode;\nimport lombok.ToString;\n\n/**\n * Value object representing lottery numbers. This lottery uses sets of 4 numbers. The numbers must\n * be unique and between 1 and 20.\n */\n@EqualsAndHashCode\n@ToString\npublic class LotteryNumbers {\n\n  private final Set<Integer> numbers;\n\n  public static final int MIN_NUMBER = 1;\n  public static final int MAX_NUMBER = 20;\n  public static final int NUM_NUMBERS = 4;\n\n  /** Constructor. Creates random lottery numbers. */\n  private LotteryNumbers() {\n    numbers = new HashSet<>();\n    generateRandomNumbers();\n  }\n\n  /** Constructor. Uses given numbers. */\n  private LotteryNumbers(Set<Integer> givenNumbers) {\n    numbers = new HashSet<>();\n    numbers.addAll(givenNumbers);\n  }\n\n  /**\n   * Creates a random lottery number.\n   *\n   * @return random LotteryNumbers\n   */\n  public static LotteryNumbers createRandom() {\n    return new LotteryNumbers();\n  }\n\n  /**\n   * Creates lottery number from given set of numbers.\n   *\n   * @return given LotteryNumbers\n   */\n  public static LotteryNumbers create(Set<Integer> givenNumbers) {\n    return new LotteryNumbers(givenNumbers);\n  }\n\n  /**\n   * Get numbers.\n   *\n   * @return lottery numbers\n   */\n  public Set<Integer> getNumbers() {\n    return Collections.unmodifiableSet(numbers);\n  }\n\n  /**\n   * Get numbers as string.\n   *\n   * @return numbers as comma separated string\n   */\n  public String getNumbersAsString() {\n    return Joiner.on(',').join(numbers);\n  }\n\n  /** Generates 4 unique random numbers between 1-20 into numbers set. */\n  private void generateRandomNumbers() {\n    numbers.clear();\n    var generator = new RandomNumberGenerator(MIN_NUMBER, MAX_NUMBER);\n    while (numbers.size() < NUM_NUMBERS) {\n      var num = generator.nextInt();\n      numbers.add(num);\n    }\n  }\n\n  /** Helper class for generating random numbers. */\n  private static class RandomNumberGenerator {\n\n    private final PrimitiveIterator.OfInt randomIterator;\n\n    /**\n     * Initialize a new random number generator that generates random numbers in the range [min,\n     * max].\n     *\n     * @param min the min value (inclusive)\n     * @param max the max value (inclusive)\n     */\n    public RandomNumberGenerator(int min, int max) {\n      randomIterator = new SecureRandom().ints(min, max + 1).iterator();\n    }\n\n    /**\n     * Gets next random integer in [min, max] range.\n     *\n     * @return a random number in the range (min, max)\n     */\n    public int nextInt() {\n      return randomIterator.nextInt();\n    }\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/domain/LotteryService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\nimport static com.iluwatar.hexagonal.domain.LotteryConstants.SERVICE_BANK_ACCOUNT;\nimport static com.iluwatar.hexagonal.domain.LotteryConstants.TICKET_PRIZE;\n\nimport com.google.inject.Inject;\nimport com.iluwatar.hexagonal.banking.WireTransfers;\nimport com.iluwatar.hexagonal.database.LotteryTicketRepository;\nimport com.iluwatar.hexagonal.eventlog.LotteryEventLog;\nimport java.util.Optional;\n\n/** Implementation for lottery service. */\npublic class LotteryService {\n\n  private final LotteryTicketRepository repository;\n  private final LotteryEventLog notifications;\n  private final WireTransfers wireTransfers;\n\n  /** Constructor. */\n  @Inject\n  public LotteryService(\n      LotteryTicketRepository repository,\n      LotteryEventLog notifications,\n      WireTransfers wireTransfers) {\n    this.repository = repository;\n    this.notifications = notifications;\n    this.wireTransfers = wireTransfers;\n  }\n\n  /** Submit lottery ticket to participate in the lottery. */\n  public Optional<LotteryTicketId> submitTicket(LotteryTicket ticket) {\n    var playerDetails = ticket.playerDetails();\n    var playerAccount = playerDetails.bankAccount();\n    var result = wireTransfers.transferFunds(TICKET_PRIZE, playerAccount, SERVICE_BANK_ACCOUNT);\n    if (!result) {\n      notifications.ticketSubmitError(playerDetails);\n      return Optional.empty();\n    }\n    var optional = repository.save(ticket);\n    if (optional.isPresent()) {\n      notifications.ticketSubmitted(playerDetails);\n    }\n    return optional;\n  }\n\n  /** Check if lottery ticket has won. */\n  public LotteryTicketCheckResult checkTicketForPrize(\n      LotteryTicketId id, LotteryNumbers winningNumbers) {\n    return LotteryUtils.checkTicketForPrize(repository, id, winningNumbers);\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicket.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\n/** Immutable value object representing lottery ticket. */\npublic record LotteryTicket(\n    LotteryTicketId id, PlayerDetails playerDetails, LotteryNumbers lotteryNumbers) {\n\n  @Override\n  public int hashCode() {\n    final var prime = 31;\n    var result = 1;\n    result = prime * result + ((lotteryNumbers == null) ? 0 : lotteryNumbers.hashCode());\n    result = prime * result + ((playerDetails == null) ? 0 : playerDetails.hashCode());\n    return result;\n  }\n\n  @Override\n  public boolean equals(Object obj) {\n    if (this == obj) {\n      return true;\n    }\n    if (obj == null) {\n      return false;\n    }\n    if (getClass() != obj.getClass()) {\n      return false;\n    }\n    var other = (LotteryTicket) obj;\n    if (lotteryNumbers == null) {\n      if (other.lotteryNumbers != null) {\n        return false;\n      }\n    } else if (!lotteryNumbers.equals(other.lotteryNumbers)) {\n      return false;\n    }\n    if (playerDetails == null) {\n      return other.playerDetails == null;\n    } else {\n      return playerDetails.equals(other.playerDetails);\n    }\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResult.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/** Represents lottery ticket check result. */\n@Getter\n@EqualsAndHashCode\n@RequiredArgsConstructor\npublic class LotteryTicketCheckResult {\n\n  /** Enumeration of Type of Outcomes of a Lottery. */\n  public enum CheckResult {\n    WIN_PRIZE,\n    NO_PRIZE,\n    TICKET_NOT_SUBMITTED\n  }\n\n  private final CheckResult result;\n  private final int prizeAmount;\n\n  /** Constructor. */\n  public LotteryTicketCheckResult(CheckResult result) {\n    this.result = result;\n    prizeAmount = 0;\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/domain/LotteryTicketId.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\nimport java.util.concurrent.atomic.AtomicInteger;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/** Lottery ticked id. */\n@Getter\n@EqualsAndHashCode\n@RequiredArgsConstructor\npublic class LotteryTicketId {\n\n  private static final AtomicInteger numAllocated = new AtomicInteger(0);\n  private final int id;\n\n  public LotteryTicketId() {\n    this.id = numAllocated.incrementAndGet();\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\"%d\", id);\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/domain/LotteryUtils.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\nimport com.iluwatar.hexagonal.database.LotteryTicketRepository;\nimport com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult;\n\n/** Lottery utilities. */\npublic class LotteryUtils {\n\n  private LotteryUtils() {}\n\n  /** Checks if lottery ticket has won. */\n  public static LotteryTicketCheckResult checkTicketForPrize(\n      LotteryTicketRepository repository, LotteryTicketId id, LotteryNumbers winningNumbers) {\n    var optional = repository.findById(id);\n    if (optional.isPresent()) {\n      if (optional.get().lotteryNumbers().equals(winningNumbers)) {\n        return new LotteryTicketCheckResult(CheckResult.WIN_PRIZE, 1000);\n      } else {\n        return new LotteryTicketCheckResult(CheckResult.NO_PRIZE);\n      }\n    } else {\n      return new LotteryTicketCheckResult(CheckResult.TICKET_NOT_SUBMITTED);\n    }\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/domain/PlayerDetails.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\n/** Immutable value object containing lottery player details. */\npublic record PlayerDetails(String email, String bankAccount, String phoneNumber) {}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/eventlog/LotteryEventLog.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.eventlog;\n\nimport com.iluwatar.hexagonal.domain.PlayerDetails;\n\n/** Event log for lottery events. */\npublic interface LotteryEventLog {\n\n  /** lottery ticket submitted. */\n  void ticketSubmitted(PlayerDetails details);\n\n  /** error submitting lottery ticket. */\n  void ticketSubmitError(PlayerDetails details);\n\n  /** lottery ticket did not win. */\n  void ticketDidNotWin(PlayerDetails details);\n\n  /** lottery ticket won. */\n  void ticketWon(PlayerDetails details, int prizeAmount);\n\n  /** error paying the prize. */\n  void prizeError(PlayerDetails details, int prizeAmount);\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/eventlog/MongoEventLog.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.eventlog;\n\nimport com.iluwatar.hexagonal.domain.PlayerDetails;\nimport com.mongodb.MongoClient;\nimport com.mongodb.client.MongoCollection;\nimport com.mongodb.client.MongoDatabase;\nimport lombok.Getter;\nimport org.bson.Document;\n\n/** Mongo based event log. */\npublic class MongoEventLog implements LotteryEventLog {\n\n  private static final String DEFAULT_DB = \"lotteryDB\";\n  private static final String DEFAULT_EVENTS_COLLECTION = \"events\";\n  private static final String EMAIL = \"email\";\n  private static final String PHONE = \"phone\";\n  public static final String MESSAGE = \"message\";\n\n  @Getter private MongoClient mongoClient;\n  @Getter private MongoDatabase database;\n  @Getter private MongoCollection<Document> eventsCollection;\n\n  private final StdOutEventLog stdOutEventLog = new StdOutEventLog();\n\n  /** Constructor. */\n  public MongoEventLog() {\n    connect();\n  }\n\n  /** Constructor accepting parameters. */\n  public MongoEventLog(String dbName, String eventsCollectionName) {\n    connect(dbName, eventsCollectionName);\n  }\n\n  /** Connect to database with default parameters. */\n  public void connect() {\n    connect(DEFAULT_DB, DEFAULT_EVENTS_COLLECTION);\n  }\n\n  /** Connect to database with given parameters. */\n  public void connect(String dbName, String eventsCollectionName) {\n    if (mongoClient != null) {\n      mongoClient.close();\n    }\n    mongoClient =\n        new MongoClient(\n            System.getProperty(\"mongo-host\"), Integer.parseInt(System.getProperty(\"mongo-port\")));\n    database = mongoClient.getDatabase(dbName);\n    eventsCollection = database.getCollection(eventsCollectionName);\n  }\n\n  @Override\n  public void ticketSubmitted(PlayerDetails details) {\n    var document = new Document(EMAIL, details.email());\n    document.put(PHONE, details.phoneNumber());\n    document.put(\"bank\", details.bankAccount());\n    document.put(\n        MESSAGE, \"Lottery ticket was submitted and bank account was charged for 3 credits.\");\n    eventsCollection.insertOne(document);\n    stdOutEventLog.ticketSubmitted(details);\n  }\n\n  @Override\n  public void ticketSubmitError(PlayerDetails details) {\n    var document = new Document(EMAIL, details.email());\n    document.put(PHONE, details.phoneNumber());\n    document.put(\"bank\", details.bankAccount());\n    document.put(MESSAGE, \"Lottery ticket could not be submitted because lack of funds.\");\n    eventsCollection.insertOne(document);\n    stdOutEventLog.ticketSubmitError(details);\n  }\n\n  @Override\n  public void ticketDidNotWin(PlayerDetails details) {\n    var document = new Document(EMAIL, details.email());\n    document.put(PHONE, details.phoneNumber());\n    document.put(\"bank\", details.bankAccount());\n    document.put(MESSAGE, \"Lottery ticket was checked and unfortunately did not win this time.\");\n    eventsCollection.insertOne(document);\n    stdOutEventLog.ticketDidNotWin(details);\n  }\n\n  @Override\n  public void ticketWon(PlayerDetails details, int prizeAmount) {\n    var document = new Document(EMAIL, details.email());\n    document.put(PHONE, details.phoneNumber());\n    document.put(\"bank\", details.bankAccount());\n    document.put(\n        MESSAGE,\n        String.format(\n            \"Lottery ticket won! The bank account was deposited with %d credits.\", prizeAmount));\n    eventsCollection.insertOne(document);\n    stdOutEventLog.ticketWon(details, prizeAmount);\n  }\n\n  @Override\n  public void prizeError(PlayerDetails details, int prizeAmount) {\n    var document = new Document(EMAIL, details.email());\n    document.put(PHONE, details.phoneNumber());\n    document.put(\"bank\", details.bankAccount());\n    document.put(\n        MESSAGE,\n        String.format(\n            \"Lottery ticket won! Unfortunately the bank credit transfer of %d failed.\",\n            prizeAmount));\n    eventsCollection.insertOne(document);\n    stdOutEventLog.prizeError(details, prizeAmount);\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/eventlog/StdOutEventLog.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.eventlog;\n\nimport com.iluwatar.hexagonal.domain.PlayerDetails;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Standard output event log. */\n@Slf4j\npublic class StdOutEventLog implements LotteryEventLog {\n\n  @Override\n  public void ticketSubmitted(PlayerDetails details) {\n    LOGGER.info(\n        \"Lottery ticket for {} was submitted. Bank account {} was charged for 3 credits.\",\n        details.email(),\n        details.bankAccount());\n  }\n\n  @Override\n  public void ticketDidNotWin(PlayerDetails details) {\n    LOGGER.info(\n        \"Lottery ticket for {} was checked and unfortunately did not win this time.\",\n        details.email());\n  }\n\n  @Override\n  public void ticketWon(PlayerDetails details, int prizeAmount) {\n    LOGGER.info(\n        \"Lottery ticket for {} has won! The bank account {} was deposited with {} credits.\",\n        details.email(),\n        details.bankAccount(),\n        prizeAmount);\n  }\n\n  @Override\n  public void prizeError(PlayerDetails details, int prizeAmount) {\n    LOGGER.error(\n        \"Lottery ticket for {} has won! Unfortunately the bank credit transfer of\" + \" {} failed.\",\n        details.email(),\n        prizeAmount);\n  }\n\n  @Override\n  public void ticketSubmitError(PlayerDetails details) {\n    LOGGER.error(\n        \"Lottery ticket for {} could not be submitted because the credit transfer\"\n            + \" of 3 credits failed.\",\n        details.email());\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/module/LotteryModule.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.module;\n\nimport com.google.inject.AbstractModule;\nimport com.iluwatar.hexagonal.banking.MongoBank;\nimport com.iluwatar.hexagonal.banking.WireTransfers;\nimport com.iluwatar.hexagonal.database.LotteryTicketRepository;\nimport com.iluwatar.hexagonal.database.MongoTicketRepository;\nimport com.iluwatar.hexagonal.eventlog.LotteryEventLog;\nimport com.iluwatar.hexagonal.eventlog.MongoEventLog;\n\n/** Guice module for binding production dependencies. */\npublic class LotteryModule extends AbstractModule {\n  @Override\n  protected void configure() {\n    bind(LotteryTicketRepository.class).to(MongoTicketRepository.class);\n    bind(LotteryEventLog.class).to(MongoEventLog.class);\n    bind(WireTransfers.class).to(MongoBank.class);\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/module/LotteryTestingModule.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.module;\n\nimport com.google.inject.AbstractModule;\nimport com.iluwatar.hexagonal.banking.InMemoryBank;\nimport com.iluwatar.hexagonal.banking.WireTransfers;\nimport com.iluwatar.hexagonal.database.InMemoryTicketRepository;\nimport com.iluwatar.hexagonal.database.LotteryTicketRepository;\nimport com.iluwatar.hexagonal.eventlog.LotteryEventLog;\nimport com.iluwatar.hexagonal.eventlog.StdOutEventLog;\n\n/** Guice module for testing dependencies. */\npublic class LotteryTestingModule extends AbstractModule {\n  @Override\n  protected void configure() {\n    bind(LotteryTicketRepository.class).to(InMemoryTicketRepository.class);\n    bind(LotteryEventLog.class).to(StdOutEventLog.class);\n    bind(WireTransfers.class).to(InMemoryBank.class);\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/mongo/MongoConnectionPropertiesLoader.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.mongo;\n\nimport java.io.FileInputStream;\nimport java.util.Properties;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Mongo connection properties loader. */\n@Slf4j\npublic class MongoConnectionPropertiesLoader {\n\n  private static final String DEFAULT_HOST = \"localhost\";\n  private static final int DEFAULT_PORT = 27017;\n\n  /** Try to load connection properties from file. Fall back to default connection properties. */\n  public static void load() {\n    var host = DEFAULT_HOST;\n    var port = DEFAULT_PORT;\n    var path = System.getProperty(\"hexagonal.properties.path\");\n    var properties = new Properties();\n    if (path != null) {\n      try (var fin = new FileInputStream(path)) {\n        properties.load(fin);\n        host = properties.getProperty(\"mongo-host\");\n        port = Integer.parseInt(properties.getProperty(\"mongo-port\"));\n      } catch (Exception e) {\n        // error occurred, use default properties\n        LOGGER.error(\"Error occurred: \", e);\n      }\n    }\n    System.setProperty(\"mongo-host\", host);\n    System.setProperty(\"mongo-port\", String.format(\"%d\", port));\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/sampledata/SampleData.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.sampledata;\n\nimport com.iluwatar.hexagonal.banking.InMemoryBank;\nimport com.iluwatar.hexagonal.domain.LotteryConstants;\nimport com.iluwatar.hexagonal.domain.LotteryNumbers;\nimport com.iluwatar.hexagonal.domain.LotteryService;\nimport com.iluwatar.hexagonal.domain.LotteryTicket;\nimport com.iluwatar.hexagonal.domain.LotteryTicketId;\nimport com.iluwatar.hexagonal.domain.PlayerDetails;\nimport java.security.SecureRandom;\nimport java.util.AbstractMap.SimpleEntry;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/** Utilities for creating sample lottery tickets. */\npublic class SampleData {\n\n  private static final List<PlayerDetails> PLAYERS;\n  private static final SecureRandom RANDOM = new SecureRandom();\n\n  static {\n    PLAYERS =\n        List.of(\n            new PlayerDetails(\"john@google.com\", \"312-342\", \"+3242434242\"),\n            new PlayerDetails(\"mary@google.com\", \"234-987\", \"+23452346\"),\n            new PlayerDetails(\"steve@google.com\", \"833-836\", \"+63457543\"),\n            new PlayerDetails(\"wayne@google.com\", \"319-826\", \"+24626\"),\n            new PlayerDetails(\"johnie@google.com\", \"983-322\", \"+3635635\"),\n            new PlayerDetails(\"andy@google.com\", \"934-734\", \"+0898245\"),\n            new PlayerDetails(\"richard@google.com\", \"536-738\", \"+09845325\"),\n            new PlayerDetails(\"kevin@google.com\", \"453-936\", \"+2423532\"),\n            new PlayerDetails(\"arnold@google.com\", \"114-988\", \"+5646346524\"),\n            new PlayerDetails(\"ian@google.com\", \"663-765\", \"+928394235\"),\n            new PlayerDetails(\"robin@google.com\", \"334-763\", \"+35448\"),\n            new PlayerDetails(\"ted@google.com\", \"735-964\", \"+98752345\"),\n            new PlayerDetails(\"larry@google.com\", \"734-853\", \"+043842423\"),\n            new PlayerDetails(\"calvin@google.com\", \"334-746\", \"+73294135\"),\n            new PlayerDetails(\"jacob@google.com\", \"444-766\", \"+358042354\"),\n            new PlayerDetails(\"edwin@google.com\", \"895-345\", \"+9752435\"),\n            new PlayerDetails(\"mary@google.com\", \"760-009\", \"+34203542\"),\n            new PlayerDetails(\"lolita@google.com\", \"425-907\", \"+9872342\"),\n            new PlayerDetails(\"bruno@google.com\", \"023-638\", \"+673824122\"),\n            new PlayerDetails(\"peter@google.com\", \"335-886\", \"+5432503945\"),\n            new PlayerDetails(\"warren@google.com\", \"225-946\", \"+9872341324\"),\n            new PlayerDetails(\"monica@google.com\", \"265-748\", \"+134124\"),\n            new PlayerDetails(\"ollie@google.com\", \"190-045\", \"+34453452\"),\n            new PlayerDetails(\"yngwie@google.com\", \"241-465\", \"+9897641231\"),\n            new PlayerDetails(\"lars@google.com\", \"746-936\", \"+42345298345\"),\n            new PlayerDetails(\"bobbie@google.com\", \"946-384\", \"+79831742\"),\n            new PlayerDetails(\"tyron@google.com\", \"310-992\", \"+0498837412\"),\n            new PlayerDetails(\"tyrell@google.com\", \"032-045\", \"+67834134\"),\n            new PlayerDetails(\"nadja@google.com\", \"000-346\", \"+498723\"),\n            new PlayerDetails(\"wendy@google.com\", \"994-989\", \"+987324454\"),\n            new PlayerDetails(\"luke@google.com\", \"546-634\", \"+987642435\"),\n            new PlayerDetails(\"bjorn@google.com\", \"342-874\", \"+7834325\"),\n            new PlayerDetails(\"lisa@google.com\", \"024-653\", \"+980742154\"),\n            new PlayerDetails(\"anton@google.com\", \"834-935\", \"+876423145\"),\n            new PlayerDetails(\"bruce@google.com\", \"284-936\", \"+09843212345\"),\n            new PlayerDetails(\"ray@google.com\", \"843-073\", \"+678324123\"),\n            new PlayerDetails(\"ron@google.com\", \"637-738\", \"+09842354\"),\n            new PlayerDetails(\"xavier@google.com\", \"143-947\", \"+375245\"),\n            new PlayerDetails(\"harriet@google.com\", \"842-404\", \"+131243252\"));\n    var wireTransfers = new InMemoryBank();\n    PLAYERS.stream()\n        .map(PlayerDetails::bankAccount)\n        .map(e -> new SimpleEntry<>(e, RANDOM.nextInt(LotteryConstants.PLAYER_MAX_BALANCE)))\n        .collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue))\n        .forEach(wireTransfers::setFunds);\n  }\n\n  /** Inserts lottery tickets into the database based on the sample data. */\n  public static void submitTickets(LotteryService lotteryService, int numTickets) {\n    for (var i = 0; i < numTickets; i++) {\n      var randomPlayerDetails = getRandomPlayerDetails();\n      var lotteryNumbers = LotteryNumbers.createRandom();\n      var lotteryTicketId = new LotteryTicketId();\n      var ticket = new LotteryTicket(lotteryTicketId, randomPlayerDetails, lotteryNumbers);\n      lotteryService.submitTicket(ticket);\n    }\n  }\n\n  private static PlayerDetails getRandomPlayerDetails() {\n    return PLAYERS.get(RANDOM.nextInt(PLAYERS.size()));\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/service/ConsoleLottery.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.service;\n\nimport com.google.inject.Guice;\nimport com.iluwatar.hexagonal.banking.WireTransfers;\nimport com.iluwatar.hexagonal.domain.LotteryService;\nimport com.iluwatar.hexagonal.module.LotteryModule;\nimport com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader;\nimport java.util.Scanner;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Console interface for lottery players. */\n@Slf4j\npublic class ConsoleLottery {\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n    MongoConnectionPropertiesLoader.load();\n    var injector = Guice.createInjector(new LotteryModule());\n    var service = injector.getInstance(LotteryService.class);\n    var bank = injector.getInstance(WireTransfers.class);\n    try (Scanner scanner = new Scanner(System.in)) {\n      var exit = false;\n      while (!exit) {\n        printMainMenu();\n        var cmd = readString(scanner);\n        var lotteryConsoleService = new LotteryConsoleServiceImpl(LOGGER);\n        if (\"1\".equals(cmd)) {\n          lotteryConsoleService.queryLotteryAccountFunds(bank, scanner);\n        } else if (\"2\".equals(cmd)) {\n          lotteryConsoleService.addFundsToLotteryAccount(bank, scanner);\n        } else if (\"3\".equals(cmd)) {\n          lotteryConsoleService.submitTicket(service, scanner);\n        } else if (\"4\".equals(cmd)) {\n          lotteryConsoleService.checkTicket(service, scanner);\n        } else if (\"5\".equals(cmd)) {\n          exit = true;\n        } else {\n          LOGGER.info(\"Unknown command\");\n        }\n      }\n    }\n  }\n\n  private static void printMainMenu() {\n    LOGGER.info(\"\");\n    LOGGER.info(\"### Lottery Service Console ###\");\n    LOGGER.info(\"(1) Query lottery account funds\");\n    LOGGER.info(\"(2) Add funds to lottery account\");\n    LOGGER.info(\"(3) Submit ticket\");\n    LOGGER.info(\"(4) Check ticket\");\n    LOGGER.info(\"(5) Exit\");\n  }\n\n  private static String readString(Scanner scanner) {\n    LOGGER.info(\"> \");\n    return scanner.next();\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/service/LotteryConsoleService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.service;\n\nimport com.iluwatar.hexagonal.banking.WireTransfers;\nimport com.iluwatar.hexagonal.domain.LotteryService;\nimport java.util.Scanner;\n\n/** Console interface for lottery service. */\npublic interface LotteryConsoleService {\n\n  void checkTicket(LotteryService service, Scanner scanner);\n\n  /** Submit lottery ticket to participate in the lottery. */\n  void submitTicket(LotteryService service, Scanner scanner);\n\n  /** Add funds to lottery account. */\n  void addFundsToLotteryAccount(WireTransfers bank, Scanner scanner);\n\n  /** Recovery funds from lottery account. */\n  void queryLotteryAccountFunds(WireTransfers bank, Scanner scanner);\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/main/java/com/iluwatar/hexagonal/service/LotteryConsoleServiceImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.service;\n\nimport com.iluwatar.hexagonal.banking.WireTransfers;\nimport com.iluwatar.hexagonal.domain.LotteryNumbers;\nimport com.iluwatar.hexagonal.domain.LotteryService;\nimport com.iluwatar.hexagonal.domain.LotteryTicket;\nimport com.iluwatar.hexagonal.domain.LotteryTicketCheckResult;\nimport com.iluwatar.hexagonal.domain.LotteryTicketId;\nimport com.iluwatar.hexagonal.domain.PlayerDetails;\nimport java.util.Arrays;\nimport java.util.Scanner;\nimport java.util.stream.Collectors;\nimport org.slf4j.Logger;\n\n/** Console implementation for lottery console service. */\npublic class LotteryConsoleServiceImpl implements LotteryConsoleService {\n\n  private final Logger logger;\n\n  /** Constructor. */\n  public LotteryConsoleServiceImpl(Logger logger) {\n    this.logger = logger;\n  }\n\n  @Override\n  public void checkTicket(LotteryService service, Scanner scanner) {\n    logger.info(\"What is the ID of the lottery ticket?\");\n    var id = readString(scanner);\n    logger.info(\"Give the 4 comma separated winning numbers?\");\n    var numbers = readString(scanner);\n    try {\n      var winningNumbers =\n          Arrays.stream(numbers.split(\",\"))\n              .map(Integer::parseInt)\n              .limit(4)\n              .collect(Collectors.toSet());\n\n      final var lotteryTicketId = new LotteryTicketId(Integer.parseInt(id));\n      final var lotteryNumbers = LotteryNumbers.create(winningNumbers);\n      var result = service.checkTicketForPrize(lotteryTicketId, lotteryNumbers);\n\n      if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.WIN_PRIZE)) {\n        logger.info(\"Congratulations! The lottery ticket has won!\");\n      } else if (result.getResult().equals(LotteryTicketCheckResult.CheckResult.NO_PRIZE)) {\n        logger.info(\"Unfortunately the lottery ticket did not win.\");\n      } else {\n        logger.info(\"Such lottery ticket has not been submitted.\");\n      }\n    } catch (Exception e) {\n      logger.info(\"Failed checking the lottery ticket - please try again.\");\n    }\n  }\n\n  @Override\n  public void submitTicket(LotteryService service, Scanner scanner) {\n    logger.info(\"What is your email address?\");\n    var email = readString(scanner);\n    logger.info(\"What is your bank account number?\");\n    var account = readString(scanner);\n    logger.info(\"What is your phone number?\");\n    var phone = readString(scanner);\n    var details = new PlayerDetails(email, account, phone);\n    logger.info(\"Give 4 comma separated lottery numbers?\");\n    var numbers = readString(scanner);\n    try {\n      var chosen =\n          Arrays.stream(numbers.split(\",\")).map(Integer::parseInt).collect(Collectors.toSet());\n      var lotteryNumbers = LotteryNumbers.create(chosen);\n      var lotteryTicket = new LotteryTicket(new LotteryTicketId(), details, lotteryNumbers);\n      service\n          .submitTicket(lotteryTicket)\n          .ifPresentOrElse(\n              (id) -> logger.info(\"Submitted lottery ticket with id: {}\", id),\n              () -> logger.info(\"Failed submitting lottery ticket - please try again.\"));\n    } catch (Exception e) {\n      logger.info(\"Failed submitting lottery ticket - please try again.\");\n    }\n  }\n\n  @Override\n  public void addFundsToLotteryAccount(WireTransfers bank, Scanner scanner) {\n    logger.info(\"What is the account number?\");\n    var account = readString(scanner);\n    logger.info(\"How many credits do you want to deposit?\");\n    var amount = readString(scanner);\n    bank.setFunds(account, Integer.parseInt(amount));\n    logger.info(\"The account {} now has {} credits.\", account, bank.getFunds(account));\n  }\n\n  @Override\n  public void queryLotteryAccountFunds(WireTransfers bank, Scanner scanner) {\n    logger.info(\"What is the account number?\");\n    var account = readString(scanner);\n    logger.info(\"The account {} has {} credits.\", account, bank.getFunds(account));\n  }\n\n  private String readString(Scanner scanner) {\n    logger.info(\"> \");\n    return scanner.next();\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Unit test for simple App. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/banking/InMemoryBankTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.banking;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests for banking */\nclass InMemoryBankTest {\n\n  private final WireTransfers bank = new InMemoryBank();\n\n  @Test\n  void testInit() {\n    assertEquals(0, bank.getFunds(\"foo\"));\n    bank.setFunds(\"foo\", 100);\n    assertEquals(100, bank.getFunds(\"foo\"));\n    bank.setFunds(\"bar\", 150);\n    assertEquals(150, bank.getFunds(\"bar\"));\n    assertTrue(bank.transferFunds(50, \"bar\", \"foo\"));\n    assertEquals(150, bank.getFunds(\"foo\"));\n    assertEquals(100, bank.getFunds(\"bar\"));\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/banking/MongoBankTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.banking;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.mongodb.client.MongoClient;\nimport com.mongodb.client.MongoClients;\nimport com.mongodb.client.MongoDatabase;\nimport de.flapdoodle.embed.mongo.commands.ServerAddress;\nimport de.flapdoodle.embed.mongo.distribution.Version;\nimport de.flapdoodle.embed.mongo.transitions.Mongod;\nimport de.flapdoodle.embed.mongo.transitions.RunningMongodProcess;\nimport de.flapdoodle.reverse.TransitionWalker;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for Mongo banking adapter */\nclass MongoBankTest {\n\n  private static final String TEST_DB = \"lotteryDBTest\";\n  private static final String TEST_ACCOUNTS_COLLECTION = \"testAccounts\";\n\n  private static MongoClient mongoClient;\n  private static MongoDatabase mongoDatabase;\n\n  private MongoBank mongoBank;\n\n  private static TransitionWalker.ReachedState<RunningMongodProcess> mongodProcess;\n\n  private static ServerAddress serverAddress;\n\n  @BeforeAll\n  static void setUp() {\n    mongodProcess = Mongod.instance().start(Version.Main.V7_0);\n    serverAddress = mongodProcess.current().getServerAddress();\n    mongoClient = MongoClients.create(\"mongodb://\" + serverAddress.toString());\n    mongoClient.startSession();\n    mongoDatabase = mongoClient.getDatabase(TEST_DB);\n  }\n\n  @AfterAll\n  static void tearDown() {\n    mongoClient.close();\n    mongodProcess.close();\n  }\n\n  @BeforeEach\n  void init() {\n    System.setProperty(\"mongo-host\", serverAddress.getHost());\n    System.setProperty(\"mongo-port\", String.valueOf(serverAddress.getPort()));\n    mongoDatabase.drop();\n    mongoBank = new MongoBank(mongoDatabase.getName(), TEST_ACCOUNTS_COLLECTION);\n  }\n\n  @Test\n  void testSetup() {\n    assertEquals(0, mongoBank.getAccountsCollection().countDocuments());\n  }\n\n  @Test\n  void testFundTransfers() {\n    assertEquals(0, mongoBank.getFunds(\"000-000\"));\n    mongoBank.setFunds(\"000-000\", 10);\n    assertEquals(10, mongoBank.getFunds(\"000-000\"));\n    assertEquals(0, mongoBank.getFunds(\"111-111\"));\n    mongoBank.transferFunds(9, \"000-000\", \"111-111\");\n    assertEquals(1, mongoBank.getFunds(\"000-000\"));\n    assertEquals(9, mongoBank.getFunds(\"111-111\"));\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/database/InMemoryTicketRepositoryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.database;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.hexagonal.test.LotteryTestUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for {@link LotteryTicketRepository} */\nclass InMemoryTicketRepositoryTest {\n\n  private final LotteryTicketRepository repository = new InMemoryTicketRepository();\n\n  @BeforeEach\n  void clear() {\n    repository.deleteAll();\n  }\n\n  @Test\n  void testCrudOperations() {\n    var repository = new InMemoryTicketRepository();\n    assertTrue(repository.findAll().isEmpty());\n    var ticket = LotteryTestUtils.createLotteryTicket();\n    var id = repository.save(ticket);\n    assertTrue(id.isPresent());\n    assertEquals(1, repository.findAll().size());\n    var optionalTicket = repository.findById(id.get());\n    assertTrue(optionalTicket.isPresent());\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/database/MongoTicketRepositoryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.database;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.hexagonal.domain.LotteryNumbers;\nimport com.iluwatar.hexagonal.domain.LotteryTicket;\nimport com.iluwatar.hexagonal.domain.LotteryTicketId;\nimport com.iluwatar.hexagonal.domain.PlayerDetails;\nimport com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader;\nimport com.mongodb.MongoClient;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Disabled;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for Mongo based ticket repository */\n@Disabled\nclass MongoTicketRepositoryTest {\n\n  private static final String TEST_DB = \"lotteryTestDB\";\n  private static final String TEST_TICKETS_COLLECTION = \"lotteryTestTickets\";\n  private static final String TEST_COUNTERS_COLLECTION = \"testCounters\";\n\n  private MongoTicketRepository repository;\n\n  @BeforeEach\n  void init() {\n    MongoConnectionPropertiesLoader.load();\n    var mongoClient =\n        new MongoClient(\n            System.getProperty(\"mongo-host\"), Integer.parseInt(System.getProperty(\"mongo-port\")));\n    mongoClient.dropDatabase(TEST_DB);\n    mongoClient.close();\n    repository =\n        new MongoTicketRepository(TEST_DB, TEST_TICKETS_COLLECTION, TEST_COUNTERS_COLLECTION);\n  }\n\n  @Test\n  void testSetup() {\n    assertEquals(1, repository.getCountersCollection().countDocuments());\n    assertEquals(0, repository.getTicketsCollection().countDocuments());\n  }\n\n  @Test\n  void testNextId() {\n    assertEquals(1, repository.getNextId());\n    assertEquals(2, repository.getNextId());\n    assertEquals(3, repository.getNextId());\n  }\n\n  @Test\n  void testCrudOperations() {\n    // create new lottery ticket and save it\n    var details = new PlayerDetails(\"foo@bar.com\", \"123-123\", \"07001234\");\n    var random = LotteryNumbers.createRandom();\n    var original = new LotteryTicket(new LotteryTicketId(), details, random);\n    var saved = repository.save(original);\n    assertEquals(1, repository.getTicketsCollection().countDocuments());\n    assertTrue(saved.isPresent());\n    // fetch the saved lottery ticket from database and check its contents\n    var found = repository.findById(saved.get());\n    assertTrue(found.isPresent());\n    var ticket = found.get();\n    assertEquals(\"foo@bar.com\", ticket.playerDetails().email());\n    assertEquals(\"123-123\", ticket.playerDetails().bankAccount());\n    assertEquals(\"07001234\", ticket.playerDetails().phoneNumber());\n    assertEquals(original.lotteryNumbers(), ticket.lotteryNumbers());\n    // clear the collection\n    repository.deleteAll();\n    assertEquals(0, repository.getTicketsCollection().countDocuments());\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/domain/LotteryNumbersTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.Set;\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for {@link LotteryNumbers} */\nclass LotteryNumbersTest {\n\n  @Test\n  void testGivenNumbers() {\n    var numbers = LotteryNumbers.create(Set.of(1, 2, 3, 4));\n    assertEquals(numbers.getNumbers().size(), 4);\n    assertTrue(numbers.getNumbers().contains(1));\n    assertTrue(numbers.getNumbers().contains(2));\n    assertTrue(numbers.getNumbers().contains(3));\n    assertTrue(numbers.getNumbers().contains(4));\n  }\n\n  @Test\n  void testNumbersCantBeModified() {\n    var numbers = LotteryNumbers.create(Set.of(1, 2, 3, 4));\n    assertThrows(UnsupportedOperationException.class, () -> numbers.getNumbers().add(5));\n  }\n\n  @Test\n  void testRandomNumbers() {\n    var numbers = LotteryNumbers.createRandom();\n    assertEquals(numbers.getNumbers().size(), LotteryNumbers.NUM_NUMBERS);\n  }\n\n  @Test\n  void testEquals() {\n    var numbers1 = LotteryNumbers.create(Set.of(1, 2, 3, 4));\n    var numbers2 = LotteryNumbers.create(Set.of(1, 2, 3, 4));\n    assertEquals(numbers1, numbers2);\n    var numbers3 = LotteryNumbers.create(Set.of(11, 12, 13, 14));\n    assertNotEquals(numbers1, numbers3);\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/domain/LotteryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.google.inject.Guice;\nimport com.google.inject.Inject;\nimport com.google.inject.Injector;\nimport com.iluwatar.hexagonal.banking.WireTransfers;\nimport com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult;\nimport com.iluwatar.hexagonal.module.LotteryTestingModule;\nimport com.iluwatar.hexagonal.test.LotteryTestUtils;\nimport java.util.Set;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Test the lottery system */\nclass LotteryTest {\n\n  private final Injector injector;\n  @Inject private LotteryAdministration administration;\n  @Inject private LotteryService service;\n  @Inject private WireTransfers wireTransfers;\n\n  LotteryTest() {\n    this.injector = Guice.createInjector(new LotteryTestingModule());\n  }\n\n  @BeforeEach\n  void setup() {\n    injector.injectMembers(this);\n    // add funds to the test player's bank account\n    wireTransfers.setFunds(\"123-12312\", 100);\n  }\n\n  @Test\n  void testLottery() {\n    // admin resets the lottery\n    administration.resetLottery();\n    assertEquals(0, administration.getAllSubmittedTickets().size());\n\n    // players submit the lottery tickets\n    var ticket1 =\n        service.submitTicket(\n            LotteryTestUtils.createLotteryTicket(\n                \"cvt@bbb.com\", \"123-12312\", \"+32425255\", Set.of(1, 2, 3, 4)));\n    assertTrue(ticket1.isPresent());\n    var ticket2 =\n        service.submitTicket(\n            LotteryTestUtils.createLotteryTicket(\n                \"ant@bac.com\", \"123-12312\", \"+32423455\", Set.of(11, 12, 13, 14)));\n    assertTrue(ticket2.isPresent());\n    var ticket3 =\n        service.submitTicket(\n            LotteryTestUtils.createLotteryTicket(\n                \"arg@boo.com\", \"123-12312\", \"+32421255\", Set.of(6, 8, 13, 19)));\n    assertTrue(ticket3.isPresent());\n    assertEquals(3, administration.getAllSubmittedTickets().size());\n\n    // perform lottery\n    var winningNumbers = administration.performLottery();\n\n    // cheat a bit for testing sake, use winning numbers to submit another ticket\n    var ticket4 =\n        service.submitTicket(\n            LotteryTestUtils.createLotteryTicket(\n                \"lucky@orb.com\", \"123-12312\", \"+12421255\", winningNumbers.getNumbers()));\n    assertTrue(ticket4.isPresent());\n    assertEquals(4, administration.getAllSubmittedTickets().size());\n\n    // check winners\n    var tickets = administration.getAllSubmittedTickets();\n    for (var id : tickets.keySet()) {\n      var checkResult = service.checkTicketForPrize(id, winningNumbers);\n      assertNotEquals(CheckResult.TICKET_NOT_SUBMITTED, checkResult.getResult());\n      if (checkResult.getResult().equals(CheckResult.WIN_PRIZE)) {\n        assertTrue(checkResult.getPrizeAmount() > 0);\n      } else {\n        assertEquals(0, checkResult.getPrizeAmount());\n      }\n    }\n\n    // check another ticket that has not been submitted\n    var checkResult = service.checkTicketForPrize(new LotteryTicketId(), winningNumbers);\n    assertEquals(CheckResult.TICKET_NOT_SUBMITTED, checkResult.getResult());\n    assertEquals(0, checkResult.getPrizeAmount());\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketCheckResultTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nimport com.iluwatar.hexagonal.domain.LotteryTicketCheckResult.CheckResult;\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for {@link LotteryTicketCheckResult} */\nclass LotteryTicketCheckResultTest {\n\n  @Test\n  void testEquals() {\n    var result1 = new LotteryTicketCheckResult(CheckResult.NO_PRIZE);\n    var result2 = new LotteryTicketCheckResult(CheckResult.NO_PRIZE);\n    assertEquals(result1, result2);\n    var result3 = new LotteryTicketCheckResult(CheckResult.WIN_PRIZE, 300000);\n    assertNotEquals(result1, result3);\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketIdTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests for lottery ticket id */\nclass LotteryTicketIdTest {\n\n  @Test\n  void testEquals() {\n    var ticketId1 = new LotteryTicketId();\n    var ticketId2 = new LotteryTicketId();\n    var ticketId3 = new LotteryTicketId();\n    assertNotEquals(ticketId1, ticketId2);\n    assertNotEquals(ticketId2, ticketId3);\n    var ticketId4 = new LotteryTicketId(ticketId1.getId());\n    assertEquals(ticketId1, ticketId4);\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/domain/LotteryTicketTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nimport java.util.Set;\nimport org.junit.jupiter.api.Test;\n\n/** Test Lottery Tickets for equality */\nclass LotteryTicketTest {\n\n  @Test\n  void testEquals() {\n    var details1 = new PlayerDetails(\"bob@foo.bar\", \"1212-121212\", \"+34332322\");\n    var numbers1 = LotteryNumbers.create(Set.of(1, 2, 3, 4));\n    var ticket1 = new LotteryTicket(new LotteryTicketId(), details1, numbers1);\n    var details2 = new PlayerDetails(\"bob@foo.bar\", \"1212-121212\", \"+34332322\");\n    var numbers2 = LotteryNumbers.create(Set.of(1, 2, 3, 4));\n    var ticket2 = new LotteryTicket(new LotteryTicketId(), details2, numbers2);\n    assertEquals(ticket1, ticket2);\n    var details3 = new PlayerDetails(\"elsa@foo.bar\", \"1223-121212\", \"+49332322\");\n    var numbers3 = LotteryNumbers.create(Set.of(1, 2, 3, 8));\n    var ticket3 = new LotteryTicket(new LotteryTicketId(), details3, numbers3);\n    assertNotEquals(ticket1, ticket3);\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/domain/PlayerDetailsTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.domain;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for {@link PlayerDetails} */\nclass PlayerDetailsTest {\n\n  @Test\n  void testEquals() {\n    var details1 = new PlayerDetails(\"tom@foo.bar\", \"11212-123434\", \"+12323425\");\n    var details2 = new PlayerDetails(\"tom@foo.bar\", \"11212-123434\", \"+12323425\");\n    assertEquals(details1, details2);\n    var details3 = new PlayerDetails(\"john@foo.bar\", \"16412-123439\", \"+34323432\");\n    assertNotEquals(details1, details3);\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/eventlog/MongoEventLogTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.eventlog;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.hexagonal.domain.PlayerDetails;\nimport com.iluwatar.hexagonal.mongo.MongoConnectionPropertiesLoader;\nimport com.mongodb.MongoClient;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Disabled;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for Mongo event log */\n@Disabled\nclass MongoEventLogTest {\n\n  private static final String TEST_DB = \"lotteryDBTest\";\n  private static final String TEST_EVENTS_COLLECTION = \"testEvents\";\n\n  private MongoEventLog mongoEventLog;\n\n  @BeforeEach\n  void init() {\n    MongoConnectionPropertiesLoader.load();\n    var mongoClient =\n        new MongoClient(\n            System.getProperty(\"mongo-host\"), Integer.parseInt(System.getProperty(\"mongo-port\")));\n    mongoClient.dropDatabase(TEST_DB);\n    mongoClient.close();\n    mongoEventLog = new MongoEventLog(TEST_DB, TEST_EVENTS_COLLECTION);\n  }\n\n  @Test\n  void testSetup() {\n    assertEquals(0, mongoEventLog.getEventsCollection().countDocuments());\n  }\n\n  @Test\n  void testFundTransfers() {\n    var playerDetails = new PlayerDetails(\"john@wayne.com\", \"000-000\", \"03432534543\");\n    mongoEventLog.prizeError(playerDetails, 1000);\n    assertEquals(1, mongoEventLog.getEventsCollection().countDocuments());\n    mongoEventLog.prizeError(playerDetails, 1000);\n    assertEquals(2, mongoEventLog.getEventsCollection().countDocuments());\n    mongoEventLog.ticketDidNotWin(playerDetails);\n    assertEquals(3, mongoEventLog.getEventsCollection().countDocuments());\n    mongoEventLog.ticketDidNotWin(playerDetails);\n    assertEquals(4, mongoEventLog.getEventsCollection().countDocuments());\n    mongoEventLog.ticketSubmitError(playerDetails);\n    assertEquals(5, mongoEventLog.getEventsCollection().countDocuments());\n    mongoEventLog.ticketSubmitError(playerDetails);\n    assertEquals(6, mongoEventLog.getEventsCollection().countDocuments());\n    mongoEventLog.ticketSubmitted(playerDetails);\n    assertEquals(7, mongoEventLog.getEventsCollection().countDocuments());\n    mongoEventLog.ticketSubmitted(playerDetails);\n    assertEquals(8, mongoEventLog.getEventsCollection().countDocuments());\n    mongoEventLog.ticketWon(playerDetails, 1000);\n    assertEquals(9, mongoEventLog.getEventsCollection().countDocuments());\n    mongoEventLog.ticketWon(playerDetails, 1000);\n    assertEquals(10, mongoEventLog.getEventsCollection().countDocuments());\n  }\n}\n"
  },
  {
    "path": "hexagonal-architecture/src/test/java/com/iluwatar/hexagonal/test/LotteryTestUtils.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.hexagonal.test;\n\nimport com.iluwatar.hexagonal.domain.LotteryNumbers;\nimport com.iluwatar.hexagonal.domain.LotteryTicket;\nimport com.iluwatar.hexagonal.domain.LotteryTicketId;\nimport com.iluwatar.hexagonal.domain.PlayerDetails;\nimport java.util.Set;\n\n/** Utilities for lottery tests */\npublic class LotteryTestUtils {\n\n  /**\n   * @return lottery ticket\n   */\n  public static LotteryTicket createLotteryTicket() {\n    return createLotteryTicket(\"foo@bar.com\", \"12231-213132\", \"+99324554\", Set.of(1, 2, 3, 4));\n  }\n\n  /**\n   * @return lottery ticket\n   */\n  public static LotteryTicket createLotteryTicket(\n      String email, String account, String phone, Set<Integer> givenNumbers) {\n    var details = new PlayerDetails(email, account, phone);\n    var numbers = LotteryNumbers.create(givenNumbers);\n    return new LotteryTicket(new LotteryTicketId(), details, numbers);\n  }\n}\n"
  },
  {
    "path": "identity-map/README.md",
    "content": "---\ntitle: \"Identity Map Pattern in Java: Managing Object Identity for Efficiency\"\nshortTitle: Identity Map\ndescription: \"Learn about the Identity Map pattern in Java. This design pattern prevents duplicate objects in memory, improving performance and consistency in your applications. Explore implementation examples, benefits, and best practices.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Data access\n  - Decoupling\n  - Enterprise patterns\n  - Object mapping\n  - Persistence\n  - Performance\n---\n\n## Intent of Identity Map Design Pattern\n\nThe Identity Map design pattern in Java aims to ensure that each object gets loaded only once by keeping every loaded object in a map, enhancing database performance and memory management.\n\n## Detailed Explanation of Identity Map Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine you are organizing a conference and have a registration desk where every attendee must check in. This scenario illustrates the Identity Map pattern in Java which prevents duplicate objects. To avoid unnecessary delays and confusion, each attendee's details are entered into a computer system the first time they check in. If the same attendee comes to the desk again, the system quickly retrieves their details without requiring them to re-submit the same information. This ensures each attendee's information is handled efficiently and consistently, similar to how the Identity Map pattern ensures that an object is loaded only once and reused throughout the application.\n\nIn plain words\n\n> The Identity Map design pattern ensures that each unique object is loaded only once and reused from a central registry, preventing duplicate objects in an application's memory.\n\nWikipedia says\n\n> In the design of DBMS, the identity map pattern is a database access design pattern used to improve performance by providing a context-specific, in-memory cache to prevent duplicate retrieval of the same object data from the database.\n\nSequence diagram\n\n![Identity Map sequence diagram](./etc/identity-map-sequence-diagram.png)\n\n## Programmatic Example of Identity Map Pattern in Java\n\nFor the purpose of this demonstration in Java programming, assume we have already created a database instance, showcasing the Identity Map pattern to avoid duplicate objects in memory.\n\nLet's first look at the implementation of `Person` entity, and it's fields:\n\n```java\n@EqualsAndHashCode(onlyExplicitlyIncluded = true)\n@Getter\n@Setter\n@AllArgsConstructor\npublic final class Person implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    @EqualsAndHashCode.Include\n    private int personNationalId;\n    private String name;\n    private long phoneNum;\n\n    @Override\n    public String toString() {\n        return \"Person ID is : \" + personNationalId + \" ; Person Name is : \" + name + \" ; Phone Number is :\" + phoneNum;\n    }\n}\n\n```\n\nThe following is the implementation of the `PersonFinder` which is the entity that the user will utilize in order to search for a record in our database. It has the relevant DB attached to it. It also maintains an `IdentityMap` to store the recently read records.\n\n```java\n@Slf4j\n@Getter\n@Setter\npublic class PersonFinder {\n    private static final long serialVersionUID = 1L;\n    //  Access to the Identity Map\n    private IdentityMap identityMap = new IdentityMap();\n    private PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n\n    public Person getPerson(int key) {\n        // Try to find person in the identity map\n        Person person = this.identityMap.getPerson(key);\n        if (person != null) {\n            LOGGER.info(\"Person found in the Map\");\n            return person;\n        } else {\n            // Try to find person in the database\n            person = this.db.find(key);\n            if (person != null) {\n                this.identityMap.addPerson(person);\n                LOGGER.info(\"Person found in DB.\");\n                return person;\n            }\n            LOGGER.info(\"Person with this ID does not exist.\");\n            return null;\n        }\n    }\n}\n\n```\n\nThe identity map field in the above class is simply an abstraction of a hashMap with **personNationalId** as the keys and the corresponding person object as the value. Here is its implementation:\n\n```java\n@Slf4j\n@Getter\npublic class IdentityMap {\n    private Map<Integer, Person> personMap = new HashMap<>();\n\n    public void addPerson(Person person) {\n        if (!personMap.containsKey(person.getPersonNationalId())) {\n            personMap.put(person.getPersonNationalId(), person);\n        } else { // Ensure that addPerson does not update a record. This situation will never arise in our implementation. Added only for testing purposes.\n            LOGGER.info(\"Key already in Map\");\n        }\n    }\n\n    public Person getPerson(int id) {\n        Person person = personMap.get(id);\n        if (person == null) {\n            LOGGER.info(\"ID not in Map.\");\n        }\n        return person;\n    }\n\n    public int size() {\n        if (personMap == null) {\n            return 0;\n        }\n        return personMap.size();\n    }\n}\n```\n\nNow, let's see how the identity map works in our `App`'s `main` function.\n\n```java\npublic static void main(String[] args) {\n\n    // Dummy Persons\n    Person person1 = new Person(1, \"John\", 27304159);\n    Person person2 = new Person(2, \"Thomas\", 42273631);\n    Person person3 = new Person(3, \"Arthur\", 27489171);\n    Person person4 = new Person(4, \"Finn\", 20499078);\n    Person person5 = new Person(5, \"Michael\", 40599078);\n\n    // Init database\n    PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n    db.insert(person1);\n    db.insert(person2);\n    db.insert(person3);\n    db.insert(person4);\n    db.insert(person5);\n\n    // Init a personFinder\n    PersonFinder finder = new PersonFinder();\n    finder.setDb(db);\n\n    // Find persons in DataBase not the map.\n    LOGGER.info(finder.getPerson(2).toString());\n    LOGGER.info(finder.getPerson(4).toString());\n    LOGGER.info(finder.getPerson(5).toString());\n    // Find the person in the map.\n    LOGGER.info(finder.getPerson(2).toString());\n}\n```\n\nRunning the example produces the following console output:\n\n```\n11:19:43.775 [main] INFO com.iluwatar.identitymap.IdentityMap -- ID not in Map.\n11:19:43.780 [main] INFO com.iluwatar.identitymap.PersonDbSimulatorImplementation -- Person ID is : 2 ; Person Name is : Thomas ; Phone Number is :42273631\n11:19:43.780 [main] INFO com.iluwatar.identitymap.PersonFinder -- Person found in DB.\n11:19:43.780 [main] INFO com.iluwatar.identitymap.App -- Person ID is : 2 ; Person Name is : Thomas ; Phone Number is :42273631\n11:19:43.780 [main] INFO com.iluwatar.identitymap.IdentityMap -- ID not in Map.\n11:19:43.780 [main] INFO com.iluwatar.identitymap.PersonDbSimulatorImplementation -- Person ID is : 4 ; Person Name is : Finn ; Phone Number is :20499078\n11:19:43.780 [main] INFO com.iluwatar.identitymap.PersonFinder -- Person found in DB.\n11:19:43.780 [main] INFO com.iluwatar.identitymap.App -- Person ID is : 4 ; Person Name is : Finn ; Phone Number is :20499078\n11:19:43.780 [main] INFO com.iluwatar.identitymap.IdentityMap -- ID not in Map.\n11:19:43.780 [main] INFO com.iluwatar.identitymap.PersonDbSimulatorImplementation -- Person ID is : 5 ; Person Name is : Michael ; Phone Number is :40599078\n11:19:43.780 [main] INFO com.iluwatar.identitymap.PersonFinder -- Person found in DB.\n11:19:43.780 [main] INFO com.iluwatar.identitymap.App -- Person ID is : 5 ; Person Name is : Michael ; Phone Number is :40599078\n11:19:43.780 [main] INFO com.iluwatar.identitymap.IdentityMap -- Person ID is : 2 ; Person Name is : Thomas ; Phone Number is :42273631\n11:19:43.780 [main] INFO com.iluwatar.identitymap.PersonFinder -- Person found in the Map\n11:19:43.780 [main] INFO com.iluwatar.identitymap.App -- Person ID is : 2 ; Person Name is : Thomas ; Phone Number is :42273631\n```\n\n## When to Use the Identity Map Pattern in Java\n\nThe Identity Map design pattern is used in Java applications where multiple accesses to the same data occur within a single session or transaction, ensuring efficient object mapping and consistency.\n\n## Identity Map Pattern Java Tutorials\n\n* [Identity Map Pattern (Source Code Examples)](https://www.sourcecodeexamples.net/2018/04/identity-map-pattern.html)\n\n## Real-World Applications of Identity Map Pattern in Java\n\n* ORM (Object-Relational Mapping) frameworks in Java often implement Identity Maps to handle database interactions more efficiently, demonstrating the pattern’s importance in Java design patterns.\n* Enterprise applications to maintain consistent data states across different business processes.\n\n## Benefits and Trade-offs of Identity Map Pattern\n\nBenefits:\n\n* Reduces memory usage by ensuring that only one copy of each object resides in memory.\n* Prevents inconsistencies during updates, as all parts of the application refer to the same instance.\n* Improves performance by avoiding repeated database reads for the same data.\n\nTrade-offs:\n\n* Increases complexity in object management and persistence logic.\n* Can lead to stale data if not managed correctly, especially in concurrent environments.\n\n## Related Java Design Patterns\n\n* [Data Mapper](https://java-design-patterns.com/patterns/data-mapper/): Separates persistence logic from domain logic. Identity Map can be used by a Data Mapper to ensure that each object is loaded only once, enhancing performance and data consistency.\n* [Unit of Work](https://java-design-patterns.com/patterns/unit-of-work/): Coordinates the actions of multiple objects by keeping track of changes and handling transactional consistency. Identity Map is used within the Unit of Work to track the objects being affected by a transaction.\n\n## References and Credits\n\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Java Persistence with Hibernate](https://amzn.to/4aUfyhd)\n* [Pro Java EE Spring Patterns: Best Practices and Design Strategies Implementing Java EE Patterns with the Spring Framework](https://amzn.to/49YQN24)\n"
  },
  {
    "path": "identity-map/etc/identity-map.urm.puml",
    "content": "@startuml\npackage com.iluwatar.identitymap {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class IdentityMap {\n    - LOGGER : Logger {static}\n    - personMap : Map<Integer, Person>\n    + IdentityMap()\n    + addPerson(person : Person)\n    + getPerson(id : int) : Person\n    + getPersonMap() : Map<Integer, Person>\n    + size() : int\n  }\n  class Person {\n    - name : String\n    - personNationalId : int\n    - phoneNum : long\n    - serialVersionUID : long {static}\n    + Person(personNationalId : int, name : String, phoneNum : long)\n    + equals(o : Object) : boolean\n    + getName() : String\n    + getPersonNationalId() : int\n    + getPhoneNum() : long\n    + hashCode() : int\n    + setName(name : String)\n    + setPersonNationalId(personNationalId : int)\n    + setPhoneNum(phoneNum : long)\n    + toString() : String\n  }\n  interface PersonDbSimulator {\n    + delete(int) {abstract}\n    + find(int) : Person {abstract}\n    + insert(Person) {abstract}\n    + update(Person) {abstract}\n  }\n  class PersonDbSimulatorImplementation {\n    ~ ID_STR : String {static}\n    - LOGGER : Logger {static}\n    ~ NOT_IN_DATA_BASE : String {static}\n    - personList : List<Person>\n    + PersonDbSimulatorImplementation()\n    + delete(id : int)\n    + find(personNationalID : int) : Person\n    + insert(person : Person)\n    + size() : int\n    + update(person : Person)\n  }\n  class PersonFinder {\n    - LOGGER : Logger {static}\n    - db : PersonDbSimulatorImplementation\n    - identityMap : IdentityMap\n    + PersonFinder()\n    + getDB() : PersonDbSimulatorImplementation\n    + getIdentityMap() : IdentityMap\n    + getPerson(key : int) : Person\n    + setDb(db : PersonDbSimulatorImplementation)\n    + setIdentityMap(identityMap : IdentityMap)\n  }\n}\nPersonFinder -->  \"-db\" PersonDbSimulatorImplementation\nPersonFinder -->  \"-identityMap\" IdentityMap\nPersonDbSimulatorImplementation -->  \"-personList\" Person\nPersonDbSimulatorImplementation ..|> PersonDbSimulator \n@enduml"
  },
  {
    "path": "identity-map/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>java-design-patterns</artifactId>\n        <groupId>com.iluwatar</groupId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>identity-map</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.identitymap.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "identity-map/src/main/java/com/iluwatar/identitymap/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.identitymap;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The basic idea behind the Identity Map is to have a series of maps containing objects that have\n * been pulled from the database. The below example demonstrates the identity map pattern by\n * creating a sample DB. Since only 1 DB has been created we only have 1 map corresponding to it for\n * the purpose of this demo. When you load an object from the database, you first check the map. If\n * there’s an object in it that corresponds to the one you’re loading, you return it. If not, you go\n * to the database, putting the objects on the map for future reference as you load them.\n */\n@Slf4j\npublic class App {\n  /**\n   * Program entry point.\n   *\n   * @param args command line args.\n   */\n  public static void main(String[] args) {\n\n    // Dummy Persons\n    Person person1 = new Person(1, \"John\", 27304159);\n    Person person2 = new Person(2, \"Thomas\", 42273631);\n    Person person3 = new Person(3, \"Arthur\", 27489171);\n    Person person4 = new Person(4, \"Finn\", 20499078);\n    Person person5 = new Person(5, \"Michael\", 40599078);\n\n    // Init database\n    PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n    db.insert(person1);\n    db.insert(person2);\n    db.insert(person3);\n    db.insert(person4);\n    db.insert(person5);\n\n    // Init a personFinder\n    PersonFinder finder = new PersonFinder();\n    finder.setDb(db);\n\n    // Find persons in DataBase not the map.\n    LOGGER.info(finder.getPerson(2).toString());\n    LOGGER.info(finder.getPerson(4).toString());\n    LOGGER.info(finder.getPerson(5).toString());\n    // Find the person in the map.\n    LOGGER.info(finder.getPerson(2).toString());\n  }\n}\n"
  },
  {
    "path": "identity-map/src/main/java/com/iluwatar/identitymap/IdNotFoundException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.identitymap;\n\n/** Using Runtime Exception to control the flow in case Person Id doesn't exist. */\npublic class IdNotFoundException extends RuntimeException {\n  public IdNotFoundException(final String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "identity-map/src/main/java/com/iluwatar/identitymap/IdentityMap.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.identitymap;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This class stores the map into which we will be caching records after loading them from a\n * DataBase. Stores the records as a Hash Map with the personNationalIDs as keys.\n */\n@Slf4j\n@Getter\npublic class IdentityMap {\n  private Map<Integer, Person> personMap = new HashMap<>();\n\n  /** Add person to the map. */\n  public void addPerson(Person person) {\n    if (!personMap.containsKey(person.getPersonNationalId())) {\n      personMap.put(person.getPersonNationalId(), person);\n    } else { // Ensure that addPerson does not update a record. This situation will never arise in\n      // our implementation. Added only for testing purposes.\n      LOGGER.info(\"Key already in Map\");\n    }\n  }\n\n  /**\n   * Get Person with given id.\n   *\n   * @param id : personNationalId as requested by user.\n   */\n  public Person getPerson(int id) {\n    Person person = personMap.get(id);\n    if (person == null) {\n      LOGGER.info(\"ID not in Map.\");\n      return null;\n    }\n    LOGGER.info(person.toString());\n    return person;\n  }\n\n  /** Get the size of the map. */\n  public int size() {\n    if (personMap == null) {\n      return 0;\n    }\n    return personMap.size();\n  }\n}\n"
  },
  {
    "path": "identity-map/src/main/java/com/iluwatar/identitymap/Person.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.identitymap;\n\nimport java.io.Serial;\nimport java.io.Serializable;\nimport lombok.AllArgsConstructor;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Person definition. */\n@EqualsAndHashCode(onlyExplicitlyIncluded = true)\n@Getter\n@Setter\n@AllArgsConstructor\npublic final class Person implements Serializable {\n\n  @Serial private static final long serialVersionUID = 1L;\n\n  @EqualsAndHashCode.Include private int personNationalId;\n  private String name;\n  private long phoneNum;\n\n  @Override\n  public String toString() {\n\n    return \"Person ID is : \"\n        + personNationalId\n        + \" ; Person Name is : \"\n        + name\n        + \" ; Phone Number is :\"\n        + phoneNum;\n  }\n}\n"
  },
  {
    "path": "identity-map/src/main/java/com/iluwatar/identitymap/PersonDbSimulator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.identitymap;\n\n/** Simulator interface for Person DB. */\npublic interface PersonDbSimulator {\n  Person find(int personNationalId);\n\n  void insert(Person person);\n\n  void update(Person person);\n\n  void delete(int personNationalId);\n}\n"
  },
  {
    "path": "identity-map/src/main/java/com/iluwatar/identitymap/PersonDbSimulatorImplementation.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.identitymap;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Optional;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This is a sample database implementation. The database is in the form of an arraylist which\n * stores records of different persons. The personNationalId acts as the primary key for a record.\n * Operations : -> find (look for object with a particular ID) -> insert (insert record for a new\n * person into the database) -> update (update the record of a person). To do this, create a new\n * person instance with the same ID as the record you want to update. Then call this method with\n * that person as an argument. -> delete (delete the record for a particular ID)\n */\n@Slf4j\npublic class PersonDbSimulatorImplementation implements PersonDbSimulator {\n\n  // This simulates a table in the database. To extend logic to multiple tables just add more lists\n  // to the implementation.\n  private List<Person> personList = new ArrayList<>();\n  static final String NOT_IN_DATA_BASE = \" not in DataBase\";\n  static final String ID_STR = \"ID : \";\n\n  @Override\n  public Person find(int personNationalId) throws IdNotFoundException {\n    Optional<Person> elem =\n        personList.stream().filter(p -> p.getPersonNationalId() == personNationalId).findFirst();\n    if (elem.isEmpty()) {\n      throw new IdNotFoundException(ID_STR + personNationalId + NOT_IN_DATA_BASE);\n    }\n    LOGGER.info(elem.get().toString());\n    return elem.get();\n  }\n\n  @Override\n  public void insert(Person person) {\n    Optional<Person> elem =\n        personList.stream()\n            .filter(p -> p.getPersonNationalId() == person.getPersonNationalId())\n            .findFirst();\n    if (elem.isPresent()) {\n      LOGGER.info(\"Record already exists.\");\n      return;\n    }\n    personList.add(person);\n  }\n\n  @Override\n  public void update(Person person) throws IdNotFoundException {\n    Optional<Person> elem =\n        personList.stream()\n            .filter(p -> p.getPersonNationalId() == person.getPersonNationalId())\n            .findFirst();\n    if (elem.isPresent()) {\n      elem.get().setName(person.getName());\n      elem.get().setPhoneNum(person.getPhoneNum());\n      LOGGER.info(\"Record updated successfully\");\n      return;\n    }\n    throw new IdNotFoundException(ID_STR + person.getPersonNationalId() + NOT_IN_DATA_BASE);\n  }\n\n  /**\n   * Delete the record corresponding to given ID from the DB.\n   *\n   * @param id : personNationalId for person whose record is to be deleted.\n   */\n  public void delete(int id) throws IdNotFoundException {\n    Optional<Person> elem =\n        personList.stream().filter(p -> p.getPersonNationalId() == id).findFirst();\n    if (elem.isPresent()) {\n      personList.remove(elem.get());\n      LOGGER.info(\"Record deleted successfully.\");\n      return;\n    }\n    throw new IdNotFoundException(ID_STR + id + NOT_IN_DATA_BASE);\n  }\n\n  /** Return the size of the database. */\n  public int size() {\n    if (personList == null) {\n      return 0;\n    }\n    return personList.size();\n  }\n}\n"
  },
  {
    "path": "identity-map/src/main/java/com/iluwatar/identitymap/PersonFinder.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.identitymap;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Any object of this class stores a DataBase and an Identity Map. When we try to look for a key we\n * first check if it has been cached in the Identity Map and return it if it is indeed in the map.\n * If that is not the case then go to the DataBase, get the record, store it in the Identity Map and\n * then return the record. Now if we look for the record again we will find it in the table itself\n * which will make lookup faster.\n */\n@Slf4j\n@Getter\n@Setter\npublic class PersonFinder {\n  private static final long serialVersionUID = 1L;\n  //  Access to the Identity Map\n  private IdentityMap identityMap = new IdentityMap();\n  private PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n\n  /**\n   * get person corresponding to input ID.\n   *\n   * @param key : personNationalId to look for.\n   */\n  public Person getPerson(int key) {\n    // Try to find person in the identity map\n    Person person = this.identityMap.getPerson(key);\n    if (person != null) {\n      LOGGER.info(\"Person found in the Map\");\n      return person;\n    } else {\n      // Try to find person in the database\n      person = this.db.find(key);\n      if (person != null) {\n        this.identityMap.addPerson(person);\n        LOGGER.info(\"Person found in DB.\");\n        return person;\n      }\n      LOGGER.info(\"Person with this ID does not exist.\");\n      return null;\n    }\n  }\n}\n"
  },
  {
    "path": "identity-map/src/test/java/com/iluwatar/identitymap/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.identitymap;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "identity-map/src/test/java/com/iluwatar/identitymap/IdentityMapTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.identitymap;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass IdentityMapTest {\n  @Test\n  void addToMap() {\n    // new instance of an identity map(not connected to any DB here)\n    IdentityMap idMap = new IdentityMap();\n    // Dummy person instances\n    Person person1 = new Person(11, \"Michael\", 27304159);\n    Person person2 = new Person(22, \"John\", 42273631);\n    Person person3 = new Person(33, \"Arthur\", 27489171);\n    Person person4 = new Person(44, \"Finn\", 20499078);\n    // id already in map\n    Person person5 = new Person(11, \"Michael\", 40599078);\n    // All records go into identity map\n    idMap.addPerson(person1);\n    idMap.addPerson(person2);\n    idMap.addPerson(person3);\n    idMap.addPerson(person4);\n    idMap.addPerson(person5);\n    // Test no duplicate in our Map.\n    Assertions.assertEquals(4, idMap.size(), \"Size of the map is incorrect\");\n    // Test record not updated by add method.\n    Assertions.assertEquals(\n        27304159, idMap.getPerson(11).getPhoneNum(), \"Incorrect return value for phone number\");\n  }\n\n  @Test\n  void testGetFromMap() {\n    // new instance of an identity map(not connected to any DB here)\n    IdentityMap idMap = new IdentityMap();\n    // Dummy person instances\n    Person person1 = new Person(11, \"Michael\", 27304159);\n    Person person2 = new Person(22, \"John\", 42273631);\n    Person person3 = new Person(33, \"Arthur\", 27489171);\n    Person person4 = new Person(44, \"Finn\", 20499078);\n    Person person5 = new Person(55, \"Michael\", 40599078);\n    // All records go into identity map\n    idMap.addPerson(person1);\n    idMap.addPerson(person2);\n    idMap.addPerson(person3);\n    idMap.addPerson(person4);\n    idMap.addPerson(person5);\n    // Test for dummy persons in the map\n    Assertions.assertEquals(person1, idMap.getPerson(11), \"Incorrect person record returned\");\n    Assertions.assertEquals(person4, idMap.getPerson(44), \"Incorrect person record returned\");\n    // Test for person with given id not in map\n    Assertions.assertNull(idMap.getPerson(1), \"Incorrect person record returned\");\n  }\n}\n"
  },
  {
    "path": "identity-map/src/test/java/com/iluwatar/identitymap/PersonDbSimulatorImplementationTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.identitymap;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass PersonDbSimulatorImplementationTest {\n  @Test\n  void testInsert() {\n    // DataBase initialization.\n    PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n    Assertions.assertEquals(0, db.size(), \"Size of null database should be 0\");\n    // Dummy persons.\n    Person person1 = new Person(1, \"Thomas\", 27304159);\n    Person person2 = new Person(2, \"John\", 42273631);\n    Person person3 = new Person(3, \"Arthur\", 27489171);\n    db.insert(person1);\n    db.insert(person2);\n    db.insert(person3);\n    // Test size after insertion.\n    Assertions.assertEquals(3, db.size(), \"Incorrect size for database.\");\n    Person person4 = new Person(4, \"Finn\", 20499078);\n    Person person5 = new Person(5, \"Michael\", 40599078);\n    db.insert(person4);\n    db.insert(person5);\n    // Test size after more insertions.\n    Assertions.assertEquals(5, db.size(), \"Incorrect size for database.\");\n    Person person5duplicate = new Person(5, \"Kevin\", 89589122);\n    db.insert(person5duplicate);\n    // Test size after attempt to insert record with duplicate key.\n    Assertions.assertEquals(5, db.size(), \"Incorrect size for data base\");\n  }\n\n  @Test\n  void findNotInDb() {\n    PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n    Person person1 = new Person(1, \"Thomas\", 27304159);\n    Person person2 = new Person(2, \"John\", 42273631);\n    db.insert(person1);\n    db.insert(person2);\n    // Test if IdNotFoundException is thrown where expected.\n    Assertions.assertThrows(IdNotFoundException.class, () -> db.find(3));\n  }\n\n  @Test\n  void findInDb() {\n    PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n    Person person1 = new Person(1, \"Thomas\", 27304159);\n    Person person2 = new Person(2, \"John\", 42273631);\n    db.insert(person1);\n    db.insert(person2);\n    Assertions.assertEquals(person2, db.find(2), \"Record that was found was incorrect.\");\n  }\n\n  @Test\n  void updateNotInDb() {\n    PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n    Person person1 = new Person(1, \"Thomas\", 27304159);\n    Person person2 = new Person(2, \"John\", 42273631);\n    db.insert(person1);\n    db.insert(person2);\n    Person person3 = new Person(3, \"Micheal\", 25671234);\n    // Test if IdNotFoundException is thrown when person with ID 3 is not in DB.\n    Assertions.assertThrows(IdNotFoundException.class, () -> db.update(person3));\n  }\n\n  @Test\n  void updateInDb() {\n    PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n    Person person1 = new Person(1, \"Thomas\", 27304159);\n    Person person2 = new Person(2, \"John\", 42273631);\n    db.insert(person1);\n    db.insert(person2);\n    Person person = new Person(2, \"Thomas\", 42273690);\n    db.update(person);\n    Assertions.assertEquals(person, db.find(2), \"Incorrect update.\");\n  }\n\n  @Test\n  void deleteNotInDb() {\n    PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n    Person person1 = new Person(1, \"Thomas\", 27304159);\n    Person person2 = new Person(2, \"John\", 42273631);\n    db.insert(person1);\n    db.insert(person2);\n    // Test if IdNotFoundException is thrown when person with this ID not in DB.\n    Assertions.assertThrows(IdNotFoundException.class, () -> db.delete(3));\n  }\n\n  @Test\n  void deleteInDb() {\n    PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n    Person person1 = new Person(1, \"Thomas\", 27304159);\n    Person person2 = new Person(2, \"John\", 42273631);\n    db.insert(person1);\n    db.insert(person2);\n    // delete the record.\n    db.delete(1);\n    // test size of database after deletion.\n    Assertions.assertEquals(1, db.size(), \"Size after deletion is incorrect.\");\n    // try to find deleted record in db.\n    Assertions.assertThrows(IdNotFoundException.class, () -> db.find(1));\n  }\n}\n"
  },
  {
    "path": "identity-map/src/test/java/com/iluwatar/identitymap/PersonFinderTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.identitymap;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass PersonFinderTest {\n  @Test\n  void personFoundInDB() {\n    // personFinderInstance\n    PersonFinder personFinder = new PersonFinder();\n    // init database for our personFinder\n    PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n    // Dummy persons\n    Person person1 = new Person(1, \"John\", 27304159);\n    Person person2 = new Person(2, \"Thomas\", 42273631);\n    Person person3 = new Person(3, \"Arthur\", 27489171);\n    Person person4 = new Person(4, \"Finn\", 20499078);\n    Person person5 = new Person(5, \"Michael\", 40599078);\n    // Add data to the database.\n    db.insert(person1);\n    db.insert(person2);\n    db.insert(person3);\n    db.insert(person4);\n    db.insert(person5);\n    personFinder.setDb(db);\n\n    Assertions.assertEquals(\n        person1, personFinder.getPerson(1), \"Find person returns incorrect record.\");\n    Assertions.assertEquals(\n        person3, personFinder.getPerson(3), \"Find person returns incorrect record.\");\n    Assertions.assertEquals(\n        person2, personFinder.getPerson(2), \"Find person returns incorrect record.\");\n    Assertions.assertEquals(\n        person5, personFinder.getPerson(5), \"Find person returns incorrect record.\");\n    Assertions.assertEquals(\n        person4, personFinder.getPerson(4), \"Find person returns incorrect record.\");\n  }\n\n  @Test\n  void personFoundInIdMap() {\n    // personFinderInstance\n    PersonFinder personFinder = new PersonFinder();\n    // init database for our personFinder\n    PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n    // Dummy persons\n    Person person1 = new Person(1, \"John\", 27304159);\n    Person person2 = new Person(2, \"Thomas\", 42273631);\n    Person person3 = new Person(3, \"Arthur\", 27489171);\n    Person person4 = new Person(4, \"Finn\", 20499078);\n    Person person5 = new Person(5, \"Michael\", 40599078);\n    // Add data to the database.\n    db.insert(person1);\n    db.insert(person2);\n    db.insert(person3);\n    db.insert(person4);\n    db.insert(person5);\n    personFinder.setDb(db);\n    // Assure key is not in the ID map.\n    Assertions.assertFalse(personFinder.getIdentityMap().getPersonMap().containsKey(3));\n    // Assure key is in the database.\n    Assertions.assertEquals(person3, personFinder.getPerson(3), \"Finder returns incorrect record.\");\n    // Assure that the record for this key is cached in the Map now.\n    Assertions.assertTrue(personFinder.getIdentityMap().getPersonMap().containsKey(3));\n    // Find the record again. This time it will be found in the map.\n    Assertions.assertEquals(person3, personFinder.getPerson(3), \"Finder returns incorrect record.\");\n  }\n\n  @Test\n  void personNotFoundInDB() {\n    PersonFinder personFinder = new PersonFinder();\n    // init database for our personFinder\n    PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n    personFinder.setDb(db);\n    Assertions.assertThrows(IdNotFoundException.class, () -> personFinder.getPerson(1));\n    // Dummy persons\n    Person person1 = new Person(1, \"John\", 27304159);\n    Person person2 = new Person(2, \"Thomas\", 42273631);\n    Person person3 = new Person(3, \"Arthur\", 27489171);\n    Person person4 = new Person(4, \"Finn\", 20499078);\n    Person person5 = new Person(5, \"Michael\", 40599078);\n    db.insert(person1);\n    db.insert(person2);\n    db.insert(person3);\n    db.insert(person4);\n    db.insert(person5);\n    personFinder.setDb(db);\n    // Assure that the database has been updated.\n    Assertions.assertEquals(person4, personFinder.getPerson(4), \"Find returns incorrect record\");\n    // Assure key is in DB now.\n    Assertions.assertDoesNotThrow(() -> personFinder.getPerson(1));\n    // Assure key not in DB.\n    Assertions.assertThrows(IdNotFoundException.class, () -> personFinder.getPerson(6));\n  }\n}\n"
  },
  {
    "path": "identity-map/src/test/java/com/iluwatar/identitymap/PersonTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.identitymap;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass PersonTest {\n  @Test\n  void testEquality() {\n    // dummy persons.\n    Person person1 = new Person(1, \"Harry\", 989950022);\n    Person person2 = new Person(2, \"Kane\", 989920011);\n    Assertions.assertNotEquals(person1, person2, \"Incorrect equality condition\");\n    // person with duplicate nationalID.\n    Person person3 = new Person(2, \"John\", 789012211);\n    // If nationalID is equal then persons are equal(even if name or phoneNum are different).\n    // This situation will never arise in this implementation. Only for testing.\n    Assertions.assertEquals(person2, person3, \"Incorrect inequality condition\");\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/README.md",
    "content": "---\ntitle: \"Intercepting Filter Pattern in Java: Enhancing Request Processing in Web Applications\"\nshortTitle: Intercepting Filter\ndescription: \"Learn about the Intercepting Filter Pattern in Java. Discover how to design, implement, and use this pattern to enhance web request handling with practical examples and detailed explanations.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - API design\n  - Decoupling\n  - Layered architecture\n  - Performance\n  - Security\n  - Web development\n---\n\n## Intent of Intercepting Filter Design Pattern\n\nThe Intercepting Filter Pattern in Java is a powerful design pattern that allows for efficient web request handling. This pattern enables the application of multiple filters in a filter chain to process and modify requests and responses.\n\n## Detailed Explanation of Intercepting Filter Pattern with Real-World Examples\n\nReal-world example\n\n> Consider entering a secure office building where you pass through several checkpoints: a security desk checks your ID, a metal detector ensures safety, and a registration desk logs your visit. Each checkpoint acts like a filter in the Intercepting Filter pattern, processing and validating your entry step-by-step, similar to how filters handle different aspects of web requests and responses in a software system.\n\nIn plain words\n\n> The Intercepting Filter design pattern allows you to define processing steps (filters) that execute sequentially to handle and modify web requests and responses before they reach the application or are sent to the client.\n\nWikipedia says\n\n> Intercepting Filter is a Java pattern which creates pluggable filters to process common services in a standard manner without requiring changes to core request processing code.\n\nArchitecture diagram\n\n![Intercepting Filter Architecture Diagram](./etc/intercepting-filter-architecture-diagram.png)\n\n## Programmatic Example of Intercepting Filter Pattern in Java\n\nIn this article, we delve into the Intercepting Filter Pattern and provide a Java example to illustrate its use. This pattern is essential for Java web development, offering a modular approach to handling common services such as logging, authentication, and data compression.\n\nThe Java implementation of the Intercepting Filter Pattern includes classes like `FilterManager` and `Client`, which facilitate the management and application of filters. Each filter in the chain performs specific tasks, ensuring a clean and efficient design.\n\nThe `App` class is the entry point of the application. It creates an instance of `FilterManager`, adds various filters to it, and sets it to a `Client`.\n\n```java\npublic class App {\n\n  public static void main(String[] args) {\n    var filterManager = new FilterManager();\n    filterManager.addFilter(new NameFilter());\n    filterManager.addFilter(new ContactFilter());\n    filterManager.addFilter(new AddressFilter());\n    filterManager.addFilter(new DepositFilter());\n    filterManager.addFilter(new OrderFilter());\n\n    var client = new Client();\n    client.setFilterManager(filterManager);\n  }\n}\n```\n\nThe `FilterManager` class manages the filters and applies them to the requests.\n\n```java\npublic class FilterManager {\n  private final List<Filter> filters = new ArrayList<>();\n\n  public void addFilter(Filter filter) {\n    filters.add(filter);\n  }\n\n  public void filterRequest(String request) {\n    for (Filter filter : filters) {\n      filter.execute(request);\n    }\n  }\n}\n```\n\nThe `Client` class sends the request to the `FilterManager`.\n\n```java\npublic class Client {\n  private FilterManager filterManager;\n\n  public void setFilterManager(FilterManager filterManager) {\n    this.filterManager = filterManager;\n  }\n\n  public void sendRequest(String request) {\n    filterManager.filterRequest(request);\n  }\n}\n```\n\nThe `Filter` interface and its implementations (`NameFilter`, `ContactFilter`, `AddressFilter`, `DepositFilter`, `OrderFilter`) define the filters that can be applied to the requests.\n\n```java\npublic interface Filter {\n  void execute(String request);\n}\n\npublic class NameFilter extends AbstractFilter {\n\n    @Override\n    public String execute(Order order) {\n        var result = super.execute(order);\n        var name = order.getName();\n        if (name == null || name.isEmpty() || name.matches(\".*[^\\\\w|\\\\s]+.*\")) {\n            return result + \"Invalid name! \";\n        } else {\n            return result;\n        }\n    }\n}\n\n// Other Filter implementations...\n```\n\nIn this example, the `App` class sets up a `FilterManager` with various filters and assigns it to a `Client`. When the `Client` sends a request, the `FilterManager` applies all the filters to the request. This is a basic example of the Intercepting Filter pattern, where common processing tasks are encapsulated in filters and applied to requests in a standard manner.\n\n## When to Use the Intercepting Filter Pattern in Java\n\nUse the Intercepting Filter pattern when\n\n* In Java web applications to manage cross-cutting concerns.\n* When you need to apply pre-processing and post-processing steps to requests and responses, typically in web applications.\n* Suitable for handling cross-cutting concerns such as logging, authentication, data compression, and encryption transparently.\n\n## Intercepting Filter Pattern Java Tutorials\n\n* [Introduction to Intercepting Filter Pattern in Java (Baeldung)](https://www.baeldung.com/intercepting-filter-pattern-in-java)\n* [Design Pattern - Intercepting Filter Pattern (TutorialsPoint)](http://www.tutorialspoint.com/design_pattern/intercepting_filter_pattern.htm)\n\n## Real-World Applications of Intercepting Filter Pattern in Java\n\n* Frameworks like Spring MVC and web servers such as Apache Tomcat utilize the Intercepting Filter Pattern to enhance Java web development. This pattern's ability to centralize control and streamline web request handling makes it a go-to choice for developers.\n* [javax.servlet.FilterChain](https://tomcat.apache.org/tomcat-8.0-doc/servletapi/javax/servlet/FilterChain.html) and [javax.servlet.Filter](https://tomcat.apache.org/tomcat-8.0-doc/servletapi/javax/servlet/Filter.html)\n* [Struts 2 - Interceptors](https://struts.apache.org/core-developers/interceptors.html)\n\n## Benefits and Trade-offs of Intercepting Filter Pattern\n\nBenefits:\n\n* Promotes separation of concerns by allowing filters to be independently developed, tested, and reused.\n* Enhances flexibility through configurable filter chains.\n* Simplifies application maintenance by centralizing control in filter management.\n\nTrade-offs:\n\n* Introducing many filters can lead to performance overhead due to the processing of each request and response through multiple filters.\n* Debugging and tracing the request flow through multiple filters can be complex.\n\n## Related Java Design Patterns\n\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Filters in the Intercepting Filter pattern can be considered as decorators that add additional responsibilities to request handling. They modify the request/response without altering their fundamental behavior.\n* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Filters are linked in a chain, where each filter processes the request or response and optionally passes it to the next filter in the chain, similar to how responsibilities are passed along in the Chain of Responsibility pattern.\n\n## References and Credits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap)\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "intercepting-filter/etc/intercepting-filter.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.intercepting.filter.FilterManager\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterManager.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"176\" x=\"768\" y=\"500\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.intercepting.filter.NameFilter\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/NameFilter.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"169\" x=\"-381\" y=\"881\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.intercepting.filter.AddressFilter\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AddressFilter.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"169\" x=\"-172\" y=\"881\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.intercepting.filter.Order\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Order.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"376\" width=\"252\" x=\"47\" y=\"84\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.intercepting.filter.DepositFilter\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/DepositFilter.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"169\" x=\"37\" y=\"881\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.intercepting.filter.FilterChain\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterChain.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"169\" x=\"768\" y=\"664\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.intercepting.filter.AbstractFilter\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AbstractFilter.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"177\" width=\"169\" x=\"246\" y=\"664\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.intercepting.filter.OrderFilter\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/OrderFilter.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"169\" x=\"246\" y=\"881\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"9\" language=\"java\" name=\"com.iluwatar.intercepting.filter.ContactFilter\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/ContactFilter.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"169\" x=\"455\" y=\"881\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"10\" language=\"java\" name=\"com.iluwatar.intercepting.filter.Client\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Client.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"250\" width=\"236\" x=\"768\" y=\"84\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"11\" language=\"java\" name=\"com.iluwatar.intercepting.filter.Target\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Target.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"214\" width=\"169\" x=\"873\" y=\"881\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"12\" language=\"java\" name=\"com.iluwatar.intercepting.filter.Filter\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Filter.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"142\" width=\"169\" x=\"664\" y=\"881\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"13\" language=\"java\" name=\"com.iluwatar.intercepting.filter.Target.DListener\" project=\"intercepting-filter\" \n    file=\"/intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Target.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"223\" x=\"819\" y=\"1135\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"14\">    \n    <end type=\"SOURCE\" refId=\"10\" navigable=\"false\">      \n      <attribute id=\"15\" name=\"filterManager\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"16\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"17\">    \n    <end type=\"SOURCE\" refId=\"6\" navigable=\"false\">      \n      <attribute id=\"18\" name=\"chain\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"19\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"12\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"20\">    \n    <end type=\"SOURCE\" refId=\"7\" navigable=\"false\">      \n      <attribute id=\"21\" name=\"next\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"22\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"12\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <nesting id=\"23\">    \n    <end type=\"SOURCE\" refId=\"11\"/>    \n    <end type=\"TARGET\" refId=\"13\"/>  \n  </nesting>  \n  <generalization id=\"24\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <generalization id=\"25\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <generalization id=\"26\">    \n    <end type=\"SOURCE\" refId=\"9\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <generalization id=\"27\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <realization id=\"28\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"12\"/>  \n  </realization>  \n  <association id=\"29\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"30\" name=\"filterChain\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"31\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"6\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"32\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <association id=\"33\">    \n    <end type=\"SOURCE\" refId=\"6\" navigable=\"false\">      \n      <attribute id=\"34\" name=\"target\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"35\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"11\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "intercepting-filter/etc/intercepting-filter.urm.puml",
    "content": "@startuml\npackage com.iluwatar.intercepting.filter {\n  abstract class AbstractFilter {\n    - next : Filter\n    + AbstractFilter()\n    + AbstractFilter(next : Filter)\n    + execute(order : Order) : String\n    + getLast() : Filter\n    + getNext() : Filter\n    + setNext(filter : Filter)\n  }\n  class AddressFilter {\n    + AddressFilter()\n    + execute(order : Order) : String\n  }\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class ContactFilter {\n    + ContactFilter()\n    + execute(order : Order) : String\n  }\n  class DepositFilter {\n    + DepositFilter()\n    + execute(order : Order) : String\n  }\n  interface Filter {\n    + execute(Order) : String {abstract}\n    + getLast() : Filter {abstract}\n    + getNext() : Filter {abstract}\n    + setNext(Filter) {abstract}\n  }\n  class FilterChain {\n    - chain : Filter\n    + FilterChain()\n    + addFilter(filter : Filter)\n    + execute(order : Order) : String\n  }\n  class FilterManager {\n    - filterChain : FilterChain\n    + FilterManager()\n    + addFilter(filter : Filter)\n    + filterRequest(order : Order) : String\n  }\n  class NameFilter {\n    + NameFilter()\n    + execute(order : Order) : String\n  }\n  class Order {\n    - address : String\n    - contactNumber : String\n    - depositNumber : String\n    - name : String\n    - orderItem : String\n    + Order()\n    + Order(name : String, contactNumber : String, address : String, depositNumber : String, order : String)\n    + getAddress() : String\n    + getContactNumber() : String\n    + getDepositNumber() : String\n    + getName() : String\n    + getOrderItem() : String\n    + setAddress(address : String)\n    + setContactNumber(contactNumber : String)\n    + setDepositNumber(depositNumber : String)\n    + setName(name : String)\n    + setOrderItem(order : String)\n  }\n  class OrderFilter {\n    + OrderFilter()\n    + execute(order : Order) : String\n  }\n  ~class DListener {\n    ~ DListener()\n    + actionPerformed(e : ActionEvent)\n  }\n}\nAbstractFilter -->  \"-next\" Filter\nDListener --+ Target\nFilterManager -->  \"-filterChain\" FilterChain\nFilterChain -->  \"-chain\" Filter\nAbstractFilter ..|> Filter \nAddressFilter --|> AbstractFilter \nContactFilter --|> AbstractFilter \nDepositFilter --|> AbstractFilter \nNameFilter --|> AbstractFilter \nOrderFilter --|> AbstractFilter \n@enduml"
  },
  {
    "path": "intercepting-filter/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>intercepting-filter</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-params</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.intercepting.filter.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AbstractFilter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\n/** Base class for order processing filters. Handles chain management. */\npublic abstract class AbstractFilter implements Filter {\n\n  private Filter next;\n\n  public AbstractFilter() {}\n\n  public AbstractFilter(Filter next) {\n    this.next = next;\n  }\n\n  @Override\n  public void setNext(Filter filter) {\n    this.next = filter;\n  }\n\n  @Override\n  public Filter getNext() {\n    return next;\n  }\n\n  @Override\n  public Filter getLast() {\n    Filter last = this;\n    while (last.getNext() != null) {\n      last = last.getNext();\n    }\n    return last;\n  }\n\n  @Override\n  public String execute(Order order) {\n    if (getNext() != null) {\n      return getNext().execute(order);\n    } else {\n      return \"\";\n    }\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/AddressFilter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\n/**\n * Concrete implementation of filter This filter is responsible for checking/filtering the input in\n * the address field.\n */\npublic class AddressFilter extends AbstractFilter {\n\n  @Override\n  public String execute(Order order) {\n    var result = super.execute(order);\n    if (order.getAddress() == null || order.getAddress().isEmpty()) {\n      return result + \"Invalid address! \";\n    } else {\n      return result;\n    }\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\n/**\n * When a request enters a Web application, it often must pass several entrance tests prior to the\n * main processing stage. For example, - Has the client been authenticated? - Does the client have a\n * valid session? - Is the client's IP address from a trusted network? - Does the request path\n * violate any constraints? - What encoding does the client use to send the data? - Do we support\n * the browser type of the client? Some of these checks are tests, resulting in a yes or no answer\n * that determines whether processing will continue. Other checks manipulate the incoming data\n * stream into a form suitable for processing.\n *\n * <p>The classic solution consists of a series of conditional checks, with any failed check\n * aborting the request. Nested if/else statements are a standard strategy, but this solution leads\n * to code fragility and a copy-and-paste style of programming, because the flow of the filtering\n * and the action of the filters is compiled into the application.\n *\n * <p>The key to solving this problem in a flexible and unobtrusive manner is to have a simple\n * mechanism for adding and removing processing components, in which each component completes a\n * specific filtering action. This is the Intercepting Filter pattern in action.\n *\n * <p>In this example we check whether the order request is valid through pre-processing done via\n * {@link Filter}. Each field has its own corresponding {@link Filter}.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var filterManager = new FilterManager();\n    filterManager.addFilter(new NameFilter());\n    filterManager.addFilter(new ContactFilter());\n    filterManager.addFilter(new AddressFilter());\n    filterManager.addFilter(new DepositFilter());\n    filterManager.addFilter(new OrderFilter());\n\n    var client = new Client();\n    client.setFilterManager(filterManager);\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Client.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\nimport java.awt.BorderLayout;\nimport java.awt.GridLayout;\nimport java.awt.event.ActionEvent;\nimport java.io.Serial;\nimport java.util.Arrays;\nimport javax.swing.JButton;\nimport javax.swing.JFrame;\nimport javax.swing.JLabel;\nimport javax.swing.JPanel;\nimport javax.swing.JRootPane;\nimport javax.swing.JTextArea;\nimport javax.swing.JTextField;\nimport javax.swing.SwingUtilities;\nimport javax.swing.WindowConstants;\n\n/**\n * The Client class is responsible for handling the input and running them through filters inside\n * the {@link FilterManager}.\n *\n * <p>This is where {@link Filter}s come to play as the client pre-processes the request before\n * being displayed in the {@link Target}.\n */\npublic class Client extends JFrame { // NOSONAR\n\n  @Serial private static final long serialVersionUID = 1L;\n\n  private transient FilterManager filterManager;\n  private final JLabel jl;\n  private final JTextField[] jtFields;\n  private final JTextArea[] jtAreas;\n  private final JButton clearButton;\n  private final JButton processButton;\n\n  /** Constructor. */\n  public Client() {\n    super(\"Client System\");\n    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);\n    setSize(300, 300);\n    jl = new JLabel(\"RUNNING...\");\n    jtFields = new JTextField[3];\n    for (var i = 0; i < 3; i++) {\n      jtFields[i] = new JTextField();\n    }\n    jtAreas = new JTextArea[2];\n    for (var i = 0; i < 2; i++) {\n      jtAreas[i] = new JTextArea();\n    }\n    clearButton = new JButton(\"Clear\");\n    processButton = new JButton(\"Process\");\n\n    setup();\n  }\n\n  private void setup() {\n    setLayout(new BorderLayout());\n    var panel = new JPanel();\n    add(jl, BorderLayout.SOUTH);\n    add(panel, BorderLayout.CENTER);\n    panel.setLayout(new GridLayout(6, 2));\n    panel.add(new JLabel(\"Name\"));\n    panel.add(jtFields[0]);\n    panel.add(new JLabel(\"Contact Number\"));\n    panel.add(jtFields[1]);\n    panel.add(new JLabel(\"Address\"));\n    panel.add(jtAreas[0]);\n    panel.add(new JLabel(\"Deposit Number\"));\n    panel.add(jtFields[2]);\n    panel.add(new JLabel(\"Order\"));\n    panel.add(jtAreas[1]);\n    panel.add(clearButton);\n    panel.add(processButton);\n\n    clearButton.addActionListener(\n        e -> {\n          Arrays.stream(jtAreas).forEach(i -> i.setText(\"\"));\n          Arrays.stream(jtFields).forEach(i -> i.setText(\"\"));\n        });\n\n    processButton.addActionListener(this::actionPerformed);\n\n    JRootPane rootPane = SwingUtilities.getRootPane(processButton);\n    rootPane.setDefaultButton(processButton);\n    setVisible(true);\n  }\n\n  public void setFilterManager(FilterManager filterManager) {\n    this.filterManager = filterManager;\n  }\n\n  public String sendRequest(Order order) {\n    return filterManager.filterRequest(order);\n  }\n\n  private void actionPerformed(ActionEvent e) {\n    var fieldText1 = jtFields[0].getText();\n    var fieldText2 = jtFields[1].getText();\n    var areaText1 = jtAreas[0].getText();\n    var fieldText3 = jtFields[2].getText();\n    var areaText2 = jtAreas[1].getText();\n    var order = new Order(fieldText1, fieldText2, areaText1, fieldText3, areaText2);\n    jl.setText(sendRequest(order));\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/ContactFilter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\n/**\n * Concrete implementation of filter This filter checks for the contact field in which it checks if\n * the input consist of numbers and it also checks if the input follows the length constraint (11\n * digits).\n */\npublic class ContactFilter extends AbstractFilter {\n\n  @Override\n  public String execute(Order order) {\n    var result = super.execute(order);\n    var contactNumber = order.getContactNumber();\n    if (contactNumber == null\n        || contactNumber.matches(\".*[^\\\\d]+.*\")\n        || contactNumber.length() != 11) {\n      return result + \"Invalid contact number! \";\n    } else {\n      return result;\n    }\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/DepositFilter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\n/** Concrete implementation of filter This checks for the deposit code. */\npublic class DepositFilter extends AbstractFilter {\n\n  @Override\n  public String execute(Order order) {\n    var result = super.execute(order);\n    var depositNumber = order.getDepositNumber();\n    if (depositNumber == null || depositNumber.isEmpty()) {\n      return result + \"Invalid deposit number! \";\n    } else {\n      return result;\n    }\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Filter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\n/**\n * Filters perform certain tasks prior or after execution of request by request handler. In this\n * case, before the request is handled by the target, the request undergoes through each Filter\n */\npublic interface Filter {\n\n  /** Execute order processing filter. */\n  String execute(Order order);\n\n  /** Set next filter in chain after this. */\n  void setNext(Filter filter);\n\n  /** Get next filter in chain after this. */\n  Filter getNext();\n\n  /** Get last filter in the chain. */\n  Filter getLast();\n}\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterChain.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\n/** Filter Chain carries multiple filters and help to execute them in defined order on target. */\npublic class FilterChain {\n\n  private Filter chain;\n\n  /** Adds filter. */\n  public void addFilter(Filter filter) {\n    if (chain == null) {\n      chain = filter;\n    } else {\n      chain.getLast().setNext(filter);\n    }\n  }\n\n  /** Execute filter chain. */\n  public String execute(Order order) {\n    if (chain != null) {\n      return chain.execute(order);\n    } else {\n      return \"RUNNING...\";\n    }\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/FilterManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\n/** Filter Manager manages the filters and {@link FilterChain}. */\npublic class FilterManager {\n\n  private final FilterChain filterChain;\n\n  public FilterManager() {\n    filterChain = new FilterChain();\n  }\n\n  public void addFilter(Filter filter) {\n    filterChain.addFilter(filter);\n  }\n\n  public String filterRequest(Order order) {\n    return filterChain.execute(order);\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/NameFilter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\n/**\n * Concrete implementation of filter. This filter checks if the input in the Name field is valid.\n * (alphanumeric)\n */\npublic class NameFilter extends AbstractFilter {\n\n  @Override\n  public String execute(Order order) {\n    var result = super.execute(order);\n    var name = order.getName();\n    if (name == null || name.isEmpty() || name.matches(\".*[^\\\\w|\\\\s]+.*\")) {\n      return result + \"Invalid name! \";\n    } else {\n      return result;\n    }\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Order.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n/** Order class carries the order data. */\n@Getter\n@Setter\n@NoArgsConstructor\n@AllArgsConstructor\npublic class Order {\n\n  private String name;\n  private String contactNumber;\n  private String address;\n  private String depositNumber;\n  private String orderItem;\n}\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/OrderFilter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\n/** Concrete implementation of filter. This checks for the order field. */\npublic class OrderFilter extends AbstractFilter {\n\n  @Override\n  public String execute(Order order) {\n    var result = super.execute(order);\n    var orderItem = order.getOrderItem();\n    if (orderItem == null || orderItem.isEmpty()) {\n      return result + \"Invalid order! \";\n    } else {\n      return result;\n    }\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/main/java/com/iluwatar/intercepting/filter/Target.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\nimport java.awt.BorderLayout;\nimport java.awt.Dimension;\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\nimport java.io.Serial;\nimport java.util.stream.IntStream;\nimport javax.swing.JButton;\nimport javax.swing.JFrame;\nimport javax.swing.JPanel;\nimport javax.swing.JScrollPane;\nimport javax.swing.JTable;\nimport javax.swing.SwingUtilities;\nimport javax.swing.WindowConstants;\nimport javax.swing.table.DefaultTableModel;\n\n/** This is where the requests are displayed after being validated by filters. */\npublic class Target extends JFrame { // NOSONAR\n\n  @Serial private static final long serialVersionUID = 1L;\n\n  private final JTable jt;\n  private final DefaultTableModel dtm;\n  private final JButton del;\n\n  /** Constructor. */\n  public Target() {\n    super(\"Order System\");\n    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);\n    setSize(640, 480);\n    dtm =\n        new DefaultTableModel(\n            new Object[] {\"Name\", \"Contact Number\", \"Address\", \"Deposit Number\", \"Order\"}, 0);\n    jt = new JTable(dtm);\n    del = new JButton(\"Delete\");\n    setup();\n  }\n\n  private void setup() {\n    setLayout(new BorderLayout());\n    var bot = new JPanel();\n    add(jt.getTableHeader(), BorderLayout.NORTH);\n    bot.setLayout(new BorderLayout());\n    bot.add(del, BorderLayout.EAST);\n    add(bot, BorderLayout.SOUTH);\n    var jsp = new JScrollPane(jt);\n    jsp.setPreferredSize(new Dimension(500, 250));\n    add(jsp, BorderLayout.CENTER);\n\n    del.addActionListener(new TargetListener());\n\n    var rootPane = SwingUtilities.getRootPane(del);\n    rootPane.setDefaultButton(del);\n    setVisible(true);\n  }\n\n  public void execute(String[] request) {\n    dtm.addRow(new Object[] {request[0], request[1], request[2], request[3], request[4]});\n  }\n\n  class TargetListener implements ActionListener {\n    @Override\n    public void actionPerformed(ActionEvent e) {\n      var temp = jt.getSelectedRow();\n      if (temp == -1) {\n        return;\n      }\n      var temp2 = jt.getSelectedRowCount();\n      IntStream.range(0, temp2).forEach(i -> dtm.removeRow(temp));\n    }\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterManagerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\nimport static org.mockito.Mockito.when;\n\nimport org.junit.jupiter.api.Test;\n\n/** FilterManagerTest */\nclass FilterManagerTest {\n\n  @Test\n  void testFilterRequest() {\n    final var target = mock(Target.class);\n    final var filterManager = new FilterManager();\n    assertEquals(\"RUNNING...\", filterManager.filterRequest(mock(Order.class)));\n    verifyNoMoreInteractions(target);\n  }\n\n  @Test\n  void testAddFilter() {\n    final var target = mock(Target.class);\n    final var filterManager = new FilterManager();\n\n    verifyNoMoreInteractions(target);\n\n    final var filter = mock(Filter.class);\n    when(filter.execute(any(Order.class))).thenReturn(\"filter\");\n\n    filterManager.addFilter(filter);\n\n    final Order order = mock(Order.class);\n    assertEquals(\"filter\", filterManager.filterRequest(order));\n\n    verify(filter, times(1)).execute(any(Order.class));\n    verifyNoMoreInteractions(target, filter, order);\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/FilterTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertSame;\n\nimport java.util.List;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\n/** FilterTest */\nclass FilterTest {\n\n  private static final Order PERFECT_ORDER =\n      new Order(\"name\", \"12345678901\", \"addr\", \"dep\", \"order\");\n  private static final Order WRONG_ORDER = new Order(\"name\", \"12345678901\", \"addr\", \"dep\", \"\");\n  private static final Order WRONG_DEPOSIT = new Order(\"name\", \"12345678901\", \"addr\", \"\", \"order\");\n  private static final Order WRONG_ADDRESS = new Order(\"name\", \"12345678901\", \"\", \"dep\", \"order\");\n  private static final Order WRONG_CONTACT = new Order(\"name\", \"\", \"addr\", \"dep\", \"order\");\n  private static final Order WRONG_NAME = new Order(\"\", \"12345678901\", \"addr\", \"dep\", \"order\");\n\n  static List<Object[]> getTestData() {\n    return List.of(\n        new Object[] {new NameFilter(), PERFECT_ORDER, \"\"},\n        new Object[] {new NameFilter(), WRONG_NAME, \"Invalid name!\"},\n        new Object[] {new NameFilter(), WRONG_CONTACT, \"\"},\n        new Object[] {new NameFilter(), WRONG_ADDRESS, \"\"},\n        new Object[] {new NameFilter(), WRONG_DEPOSIT, \"\"},\n        new Object[] {new NameFilter(), WRONG_ORDER, \"\"},\n        new Object[] {new ContactFilter(), PERFECT_ORDER, \"\"},\n        new Object[] {new ContactFilter(), WRONG_NAME, \"\"},\n        new Object[] {new ContactFilter(), WRONG_CONTACT, \"Invalid contact number!\"},\n        new Object[] {new ContactFilter(), WRONG_ADDRESS, \"\"},\n        new Object[] {new ContactFilter(), WRONG_DEPOSIT, \"\"},\n        new Object[] {new ContactFilter(), WRONG_ORDER, \"\"},\n        new Object[] {new AddressFilter(), PERFECT_ORDER, \"\"},\n        new Object[] {new AddressFilter(), WRONG_NAME, \"\"},\n        new Object[] {new AddressFilter(), WRONG_CONTACT, \"\"},\n        new Object[] {new AddressFilter(), WRONG_ADDRESS, \"Invalid address!\"},\n        new Object[] {new AddressFilter(), WRONG_DEPOSIT, \"\"},\n        new Object[] {new AddressFilter(), WRONG_ORDER, \"\"},\n        new Object[] {new DepositFilter(), PERFECT_ORDER, \"\"},\n        new Object[] {new DepositFilter(), WRONG_NAME, \"\"},\n        new Object[] {new DepositFilter(), WRONG_CONTACT, \"\"},\n        new Object[] {new DepositFilter(), WRONG_ADDRESS, \"\"},\n        new Object[] {new DepositFilter(), WRONG_DEPOSIT, \"Invalid deposit number!\"},\n        new Object[] {new DepositFilter(), WRONG_ORDER, \"\"},\n        new Object[] {new OrderFilter(), PERFECT_ORDER, \"\"},\n        new Object[] {new OrderFilter(), WRONG_NAME, \"\"},\n        new Object[] {new OrderFilter(), WRONG_CONTACT, \"\"},\n        new Object[] {new OrderFilter(), WRONG_ADDRESS, \"\"},\n        new Object[] {new OrderFilter(), WRONG_DEPOSIT, \"\"},\n        new Object[] {new OrderFilter(), WRONG_ORDER, \"Invalid order!\"});\n  }\n\n  @ParameterizedTest\n  @MethodSource(\"getTestData\")\n  void testExecute(Filter filter, Order order, String expectedResult) {\n    final var result = filter.execute(order);\n    assertNotNull(result);\n    assertEquals(expectedResult, result.trim());\n  }\n\n  @ParameterizedTest\n  @MethodSource(\"getTestData\")\n  void testNext(Filter filter) {\n    assertNull(filter.getNext());\n    assertSame(filter, filter.getLast());\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/OrderTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** OrderTest */\nclass OrderTest {\n\n  private static final String EXPECTED_VALUE = \"test\";\n\n  @Test\n  void testSetName() {\n    final var order = new Order();\n    order.setName(EXPECTED_VALUE);\n    assertEquals(EXPECTED_VALUE, order.getName());\n  }\n\n  @Test\n  void testSetContactNumber() {\n    final var order = new Order();\n    order.setContactNumber(EXPECTED_VALUE);\n    assertEquals(EXPECTED_VALUE, order.getContactNumber());\n  }\n\n  @Test\n  void testSetAddress() {\n    final var order = new Order();\n    order.setAddress(EXPECTED_VALUE);\n    assertEquals(EXPECTED_VALUE, order.getAddress());\n  }\n\n  @Test\n  void testSetDepositNumber() {\n    final var order = new Order();\n    order.setDepositNumber(EXPECTED_VALUE);\n    assertEquals(EXPECTED_VALUE, order.getDepositNumber());\n  }\n\n  @Test\n  void testSetOrder() {\n    final var order = new Order();\n    order.setOrderItem(EXPECTED_VALUE);\n    assertEquals(EXPECTED_VALUE, order.getOrderItem());\n  }\n}\n"
  },
  {
    "path": "intercepting-filter/src/test/java/com/iluwatar/intercepting/filter/TargetTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.intercepting.filter;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** TargetTest */\nclass TargetTest {\n\n  @Test\n  void testSetup() {\n    final var target = new Target();\n    assertEquals(target.getSize().getWidth(), Double.valueOf(640));\n    assertEquals(target.getSize().getHeight(), Double.valueOf(480));\n    assertTrue(target.isVisible());\n  }\n}\n"
  },
  {
    "path": "interpreter/README.md",
    "content": "---\ntitle: \"Interpreter Pattern in Java: Building Custom Parsers for Java Applications\"\nshortTitle: Interpreter\ndescription: \"Explore the Interpreter Design Pattern in Java with real-world examples, class diagrams, and step-by-step implementation. Learn when and how to use this powerful behavioral pattern.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Abstraction\n  - Data transformation\n  - Decoupling\n  - Domain\n  - Gang of Four\n  - Polymorphism\n  - Runtime\n---\n\n## Intent of Interpreter Design Pattern\n\nThe Interpreter design pattern is used to define a grammatical representation for a language and provides an interpreter to handle this grammar. This pattern is useful in scenarios where a specific set of rules or grammar needs to be interpreted and acted upon, such as in arithmetic expressions or scripting languages.\n\n## Detailed Explanation of Interpreter Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a calculator application designed to interpret and calculate expressions entered by users. The application uses the Interpreter pattern in Java to parse and evaluate arithmetic expressions such as \"5 + 3 * 2\". Here, the Interpreter translates each part of the expression into objects that represent numbers and operations. These objects follow a defined grammar that allows the application to understand and compute the result correctly based on the rules of arithmetic. Each element of the expression corresponds to a class in the program's structure, simplifying the parsing and evaluation process for any inputted arithmetic formula.\n\nIn plain words\n\n> The Interpreter design pattern defines a representation for a language's grammar along with an interpreter that uses the representation to interpret sentences in the language.\n\nWikipedia says\n\n> In computer programming, the interpreter pattern is a design pattern that specifies how to evaluate sentences in a language. The basic idea is to have a class for each symbol (terminal or nonterminal) in a specialized computer language. The syntax tree of a sentence in the language is an instance of the composite pattern and is used to evaluate (interpret) the sentence for a client.\n\nSequence diagram\n\n![Interpreter sequence diagram](./etc/interpreter-sequence-diagram.png)\n\n## Programmatic Example of Interpreter Pattern in Java\n\nTo be able to interpret basic math in Java, we need a hierarchy of expressions. The `Expression` class is the base, and concrete implementations like `NumberExpression` handle specific parts of the grammar. The Interpreter pattern in Java simplifies parsing and evaluating arithmetic expressions by translating them into a structured format that the application can process.\n\n```java\npublic abstract class Expression {\n\n    public abstract int interpret();\n\n    @Override\n    public abstract String toString();\n}\n```\n\nThe simplest of the expressions is the `NumberExpression` that contains only a single integer number.\n\n```java\npublic class NumberExpression extends Expression {\n\n    private final int number;\n\n    public NumberExpression(int number) {\n        this.number = number;\n    }\n\n    public NumberExpression(String s) {\n        this.number = Integer.parseInt(s);\n    }\n\n    @Override\n    public int interpret() {\n        return number;\n    }\n\n    @Override\n    public String toString() {\n        return \"number\";\n    }\n}\n```\n\nThe more complex expressions are operations such as `PlusExpression`, `MinusExpression`, and `MultiplyExpression`. Here's the first of them, the others are similar.\n\n```java\npublic class PlusExpression extends Expression {\n\n    private final Expression leftExpression;\n    private final Expression rightExpression;\n\n    public PlusExpression(Expression leftExpression, Expression rightExpression) {\n        this.leftExpression = leftExpression;\n        this.rightExpression = rightExpression;\n    }\n\n    @Override\n    public int interpret() {\n        return leftExpression.interpret() + rightExpression.interpret();\n    }\n\n    @Override\n    public String toString() {\n        return \"+\";\n    }\n}\n```\n\nNow, we are able to show the interpreter pattern in action parsing some simple math.\n\n```java\n@Slf4j\npublic class App {\n\n    public static void main(String[] args) {\n\n        // the halfling kids are learning some basic math at school\n        // define the math string we want to parse\n        final var tokenString = \"4 3 2 - 1 + *\";\n\n        // the stack holds the parsed expressions\n        var stack = new Stack<Expression>();\n\n        // tokenize the string and go through them one by one\n        var tokenList = tokenString.split(\" \");\n        for (var s : tokenList) {\n            if (isOperator(s)) {\n                // when an operator is encountered we expect that the numbers can be popped from the top of\n                // the stack\n                var rightExpression = stack.pop();\n                var leftExpression = stack.pop();\n                LOGGER.info(\"popped from stack left: {} right: {}\",\n                        leftExpression.interpret(), rightExpression.interpret());\n                var operator = getOperatorInstance(s, leftExpression, rightExpression);\n                LOGGER.info(\"operator: {}\", operator);\n                var result = operator.interpret();\n                // the operation result is pushed on top of the stack\n                var resultExpression = new NumberExpression(result);\n                stack.push(resultExpression);\n                LOGGER.info(\"push result to stack: {}\", resultExpression.interpret());\n            } else {\n                // numbers are pushed on top of the stack\n                var i = new NumberExpression(s);\n                stack.push(i);\n                LOGGER.info(\"push to stack: {}\", i.interpret());\n            }\n        }\n        // in the end, the final result lies on top of the stack\n        LOGGER.info(\"result: {}\", stack.pop().interpret());\n    }\n\n    public static boolean isOperator(String s) {\n        return s.equals(\"+\") || s.equals(\"-\") || s.equals(\"*\");\n    }\n\n    public static Expression getOperatorInstance(String s, Expression left, Expression right) {\n        return switch (s) {\n            case \"+\" -> new PlusExpression(left, right);\n            case \"-\" -> new MinusExpression(left, right);\n            default -> new MultiplyExpression(left, right);\n        };\n    }\n}\n ```\n\nExecuting the program produces the following console output.\n\n```\n13:33:15.437 [main] INFO com.iluwatar.interpreter.App -- push to stack: 4\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- push to stack: 3\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- push to stack: 2\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- popped from stack left: 3 right: 2\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- operator: -\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- push result to stack: 1\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- push to stack: 1\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- popped from stack left: 1 right: 1\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- operator: +\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- push result to stack: 2\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- popped from stack left: 4 right: 2\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- operator: *\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- push result to stack: 8\n13:33:15.440 [main] INFO com.iluwatar.interpreter.App -- result: 8\n```\n\n## When to Use the Interpreter Pattern in Java\n\nUse the Interpreter design pattern when there is a language to interpret, and you can represent statements in the language as abstract syntax trees. The Interpreter pattern works best when\n\n* The grammar is simple. For complex grammars, the class hierarchy for the grammar becomes large and unmanageable. Tools such as parser generators are a better alternative in such cases. They can interpret expressions without building abstract syntax trees, which can save space and possibly time.\n* Efficiency is not a critical concern. The most efficient interpreters are usually not implemented by interpreting parse trees directly but by first translating them into another form. For example, regular expressions are often transformed into state machines. But even then, the translator can be implemented by the Interpreter pattern, so the pattern is still applicable.\n\n## Real-World Applications of Interpreter Pattern in Java\n\n* [java.util.Pattern](http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html)\n* [java.text.Normalizer](http://docs.oracle.com/javase/8/docs/api/java/text/Normalizer.html)\n* All subclasses of [java.text.Format](http://docs.oracle.com/javase/8/docs/api/java/text/Format.html)\n* [javax.el.ELResolver](http://docs.oracle.com/javaee/7/api/javax/el/ELResolver.html)\n* SQL parsers in various database management systems.\n\n## Benefits and Trade-offs of Interpreter Pattern\n\nBenefits:\n\n* Adds new operations to interpret expressions easily without changing the grammar or classes of data.\n* Implements grammar directly in the language, making it easy to modify or extend.\n\nTrade-offs:\n\n* Can become complex and inefficient for large grammars.\n* Each rule in the grammar results in a class, leading to a large number of classes for complex grammars.\n\n## Related Java Design Patterns\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): Often used together, where the Interpreter pattern leverages the Composite pattern to represent the grammar as a tree structure.\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Useful for sharing state to reduce memory usage in the Interpreter pattern, particularly for interpreters that deal with repetitive elements in a language.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "interpreter/etc/interpreter.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.interpreter.Expression\" project=\"interpreter\" \n    file=\"/interpreter/src/main/java/com/iluwatar/interpreter/Expression.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"123\" width=\"138\" x=\"508\" y=\"389\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.interpreter.NumberExpression\" project=\"interpreter\" \n    file=\"/interpreter/src/main/java/com/iluwatar/interpreter/NumberExpression.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"160\" width=\"178\" x=\"508\" y=\"552\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.interpreter.MinusExpression\" project=\"interpreter\" \n    file=\"/interpreter/src/main/java/com/iluwatar/interpreter/MinusExpression.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"268\" x=\"200\" y=\"225\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.interpreter.MultiplyExpression\" project=\"interpreter\" \n    file=\"/interpreter/src/main/java/com/iluwatar/interpreter/MultiplyExpression.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"278\" x=\"508\" y=\"225\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.interpreter.PlusExpression\" project=\"interpreter\" \n    file=\"/interpreter/src/main/java/com/iluwatar/interpreter/PlusExpression.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"259\" x=\"826\" y=\"225\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"6\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"7\" name=\"leftExpression\"/>      \n      <multiplicity id=\"8\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"9\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"10\" name=\"leftExpression\"/>      \n      <multiplicity id=\"11\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"12\">    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"13\" name=\"leftExpression\"/>      \n      <multiplicity id=\"14\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"15\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"16\" name=\"rightExpression\"/>      \n      <multiplicity id=\"17\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"18\">    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"19\" name=\"rightExpression\"/>      \n      <multiplicity id=\"20\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"21\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <association id=\"22\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"23\" name=\"rightExpression\"/>      \n      <multiplicity id=\"24\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"25\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <generalization id=\"26\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <generalization id=\"27\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "interpreter/etc/interpreter.urm.puml",
    "content": "@startuml\npackage com.iluwatar.interpreter {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + getOperatorInstance(s : String, left : Expression, right : Expression) : Expression {static}\n    + isOperator(s : String) : boolean {static}\n    + main(args : String[]) {static}\n  }\n  abstract class Expression {\n    + Expression()\n    + interpret() : int {abstract}\n    + toString() : String {abstract}\n  }\n  class MinusExpression {\n    - leftExpression : Expression\n    - rightExpression : Expression\n    + MinusExpression(leftExpression : Expression, rightExpression : Expression)\n    + interpret() : int\n    + toString() : String\n  }\n  class MultiplyExpression {\n    - leftExpression : Expression\n    - rightExpression : Expression\n    + MultiplyExpression(leftExpression : Expression, rightExpression : Expression)\n    + interpret() : int\n    + toString() : String\n  }\n  class NumberExpression {\n    - number : int\n    + NumberExpression(number : int)\n    + NumberExpression(s : String)\n    + interpret() : int\n    + toString() : String\n  }\n  class PlusExpression {\n    - leftExpression : Expression\n    - rightExpression : Expression\n    + PlusExpression(leftExpression : Expression, rightExpression : Expression)\n    + interpret() : int\n    + toString() : String\n  }\n}\nMultiplyExpression -->  \"-leftExpression\" Expression\nMinusExpression -->  \"-leftExpression\" Expression\nPlusExpression -->  \"-leftExpression\" Expression\nMinusExpression --|> Expression \nMultiplyExpression --|> Expression \nNumberExpression --|> Expression \nPlusExpression --|> Expression \n@enduml"
  },
  {
    "path": "interpreter/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>interpreter</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-params</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.interpreter.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "interpreter/src/main/java/com/iluwatar/interpreter/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.interpreter;\n\nimport java.util.Stack;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Interpreter pattern is a design pattern that specifies how to evaluate sentences in a\n * language. The basic idea is to have a class for each symbol (terminal or nonterminal) in a\n * specialized computer language. The syntax tree of a sentence in the language is an instance of\n * the composite pattern and is used to evaluate (interpret) the sentence for a client.\n *\n * <p>In this example we use the Interpreter pattern to break sentences into expressions ({@link\n * Expression}) that can be evaluated and as a whole form the result.\n *\n * <p>Expressions can be evaluated using prefix, infix or postfix notations This sample uses\n * postfix, where operator comes after the operands.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args program arguments\n   */\n  public static void main(String[] args) {\n\n    // the halfling kids are learning some basic math at school\n    // define the math string we want to parse\n    final var tokenString = \"4 3 2 - 1 + *\";\n\n    // the stack holds the parsed expressions\n    var stack = new Stack<Expression>();\n\n    // tokenize the string and go through them one by one\n    var tokenList = tokenString.split(\" \");\n    for (var s : tokenList) {\n      if (isOperator(s)) {\n        // when an operator is encountered we expect that the numbers can be popped from the top of\n        // the stack\n        var rightExpression = stack.pop();\n        var leftExpression = stack.pop();\n        LOGGER.info(\n            \"popped from stack left: {} right: {}\",\n            leftExpression.interpret(),\n            rightExpression.interpret());\n        var operator = getOperatorInstance(s, leftExpression, rightExpression);\n        LOGGER.info(\"operator: {}\", operator);\n        var result = operator.interpret();\n        // the operation result is pushed on top of the stack\n        var resultExpression = new NumberExpression(result);\n        stack.push(resultExpression);\n        LOGGER.info(\"push result to stack: {}\", resultExpression.interpret());\n      } else {\n        // numbers are pushed on top of the stack\n        var i = new NumberExpression(s);\n        stack.push(i);\n        LOGGER.info(\"push to stack: {}\", i.interpret());\n      }\n    }\n    // in the end, the final result lies on top of the stack\n    LOGGER.info(\"result: {}\", stack.pop().interpret());\n  }\n\n  /**\n   * Checks whether the input parameter is an operator.\n   *\n   * @param s input string\n   * @return true if the input parameter is an operator\n   */\n  public static boolean isOperator(String s) {\n    return s.equals(\"+\") || s.equals(\"-\") || s.equals(\"*\");\n  }\n\n  /**\n   * Returns correct expression based on the parameters.\n   *\n   * @param s input string\n   * @param left expression\n   * @param right expression\n   * @return expression\n   */\n  public static Expression getOperatorInstance(String s, Expression left, Expression right) {\n    return switch (s) {\n      case \"+\" -> new PlusExpression(left, right);\n      case \"-\" -> new MinusExpression(left, right);\n      default -> new MultiplyExpression(left, right);\n    };\n  }\n}\n"
  },
  {
    "path": "interpreter/src/main/java/com/iluwatar/interpreter/Expression.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.interpreter;\n\n/** Expression. */\npublic abstract class Expression {\n\n  public abstract int interpret();\n\n  @Override\n  public abstract String toString();\n}\n"
  },
  {
    "path": "interpreter/src/main/java/com/iluwatar/interpreter/MinusExpression.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.interpreter;\n\n/** MinusExpression. */\npublic class MinusExpression extends Expression {\n\n  private final Expression leftExpression;\n  private final Expression rightExpression;\n\n  public MinusExpression(Expression leftExpression, Expression rightExpression) {\n    this.leftExpression = leftExpression;\n    this.rightExpression = rightExpression;\n  }\n\n  @Override\n  public int interpret() {\n    return leftExpression.interpret() - rightExpression.interpret();\n  }\n\n  @Override\n  public String toString() {\n    return \"-\";\n  }\n}\n"
  },
  {
    "path": "interpreter/src/main/java/com/iluwatar/interpreter/MultiplyExpression.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.interpreter;\n\n/** MultiplyExpression. */\npublic class MultiplyExpression extends Expression {\n\n  private final Expression leftExpression;\n  private final Expression rightExpression;\n\n  public MultiplyExpression(Expression leftExpression, Expression rightExpression) {\n    this.leftExpression = leftExpression;\n    this.rightExpression = rightExpression;\n  }\n\n  @Override\n  public int interpret() {\n    return leftExpression.interpret() * rightExpression.interpret();\n  }\n\n  @Override\n  public String toString() {\n    return \"*\";\n  }\n}\n"
  },
  {
    "path": "interpreter/src/main/java/com/iluwatar/interpreter/NumberExpression.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.interpreter;\n\n/** NumberExpression. */\npublic class NumberExpression extends Expression {\n\n  private final int number;\n\n  public NumberExpression(int number) {\n    this.number = number;\n  }\n\n  public NumberExpression(String s) {\n    this.number = Integer.parseInt(s);\n  }\n\n  @Override\n  public int interpret() {\n    return number;\n  }\n\n  @Override\n  public String toString() {\n    return \"number\";\n  }\n}\n"
  },
  {
    "path": "interpreter/src/main/java/com/iluwatar/interpreter/PlusExpression.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.interpreter;\n\n/** PlusExpression. */\npublic class PlusExpression extends Expression {\n\n  private final Expression leftExpression;\n  private final Expression rightExpression;\n\n  public PlusExpression(Expression leftExpression, Expression rightExpression) {\n    this.leftExpression = leftExpression;\n    this.rightExpression = rightExpression;\n  }\n\n  @Override\n  public int interpret() {\n    return leftExpression.interpret() + rightExpression.interpret();\n  }\n\n  @Override\n  public String toString() {\n    return \"+\";\n  }\n}\n"
  },
  {
    "path": "interpreter/src/test/java/com/iluwatar/interpreter/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.interpreter;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "interpreter/src/test/java/com/iluwatar/interpreter/ExpressionTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.interpreter;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport java.util.ArrayList;\nimport java.util.function.BiFunction;\nimport java.util.function.IntBinaryOperator;\nimport java.util.stream.Stream;\nimport org.junit.jupiter.api.TestInstance;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\n\n/**\n * Test Case for Expressions\n *\n * @param <E> Type of Expression\n */\n@TestInstance(TestInstance.Lifecycle.PER_CLASS)\npublic abstract class ExpressionTest<E extends Expression> {\n\n  /**\n   * Generate inputs ranging from -10 to 10 for both input params and calculate the expected result\n   *\n   * @param resultCalc The function used to calculate the expected result\n   * @return A stream with test entries\n   */\n  static Stream<Arguments> prepareParameters(final IntBinaryOperator resultCalc) {\n    final var testData = new ArrayList<Arguments>();\n    for (var i = -10; i < 10; i++) {\n      for (var j = -10; j < 10; j++) {\n        testData.add(\n            Arguments.of(\n                new NumberExpression(i), new NumberExpression(j), resultCalc.applyAsInt(i, j)));\n      }\n    }\n    return testData.stream();\n  }\n\n  /** The expected {@link E#toString()} response */\n  private final String expectedToString;\n\n  /**\n   * Factory, used to create a new test object instance with the correct first and second parameter\n   */\n  private final BiFunction<NumberExpression, NumberExpression, E> factory;\n\n  /**\n   * Create a new test instance with the given parameters and expected results\n   *\n   * @param expectedToString The expected {@link E#toString()} response\n   * @param factory Factory, used to create a new test object instance\n   */\n  ExpressionTest(\n      final String expectedToString,\n      final BiFunction<NumberExpression, NumberExpression, E> factory) {\n    this.expectedToString = expectedToString;\n    this.factory = factory;\n  }\n\n  /**\n   * Create a new set of test entries with the expected result\n   *\n   * @return The list of parameters used during this test\n   */\n  public abstract Stream<Arguments> expressionProvider();\n\n  /** Verify if the expression calculates the correct result when calling {@link E#interpret()} */\n  @ParameterizedTest\n  @MethodSource(\"expressionProvider\")\n  void testInterpret(NumberExpression first, NumberExpression second, int result) {\n    final var expression = factory.apply(first, second);\n    assertNotNull(expression);\n    assertEquals(result, expression.interpret());\n  }\n\n  /** Verify if the expression has the expected {@link E#toString()} value */\n  @ParameterizedTest\n  @MethodSource(\"expressionProvider\")\n  void testToString(NumberExpression first, NumberExpression second) {\n    final var expression = factory.apply(first, second);\n    assertNotNull(expression);\n    assertEquals(expectedToString, expression.toString());\n  }\n}\n"
  },
  {
    "path": "interpreter/src/test/java/com/iluwatar/interpreter/MinusExpressionTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.interpreter;\n\nimport java.util.stream.Stream;\nimport org.junit.jupiter.params.provider.Arguments;\n\n/** MinusExpressionTest */\nclass MinusExpressionTest extends ExpressionTest<MinusExpression> {\n\n  /**\n   * Create a new set of test entries with the expected result\n   *\n   * @return The list of parameters used during this test\n   */\n  @Override\n  public Stream<Arguments> expressionProvider() {\n    return prepareParameters((f, s) -> f - s);\n  }\n\n  /** Create a new test instance using the given test parameters and expected result */\n  public MinusExpressionTest() {\n    super(\"-\", MinusExpression::new);\n  }\n}\n"
  },
  {
    "path": "interpreter/src/test/java/com/iluwatar/interpreter/MultiplyExpressionTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.interpreter;\n\nimport java.util.stream.Stream;\nimport org.junit.jupiter.params.provider.Arguments;\n\n/** MultiplyExpressionTest */\nclass MultiplyExpressionTest extends ExpressionTest<MultiplyExpression> {\n\n  /**\n   * Create a new set of test entries with the expected result\n   *\n   * @return The list of parameters used during this test\n   */\n  @Override\n  public Stream<Arguments> expressionProvider() {\n    return prepareParameters((f, s) -> f * s);\n  }\n\n  /** Create a new test instance using the given test parameters and expected result */\n  public MultiplyExpressionTest() {\n    super(\"*\", MultiplyExpression::new);\n  }\n}\n"
  },
  {
    "path": "interpreter/src/test/java/com/iluwatar/interpreter/NumberExpressionTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.interpreter;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.stream.Stream;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\n\n/** NumberExpressionTest */\nclass NumberExpressionTest extends ExpressionTest<NumberExpression> {\n\n  /**\n   * Create a new set of test entries with the expected result\n   *\n   * @return The list of parameters used during this test\n   */\n  @Override\n  public Stream<Arguments> expressionProvider() {\n    return prepareParameters((f, s) -> f);\n  }\n\n  /** Create a new test instance using the given test parameters and expected result */\n  public NumberExpressionTest() {\n    super(\"number\", (f, s) -> f);\n  }\n\n  /**\n   * Verify if the {@link NumberExpression#NumberExpression(String)} constructor works as expected\n   */\n  @ParameterizedTest\n  @MethodSource(\"expressionProvider\")\n  void testFromString(NumberExpression first) {\n    final var expectedValue = first.interpret();\n    final var testStringValue = String.valueOf(expectedValue);\n    final var numberExpression = new NumberExpression(testStringValue);\n    assertEquals(expectedValue, numberExpression.interpret());\n  }\n}\n"
  },
  {
    "path": "interpreter/src/test/java/com/iluwatar/interpreter/PlusExpressionTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.interpreter;\n\nimport java.util.stream.Stream;\nimport org.junit.jupiter.params.provider.Arguments;\n\n/** PlusExpressionTest */\nclass PlusExpressionTest extends ExpressionTest<PlusExpression> {\n\n  /**\n   * Create a new set of test entries with the expected result\n   *\n   * @return The list of parameters used during this test\n   */\n  @Override\n  public Stream<Arguments> expressionProvider() {\n    return prepareParameters(Integer::sum);\n  }\n\n  /** Create a new test instance using the given test parameters and expected result */\n  public PlusExpressionTest() {\n    super(\"+\", PlusExpression::new);\n  }\n}\n"
  },
  {
    "path": "iterator/README.md",
    "content": "---\ntitle: \"Iterator Pattern in Java: Mastering Sequential Element Access\"\nshortTitle: Iterator\ndescription: \"Learn how to implement the Iterator Design Pattern in Java. Access elements of a collection sequentially without exposing its underlying structure. Explore real-world examples, code snippets, and benefits of using iterators.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Data access\n  - Data transformation\n  - Decoupling\n  - Gang of Four\n  - Object composition\n  - Polymorphism\n---\n\n## Also known as\n\n* Cursor\n\n## Intent of Iterator Design Pattern\n\nThe Iterator Design Pattern in Java provides a way to access elements of an aggregate object sequentially without exposing its underlying representation. This behavioral pattern is crucial for efficient collection traversal.\n\n## Detailed Explanation of Iterator Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine visiting a library with a vast collection of books organized in different sections such as fiction, non-fiction, science, etc. Instead of searching through every shelf yourself, the librarian provides you with a specific guidebook or a digital catalog for each section. This guidebook acts as an \"iterator,\" allowing you to go through the books section by section, or even skip to specific types of books, without needing to know how the books are organized on the shelves. Each guidebook handles the traversal through its section, providing a consistent and efficient way to access the books, much like how the Iterator design pattern offers a uniform method to traverse different data structures in a software application.\n\nIn plain words\n\n> The Java Iterator Design Pattern provides a method to sequentially access elements of a collection without exposing its underlying structure. This pattern is widely used in Java programming for efficient data access.\n\nWikipedia says\n\n> In object-oriented programming, the iterator pattern is a design pattern in which an iterator is used to traverse a container and access the container's elements.\n\nSequence diagram\n\n![Iterator sequence diagram](./etc/iterator-sequence-diagram.png)\n\n## Programmatic Example of Iterator Pattern in Java\n\nThe main class in our Java Iterator Design Pattern example is the `TreasureChest` that contains items. This demonstrates how to implement and use iterators for efficient collection traversal in Java.\n\n```java\npublic class TreasureChest {\n\n  private final List<Item> items;\n\n  public TreasureChest() {\n    items = List.of(\n        new Item(ItemType.POTION, \"Potion of courage\"),\n        new Item(ItemType.RING, \"Ring of shadows\"),\n        new Item(ItemType.POTION, \"Potion of wisdom\"),\n        new Item(ItemType.POTION, \"Potion of blood\"),\n        new Item(ItemType.WEAPON, \"Sword of silver +1\"),\n        new Item(ItemType.POTION, \"Potion of rust\"),\n        new Item(ItemType.POTION, \"Potion of healing\"),\n        new Item(ItemType.RING, \"Ring of armor\"),\n        new Item(ItemType.WEAPON, \"Steel halberd\"),\n        new Item(ItemType.WEAPON, \"Dagger of poison\"));\n  }\n\n  public Iterator<Item> iterator(ItemType itemType) {\n    return new TreasureChestItemIterator(this, itemType);\n  }\n\n  public List<Item> getItems() {\n    return new ArrayList<>(items);\n  }\n}\n```\n\nHere's the `Item` class:\n\n```java\npublic class Item {\n\n  private ItemType type;\n  private final String name;\n\n  public Item(ItemType type, String name) {\n    this.setType(type);\n    this.name = name;\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n\n  public ItemType getType() {\n    return type;\n  }\n\n  public final void setType(ItemType type) {\n    this.type = type;\n  }\n}\n\npublic enum ItemType {\n\n  ANY, WEAPON, RING, POTION\n\n}\n```\n\nThe `Iterator` interface is extremely simple.\n\n```java\npublic interface Iterator<T> {\n\n  boolean hasNext();\n\n  T next();\n}\n```\n\nIn the following example, we demonstrate different kinds of iterators.\n\n```java\n@Slf4j\npublic class App {\n\n    private static final TreasureChest TREASURE_CHEST = new TreasureChest();\n\n    private static void demonstrateTreasureChestIteratorForType(ItemType itemType) {\n        LOGGER.info(\"------------------------\");\n        LOGGER.info(\"Item Iterator for ItemType \" + itemType + \": \");\n        var itemIterator = TREASURE_CHEST.iterator(itemType);\n        while (itemIterator.hasNext()) {\n            LOGGER.info(itemIterator.next().toString());\n        }\n    }\n\n    private static void demonstrateBstIterator() {\n        LOGGER.info(\"------------------------\");\n        LOGGER.info(\"BST Iterator: \");\n        var root = buildIntegerBst();\n        var bstIterator = new BstIterator<>(root);\n        while (bstIterator.hasNext()) {\n            LOGGER.info(\"Next node: \" + bstIterator.next().getVal());\n        }\n    }\n\n    private static TreeNode<Integer> buildIntegerBst() {\n        var root = new TreeNode<>(8);\n\n        root.insert(3);\n        root.insert(10);\n        root.insert(1);\n        root.insert(6);\n        root.insert(14);\n        root.insert(4);\n        root.insert(7);\n        root.insert(13);\n\n        return root;\n    }\n\n    public static void main(String[] args) {\n        demonstrateTreasureChestIteratorForType(RING);\n        demonstrateTreasureChestIteratorForType(POTION);\n        demonstrateTreasureChestIteratorForType(WEAPON);\n        demonstrateTreasureChestIteratorForType(ANY);\n        demonstrateBstIterator();\n    }\n}\n```\n\nProgram output:\n\n```\n13:36:37.087 [main] INFO com.iluwatar.iterator.App -- ------------------------\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Item Iterator for ItemType RING: \n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Ring of shadows\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Ring of armor\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- ------------------------\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Item Iterator for ItemType POTION: \n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of courage\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of wisdom\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of blood\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of rust\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of healing\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- ------------------------\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Item Iterator for ItemType WEAPON: \n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Sword of silver +1\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Steel halberd\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Dagger of poison\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- ------------------------\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Item Iterator for ItemType ANY: \n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of courage\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Ring of shadows\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of wisdom\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of blood\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Sword of silver +1\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of rust\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Potion of healing\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Ring of armor\n13:36:37.089 [main] INFO com.iluwatar.iterator.App -- Steel halberd\n13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Dagger of poison\n13:36:37.090 [main] INFO com.iluwatar.iterator.App -- ------------------------\n13:36:37.090 [main] INFO com.iluwatar.iterator.App -- BST Iterator: \n13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 1\n13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 3\n13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 4\n13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 6\n13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 7\n13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 8\n13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 10\n13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 13\n13:36:37.090 [main] INFO com.iluwatar.iterator.App -- Next node: 14\n```\n\n## When to Use the Iterator Pattern in Java\n\nUse the Iterator design pattern in Java\n\n* To access an aggregate object's contents without exposing its internal representation.\n* To support multiple traversals of aggregate objects.\n* To provide a uniform interface for traversing different aggregate structures.\n\n## Iterator Pattern Java Tutorials\n\n* [Java - How to Use Iterator? (TutorialsPoint)](http://www.tutorialspoint.com/java/java_using_iterator.htm)\n\n## Real-World Applications of Iterator Pattern in Java\n\n* Java Collections Framework utilizes iterators extensively to allow different ways to traverse through collections.\n* Databases often use iterators to navigate through data records fetched through SQL queries.\n* [java.util.Iterator](http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html)\n* [java.util.Enumeration](http://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html)\n\n## Benefits and Trade-offs of Iterator Pattern\n\nBenefits:\n\n* Reduces the coupling between data structures and algorithms used for iteration.\n* Provides a uniform interface for iterating over various types of data structures, enhancing code reusability and flexibility.\n\nTrade-offs:\n\n* Overhead of using an iterator object may slightly reduce performance compared to direct traversal methods.\n* Complex aggregate structures may require complex iterators that can be difficult to manage or extend.\n\n## Related Java Design Patterns\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): Iterators are often used to traverse Composite trees.\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Used to create appropriate iterators for different data structures.\n* [Visitor](https://java-design-patterns.com/patterns/visitor/): Can be used with Iterator to apply operations over elements of an object structure.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n"
  },
  {
    "path": "iterator/etc/iterator.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.iterator.list.TreasureChest\" project=\"iterator\"\n    file=\"/iterator/src/main/java/com/iluwatar/iterator/TreasureChest.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"195\" x=\"1\" y=\"237\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.iterator.list.Item\" project=\"iterator\"\n    file=\"/iterator/src/main/java/com/iluwatar/iterator/Item.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"160\" width=\"157\" x=\"195\" y=\"401\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <enumeration id=\"3\" language=\"java\" name=\"com.iluwatar.iterator.list.ItemType\" project=\"iterator\"\n    file=\"/iterator/src/main/java/com/iluwatar/iterator/ItemType.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"160\" width=\"145\" x=\"388\" y=\"601\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <interface id=\"4\" language=\"java\" name=\"com.iluwatar.iterator.list.ItemIterator\" project=\"iterator\"\n    file=\"/iterator/src/main/java/com/iluwatar/iterator/ItemIterator.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"131\" x=\"236\" y=\"237\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.iterator.list.TreasureChestItemIterator\" project=\"iterator\"\n    file=\"/iterator/src/main/java/com/iluwatar/iterator/TreasureChestItemIterator.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"160\" width=\"323\" x=\"236\" y=\"37\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"6\">    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"7\" name=\"chest\"/>      \n      <multiplicity id=\"8\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"9\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"10\" name=\"items\"/>      \n      <multiplicity id=\"11\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"12\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"13\" name=\"type\"/>      \n      <multiplicity id=\"14\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"15\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <association id=\"16\">    \n    <bendpoint x=\"397\" y=\"237\"/>    \n    <bendpoint x=\"397\" y=\"401\"/>    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"17\" name=\"type\"/>      \n      <multiplicity id=\"18\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "iterator/etc/iterator.urm.puml",
    "content": "@startuml\npackage com.iluwatar.iterator {\n  class App {\n    - LOGGER : Logger {static}\n    - TREASURE_CHEST : TreasureChest {static}\n    + App()\n    - buildIntegerBst() : TreeNode<Integer> {static}\n    - demonstrateBstIterator() {static}\n    - demonstrateTreasureChestIteratorForType(itemType : ItemType) {static}\n    + main(args : String[]) {static}\n  }\n  interface Iterator<T> {\n    + hasNext() : boolean {abstract}\n    + next() : T {abstract}\n  }\n}\npackage com.iluwatar.iterator.bst {\n  class BstIterator<T extends Comparable<T>> {\n    - pathStack : ArrayDeque<TreeNode<T extends Comparable<T>>>\n    + BstIterator<T extends Comparable<T>>(root : TreeNode<T extends Comparable<T>>)\n    + hasNext() : boolean\n    + next() : TreeNode<T extends Comparable<T>>\n    - pushPathToNextSmallest(node : TreeNode<T extends Comparable<T>>)\n  }\n  class TreeNode<T extends Comparable<T>> {\n    - left : TreeNode<T extends Comparable<T>>\n    - right : TreeNode<T extends Comparable<T>>\n    - val : T extends Comparable<T>\n    + TreeNode<T extends Comparable<T>>(val : T extends Comparable<T>)\n    + getLeft() : TreeNode<T extends Comparable<T>>\n    - getParentNodeOfValueToBeInserted(valToInsert : T extends Comparable<T>) : TreeNode<T extends Comparable<T>>\n    + getRight() : TreeNode<T extends Comparable<T>>\n    + getVal() : T extends Comparable<T>\n    + insert(valToInsert : T extends Comparable<T>)\n    - insertNewChild(valToInsert : T extends Comparable<T>)\n    - isGreaterThan(val : T extends Comparable<T>) : boolean\n    - isLessThanOrEqualTo(val : T extends Comparable<T>) : boolean\n    - setLeft(left : TreeNode<T extends Comparable<T>>)\n    - setRight(right : TreeNode<T extends Comparable<T>>)\n    + toString() : String\n    - traverseOneLevelDown(value : T extends Comparable<T>) : TreeNode<T extends Comparable<T>>\n  }\n}\npackage com.iluwatar.iterator.list {\n  class Item {\n    - name : String\n    - type : ItemType\n    + Item(type : ItemType, name : String)\n    + getType() : ItemType\n    + setType(type : ItemType)\n    + toString() : String\n  }\n  enum ItemType {\n    + ANY {static}\n    + POTION {static}\n    + RING {static}\n    + WEAPON {static}\n    + valueOf(name : String) : ItemType {static}\n    + values() : ItemType[] {static}\n  }\n  class TreasureChest {\n    - items : List<Item>\n    + TreasureChest()\n    + getItems() : List<Item>\n    + iterator(itemType : ItemType) : Iterator<Item>\n  }\n  class TreasureChestItemIterator {\n    - chest : TreasureChest\n    - idx : int\n    - type : ItemType\n    + TreasureChestItemIterator(chest : TreasureChest, type : ItemType)\n    - findNextIdx() : int\n    + hasNext() : boolean\n    + next() : Item\n  }\n}\nTreasureChestItemIterator -->  \"-type\" ItemType\nTreeNode -->  \"-left\" TreeNode\nTreasureChestItemIterator -->  \"-chest\" TreasureChest\nTreasureChest -->  \"-items\" Item\nItem -->  \"-type\" ItemType\nApp -->  \"-TREASURE_CHEST\" TreasureChest\nBstIterator ..|> Iterator \nTreasureChestItemIterator ..|> Iterator \n@enduml"
  },
  {
    "path": "iterator/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>iterator</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-params</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.iterator.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "iterator/src/main/java/com/iluwatar/iterator/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.iterator;\n\nimport static com.iluwatar.iterator.list.ItemType.ANY;\nimport static com.iluwatar.iterator.list.ItemType.POTION;\nimport static com.iluwatar.iterator.list.ItemType.RING;\nimport static com.iluwatar.iterator.list.ItemType.WEAPON;\n\nimport com.iluwatar.iterator.bst.BstIterator;\nimport com.iluwatar.iterator.bst.TreeNode;\nimport com.iluwatar.iterator.list.ItemType;\nimport com.iluwatar.iterator.list.TreasureChest;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Iterator pattern is a design pattern in which an iterator is used to traverse a container and\n * access the container's elements. The Iterator pattern decouples algorithms from containers.\n *\n * <p>In this example the Iterator ({@link Iterator}) adds abstraction layer on top of a collection\n * ({@link TreasureChest}). This way the collection can change its internal implementation without\n * affecting its clients.\n */\n@Slf4j\npublic class App {\n\n  private static final TreasureChest TREASURE_CHEST = new TreasureChest();\n\n  private static void demonstrateTreasureChestIteratorForType(ItemType itemType) {\n    LOGGER.info(\"------------------------\");\n    LOGGER.info(\"Item Iterator for ItemType \" + itemType + \": \");\n    var itemIterator = TREASURE_CHEST.iterator(itemType);\n    while (itemIterator.hasNext()) {\n      LOGGER.info(itemIterator.next().toString());\n    }\n  }\n\n  private static void demonstrateBstIterator() {\n    LOGGER.info(\"------------------------\");\n    LOGGER.info(\"BST Iterator: \");\n    var root = buildIntegerBst();\n    var bstIterator = new BstIterator<>(root);\n    while (bstIterator.hasNext()) {\n      LOGGER.info(\"Next node: \" + bstIterator.next().getVal());\n    }\n  }\n\n  private static TreeNode<Integer> buildIntegerBst() {\n    var root = new TreeNode<>(8);\n\n    root.insert(3);\n    root.insert(10);\n    root.insert(1);\n    root.insert(6);\n    root.insert(14);\n    root.insert(4);\n    root.insert(7);\n    root.insert(13);\n\n    return root;\n  }\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    demonstrateTreasureChestIteratorForType(RING);\n    demonstrateTreasureChestIteratorForType(POTION);\n    demonstrateTreasureChestIteratorForType(WEAPON);\n    demonstrateTreasureChestIteratorForType(ANY);\n\n    demonstrateBstIterator();\n  }\n}\n"
  },
  {
    "path": "iterator/src/main/java/com/iluwatar/iterator/Iterator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.iterator;\n\n/**\n * Iterator interface to be implemented by iterators over various data structures.\n *\n * @param <T> generically typed for various objects\n */\npublic interface Iterator<T> {\n\n  boolean hasNext();\n\n  T next();\n}\n"
  },
  {
    "path": "iterator/src/main/java/com/iluwatar/iterator/bst/BstIterator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.iterator.bst;\n\nimport com.iluwatar.iterator.Iterator;\nimport java.util.ArrayDeque;\nimport java.util.NoSuchElementException;\n\n/**\n * An in-order implementation of a BST Iterator. For example, given a BST with Integer values,\n * expect to retrieve TreeNodes according to the Integer's natural ordering (1, 2, 3...)\n *\n * @param <T> This Iterator has been implemented with generic typing to allow for TreeNodes of\n *     different value types\n */\npublic class BstIterator<T extends Comparable<T>> implements Iterator<TreeNode<T>> {\n\n  private final ArrayDeque<TreeNode<T>> pathStack;\n\n  public BstIterator(TreeNode<T> root) {\n    pathStack = new ArrayDeque<>();\n    pushPathToNextSmallest(root);\n  }\n\n  /**\n   * This BstIterator manages to use O(h) extra space, where h is the height of the tree It achieves\n   * this by maintaining a stack of the nodes to handle (pushing all left nodes first), before\n   * handling self or right node.\n   *\n   * @param node TreeNode that acts as root of the subtree we're interested in.\n   */\n  private void pushPathToNextSmallest(TreeNode<T> node) {\n    while (node != null) {\n      pathStack.push(node);\n      node = node.getLeft();\n    }\n  }\n\n  /**\n   * Checks if there exists next element.\n   *\n   * @return true if this iterator has a \"next\" element\n   */\n  @Override\n  public boolean hasNext() {\n    return !pathStack.isEmpty();\n  }\n\n  /**\n   * Gets the next element.\n   *\n   * @return TreeNode next. The next element according to our in-order traversal of the given BST\n   * @throws NoSuchElementException if this iterator does not have a next element\n   */\n  @Override\n  public TreeNode<T> next() throws NoSuchElementException {\n    if (pathStack.isEmpty()) {\n      throw new NoSuchElementException();\n    }\n    var next = pathStack.pop();\n    pushPathToNextSmallest(next.getRight());\n    return next;\n  }\n}\n"
  },
  {
    "path": "iterator/src/main/java/com/iluwatar/iterator/bst/README.md",
    "content": "# BSTIterator\n\nAn implementation of the Iterator design pattern, for the Binary Search Tree data structure. A great \nexplanation of BSTs can be found in this \n[video tutorial](https://www.youtube.com/watch?v=i_Q0v_Ct5lY).\n\n### What It Does\n\nThis iterator assumes that the given binary search tree inserts nodes of smaller \nvalue to the left, and nodes of larger value to the right of current node. Accordingly, \nthis iterator will return nodes according to \"In Order\" binary tree traversal. \nThis means that given a binary search tree like the following, the iterator would \nreturn values in order: 1, 3, 4, 6, 7, 8, 10, 13, 14. \n\n![BST](../../../../../../../etc/bst.jpg \"Binary Search Tree\")  \n\n### How It's Done\n\n**The trivial solution** to a binary search tree iterator would be to construct a List (or similar \nlinear data structure) when you construct the BSTIterator. This would require traversing the entire\nBST, adding each node value to your list as you go. The downside to the trivial solution is twofold.\nYou're front loading the work by requiring the BSTIterator's constructor to traverse the entire tree, \nand you're taking up more memory by maintaining (worst case) every node in the tree in a separate \ndata structure. In Big O terms, here are the costs, where n is the number of nodes in the tree:\n* Constructor Run Time: O(n) \n* `next()` Run Time: O(1)\n* `hasNext()` Run Time: O(1)\n* Extra Space: O(n)\n\n**A better solution** is to maintain _only_ the path to the next smallest node. For instance, given \nthe BST above, when you first create your BSTIterator, instead of traversing the entire tree, you \nwould navigate to the next smallest node (in this case, 1), pushing nodes onto a stack along the way. \nYour BSTIterator Constructor would look like:\n```\nprivate ArrayDeque<TreeNode> pathStack;\n\npublic BSTIterator(TreeNode root) {\n  pathStack = new ArrayDeque<>();\n  pushPathToNextSmallest(root);\n}\n\nprivate void pushPathToNextSmallest(TreeNode node) {\n  while (node != null) {\n    pathStack.push(node);\n    node = node.getLeft();\n  }\n}\n```\n\nAfter the constructor is called our BST, your `pathStack` would look like this:\n\n1\\\n3\\\n8\n\nThis way, you're certain of what the next smallest node is because it lives on top of your path \nstack. In order to maintain the integrity of this path stack, when you call `next()` and pop a \nnode off the stack, you must check to see if it has a right child. If it does, then you must follow the right \nchild's path to the next smallest node (pushing onto your path stack as you go). Given our above example, \ncalling `next()` on our BSTIterator twice would return node \"3\". Node \"3\" has a right child, indicating \na path to a node smaller than 3's parent. In this case, you would push node \"6\" onto the stack, \nand node \"4\" onto the stack. `next()` would look like this:\n\n```\npublic TreeNode next() throws IllegalStateException {\n  // If the user calls next() and hasNext() is false\n  if (pathStack.isEmpty()) {\n    throw new IllegalStateException();\n  }\n  var next = pathStack.pop();\n  // follow right child to next smallest node\n  pushPathToNextSmallest(next.getRight());\n  return next;\n}\n```\n\n**Key Concept:** The path to the smallest node of a given subtree is navigating straight to the \nleftmost node of that subtree.\n\nIn Big O terms, here are the costs for our improved solution, where h is the height of the tree:\n* Constructor Run Time: O(h) \n* `next()` Amortized Run Time: O(1)\n* `hasNext()` Run Time: O(1)\n* Extra Space: O(h)\n\nAs you can see, this solution more evenly distributes the work. It yields the same amortized \nruntime for `next()`, reduces the run time of the constructor, and uses less extra space.\n"
  },
  {
    "path": "iterator/src/main/java/com/iluwatar/iterator/bst/TreeNode.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.iterator.bst;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/**\n * TreeNode Class, representing one node in a Binary Search Tree. Allows for a generically typed\n * value.\n *\n * @param <T> generically typed to accept various data types for the val property\n */\npublic class TreeNode<T extends Comparable<T>> {\n\n  private final T val;\n\n  @Getter @Setter private TreeNode<T> left;\n\n  @Getter @Setter private TreeNode<T> right;\n\n  /**\n   * Creates a TreeNode with a given value, and null children.\n   *\n   * @param val The value of the given node\n   */\n  public TreeNode(T val) {\n    this.val = val;\n    this.left = null;\n    this.right = null;\n  }\n\n  public T getVal() {\n    return val;\n  }\n\n  /**\n   * Inserts new TreeNode based on a given value into the subtree represented by self.\n   *\n   * @param valToInsert The value to insert as a new TreeNode\n   */\n  public void insert(T valToInsert) {\n    var parent = getParentNodeOfValueToBeInserted(valToInsert);\n    parent.insertNewChild(valToInsert);\n  }\n\n  /**\n   * Fetch the Parent TreeNode for a given value to insert into the BST.\n   *\n   * @param valToInsert Value of the new TreeNode to be inserted\n   * @return Parent TreeNode of `valToInsert`\n   */\n  private TreeNode<T> getParentNodeOfValueToBeInserted(T valToInsert) {\n    TreeNode<T> parent = null;\n    var curr = this;\n\n    while (curr != null) {\n      parent = curr;\n      curr = curr.traverseOneLevelDown(valToInsert);\n    }\n\n    return parent;\n  }\n\n  /**\n   * Returns left or right child of self based on a value that would be inserted; maintaining the\n   * integrity of the BST.\n   *\n   * @param value The value of the TreeNode that would be inserted beneath self\n   * @return The child TreeNode of self which represents the subtree where `value` would be inserted\n   */\n  private TreeNode<T> traverseOneLevelDown(T value) {\n    if (this.isGreaterThan(value)) {\n      return this.left;\n    }\n    return this.right;\n  }\n\n  /**\n   * Add a new Child TreeNode of given value to self. WARNING: This method is destructive (will\n   * overwrite existing tree structure, if any), and should be called only by this class's insert()\n   * method.\n   *\n   * @param valToInsert Value of the new TreeNode to be inserted\n   */\n  private void insertNewChild(T valToInsert) {\n    if (this.isLessThanOrEqualTo(valToInsert)) {\n      this.setRight(new TreeNode<>(valToInsert));\n    } else {\n      this.setLeft(new TreeNode<>(valToInsert));\n    }\n  }\n\n  private boolean isGreaterThan(T val) {\n    return this.val.compareTo(val) > 0;\n  }\n\n  private boolean isLessThanOrEqualTo(T val) {\n    return this.val.compareTo(val) < 1;\n  }\n\n  @Override\n  public String toString() {\n    return val.toString();\n  }\n}\n"
  },
  {
    "path": "iterator/src/main/java/com/iluwatar/iterator/list/Item.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.iterator.list;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Item. */\n@AllArgsConstructor\npublic class Item {\n\n  @Getter @Setter private ItemType type;\n  private final String name;\n\n  @Override\n  public String toString() {\n    return name;\n  }\n}\n"
  },
  {
    "path": "iterator/src/main/java/com/iluwatar/iterator/list/ItemType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.iterator.list;\n\n/** ItemType enumeration. */\npublic enum ItemType {\n  ANY,\n  WEAPON,\n  RING,\n  POTION\n}\n"
  },
  {
    "path": "iterator/src/main/java/com/iluwatar/iterator/list/TreasureChest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.iterator.list;\n\nimport com.iluwatar.iterator.Iterator;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** TreasureChest, the collection class. */\npublic class TreasureChest {\n\n  private final List<Item> items;\n\n  /** Constructor. */\n  public TreasureChest() {\n    items =\n        List.of(\n            new Item(ItemType.POTION, \"Potion of courage\"),\n            new Item(ItemType.RING, \"Ring of shadows\"),\n            new Item(ItemType.POTION, \"Potion of wisdom\"),\n            new Item(ItemType.POTION, \"Potion of blood\"),\n            new Item(ItemType.WEAPON, \"Sword of silver +1\"),\n            new Item(ItemType.POTION, \"Potion of rust\"),\n            new Item(ItemType.POTION, \"Potion of healing\"),\n            new Item(ItemType.RING, \"Ring of armor\"),\n            new Item(ItemType.WEAPON, \"Steel halberd\"),\n            new Item(ItemType.WEAPON, \"Dagger of poison\"));\n  }\n\n  public Iterator<Item> iterator(ItemType itemType) {\n    return new TreasureChestItemIterator(this, itemType);\n  }\n\n  /** Get all items. */\n  public List<Item> getItems() {\n    return new ArrayList<>(items);\n  }\n}\n"
  },
  {
    "path": "iterator/src/main/java/com/iluwatar/iterator/list/TreasureChestItemIterator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.iterator.list;\n\nimport com.iluwatar.iterator.Iterator;\n\n/** TreasureChestItemIterator. */\npublic class TreasureChestItemIterator implements Iterator<Item> {\n\n  private final TreasureChest chest;\n  private int idx;\n  private final ItemType type;\n\n  /** Constructor. */\n  public TreasureChestItemIterator(TreasureChest chest, ItemType type) {\n    this.chest = chest;\n    this.type = type;\n    this.idx = -1;\n  }\n\n  @Override\n  public boolean hasNext() {\n    return findNextIdx() != -1;\n  }\n\n  @Override\n  public Item next() {\n    idx = findNextIdx();\n    if (idx != -1) {\n      return chest.getItems().get(idx);\n    }\n    return null;\n  }\n\n  private int findNextIdx() {\n    var items = chest.getItems();\n    var tempIdx = idx;\n    while (true) {\n      tempIdx++;\n      if (tempIdx >= items.size()) {\n        tempIdx = -1;\n        break;\n      }\n      if (type.equals(ItemType.ANY) || items.get(tempIdx).getType().equals(type)) {\n        break;\n      }\n    }\n    return tempIdx;\n  }\n}\n"
  },
  {
    "path": "iterator/src/test/java/com/iluwatar/iterator/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.iterator;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application Test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "iterator/src/test/java/com/iluwatar/iterator/bst/BstIteratorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.iterator.bst;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.NoSuchElementException;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.TestInstance;\nimport org.junit.jupiter.api.TestInstance.Lifecycle;\n\n@TestInstance(Lifecycle.PER_CLASS)\nclass BstIteratorTest {\n\n  private TreeNode<Integer> nonEmptyRoot;\n  private TreeNode<Integer> emptyRoot;\n\n  @BeforeAll\n  void createTrees() {\n    nonEmptyRoot = new TreeNode<>(5);\n    nonEmptyRoot.insert(3);\n    nonEmptyRoot.insert(7);\n    nonEmptyRoot.insert(1);\n    nonEmptyRoot.insert(4);\n    nonEmptyRoot.insert(6);\n\n    emptyRoot = null;\n  }\n\n  @Test\n  void nextForEmptyTree() {\n    var iter = new BstIterator<>(emptyRoot);\n    assertThrows(\n        NoSuchElementException.class,\n        iter::next,\n        \"next() should throw an IllegalStateException if hasNext() is false.\");\n  }\n\n  @Test\n  void nextOverEntirePopulatedTree() {\n    var iter = new BstIterator<>(nonEmptyRoot);\n    assertEquals(Integer.valueOf(1), iter.next().getVal(), \"First Node is 1.\");\n    assertEquals(Integer.valueOf(3), iter.next().getVal(), \"Second Node is 3.\");\n    assertEquals(Integer.valueOf(4), iter.next().getVal(), \"Third Node is 4.\");\n    assertEquals(Integer.valueOf(5), iter.next().getVal(), \"Fourth Node is 5.\");\n    assertEquals(Integer.valueOf(6), iter.next().getVal(), \"Fifth Node is 6.\");\n    assertEquals(Integer.valueOf(7), iter.next().getVal(), \"Sixth Node is 7.\");\n  }\n\n  @Test\n  void hasNextForEmptyTree() {\n    var iter = new BstIterator<>(emptyRoot);\n    assertFalse(iter.hasNext(), \"hasNext() should return false for empty tree.\");\n  }\n\n  @Test\n  void hasNextForPopulatedTree() {\n    var iter = new BstIterator<>(nonEmptyRoot);\n    assertTrue(iter.hasNext(), \"hasNext() should return true for populated tree.\");\n  }\n\n  @Test\n  void nextAndHasNextOverEntirePopulatedTree() {\n    var iter = new BstIterator<>(nonEmptyRoot);\n    assertTrue(iter.hasNext(), \"Iterator hasNext() should be true.\");\n    assertEquals(Integer.valueOf(1), iter.next().getVal(), \"First Node is 1.\");\n    assertTrue(iter.hasNext(), \"Iterator hasNext() should be true.\");\n    assertEquals(Integer.valueOf(3), iter.next().getVal(), \"Second Node is 3.\");\n    assertTrue(iter.hasNext(), \"Iterator hasNext() should be true.\");\n    assertEquals(Integer.valueOf(4), iter.next().getVal(), \"Third Node is 4.\");\n    assertTrue(iter.hasNext(), \"Iterator hasNext() should be true.\");\n    assertEquals(Integer.valueOf(5), iter.next().getVal(), \"Fourth Node is 5.\");\n    assertTrue(iter.hasNext(), \"Iterator hasNext() should be true.\");\n    assertEquals(Integer.valueOf(6), iter.next().getVal(), \"Fifth Node is 6.\");\n    assertTrue(iter.hasNext(), \"Iterator hasNext() should be true.\");\n    assertEquals(Integer.valueOf(7), iter.next().getVal(), \"Sixth Node is 7.\");\n    assertFalse(iter.hasNext(), \"Iterator hasNext() should be false, end of tree.\");\n  }\n}\n"
  },
  {
    "path": "iterator/src/test/java/com/iluwatar/iterator/list/TreasureChestTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.iterator.list;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nimport java.util.List;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\n/** TreasureChestTest */\nclass TreasureChestTest {\n\n  /**\n   * Create a list of all expected items in the chest.\n   *\n   * @return The set of all expected items in the chest\n   */\n  public static List<Object[]> dataProvider() {\n    return List.of(\n        new Object[] {new Item(ItemType.POTION, \"Potion of courage\")},\n        new Object[] {new Item(ItemType.RING, \"Ring of shadows\")},\n        new Object[] {new Item(ItemType.POTION, \"Potion of wisdom\")},\n        new Object[] {new Item(ItemType.POTION, \"Potion of blood\")},\n        new Object[] {new Item(ItemType.WEAPON, \"Sword of silver +1\")},\n        new Object[] {new Item(ItemType.POTION, \"Potion of rust\")},\n        new Object[] {new Item(ItemType.POTION, \"Potion of healing\")},\n        new Object[] {new Item(ItemType.RING, \"Ring of armor\")},\n        new Object[] {new Item(ItemType.WEAPON, \"Steel halberd\")},\n        new Object[] {new Item(ItemType.WEAPON, \"Dagger of poison\")});\n  }\n\n  /**\n   * Test if the expected item can be retrieved from the chest using the {@link\n   * TreasureChestItemIterator}\n   */\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testIterator(Item expectedItem) {\n    final var chest = new TreasureChest();\n    final var iterator = chest.iterator(expectedItem.getType());\n    assertNotNull(iterator);\n\n    while (iterator.hasNext()) {\n      final var item = iterator.next();\n      assertNotNull(item);\n      assertEquals(expectedItem.getType(), item.getType());\n\n      final var name = item.toString();\n      assertNotNull(name);\n      if (expectedItem.toString().equals(name)) {\n        return;\n      }\n    }\n\n    fail(\"Expected to find item [\" + expectedItem + \"] using iterator, but we didn't.\");\n  }\n\n  /**\n   * Test if the expected item can be retrieved from the chest using the {@link\n   * TreasureChest#getItems()} method\n   */\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testGetItems(Item expectedItem) {\n    final var chest = new TreasureChest();\n    final var items = chest.getItems();\n    assertNotNull(items);\n\n    for (final var item : items) {\n      assertNotNull(item);\n      assertNotNull(item.getType());\n      assertNotNull(item.toString());\n\n      final var sameType = expectedItem.getType() == item.getType();\n      final var sameName = expectedItem.toString().equals(item.toString());\n      if (sameType && sameName) {\n        return;\n      }\n    }\n\n    fail(\"Expected to find item [\" + expectedItem + \"] in the item list, but we didn't.\");\n  }\n}\n"
  },
  {
    "path": "layered-architecture/README.md",
    "content": "---\ntitle: \"Layered Architecture Pattern in Java: Building Scalable and Maintainable Applications\"\nshortTitle: Layered Architecture\ndescription: \"Explore the Layered Architecture design pattern in Java. Learn its benefits, real-world examples, use cases, and how it enhances maintainability and scalability in enterprise applications.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - Abstraction\n  - Decoupling\n  - Enterprise patterns\n  - Layered architecture\n  - Scalability\n---\n\n## Also known as\n\n* N-Tier Architecture\n\n## Intent of Layered Architecture Design Pattern\n\nThe Layered Architecture design pattern helps organize applications into groups of subtasks at different levels of abstraction, facilitating independent development and maintenance of each layer.\n\n## Detailed Explanation of Layered Architecture Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine constructing a modern high-rise building, analogous to using the Layered Architecture design pattern in software development. This pattern allows each software layer, such as the data layer, service layer, and presentation layer, to support seamless interaction while maintaining independence, enhancing maintainability and scalability. Just as a building is divided into layers such as the foundation, structural floors, residential floors, and the rooftop, each with specific functions and built using different materials and techniques, a software application can be similarly structured.\n> \n> In this analogy, the foundation represents the data layer, responsible for managing database operations. The structural floors are akin to the service layer, which contains business logic and rules. The residential floors parallel the presentation layer, which deals with user interfaces and interactions. Finally, the rooftop could be seen as the API layer, allowing external systems to communicate with the application. \n> \n> Just as each floor in a building is constructed to support the layers above and below, each software layer supports seamless interaction with its neighboring layers while maintaining a degree of independence. This structure allows for easy maintenance and updates, such as refurbishing the interiors (presentation layer) without affecting the underlying structures (business logic and data layers).\n\nIn plain words\n\n> The Layered Architecture pattern organizes software into hierarchical groups of tasks, each encapsulated in distinct layers that interact with each other, facilitating ease of maintenance, scalability, and clear separation of concerns.\n\nWikipedia says\n\n> In software engineering, multitier architecture (often referred to as n-tier architecture) or multilayered architecture is a client–server architecture in which presentation, application processing, and data management functions are physically separated.\n\nArchitecture diagram\n\n![Layered Architecture Diagram](./etc/layered-architecture-diagram.png)\n\n## Programmatic Example of Layered Architecture in Java\n\nOn the data layer, we keep our cake building blocks. `Cake` consist of layers and topping.\n\n```java\n@Entity\npublic class Cake {\n  @Id\n  @GeneratedValue\n  private Long id;\n  @OneToOne(cascade = CascadeType.REMOVE)\n  private CakeTopping topping;\n  @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER)\n  private Set<CakeLayer> layers;\n}\n```\n\nThe service layer offers `CakeBakingService` for easy access to different aspects of cakes.\n\n```java\npublic interface CakeBakingService {\n  void bakeNewCake(CakeInfo cakeInfo) throws CakeBakingException;\n  List<CakeInfo> getAllCakes();\n  void saveNewTopping(CakeToppingInfo toppingInfo);\n  List<CakeToppingInfo> getAvailableToppings();\n  void saveNewLayer(CakeLayerInfo layerInfo);\n  List<CakeLayerInfo> getAvailableLayers();\n}\n```\n\nOn the top we have our `View` responsible for rendering the cakes.\n\n```java\npublic interface View {\n  void render();\n}\n@Slf4j\npublic class CakeViewImpl implements View {\n  private final CakeBakingService cakeBakingService;\n  public CakeViewImpl(CakeBakingService cakeBakingService) {\n    this.cakeBakingService = cakeBakingService;\n  }\n  public void render() {\n    cakeBakingService.getAllCakes().forEach(cake -> LOGGER.info(cake.toString()));\n  }\n}\n```\n\n## When to Use the Layered Architecture Pattern in Java\n\nThis pattern is suitable for structuring applications that can be divided into groups where each group has a specific role or responsibility. Common in enterprise applications, it simplifies dependencies, enhances maintainability, and supports scaling and technology stack segregation.\n\nUse the Layers architecture when\n\n* You want clearly divide software responsibilities into different parts of the program.\n* You want to prevent a change from propagating throughout the application.\n* You want to make your application more maintainable and testable.\n\n## Real-World Applications of Layered Architecture Pattern in Java\n\n* Web applications where the presentation, business logic, and data access layers are distinctly separated.\n* Enterprise systems where core functionalities are isolated from interface applications and databases.\n\n## Benefits and Trade-offs of Layered Architecture Pattern\n\nBenefits\n\n* Improved manageability with separation of concerns\n* Easier to update or modify one layer without affecting others\n* Promotes reuse of functionalities.\n\nTrade-offs\n\n* Potential performance overhead due to layer interaction\n* Complexity in layer management\n* Challenges in designing an effective layer distribution.\n\n## Related Java Design Patterns\n\n* [Model-View-Controller](https://java-design-patterns.com/patterns/model-view-controller/): Shares separation of concerns by dividing application into input, processing, and output. Layered Architecture often implements an MVC within its presentation layer.\n* Service-Oriented Architecture (SOA): Both patterns emphasize modularization but SOA focuses more on distributed services that can be reused across different systems.\n\n## References and Credits\n\n* [Clean Architecture: A Craftsman's Guide to Software Structure and Design](https://amzn.to/3UoKkaR)\n* [Java Design Pattern Essentials](https://amzn.to/4drLhHU)\n* [Pattern-Oriented Software Architecture Volume 1: A System of Patterns](https://amzn.to/3xZ1ELU)\n"
  },
  {
    "path": "layered-architecture/etc/layers.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\"\n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">\n  <interface id=\"1\" language=\"java\" name=\"com.iluwatar.layers.dao.CakeDao\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/CakeDao.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"289\" y=\"916\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </interface>\n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.layers.entity.CakeLayer\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/CakeLayer.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"1438\" y=\"826\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.layers.view.CakeViewImpl\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/CakeViewImpl.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"456\" y=\"221\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.layers.exception.CakeBakingException\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/CakeBakingException.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"143\" y=\"502\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.layers.service.CakeBakingServiceImpl\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/CakeBakingServiceImpl.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"456\" y=\"694\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <interface id=\"6\" language=\"java\" name=\"com.iluwatar.layers.dao.CakeLayerDao\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/CakeLayerDao.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"456\" y=\"918\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </interface>\n  <interface id=\"7\" language=\"java\" name=\"com.iluwatar.layers.view.View\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/View.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"456\" y=\"65\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </interface>\n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.layers.dto.CakeToppingInfo\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/CakeToppingInfo.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"817\" y=\"530\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <class id=\"9\" language=\"java\" name=\"com.iluwatar.layers.dto.CakeInfo\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/CakeInfo.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"883\" y=\"265\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <interface id=\"10\" language=\"java\" name=\"com.iluwatar.layers.dao.CakeToppingDao\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/CakeToppingDao.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"633\" y=\"918\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </interface>\n  <interface id=\"11\" language=\"java\" name=\"com.iluwatar.layers.service.CakeBakingService\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/CakeBakingService.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"456\" y=\"431\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </interface>\n  <class id=\"12\" language=\"java\" name=\"com.iluwatar.layers.dto.CakeLayerInfo\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/CakeLayerInfo.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"1055\" y=\"530\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <class id=\"13\" language=\"java\" name=\"com.iluwatar.layers.entity.Cake\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/Cake.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"1160\" y=\"826\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <class id=\"14\" language=\"java\" name=\"com.iluwatar.layers.entity.CakeTopping\" project=\"layers\"\n    file=\"/layers/src/main/java/com/iluwatar/layers/CakeTopping.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"876\" y=\"826\"/>\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\"\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    </display>\n  </class>\n  <association id=\"15\">\n    <end type=\"SOURCE\" refId=\"9\" navigable=\"false\">\n      <attribute id=\"16\" name=\"cakeToppingInfo\"/>\n      <multiplicity id=\"17\" minimum=\"0\" maximum=\"1\"/>\n    </end>\n    <end type=\"TARGET\" refId=\"8\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <dependency id=\"18\">\n    <end type=\"SOURCE\" refId=\"5\"/>\n    <end type=\"TARGET\" refId=\"10\"/>\n  </dependency>\n  <association id=\"19\">\n    <end type=\"SOURCE\" refId=\"13\" navigable=\"false\">\n      <attribute id=\"20\" name=\"layers\"/>\n      <multiplicity id=\"21\" minimum=\"0\" maximum=\"2147483647\"/>\n    </end>\n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <dependency id=\"22\">\n    <end type=\"SOURCE\" refId=\"11\"/>\n    <end type=\"TARGET\" refId=\"4\"/>\n  </dependency>\n  <realization id=\"23\">\n    <end type=\"SOURCE\" refId=\"5\"/>\n    <end type=\"TARGET\" refId=\"11\"/>\n  </realization>\n  <association id=\"24\">\n    <end type=\"SOURCE\" refId=\"13\" navigable=\"false\">\n      <attribute id=\"25\" name=\"topping\"/>\n      <multiplicity id=\"26\" minimum=\"0\" maximum=\"1\"/>\n    </end>\n    <end type=\"TARGET\" refId=\"14\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <association id=\"27\">\n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">\n      <attribute id=\"28\" name=\"cake\"/>\n      <multiplicity id=\"29\" minimum=\"0\" maximum=\"1\"/>\n    </end>\n    <end type=\"TARGET\" refId=\"13\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <dependency id=\"30\">\n    <end type=\"SOURCE\" refId=\"5\"/>\n    <end type=\"TARGET\" refId=\"14\"/>\n  </dependency>\n  <dependency id=\"31\">\n    <end type=\"SOURCE\" refId=\"11\"/>\n    <end type=\"TARGET\" refId=\"12\"/>\n  </dependency>\n  <association id=\"32\">\n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">\n      <attribute id=\"33\" name=\"cakeBakingService\"/>\n      <multiplicity id=\"34\" minimum=\"0\" maximum=\"1\"/>\n    </end>\n    <end type=\"TARGET\" refId=\"11\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <dependency id=\"35\">\n    <end type=\"SOURCE\" refId=\"5\"/>\n    <end type=\"TARGET\" refId=\"1\"/>\n  </dependency>\n  <dependency id=\"36\">\n    <end type=\"SOURCE\" refId=\"5\"/>\n    <end type=\"TARGET\" refId=\"2\"/>\n  </dependency>\n  <dependency id=\"37\">\n    <end type=\"SOURCE\" refId=\"5\"/>\n    <end type=\"TARGET\" refId=\"4\"/>\n  </dependency>\n  <dependency id=\"38\">\n    <end type=\"SOURCE\" refId=\"11\"/>\n    <end type=\"TARGET\" refId=\"8\"/>\n  </dependency>\n  <association id=\"39\">\n    <end type=\"SOURCE\" refId=\"9\" navigable=\"false\">\n      <attribute id=\"40\" name=\"cakeLayerInfos\"/>\n      <multiplicity id=\"41\" minimum=\"0\" maximum=\"2147483647\"/>\n    </end>\n    <end type=\"TARGET\" refId=\"12\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <realization id=\"42\">\n    <end type=\"SOURCE\" refId=\"3\"/>\n    <end type=\"TARGET\" refId=\"7\"/>\n  </realization>\n  <dependency id=\"43\">\n    <end type=\"SOURCE\" refId=\"5\"/>\n    <end type=\"TARGET\" refId=\"12\"/>\n  </dependency>\n  <dependency id=\"44\">\n    <end type=\"SOURCE\" refId=\"11\"/>\n    <end type=\"TARGET\" refId=\"9\"/>\n  </dependency>\n  <association id=\"45\">\n    <end type=\"SOURCE\" refId=\"14\" navigable=\"false\">\n      <attribute id=\"46\" name=\"cake\"/>\n      <multiplicity id=\"47\" minimum=\"0\" maximum=\"1\"/>\n    </end>\n    <end type=\"TARGET\" refId=\"13\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>\n  </association>\n  <dependency id=\"48\">\n    <end type=\"SOURCE\" refId=\"5\"/>\n    <end type=\"TARGET\" refId=\"6\"/>\n  </dependency>\n  <dependency id=\"49\">\n    <end type=\"SOURCE\" refId=\"5\"/>\n    <end type=\"TARGET\" refId=\"8\"/>\n  </dependency>\n  <dependency id=\"50\">\n    <end type=\"SOURCE\" refId=\"5\"/>\n    <end type=\"TARGET\" refId=\"9\"/>\n  </dependency>\n  <dependency id=\"51\">\n    <end type=\"SOURCE\" refId=\"5\"/>\n    <end type=\"TARGET\" refId=\"13\"/>\n  </dependency>\n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"true\" signature=\"true\"\n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">\n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>\n  </classifier-display>\n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "layered-architecture/etc/layers.urm.puml",
    "content": "@startuml\npackage com.iluwatar.layers.dto {\n  class CakeInfo {\n    + cakeLayerInfos : List<CakeLayerInfo>\n    + cakeToppingInfo : CakeToppingInfo\n    + id : Optional<Long>\n    + CakeInfo(cakeToppingInfo : CakeToppingInfo, cakeLayerInfos : List<CakeLayerInfo>)\n    + CakeInfo(id : Long, cakeToppingInfo : CakeToppingInfo, cakeLayerInfos : List<CakeLayerInfo>)\n    + calculateTotalCalories() : int\n    + toString() : String\n  }\n  class CakeLayerInfo {\n    + calories : int\n    + id : Optional<Long>\n    + name : String\n    + CakeLayerInfo(id : Long, name : String, calories : int)\n    + CakeLayerInfo(name : String, calories : int)\n    + toString() : String\n  }\n  class CakeToppingInfo {\n    + calories : int\n    + id : Optional<Long>\n    + name : String\n    + CakeToppingInfo(id : Long, name : String, calories : int)\n    + CakeToppingInfo(name : String, calories : int)\n    + toString() : String\n  }\n}\npackage com.iluwatar.layers.entity {\n  class Cake {\n    - id : Long\n    - layers : Set<CakeLayer>\n    - topping : CakeTopping\n    + Cake()\n    + addLayer(layer : CakeLayer)\n    + getId() : Long\n    + getLayers() : Set<CakeLayer>\n    + getTopping() : CakeTopping\n    + setId(id : Long)\n    + setLayers(layers : Set<CakeLayer>)\n    + setTopping(topping : CakeTopping)\n    + toString() : String\n  }\n  class CakeLayer {\n    - cake : Cake\n    - calories : int\n    - id : Long\n    - name : String\n    + CakeLayer()\n    + CakeLayer(name : String, calories : int)\n    + getCake() : Cake\n    + getCalories() : int\n    + getId() : Long\n    + getName() : String\n    + setCake(cake : Cake)\n    + setCalories(calories : int)\n    + setId(id : Long)\n    + setName(name : String)\n    + toString() : String\n  }\n  class CakeTopping {\n    - cake : Cake\n    - calories : int\n    - id : Long\n    - name : String\n    + CakeTopping()\n    + CakeTopping(name : String, calories : int)\n    + getCake() : Cake\n    + getCalories() : int\n    + getId() : Long\n    + getName() : String\n    + setCake(cake : Cake)\n    + setCalories(calories : int)\n    + setId(id : Long)\n    + setName(name : String)\n    + toString() : String\n  }\n}\npackage com.iluwatar.layers.view {\n  class CakeViewImpl {\n    - LOGGER : Logger {static}\n    - cakeBakingService : CakeBakingService\n    + CakeViewImpl(cakeBakingService : CakeBakingService)\n    + render()\n  }\n  interface View {\n    + render() {abstract}\n  }\n}\npackage com.iluwatar.layers.app {\n  class App {\n    - cakeBakingService : CakeBakingService {static}\n    + App()\n    - initializeData(cakeBakingService : CakeBakingService) {static}\n    + main(args : String[]) {static}\n  }\n}\npackage com.iluwatar.layers.dao {\n  interface CakeDao {\n  }\n  interface CakeLayerDao {\n  }\n  interface CakeToppingDao {\n  }\n}\npackage com.iluwatar.layers.service {\n  interface CakeBakingService {\n    + bakeNewCake(CakeInfo) {abstract}\n    + getAllCakes() : List<CakeInfo> {abstract}\n    + getAvailableLayers() : List<CakeLayerInfo> {abstract}\n    + getAvailableToppings() : List<CakeToppingInfo> {abstract}\n    + saveNewLayer(CakeLayerInfo) {abstract}\n    + saveNewTopping(CakeToppingInfo) {abstract}\n  }\n  class CakeBakingServiceImpl {\n    - context : AbstractApplicationContext\n    + CakeBakingServiceImpl()\n    + bakeNewCake(cakeInfo : CakeInfo)\n    + getAllCakes() : List<CakeInfo>\n    - getAvailableLayerEntities() : List<CakeLayer>\n    + getAvailableLayers() : List<CakeLayerInfo>\n    - getAvailableToppingEntities() : List<CakeTopping>\n    + getAvailableToppings() : List<CakeToppingInfo>\n    + saveNewLayer(layerInfo : CakeLayerInfo)\n    + saveNewTopping(toppingInfo : CakeToppingInfo)\n  }\n}\nCakeInfo -->  \"-cakeLayerInfos\" CakeLayerInfo\nCakeInfo -->  \"-cakeToppingInfo\" CakeToppingInfo\nCakeViewImpl -->  \"-cakeBakingService\" CakeBakingService\nApp -->  \"-cakeBakingService\" CakeBakingService\nCake -->  \"-topping\" CakeTopping\nCakeLayer -->  \"-cake\" Cake\nCakeBakingServiceImpl ..|> CakeBakingService\nCakeViewImpl ..|> View\n@enduml"
  },
  {
    "path": "layered-architecture/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>layered-architecture</artifactId>\n    <name>layers</name>\n    <description>layers</description>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-data-jpa</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.h2database</groupId>\n            <artifactId>h2</artifactId>\n            <scope>runtime</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.layers.Runner</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "layered-architecture/src/main/java/com/iluwatar/layers/Runner.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.layers;\n\nimport dto.CakeInfo;\nimport dto.CakeLayerInfo;\nimport dto.CakeToppingInfo;\nimport exception.CakeBakingException;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.CommandLineRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.domain.EntityScan;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.stereotype.Component;\nimport service.CakeBakingService;\nimport view.CakeViewImpl;\n\n/**\n * The Runner class is the entry point of the application. It implements CommandLineRunner, which\n * means it will execute the run method after the application context is loaded.\n *\n * <p>The Runner class is responsible for initializing the cake baking service with sample data and\n * creating a view to render the cakes. It uses the CakeBakingService to save new layers and\n * toppings and to bake new cakes. It also handles exceptions that might occur during the cake\n * baking process.\n */\n@EntityScan(basePackages = \"entity\")\n@ComponentScan(basePackages = {\"com.iluwatar.layers\", \"service\", \"dto\", \"exception\", \"view\", \"dao\"})\n@Component\n@Slf4j\npublic class Runner implements CommandLineRunner {\n  private final CakeBakingService cakeBakingService;\n  public static final String STRAWBERRY = \"strawberry\";\n\n  @Autowired\n  public Runner(CakeBakingService cakeBakingService) {\n    this.cakeBakingService = cakeBakingService;\n  }\n\n  @Override\n  public void run(String... args) {\n    // initialize sample data\n    initializeData();\n    // create view and render it\n    var cakeView = new CakeViewImpl(cakeBakingService);\n    cakeView.render();\n  }\n\n  public static void main(String[] args) {\n    SpringApplication.run(Runner.class, args);\n  }\n\n  /** Initializes the example data. */\n  private void initializeData() {\n    cakeBakingService.saveNewLayer(new CakeLayerInfo(\"chocolate\", 1200));\n    cakeBakingService.saveNewLayer(new CakeLayerInfo(\"banana\", 900));\n    cakeBakingService.saveNewLayer(new CakeLayerInfo(STRAWBERRY, 950));\n    cakeBakingService.saveNewLayer(new CakeLayerInfo(\"lemon\", 950));\n    cakeBakingService.saveNewLayer(new CakeLayerInfo(\"vanilla\", 950));\n    cakeBakingService.saveNewLayer(new CakeLayerInfo(STRAWBERRY, 950));\n\n    cakeBakingService.saveNewTopping(new CakeToppingInfo(\"candies\", 350));\n    cakeBakingService.saveNewTopping(new CakeToppingInfo(\"cherry\", 350));\n\n    var cake1 =\n        new CakeInfo(\n            new CakeToppingInfo(\"candies\", 0),\n            List.of(\n                new CakeLayerInfo(\"chocolate\", 0),\n                new CakeLayerInfo(\"banana\", 0),\n                new CakeLayerInfo(STRAWBERRY, 0)));\n    try {\n      cakeBakingService.bakeNewCake(cake1);\n    } catch (CakeBakingException e) {\n      LOGGER.error(\"Cake baking exception\", e);\n    }\n    var cake2 =\n        new CakeInfo(\n            new CakeToppingInfo(\"cherry\", 0),\n            List.of(\n                new CakeLayerInfo(\"vanilla\", 0),\n                new CakeLayerInfo(\"lemon\", 0),\n                new CakeLayerInfo(STRAWBERRY, 0)));\n    try {\n      cakeBakingService.bakeNewCake(cake2);\n    } catch (CakeBakingException e) {\n      LOGGER.error(\"Cake baking exception\", e);\n    }\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/main/java/com/iluwatar/layers/app/LayersApp.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.layers.app;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.autoconfigure.domain.EntityScan;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.data.jpa.repository.config.EnableJpaRepositories;\n\n/**\n * The Layers pattern is a structural design pattern that organizes system architecture into\n * distinct layers, each with a specific responsibility and abstraction level. This separation\n * allows for increased modularity, facilitating independent development, maintenance, and reuse of\n * each layer. Commonly, layers interact with each other through well-defined interfaces, with\n * higher layers (more abstract) depending on lower layers (more concrete), but not vice versa,\n * promoting a clear hierarchy and separation of concerns.\n */\n@SpringBootApplication\n@EnableJpaRepositories(basePackages = \"dao\")\n@EntityScan(basePackages = \"entity\")\n@ComponentScan(basePackages = {\"com.iluwatar.layers\", \"service\", \"dto\", \"exception\", \"view\", \"dao\"})\npublic class LayersApp {\n\n  public static void main(String[] args) {\n    SpringApplication.run(LayersApp.class, args);\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/main/java/dao/CakeDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage dao;\n\nimport entity.Cake;\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.stereotype.Repository;\n\n/** CRUD repository for cakes. */\n@Repository\npublic interface CakeDao extends JpaRepository<Cake, Long> {}\n"
  },
  {
    "path": "layered-architecture/src/main/java/dao/CakeLayerDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage dao;\n\nimport entity.CakeLayer;\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.stereotype.Repository;\n\n/** CRUD repository for cake layers. */\n@Repository\npublic interface CakeLayerDao extends JpaRepository<CakeLayer, Long> {}\n"
  },
  {
    "path": "layered-architecture/src/main/java/dao/CakeToppingDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage dao;\n\nimport entity.CakeTopping;\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.stereotype.Repository;\n\n/** CRUD repository cake toppings. */\n@Repository\npublic interface CakeToppingDao extends JpaRepository<CakeTopping, Long> {}\n"
  },
  {
    "path": "layered-architecture/src/main/java/dto/CakeInfo.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage dto;\n\nimport java.util.List;\n\n/** DTO for cakes. */\npublic class CakeInfo {\n\n  public final Long id;\n  public final CakeToppingInfo cakeToppingInfo;\n  public final List<CakeLayerInfo> cakeLayerInfos;\n\n  /** Constructor. */\n  public CakeInfo(Long id, CakeToppingInfo cakeToppingInfo, List<CakeLayerInfo> cakeLayerInfos) {\n    this.id = id;\n    this.cakeToppingInfo = cakeToppingInfo;\n    this.cakeLayerInfos = cakeLayerInfos;\n  }\n\n  /** Constructor. */\n  public CakeInfo(CakeToppingInfo cakeToppingInfo, List<CakeLayerInfo> cakeLayerInfos) {\n    this.id = null;\n    this.cakeToppingInfo = cakeToppingInfo;\n    this.cakeLayerInfos = cakeLayerInfos;\n  }\n\n  /** Calculate calories. */\n  public int calculateTotalCalories() {\n    var total = cakeToppingInfo != null ? cakeToppingInfo.calories : 0;\n    total += cakeLayerInfos.stream().mapToInt(c -> c.calories).sum();\n    return total;\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\n        \"CakeInfo id=%d topping=%s layers=%s totalCalories=%d\",\n        id, cakeToppingInfo, cakeLayerInfos, calculateTotalCalories());\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/main/java/dto/CakeLayerInfo.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage dto;\n\n/** DTO for cake layers. */\npublic class CakeLayerInfo {\n\n  public final Long id;\n  public final String name;\n  public final int calories;\n\n  /** Constructor. */\n  public CakeLayerInfo(Long id, String name, int calories) {\n    this.id = id;\n    this.name = name;\n    this.calories = calories;\n  }\n\n  /** Constructor. */\n  public CakeLayerInfo(String name, int calories) {\n    this.id = null;\n    this.name = name;\n    this.calories = calories;\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\"CakeLayerInfo id=%d name=%s calories=%d\", id, name, calories);\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/main/java/dto/CakeToppingInfo.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage dto;\n\n/** DTO for cake toppings. */\npublic class CakeToppingInfo {\n\n  public final Long id;\n  public final String name;\n  public final int calories;\n\n  /** Constructor. */\n  public CakeToppingInfo(Long id, String name, int calories) {\n    this.id = id;\n    this.name = name;\n    this.calories = calories;\n  }\n\n  /** Constructor. */\n  public CakeToppingInfo(String name, int calories) {\n    this.id = null;\n    this.name = name;\n    this.calories = calories;\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\"CakeToppingInfo id=%d name=%s calories=%d\", id, name, calories);\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/main/java/entity/Cake.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage entity;\n\nimport jakarta.persistence.CascadeType;\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.FetchType;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.Id;\nimport jakarta.persistence.OneToMany;\nimport jakarta.persistence.OneToOne;\nimport java.util.HashSet;\nimport java.util.Set;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Cake entity. */\n@Entity\n@Getter\n@Setter\npublic class Cake {\n\n  @Id @GeneratedValue private Long id;\n\n  @OneToOne(cascade = CascadeType.REMOVE)\n  private CakeTopping topping;\n\n  @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER)\n  private Set<CakeLayer> layers;\n\n  public Cake() {\n    setLayers(new HashSet<>());\n  }\n\n  public void addLayer(CakeLayer layer) {\n    this.layers.add(layer);\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\"id=%s topping=%s layers=%s\", id, topping, layers.toString());\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/main/java/entity/CakeLayer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage entity;\n\nimport jakarta.persistence.CascadeType;\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.Id;\nimport jakarta.persistence.ManyToOne;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n/** CakeLayer entity. */\n@Entity\n@Getter\n@Setter\n@NoArgsConstructor\n@AllArgsConstructor\n@Builder\n@EqualsAndHashCode\npublic class CakeLayer {\n\n  @Id @GeneratedValue private Long id;\n\n  private String name;\n\n  private int calories;\n\n  @ManyToOne(cascade = CascadeType.ALL)\n  private Cake cake;\n\n  public CakeLayer(String name, int calories) {\n    this.setName(name);\n    this.setCalories(calories);\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\"id=%s name=%s calories=%d\", id, name, calories);\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/main/java/entity/CakeTopping.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage entity;\n\nimport jakarta.persistence.CascadeType;\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.Id;\nimport jakarta.persistence.OneToOne;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n/** CakeTopping entity. */\n@Entity\n@Getter\n@Setter\n@NoArgsConstructor\n@AllArgsConstructor\n@Builder\n@EqualsAndHashCode\npublic class CakeTopping {\n\n  @Id @GeneratedValue private Long id;\n\n  private String name;\n\n  private int calories;\n\n  @OneToOne(cascade = CascadeType.ALL)\n  private Cake cake;\n\n  public CakeTopping(String name, int calories) {\n    this.setName(name);\n    this.setCalories(calories);\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\"id=%s name=%s calories=%d\", id, name, calories);\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/main/java/exception/CakeBakingException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage exception;\n\nimport java.io.Serial;\nimport org.springframework.stereotype.Component;\n\n/** Custom exception used in cake baking. */\n@Component\npublic class CakeBakingException extends Exception {\n\n  @Serial private static final long serialVersionUID = 1L;\n\n  public CakeBakingException() {}\n\n  public CakeBakingException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/main/java/service/CakeBakingService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage service;\n\nimport dto.CakeInfo;\nimport dto.CakeLayerInfo;\nimport dto.CakeToppingInfo;\nimport exception.CakeBakingException;\nimport java.util.List;\nimport org.springframework.stereotype.Service;\n\n/** Service for cake baking operations. */\n@Service\npublic interface CakeBakingService {\n\n  /** Bakes new cake according to parameters. */\n  void bakeNewCake(CakeInfo cakeInfo) throws CakeBakingException;\n\n  /** Get all cakes. */\n  List<CakeInfo> getAllCakes();\n\n  /** Store new cake topping. */\n  void saveNewTopping(CakeToppingInfo toppingInfo);\n\n  /** Get available cake toppings. */\n  List<CakeToppingInfo> getAvailableToppings();\n\n  /** Add new cake layer. */\n  void saveNewLayer(CakeLayerInfo layerInfo);\n\n  /** Get available cake layers. */\n  List<CakeLayerInfo> getAvailableLayers();\n\n  void deleteAllCakes();\n\n  void deleteAllLayers();\n\n  void deleteAllToppings();\n}\n"
  },
  {
    "path": "layered-architecture/src/main/java/service/CakeBakingServiceImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage service;\n\nimport dao.CakeDao;\nimport dao.CakeLayerDao;\nimport dao.CakeToppingDao;\nimport dto.CakeInfo;\nimport dto.CakeLayerInfo;\nimport dto.CakeToppingInfo;\nimport entity.Cake;\nimport entity.CakeLayer;\nimport entity.CakeTopping;\nimport exception.CakeBakingException;\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\n/** Implementation of CakeBakingService. */\n@Service\n@Transactional\npublic class CakeBakingServiceImpl implements CakeBakingService {\n\n  private final CakeDao cakeDao;\n  private final CakeLayerDao cakeLayerDao;\n  private final CakeToppingDao cakeToppingDao;\n\n  /**\n   * Constructs a new instance of CakeBakingServiceImpl.\n   *\n   * @param cakeDao the DAO for cake-related operations\n   * @param cakeLayerDao the DAO for cake layer-related operations\n   * @param cakeToppingDao the DAO for cake topping-related operations\n   */\n  @Autowired\n  public CakeBakingServiceImpl(\n      CakeDao cakeDao, CakeLayerDao cakeLayerDao, CakeToppingDao cakeToppingDao) {\n    this.cakeDao = cakeDao;\n    this.cakeLayerDao = cakeLayerDao;\n    this.cakeToppingDao = cakeToppingDao;\n  }\n\n  @Override\n  public void bakeNewCake(CakeInfo cakeInfo) throws CakeBakingException {\n    var allToppings = getAvailableToppingEntities();\n    var matchingToppings =\n        allToppings.stream()\n            .filter(t -> t.getName().equals(cakeInfo.cakeToppingInfo.name))\n            .toList();\n    if (matchingToppings.isEmpty()) {\n      throw new CakeBakingException(\n          String.format(\"Topping %s is not available\", cakeInfo.cakeToppingInfo.name));\n    }\n    var allLayers = getAvailableLayerEntities();\n    Set<CakeLayer> foundLayers = new HashSet<>();\n    for (var info : cakeInfo.cakeLayerInfos) {\n      var found = allLayers.stream().filter(layer -> layer.getName().equals(info.name)).findFirst();\n      if (found.isEmpty()) {\n        throw new CakeBakingException(String.format(\"Layer %s is not available\", info.name));\n      } else {\n        foundLayers.add(found.get());\n      }\n    }\n\n    var topping = cakeToppingDao.findById(matchingToppings.iterator().next().getId());\n    if (topping.isPresent()) {\n      var cake = new Cake();\n      cake.setTopping(topping.get());\n      cake.setLayers(foundLayers);\n      cakeDao.save(cake);\n      topping.get().setCake(cake);\n      cakeToppingDao.save(topping.get());\n      Set<CakeLayer> foundLayersToUpdate =\n          new HashSet<>(foundLayers); // copy set to avoid a ConcurrentModificationException\n\n      for (var layer : foundLayersToUpdate) {\n        layer.setCake(cake);\n        cakeLayerDao.save(layer);\n      }\n\n    } else {\n      throw new CakeBakingException(\n          String.format(\"Topping %s is not available\", cakeInfo.cakeToppingInfo.name));\n    }\n  }\n\n  @Override\n  public void saveNewTopping(CakeToppingInfo toppingInfo) {\n    cakeToppingDao.save(new CakeTopping(toppingInfo.name, toppingInfo.calories));\n  }\n\n  @Override\n  public void saveNewLayer(CakeLayerInfo layerInfo) {\n    cakeLayerDao.save(new CakeLayer(layerInfo.name, layerInfo.calories));\n  }\n\n  private List<CakeTopping> getAvailableToppingEntities() {\n    List<CakeTopping> result = new ArrayList<>();\n    for (CakeTopping topping : cakeToppingDao.findAll()) {\n      if (topping.getCake() == null) {\n        result.add(topping);\n      }\n    }\n    return result;\n  }\n\n  @Override\n  public List<CakeToppingInfo> getAvailableToppings() {\n    List<CakeToppingInfo> result = new ArrayList<>();\n    for (CakeTopping next : cakeToppingDao.findAll()) {\n      if (next.getCake() == null) {\n        result.add(new CakeToppingInfo(next.getId(), next.getName(), next.getCalories()));\n      }\n    }\n    return result;\n  }\n\n  private List<CakeLayer> getAvailableLayerEntities() {\n    List<CakeLayer> result = new ArrayList<>();\n    for (CakeLayer next : cakeLayerDao.findAll()) {\n      if (next.getCake() == null) {\n        result.add(next);\n      }\n    }\n    return result;\n  }\n\n  @Override\n  public List<CakeLayerInfo> getAvailableLayers() {\n    List<CakeLayerInfo> result = new ArrayList<>();\n    for (CakeLayer next : cakeLayerDao.findAll()) {\n      if (next.getCake() == null) {\n        result.add(new CakeLayerInfo(next.getId(), next.getName(), next.getCalories()));\n      }\n    }\n    return result;\n  }\n\n  @Override\n  public void deleteAllCakes() {\n    cakeDao.deleteAll();\n  }\n\n  @Override\n  public void deleteAllLayers() {\n    cakeLayerDao.deleteAll();\n  }\n\n  @Override\n  public void deleteAllToppings() {\n    cakeToppingDao.deleteAll();\n  }\n\n  @Override\n  public List<CakeInfo> getAllCakes() {\n    List<CakeInfo> result = new ArrayList<>();\n    for (Cake cake : cakeDao.findAll()) {\n      var cakeToppingInfo =\n          new CakeToppingInfo(\n              cake.getTopping().getId(),\n              cake.getTopping().getName(),\n              cake.getTopping().getCalories());\n      List<CakeLayerInfo> cakeLayerInfos = new ArrayList<>();\n      for (var layer : cake.getLayers()) {\n        cakeLayerInfos.add(new CakeLayerInfo(layer.getId(), layer.getName(), layer.getCalories()));\n      }\n      var cakeInfo = new CakeInfo(cake.getId(), cakeToppingInfo, cakeLayerInfos);\n      result.add(cakeInfo);\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/main/java/view/CakeViewImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage view;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport service.CakeBakingService;\n\n/** View implementation for displaying cakes. */\npublic class CakeViewImpl implements View {\n\n  private final CakeBakingService cakeBakingService;\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(CakeViewImpl.class);\n\n  public CakeViewImpl(CakeBakingService cakeBakingService) {\n    this.cakeBakingService = cakeBakingService;\n  }\n\n  public void render() {\n    cakeBakingService.getAllCakes().forEach(cake -> LOGGER.info(cake.toString()));\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/main/java/view/View.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage view;\n\n/** View interface. */\npublic interface View {\n\n  void render();\n}\n"
  },
  {
    "path": "layered-architecture/src/main/resources/META-INF/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<configuration>\n    <appender name=\"FILE\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>layers.log</file>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\">\n            <fileNamePattern>layers-%d.log</fileNamePattern>\n            <maxHistory>5</maxHistory>\n        </rollingPolicy>\n        <encoder>\n            <pattern>%-5p [%d{ISO8601,UTC}] %c: %m%n</pattern>\n        </encoder>\n    </appender>\n    <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n        <encoder>\n            <pattern>%-5p [%d{ISO8601,UTC}] %c: %m%n</pattern>\n        </encoder>\n    </appender>\n    <logger name=\"com.iluwatar\" additivity=\"false\">\n        <level value=\"DEBUG\" />\n        <appender-ref ref=\"FILE\" />\n    </logger>\n    <logger name=\"org.hibernate\" additivity=\"false\">\n        <level value=\"ERROR\" />\n        <appender-ref ref=\"STDOUT\" />\n    </logger>\n    <root level=\"WARN\">\n        <appender-ref ref=\"STDOUT\" />\n    </root>\n</configuration>\n"
  },
  {
    "path": "layered-architecture/src/main/resources/application.properties",
    "content": "\nspring.main.web-application-type=none\n\n#datasource settings\nspring.datasource.url=jdbc:h2:mem:databases-cake\nspring.datasource.driverClassName=org.h2.Driver\nspring.datasource.username=sa\nspring.datasource.password=sa\n\n#data settings\nspring.jpa.database-platform=org.hibernate.dialect.H2Dialect\nspring.jpa.hibernate.ddl-auto=create-drop\n"
  },
  {
    "path": "layered-architecture/src/test/java/com/iluwatar/layers/app/LayersAppTests.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.layers.app;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.context.ApplicationContext;\n\n@SpringBootTest(classes = LayersApp.class)\nclass LayersAppTests {\n\n  private final ApplicationContext applicationContext;\n\n  @Autowired\n  LayersAppTests(ApplicationContext applicationContext) {\n    this.applicationContext = applicationContext;\n  }\n\n  @Test\n  void contextLoads() {\n    assertNotNull(applicationContext);\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/test/java/com/iluwatar/layers/entity/CakeTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.layers.entity;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport entity.Cake;\nimport entity.CakeLayer;\nimport entity.CakeTopping;\nimport java.util.HashSet;\nimport java.util.Set;\nimport org.junit.jupiter.api.Test;\n\n/**\n * This class contains unit tests for the Cake class. It tests the functionality of setting and\n * getting the id, topping, and layers of a Cake object. It also tests the functionality of adding a\n * layer to a Cake object and converting a Cake object to a string.\n */\nclass CakeTest {\n\n  @Test\n  void testSetId() {\n    final var cake = new Cake();\n    assertNull(cake.getId());\n\n    final var expectedId = 1234L;\n    cake.setId(expectedId);\n    assertEquals(expectedId, cake.getId());\n  }\n\n  @Test\n  void testSetTopping() {\n    final var cake = new Cake();\n    assertNull(cake.getTopping());\n\n    final var expectedTopping = new CakeTopping(\"DummyTopping\", 1000);\n    cake.setTopping(expectedTopping);\n    assertEquals(expectedTopping, cake.getTopping());\n  }\n\n  @Test\n  void testSetLayers() {\n    final var cake = new Cake();\n    assertNotNull(cake.getLayers());\n    assertTrue(cake.getLayers().isEmpty());\n\n    final var expectedLayers =\n        Set.of(\n            new CakeLayer(\"layer1\", 1000),\n            new CakeLayer(\"layer2\", 2000),\n            new CakeLayer(\"layer3\", 3000));\n    cake.setLayers(expectedLayers);\n    assertEquals(expectedLayers, cake.getLayers());\n  }\n\n  @Test\n  void testAddLayer() {\n    final var cake = new Cake();\n    assertNotNull(cake.getLayers());\n    assertTrue(cake.getLayers().isEmpty());\n\n    final Set<CakeLayer> initialLayers = new HashSet<>();\n    initialLayers.add(new CakeLayer(\"layer1\", 1000));\n    initialLayers.add(new CakeLayer(\"layer2\", 2000));\n\n    cake.setLayers(initialLayers);\n    assertEquals(initialLayers, cake.getLayers());\n\n    final var newLayer = new CakeLayer(\"layer3\", 3000);\n    cake.addLayer(newLayer);\n\n    final Set<CakeLayer> expectedLayers = new HashSet<>();\n    expectedLayers.addAll(initialLayers);\n    expectedLayers.addAll(initialLayers);\n    expectedLayers.add(newLayer);\n    assertEquals(expectedLayers, cake.getLayers());\n  }\n\n  @Test\n  void testToString() {\n    final var topping = new CakeTopping(\"topping\", 20);\n    topping.setId(2345L);\n\n    final var layer = new CakeLayer(\"layer\", 100);\n    layer.setId(3456L);\n\n    final var cake = new Cake();\n    cake.setId(1234L);\n    cake.setTopping(topping);\n    cake.addLayer(layer);\n\n    final var expected =\n        \"id=1234 topping=id=2345 name=topping calories=20 \"\n            + \"layers=[id=3456 name=layer calories=100]\";\n    assertEquals(expected, cake.toString());\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/test/java/com/iluwatar/layers/exception/CakeBakingExceptionTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.layers.exception;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nimport exception.CakeBakingException;\nimport org.junit.jupiter.api.Test;\n\n/**\n * Tests for the {@link CakeBakingException} class. This class contains unit tests to verify the\n * correct functionality of the {@code CakeBakingException} class constructors, including the\n * default constructor and the constructor that accepts a message parameter.\n */\nclass CakeBakingExceptionTest {\n\n  /**\n   * Tests the default constructor of {@link CakeBakingException}. Ensures that an exception created\n   * with the default constructor has {@code null} as its message and cause.\n   */\n  @Test\n  void testConstructor() {\n    final var exception = new CakeBakingException();\n    assertNull(exception.getMessage(), \"The message should be null for the default constructor.\");\n    assertNull(exception.getCause(), \"The cause should be null for the default constructor.\");\n  }\n\n  /**\n   * Tests the constructor of {@link CakeBakingException} that accepts a message. Ensures that an\n   * exception created with this constructor correctly stores the provided message and has {@code\n   * null} as its cause.\n   */\n  @Test\n  void testConstructorWithMessage() {\n    final var expectedMessage = \"message\";\n    final var exception = new CakeBakingException(expectedMessage);\n    assertEquals(\n        expectedMessage,\n        exception.getMessage(),\n        \"The stored message should match the expected message.\");\n    assertNull(\n        exception.getCause(),\n        \"The cause should be null when an exception is created with only a message.\");\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/test/java/com/iluwatar/layers/service/CakeBakingServiceImplTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.layers.service;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.layers.app.LayersApp;\nimport dto.CakeInfo;\nimport dto.CakeLayerInfo;\nimport dto.CakeToppingInfo;\nimport exception.CakeBakingException;\nimport java.util.Collections;\nimport java.util.List;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport service.CakeBakingServiceImpl;\n\n/** Constructs a new instance of CakeBakingServiceImplTest. */\n@SpringBootTest(classes = LayersApp.class)\nclass CakeBakingServiceImplTest {\n\n  private final CakeBakingServiceImpl cakeBakingService;\n\n  @Autowired\n  CakeBakingServiceImplTest(CakeBakingServiceImpl cakeBakingService) {\n    this.cakeBakingService = cakeBakingService;\n  }\n\n  @BeforeEach\n  void setUp() {\n    cakeBakingService.deleteAllCakes();\n    cakeBakingService.deleteAllLayers();\n    cakeBakingService.deleteAllToppings();\n  }\n\n  @Test\n  void testLayers() {\n    final var initialLayers = cakeBakingService.getAvailableLayers();\n    assertNotNull(initialLayers);\n    assertTrue(initialLayers.isEmpty());\n\n    cakeBakingService.saveNewLayer(new CakeLayerInfo(\"Layer1\", 1000));\n    cakeBakingService.saveNewLayer(new CakeLayerInfo(\"Layer2\", 2000));\n\n    final var availableLayers = cakeBakingService.getAvailableLayers();\n    assertNotNull(availableLayers);\n    assertEquals(2, availableLayers.size());\n    for (final var layer : availableLayers) {\n      assertNotNull(layer.id);\n      assertNotNull(layer.name);\n      assertNotNull(layer.toString());\n      assertTrue(layer.calories > 0);\n    }\n  }\n\n  @Test\n  void testToppings() {\n    final var initialToppings = cakeBakingService.getAvailableToppings();\n    assertNotNull(initialToppings);\n    assertTrue(initialToppings.isEmpty());\n\n    cakeBakingService.saveNewTopping(new CakeToppingInfo(\"Topping1\", 1000));\n    cakeBakingService.saveNewTopping(new CakeToppingInfo(\"Topping2\", 2000));\n\n    final var availableToppings = cakeBakingService.getAvailableToppings();\n    assertNotNull(availableToppings);\n    assertEquals(2, availableToppings.size());\n    for (final var topping : availableToppings) {\n      assertNotNull(topping.id);\n      assertNotNull(topping.name);\n      assertNotNull(topping.toString());\n      assertTrue(topping.calories > 0);\n    }\n  }\n\n  @Test\n  void testBakeCakes() throws CakeBakingException {\n\n    final var initialCakes = cakeBakingService.getAllCakes();\n    assertNotNull(initialCakes);\n    assertTrue(initialCakes.isEmpty());\n\n    final var topping1 = new CakeToppingInfo(\"Topping1\", 1000);\n    final var topping2 = new CakeToppingInfo(\"Topping2\", 2000);\n    cakeBakingService.saveNewTopping(topping1);\n    cakeBakingService.saveNewTopping(topping2);\n\n    final var layer1 = new CakeLayerInfo(\"Layer1\", 1000);\n    final var layer2 = new CakeLayerInfo(\"Layer2\", 2000);\n    final var layer3 = new CakeLayerInfo(\"Layer3\", 2000);\n    cakeBakingService.saveNewLayer(layer1);\n    cakeBakingService.saveNewLayer(layer2);\n    cakeBakingService.saveNewLayer(layer3);\n\n    cakeBakingService.bakeNewCake(new CakeInfo(topping1, List.of(layer1, layer2)));\n    cakeBakingService.bakeNewCake(new CakeInfo(topping2, Collections.singletonList(layer3)));\n\n    final var allCakes = cakeBakingService.getAllCakes();\n    assertNotNull(allCakes);\n    assertEquals(2, allCakes.size());\n    for (final var cakeInfo : allCakes) {\n      assertNotNull(cakeInfo.id);\n      assertNotNull(cakeInfo.cakeToppingInfo);\n      assertNotNull(cakeInfo.cakeLayerInfos);\n      assertNotNull(cakeInfo.toString());\n      assertFalse(cakeInfo.cakeLayerInfos.isEmpty());\n      assertTrue(cakeInfo.calculateTotalCalories() > 0);\n    }\n  }\n\n  @Test\n  void testBakeCakeMissingTopping() {\n    final var layer1 = new CakeLayerInfo(\"Layer1\", 1000);\n    final var layer2 = new CakeLayerInfo(\"Layer2\", 2000);\n    cakeBakingService.saveNewLayer(layer1);\n    cakeBakingService.saveNewLayer(layer2);\n\n    final var missingTopping = new CakeToppingInfo(\"Topping1\", 1000);\n    assertThrows(\n        CakeBakingException.class,\n        () -> cakeBakingService.bakeNewCake(new CakeInfo(missingTopping, List.of(layer1, layer2))));\n  }\n\n  @Test\n  void testBakeCakeMissingLayer() {\n    final var initialCakes = cakeBakingService.getAllCakes();\n    assertNotNull(initialCakes);\n    assertTrue(initialCakes.isEmpty());\n\n    final var topping1 = new CakeToppingInfo(\"Topping1\", 1000);\n    cakeBakingService.saveNewTopping(topping1);\n\n    final var layer1 = new CakeLayerInfo(\"Layer1\", 1000);\n    cakeBakingService.saveNewLayer(layer1);\n\n    final var missingLayer = new CakeLayerInfo(\"Layer2\", 2000);\n    assertThrows(\n        CakeBakingException.class,\n        () -> cakeBakingService.bakeNewCake(new CakeInfo(topping1, List.of(layer1, missingLayer))));\n  }\n\n  @Test\n  void testBakeCakesUsedLayer() throws CakeBakingException {\n    final var initialCakes = cakeBakingService.getAllCakes();\n    assertNotNull(initialCakes);\n    assertTrue(initialCakes.isEmpty());\n\n    final var topping1 = new CakeToppingInfo(\"Topping1\", 1000);\n    final var topping2 = new CakeToppingInfo(\"Topping2\", 2000);\n    cakeBakingService.saveNewTopping(topping1);\n    cakeBakingService.saveNewTopping(topping2);\n\n    final var layer1 = new CakeLayerInfo(\"Layer1\", 1000);\n    final var layer2 = new CakeLayerInfo(\"Layer2\", 2000);\n    cakeBakingService.saveNewLayer(layer1);\n    cakeBakingService.saveNewLayer(layer2);\n\n    cakeBakingService.bakeNewCake(new CakeInfo(topping1, List.of(layer1, layer2)));\n    assertThrows(\n        CakeBakingException.class,\n        () ->\n            cakeBakingService.bakeNewCake(\n                new CakeInfo(topping2, Collections.singletonList(layer2))));\n  }\n}\n"
  },
  {
    "path": "layered-architecture/src/test/java/com/iluwatar/layers/view/CakeViewImplTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.layers.view;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport dto.CakeInfo;\nimport dto.CakeLayerInfo;\nimport dto.CakeToppingInfo;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\nimport service.CakeBakingService;\nimport view.CakeViewImpl;\n\n/**\n * This class contains unit tests for the CakeViewImpl class. It tests the functionality of\n * rendering cakes using the CakeViewImpl class. It also tests the logging functionality of the\n * CakeViewImpl class.\n */\nclass CakeViewImplTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(CakeViewImpl.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /** Verify if the cake view renders the expected result. */\n  @Test\n  void testRender() {\n\n    final var layers =\n        List.of(\n            new CakeLayerInfo(\"layer1\", 1000),\n            new CakeLayerInfo(\"layer2\", 2000),\n            new CakeLayerInfo(\"layer3\", 3000));\n\n    final var cake = new CakeInfo(new CakeToppingInfo(\"topping\", 1000), layers);\n    final var cakes = List.of(cake);\n\n    final var bakingService = mock(CakeBakingService.class);\n    when(bakingService.getAllCakes()).thenReturn(cakes);\n\n    final var cakeView = new CakeViewImpl(bakingService);\n\n    assertEquals(0, appender.getLogSize());\n\n    cakeView.render();\n    assertEquals(cake.toString(), appender.getLastMessage());\n  }\n\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender(Class clazz) {\n      ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public String getLastMessage() {\n      return log.get(log.size() - 1).getFormattedMessage();\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n  }\n}\n"
  },
  {
    "path": "lazy-loading/README.md",
    "content": "---\ntitle: \"Lazy Loading Pattern in Java: Enhancing Performance with On-Demand Object Initialization\"\nshortTitle: Lazy Loading\ndescription: \"Learn how to implement the Lazy Loading design pattern in Java to optimize memory usage and improve application startup times. Discover practical examples, benefits, and best practices for efficient resource management.\"\ncategory: Performance optimization\nlanguage: en\ntag:\n  - Instantiation\n  - Memory management\n  - Optimization\n  - Performance\n  - Persistence\n  - Resource management\n---\n\n## Also known as\n\n* Lazy Initialization\n\n## Intent of Lazy Loading Design Pattern\n\nThe Lazy Loading design pattern in Java defers object initialization until the object is actually needed, minimizing memory usage and reducing startup times. This technique is crucial for optimizing Java application performance.\n\n## Detailed Explanation of Lazy Loading Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy for the Lazy Loading pattern in Java is using lights in a smart home. Instead of switching all lights on at once when someone enters the house, motion sensors detect and turn on lights only in rooms being used. This mirrors how Java developers can optimize performance by delaying object creation.\n\nIn plain words\n\n> The Lazy Loading pattern defers the creation of an object or resource until it's actually needed, optimizing memory usage and improving performance.\n\nWikipedia says\n\n> Lazy loading (also known as asynchronous loading) is a technique used in computer programming, especially web design and web development, to defer initialization of an object until it is needed. It can contribute to efficiency in the program's operation if properly and appropriately used. This makes it ideal in use cases where network content is accessed and initialization times are to be kept at a minimum, such as in the case of web pages. For example, deferring loading of images on a web page until they are needed for viewing can make the initial display of the web page faster. The opposite of lazy loading is eager loading.\n\nSequence diagram\n\n![Lazy Loading Sequence Diagram](./etc/lazy-loading-sequence-diagram.png)\n\n## Programmatic Example of Lazy Loading Pattern in Java\n\nThe Lazy Loading design pattern is a performance optimization technique that delays the initialization of an object or a costly computation until it's absolutely necessary. This pattern can significantly improve the performance of your application by avoiding unnecessary computation and reducing memory usage.\n\nIn the provided code, we can see an example of the Lazy Loading pattern in the `App`, `HolderNaive`, `HolderThreadSafe`, and `Java8Holder` classes.\n\nThe `App` class is the entry point of the application. It creates instances of `HolderNaive`, `HolderThreadSafe`, and `Java8Holder`, and retrieves the `Heavy` object from them.\n\n```java\n@Slf4j\npublic class App {\n\n  public static void main(String[] args) {\n\n    var holderNaive = new HolderNaive();\n    var heavy = holderNaive.getHeavy();\n    LOGGER.info(\"heavy={}\", heavy);\n\n    var holderThreadSafe = new HolderThreadSafe();\n    var another = holderThreadSafe.getHeavy();\n    LOGGER.info(\"another={}\", another);\n\n    var java8Holder = new Java8Holder();\n    var next = java8Holder.getHeavy();\n    LOGGER.info(\"next={}\", next);\n  }\n}\n```\n\nThe `HolderNaive`, `HolderThreadSafe`, and `Java8Holder` classes are implementations of the Lazy Loading pattern with increasing sophistication.\n\nThe `HolderNaive` class is a simple, non-thread-safe implementation of the pattern.\n\n```java\npublic class HolderNaive {\n  private Heavy heavy;\n\n  public HolderNaive() {\n      LOGGER.info(\"HolderNaive created\");\n  }\n\n  public Heavy getHeavy() {\n    if (heavy == null) {\n      heavy = new Heavy();\n    }\n    return heavy;\n  }\n}\n```\n\nThe `HolderThreadSafe` class is a thread-safe implementation of the pattern, but with heavy synchronization on each access.\n\n```java\npublic class HolderThreadSafe {\n  private Heavy heavy;\n\n  public synchronized Heavy getHeavy() {\n    if (heavy == null) {\n      heavy = new Heavy();\n    }\n    return heavy;\n  }\n}\n```\n\nThe `Java8Holder` class is the most efficient implementation of the pattern, utilizing Java 8 features.\n\n```java\npublic class Java8Holder {\n\n  private Supplier<Heavy> heavy = this::createAndCacheHeavy;\n\n  public Java8Holder() {\n      LOGGER.info(\"Java8Holder created\");\n  }\n\n  public Heavy getHeavy() {\n    return heavy.get();\n  }\n\n  private synchronized Heavy createAndCacheHeavy() {\n    class HeavyFactory implements Supplier<Heavy> {\n      private final Heavy heavyInstance = new Heavy();\n\n      public Heavy get() {\n        return heavyInstance;\n      }\n    }\n\n    if (!(heavy instanceof HeavyFactory)) {\n      heavy = new HeavyFactory();\n    }\n\n    return heavy.get();\n  }\n}\n```\n\nIn this example, the `App` class retrieves a `Heavy` object from `HolderNaive`, `HolderThreadSafe`, and `Java8Holder`. These classes delay the creation of the `Heavy` object until it's actually needed, demonstrating the Lazy Loading pattern.\n\n## When to Use the Lazy Loading Pattern in Java\n\nUse Lazy Loading when:\n\n* An object is resource-intensive to create and might not always be used.\n* You need to delay object creation to optimize memory usage or improve startup times.\n* Loading data or resources should happen just-in-time rather than at application startup.\n\n## Real-World Applications of Lazy Loading Pattern in Java\n\n* Hibernate (Java ORM Framework): Delays loading of related objects until they are accessed, leveraging the Lazy Loading pattern to optimize Java application performance.\n* JPA annotations @OneToOne, @OneToMany, @ManyToOne, @ManyToMany and fetch = FetchType.LAZY\n* Spring Framework (Dependency Injection): Loads beans only when required, reducing application startup time.\n\n## Benefits and Trade-offs of Lazy Loading Pattern\n\nBenefits:\n\n* Reduces memory usage by initializing objects only when required.\n* Improves application startup performance by postponing expensive object creation.\n\nTrade-offs:\n\n* Complexity in implementation if objects are interdependent.\n* Risk of latency spikes if initialization occurs at an unexpected point.\n\n## Related Java Design Patterns\n\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): Can act as a placeholder for lazy-loaded objects, deferring their actual loading until necessary.\n* Virtual Proxy: Specific type of Proxy that handles object creation on demand.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Often combined with Lazy Loading to ensure only one instance of an object is created and loaded lazily.\n\n## References and Credits\n\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Java Performance: The Definitive Guide: Getting the Most Out of Your Code](https://amzn.to/3Wu5neF)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "lazy-loading/etc/lazy-loading.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.HolderNaive\" project=\"lazy-loading\" \n    file=\"/lazy-loading/src/main/java/com/iluwatar/HolderNaive.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"126\" x=\"206\" y=\"297\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.Heavy\" project=\"lazy-loading\" \n    file=\"/lazy-loading/src/main/java/com/iluwatar/Heavy.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"104\" x=\"289\" y=\"479\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.Java8Holder\" project=\"lazy-loading\" \n    file=\"/lazy-loading/src/main/java/com/iluwatar/Java8Holder.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"142\" width=\"204\" x=\"567\" y=\"297\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.HolderThreadSafe\" project=\"lazy-loading\" \n    file=\"/lazy-loading/src/main/java/com/iluwatar/HolderThreadSafe.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"155\" x=\"372\" y=\"297\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"5\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"6\" name=\"heavy\"/>      \n      <multiplicity id=\"7\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <dependency id=\"8\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </dependency>  \n  <association id=\"9\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"10\" name=\"heavy\"/>      \n      <multiplicity id=\"11\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "lazy-loading/etc/lazy-loading.urm.puml",
    "content": "@startuml\npackage com.iluwatar.lazy.loading {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Heavy {\n    - LOGGER : Logger {static}\n    + Heavy()\n  }\n  class HolderNaive {\n    - LOGGER : Logger {static}\n    - heavy : Heavy\n    + HolderNaive()\n    + getHeavy() : Heavy\n  }\n  class HolderThreadSafe {\n    - LOGGER : Logger {static}\n    - heavy : Heavy\n    + HolderThreadSafe()\n    + getHeavy() : Heavy\n  }\n  class Java8Holder {\n    - LOGGER : Logger {static}\n    - heavy : Supplier<Heavy>\n    + Java8Holder()\n    - createAndCacheHeavy() : Heavy\n    + getHeavy() : Heavy\n  }\n  ~class HeavyFactory {\n    - heavyInstance : Heavy\n    ~ HeavyFactory()\n    + get() : Heavy\n  }\n}\nHolderThreadSafe -->  \"-heavy\" Heavy\nHolderNaive -->  \"-heavy\" Heavy\nHeavyFactory -->  \"-heavyInstance\" Heavy\n@enduml"
  },
  {
    "path": "lazy-loading/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>lazy-loading</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.lazy.loading.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "lazy-loading/src/main/java/com/iluwatar/lazy/loading/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lazy.loading;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Lazy loading idiom defers object creation until needed.\n *\n * <p>This example shows different implementations of the pattern with increasing sophistication.\n *\n * <p>Additional information and lazy loading flavours are described in\n * http://martinfowler.com/eaaCatalog/lazyLoad.html\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    // Simple lazy loader - not thread safe\n    var holderNaive = new HolderNaive();\n    var heavy = holderNaive.getHeavy();\n    LOGGER.info(\"heavy={}\", heavy);\n\n    // Thread safe lazy loader, but with heavy synchronization on each access\n    var holderThreadSafe = new HolderThreadSafe();\n    var another = holderThreadSafe.getHeavy();\n    LOGGER.info(\"another={}\", another);\n\n    // The most efficient lazy loader utilizing Java 8 features\n    var java8Holder = new Java8Holder();\n    var next = java8Holder.getHeavy();\n    LOGGER.info(\"next={}\", next);\n  }\n}\n"
  },
  {
    "path": "lazy-loading/src/main/java/com/iluwatar/lazy/loading/Heavy.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lazy.loading;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Heavy objects are expensive to create. */\n@Slf4j\npublic class Heavy {\n\n  /** Constructor. */\n  public Heavy() {\n    LOGGER.info(\"Creating Heavy ...\");\n    try {\n      Thread.sleep(1000);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Exception caught.\", e);\n    }\n    LOGGER.info(\"... Heavy created\");\n  }\n}\n"
  },
  {
    "path": "lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderNaive.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lazy.loading;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Simple implementation of the lazy loading idiom. However, this is not thread safe. */\n@Slf4j\npublic class HolderNaive {\n\n  private Heavy heavy;\n\n  /** Constructor. */\n  public HolderNaive() {\n    LOGGER.info(\"HolderNaive created\");\n  }\n\n  /** Get heavy object. */\n  public Heavy getHeavy() {\n    if (heavy == null) {\n      heavy = new Heavy();\n    }\n    return heavy;\n  }\n}\n"
  },
  {
    "path": "lazy-loading/src/main/java/com/iluwatar/lazy/loading/HolderThreadSafe.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lazy.loading;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Same as HolderNaive but with added synchronization. This implementation is thread safe, but each\n * {@link #getHeavy()} call costs additional synchronization overhead.\n */\n@Slf4j\npublic class HolderThreadSafe {\n\n  private Heavy heavy;\n\n  /** Constructor. */\n  public HolderThreadSafe() {\n    LOGGER.info(\"HolderThreadSafe created\");\n  }\n\n  /** Get heavy object. */\n  public synchronized Heavy getHeavy() {\n    if (heavy == null) {\n      heavy = new Heavy();\n    }\n    return heavy;\n  }\n}\n"
  },
  {
    "path": "lazy-loading/src/main/java/com/iluwatar/lazy/loading/Java8Holder.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lazy.loading;\n\nimport java.util.function.Supplier;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This lazy loader is thread safe and more efficient than {@link HolderThreadSafe}. It utilizes\n * Java 8 functional interface {@link Supplier} as {@link Heavy} factory.\n */\n@Slf4j\npublic class Java8Holder {\n\n  private Supplier<Heavy> heavy = this::createAndCacheHeavy;\n\n  public Java8Holder() {\n    LOGGER.info(\"Java8Holder created\");\n  }\n\n  public Heavy getHeavy() {\n    return heavy.get();\n  }\n\n  private synchronized Heavy createAndCacheHeavy() {\n    class HeavyFactory implements Supplier<Heavy> {\n      private final Heavy heavyInstance = new Heavy();\n\n      @Override\n      public Heavy get() {\n        return heavyInstance;\n      }\n    }\n\n    if (!(heavy instanceof HeavyFactory)) {\n      heavy = new HeavyFactory();\n    }\n\n    return heavy.get();\n  }\n}\n"
  },
  {
    "path": "lazy-loading/src/test/java/com/iluwatar/lazy/loading/AbstractHolderTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lazy.loading;\n\nimport static java.time.Duration.ofMillis;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertSame;\nimport static org.junit.jupiter.api.Assertions.assertTimeout;\n\nimport org.junit.jupiter.api.Test;\n\n/** AbstractHolderTest */\npublic abstract class AbstractHolderTest {\n\n  /**\n   * Get the internal state of the holder value\n   *\n   * @return The internal value\n   */\n  abstract Heavy getInternalHeavyValue() throws Exception;\n\n  /**\n   * Request a lazy loaded {@link Heavy} object from the holder.\n   *\n   * @return The lazy loaded {@link Heavy} object\n   */\n  abstract Heavy getHeavy();\n\n  /**\n   * This test shows that the heavy field is not instantiated until the method getHeavy is called\n   */\n  @Test\n  void testGetHeavy() {\n    assertTimeout(\n        ofMillis(3000),\n        () -> {\n          assertNull(getInternalHeavyValue());\n          assertNotNull(getHeavy());\n          assertNotNull(getInternalHeavyValue());\n          assertSame(getHeavy(), getInternalHeavyValue());\n        });\n  }\n}\n"
  },
  {
    "path": "lazy-loading/src/test/java/com/iluwatar/lazy/loading/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lazy.loading;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderNaiveTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lazy.loading;\n\n/** HolderNaiveTest */\nclass HolderNaiveTest extends AbstractHolderTest {\n\n  private final HolderNaive holder = new HolderNaive();\n\n  @Override\n  Heavy getInternalHeavyValue() throws Exception {\n    final var holderField = HolderNaive.class.getDeclaredField(\"heavy\");\n    holderField.setAccessible(true);\n    return (Heavy) holderField.get(this.holder);\n  }\n\n  @Override\n  Heavy getHeavy() {\n    return holder.getHeavy();\n  }\n}\n"
  },
  {
    "path": "lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderThreadSafeTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lazy.loading;\n\n/** HolderThreadSafeTest */\nclass HolderThreadSafeTest extends AbstractHolderTest {\n\n  private final HolderThreadSafe holder = new HolderThreadSafe();\n\n  @Override\n  Heavy getInternalHeavyValue() throws Exception {\n    final var holderField = HolderThreadSafe.class.getDeclaredField(\"heavy\");\n    holderField.setAccessible(true);\n    return (Heavy) holderField.get(this.holder);\n  }\n\n  @Override\n  Heavy getHeavy() {\n    return this.holder.getHeavy();\n  }\n}\n"
  },
  {
    "path": "lazy-loading/src/test/java/com/iluwatar/lazy/loading/Java8HolderTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lazy.loading;\n\nimport java.util.function.Supplier;\n\n/** Java8HolderTest */\nclass Java8HolderTest extends AbstractHolderTest {\n\n  private final Java8Holder holder = new Java8Holder();\n\n  @Override\n  Heavy getInternalHeavyValue() throws Exception {\n    final var holderField = Java8Holder.class.getDeclaredField(\"heavy\");\n    holderField.setAccessible(true);\n\n    final var supplier = (Supplier<Heavy>) holderField.get(this.holder);\n    final var supplierClass = supplier.getClass();\n\n    // This is a little fishy, but I don't know another way to test this:\n    // The lazy holder is at first a lambda, but gets replaced with a new supplier after loading ...\n    if (supplierClass.isLocalClass()) {\n      final var instanceField = supplierClass.getDeclaredField(\"heavyInstance\");\n      instanceField.setAccessible(true);\n      return (Heavy) instanceField.get(supplier);\n    } else {\n      return null;\n    }\n  }\n\n  @Override\n  Heavy getHeavy() {\n    return holder.getHeavy();\n  }\n}\n"
  },
  {
    "path": "leader-election/README.md",
    "content": "---\ntitle: \"Leader Election Pattern in Java: Mastering Node Coordination and Consensus\"\nshortTitle: Leader Election\ndescription: \"Learn how the Leader Election design pattern helps Java applications maintain consistency, fault tolerance, and scalability in distributed systems. Discover examples, use cases, and implementation details.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - API design\n  - Cloud distributed\n  - Fault tolerance\n  - Scalability\n  - Synchronization\n---\n\n## Also known as\n\n* Coordinator Election\n* Master Election\n\n## Intent of Leader Election Design Pattern\n\nThe Leader Election design pattern is crucial for enabling a system to elect a leader from a group of nodes, ensuring the leader is consistently recognized and able to coordinate tasks while other nodes remain followers. This pattern is fundamental in distributed systems, particularly for achieving fault tolerance and high availability.\n\n## Detailed Explanation of Leader Election Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy to the Leader Election pattern is the election of a team captain in sports. All team members (nodes) participate in the election process, following a set of agreed-upon rules (protocol). Once a captain (leader) is chosen, they assume responsibility for coordinating strategies, giving directions, and representing the team in discussions. If the captain is injured or unavailable, the team holds a new election or appoints a vice-captain (failover mechanism) to ensure that leadership and direction are maintained consistently.\n\nIn plain words\n\n> The leader election pattern is a design approach that enables a distributed system to select one node as the coordinator or leader to manage tasks and maintain order, while other nodes operate as followers.\n\nWikipedia says\n\n> In distributed computing, leader election is the process of designating a single process as the organizer of some task distributed among several computers (nodes). Before the task has begun, all network nodes are either unaware which node will serve as the \"leader\" (or coordinator) of the task, or unable to communicate with the current coordinator. After a leader election algorithm has been run, however, each node throughout the network recognizes a particular, unique node as the task leader.\n\nSequence diagram\n\n![Leader Election Sequence Diagram](./etc/leader-election-sequence-diagram.png)\n\n## Programmatic Example of Leader Election Pattern in Java\n\nThe Leader Election pattern is a design approach that enables a distributed system to select one node as the coordinator or leader to manage tasks and maintain order, while other nodes operate as followers. This pattern is particularly useful in distributed systems where one node needs to act as a central coordinator for a specific function or decision-making process.\n\nIn the provided code, we have an `AbstractMessageManager` class and `AbstractInstance` class. The `AbstractMessageManager` class is responsible for managing messages between instances and finding the next instance (potential leader) based on certain conditions. The `AbstractInstance` class represents a node in the distributed system.\n\nLet's break down the code and explain how it works:\n\n```java\npublic abstract class AbstractMessageManager implements MessageManager {\n\n  protected Map<Integer, Instance> instanceMap;\n\n  public AbstractMessageManager(Map<Integer, Instance> instanceMap) {\n    this.instanceMap = instanceMap;\n  }\n\n  protected Instance findNextInstance(int currentId) {\n    // Implementation details...\n  }\n\n}\n```\n\nThe `AbstractMessageManager` class manages the instances in the system. It contains a map of instances, where the key is the instance ID and the value is the instance itself. The `findNextInstance` method is used to find the next instance with the smallest ID that is alive. This method can be used in the leader election process to determine the next leader if the current leader fails.\n\n```java\npublic abstract class AbstractInstance implements Instance {\n\n  protected int id;\n  protected boolean alive;\n  protected MessageManager messageManager;\n\n  public AbstractInstance(MessageManager messageManager, int id) {\n    this.messageManager = messageManager;\n    this.id = id;\n    this.alive = true;\n  }\n\n  public boolean isAlive() {\n    return alive;\n  }\n\n  public void setAlive(boolean alive) {\n    this.alive = alive;\n  }\n\n  public void onMessage(Message message) {\n    // Implementation details...\n  }\n\n}\n```\n\nThe `AbstractInstance` class represents a node in the distributed system. Each instance can check if it's alive, set its health status, and consume messages from other instances.\n\nNow, let's look at the `BullyApp` and `RingApp` classes, which implement two different leader election algorithms:\n\n```java\npublic class BullyApp {\n\n  public static void main(String[] args) {\n\n    Map<Integer, Instance> instanceMap = new HashMap<>();\n    var messageManager = new BullyMessageManager(instanceMap);\n\n    var instance1 = new BullyInstance(messageManager, 1, 1);\n    // ... more instances ...\n\n    instanceMap.put(1, instance1);\n    // ... more instances ...\n\n    instance1.setAlive(false);\n  }\n}\n```\n\nThe `BullyApp` class implements the Bully algorithm for leader election. In this algorithm, when a node notices the leader is down, it starts an election by sending an election message to all nodes with higher IDs. If it doesn't receive a response, it declares itself the leader and sends a victory message to all nodes with lower IDs.\n\n```java\npublic class RingApp {\n\n  public static void main(String[] args) {\n\n    Map<Integer, Instance> instanceMap = new HashMap<>();\n    var messageManager = new RingMessageManager(instanceMap);\n\n    var instance1 = new RingInstance(messageManager, 1, 1);\n    // ... more instances ...\n\n    instanceMap.put(1, instance1);\n    // ... more instances ...\n\n    instance1.setAlive(false);\n  }\n}\n```\n\nThe `RingApp` class implements the Ring algorithm for leader election. In this algorithm, each node sends an election message to its neighbor in a logical ring topology. When a node receives an election message, it passes it on if the ID in the message is higher than its own. The process continues until the message has made a full circle, at which point the node with the highest ID becomes the leader.\n\nThese examples demonstrate how the Leader Election pattern can be implemented in different ways to suit the specific requirements of a distributed system.\n\n## When to Use the Leader Election Pattern in Java\n\nUse the Leader Election pattern in Java applications where:\n\n* A distributed system needs one node to act as the central coordinator for a specific function or decision-making process.\n* High availability is essential, and the leader should be replaceable in case of failure.\n* Coordination is required across different nodes in a cluster, particularly in cloud environments.\n\n## Real-World Applications of Leader Election Pattern in Java\n\n* Apache ZooKeeper: Provides leader election for distributed services.\n* Kubernetes: Elects a leader pod to manage stateful workloads.\n* Hazelcast: Distributed data grid uses leader election for cluster management.\n\n## Benefits and Trade-offs of Leader Election Pattern\n\nBenefits:\n\n* Consistency: Ensures a single, consistent leader handles coordination tasks.\n* Fault Tolerance: Allows for leader replacement if the current leader fails.\n* Scalability: Works effectively in large, distributed systems where multiple nodes are present.\n\nTrade-offs:\n\n* Complexity: Requires careful implementation to handle network partitions and latency.\n* Overhead: Election processes may introduce performance overhead.\n* Single Point of Failure: Even with redundancy, the leader can become a bottleneck if not carefully designed.\n\n## Related Java Design Patterns\n\n* [Observer](https://java-design-patterns.com/patterns/observer/): Followers can observe changes from the leader to stay updated.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): The leader functions as a single instance, acting as a unique decision-maker.\n* [State](https://java-design-patterns.com/patterns/state/): Helps in managing state transitions, particularly in switching leadership roles.\n\n## References and Credits\n\n* [Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems](https://amzn.to/3y6yv1z)\n* [Distributed Systems: Principles and Paradigms](https://amzn.to/3UN2vbH)\n* [Site Reliability Engineering: How Google Runs Production Systems](https://amzn.to/4brjBRI)\n* [Leader Election pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/patterns/leader-election)\n"
  },
  {
    "path": "leader-election/etc/leader-election.urm.puml",
    "content": "@startuml\npackage com.iluwatar.leaderelection.ring {\n  class RingApp {\n    + RingApp()\n    + main(args : String[]) {static}\n  }\n  class RingInstance {\n    - LOGGER : Logger {static}\n    + RingInstance(messageManager : MessageManager, localId : int, leaderId : int)\n    # handleElectionInvokeMessage()\n    # handleElectionMessage(message : Message)\n    # handleHeartbeatInvokeMessage()\n    # handleHeartbeatMessage(message : Message)\n    # handleLeaderInvokeMessage()\n    # handleLeaderMessage(message : Message)\n  }\n  class RingMessageManager {\n    + RingMessageManager(instanceMap : Map<Integer, Instance>)\n    + sendElectionMessage(currentId : int, content : String) : boolean\n    + sendHeartbeatInvokeMessage(currentId : int)\n    + sendHeartbeatMessage(leaderId : int) : boolean\n    + sendLeaderMessage(currentId : int, leaderId : int) : boolean\n  }\n}\npackage com.iluwatar.leaderelection {\n  abstract class AbstractInstance {\n    # HEARTBEAT_INTERVAL : int {static}\n    - LOGGER : Logger {static}\n    # alive : boolean\n    # leaderId : int\n    # localId : int\n    # messageManager : MessageManager\n    # messageQueue : Queue<Message>\n    + AbstractInstance(messageManager : MessageManager, localId : int, leaderId : int)\n    # handleElectionInvokeMessage() {abstract}\n    # handleElectionMessage(Message) {abstract}\n    # handleHeartbeatInvokeMessage() {abstract}\n    # handleHeartbeatMessage(Message) {abstract}\n    # handleLeaderInvokeMessage() {abstract}\n    # handleLeaderMessage(Message) {abstract}\n    + isAlive() : boolean\n    + onMessage(message : Message)\n    - processMessage(message : Message)\n    + run()\n    + setAlive(alive : boolean)\n  }\n  abstract class AbstractMessageManager {\n    # instanceMap : Map<Integer, Instance>\n    + AbstractMessageManager(instanceMap : Map<Integer, Instance>)\n    # findNextInstance(currentId : int) : Instance\n  }\n  interface Instance {\n    + isAlive() : boolean {abstract}\n    + onMessage(Message) {abstract}\n    + setAlive(boolean) {abstract}\n  }\n  class Message {\n    - content : String\n    - type : MessageType\n    + Message()\n    + Message(type : MessageType, content : String)\n    + equals(o : Object) : boolean\n    + getContent() : String\n    + getType() : MessageType\n    + hashCode() : int\n    + setContent(content : String)\n    + setType(type : MessageType)\n  }\n  interface MessageManager {\n    + sendElectionMessage(int, String) : boolean {abstract}\n    + sendHeartbeatInvokeMessage(int) {abstract}\n    + sendHeartbeatMessage(int) : boolean {abstract}\n    + sendLeaderMessage(int, int) : boolean {abstract}\n  }\n  enum MessageType {\n    + ELECTION {static}\n    + ELECTION_INVOKE {static}\n    + HEARTBEAT {static}\n    + HEARTBEAT_INVOKE {static}\n    + LEADER {static}\n    + LEADER_INVOKE {static}\n    + valueOf(name : String) : MessageType {static}\n    + values() : MessageType[] {static}\n  }\n}\npackage com.iluwatar.leaderelection.bully {\n  class BullyApp {\n    + BullyApp()\n    + main(args : String[]) {static}\n  }\n  class BullyInstance {\n    - LOGGER : Logger {static}\n    + BullyInstance(messageManager : MessageManager, localId : int, leaderId : int)\n    # handleElectionInvokeMessage()\n    # handleElectionMessage(message : Message)\n    # handleHeartbeatInvokeMessage()\n    # handleHeartbeatMessage(message : Message)\n    # handleLeaderInvokeMessage()\n    # handleLeaderMessage(message : Message)\n    - isLeader() : boolean\n  }\n  class BullyMessageManager {\n    + BullyMessageManager(instanceMap : Map<Integer, Instance>)\n    - findElectionCandidateInstanceList(currentId : int) : List<Integer>\n    + sendElectionMessage(currentId : int, content : String) : boolean\n    + sendHeartbeatInvokeMessage(currentId : int)\n    + sendHeartbeatMessage(leaderId : int) : boolean\n    + sendLeaderMessage(currentId : int, leaderId : int) : boolean\n  }\n}\nAbstractInstance -->  \"-messageQueue\" Message\nMessage -->  \"-type\" MessageType\nAbstractInstance -->  \"-messageManager\" MessageManager\nAbstractInstance ..|> Instance \nAbstractMessageManager ..|> MessageManager \nBullyInstance --|> AbstractInstance \nBullyMessageManager --|> AbstractMessageManager \nRingInstance --|> AbstractInstance \nRingMessageManager --|> AbstractMessageManager \n@enduml"
  },
  {
    "path": "leader-election/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>leader-election</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <id>bully</id>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.leaderelection.bully.BullyApp</mainClass>\n                </manifest>\n              </archive>\n              <finalName>${project.artifactId}-Bully</finalName>\n            </configuration>\n          </execution>\n          <execution>\n            <id>ring</id>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.leaderelection.ring.RingApp</mainClass>\n                </manifest>\n              </archive>\n              <finalName>${project.artifactId}-Ring</finalName>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "leader-election/src/main/java/com/iluwatar/leaderelection/AbstractInstance.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection;\n\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Abstract class of all the instance implementation classes. */\n@Slf4j\npublic abstract class AbstractInstance implements Instance, Runnable {\n\n  protected static final int HEARTBEAT_INTERVAL = 5000;\n  private static final String INSTANCE = \"Instance \";\n\n  protected MessageManager messageManager;\n  protected Queue<Message> messageQueue;\n  protected final int localId;\n  protected int leaderId;\n  protected boolean alive;\n\n  /** Constructor of BullyInstance. */\n  public AbstractInstance(MessageManager messageManager, int localId, int leaderId) {\n    this.messageManager = messageManager;\n    this.messageQueue = new ConcurrentLinkedQueue<>();\n    this.localId = localId;\n    this.leaderId = leaderId;\n    this.alive = true;\n  }\n\n  /** The instance will execute the message in its message queue periodically once it is alive. */\n  @Override\n  @SuppressWarnings(\"squid:S2189\")\n  public void run() {\n    while (true) {\n      if (!this.messageQueue.isEmpty()) {\n        this.processMessage(this.messageQueue.remove());\n      }\n    }\n  }\n\n  /**\n   * Once messages are sent to the certain instance, it will firstly be added to the queue and wait\n   * to be executed.\n   *\n   * @param message Message sent by other instances\n   */\n  @Override\n  public void onMessage(Message message) {\n    messageQueue.offer(message);\n  }\n\n  /**\n   * Check if the instance is alive or not.\n   *\n   * @return {@code true} if the instance is alive.\n   */\n  @Override\n  public boolean isAlive() {\n    return alive;\n  }\n\n  /**\n   * Set the health status of the certain instance.\n   *\n   * @param alive {@code true} for alive.\n   */\n  @Override\n  public void setAlive(boolean alive) {\n    this.alive = alive;\n  }\n\n  /**\n   * Process the message according to its type.\n   *\n   * @param message Message polled from queue.\n   */\n  private void processMessage(Message message) {\n    switch (message.getType()) {\n      case ELECTION -> {\n        LOGGER.info(INSTANCE + localId + \" - Election Message handling...\");\n        handleElectionMessage(message);\n      }\n      case LEADER -> {\n        LOGGER.info(INSTANCE + localId + \" - Leader Message handling...\");\n        handleLeaderMessage(message);\n      }\n      case HEARTBEAT -> {\n        LOGGER.info(INSTANCE + localId + \" - Heartbeat Message handling...\");\n        handleHeartbeatMessage(message);\n      }\n      case ELECTION_INVOKE -> {\n        LOGGER.info(INSTANCE + localId + \" - Election Invoke Message handling...\");\n        handleElectionInvokeMessage();\n      }\n      case LEADER_INVOKE -> {\n        LOGGER.info(INSTANCE + localId + \" - Leader Invoke Message handling...\");\n        handleLeaderInvokeMessage();\n      }\n      case HEARTBEAT_INVOKE -> {\n        LOGGER.info(INSTANCE + localId + \" - Heartbeat Invoke Message handling...\");\n        handleHeartbeatInvokeMessage();\n      }\n      default -> {}\n    }\n  }\n\n  /**\n   * Abstract methods to handle different types of message. These methods need to be implemented in\n   * concrete instance class to implement corresponding leader-selection pattern.\n   */\n  protected abstract void handleElectionMessage(Message message);\n\n  protected abstract void handleElectionInvokeMessage();\n\n  protected abstract void handleLeaderMessage(Message message);\n\n  protected abstract void handleLeaderInvokeMessage();\n\n  protected abstract void handleHeartbeatMessage(Message message);\n\n  protected abstract void handleHeartbeatInvokeMessage();\n}\n"
  },
  {
    "path": "leader-election/src/main/java/com/iluwatar/leaderelection/AbstractMessageManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection;\n\nimport java.util.Map;\n\n/** Abstract class of all the message manager classes. */\npublic abstract class AbstractMessageManager implements MessageManager {\n\n  /** Contain all the instances in the system. Key is its ID, and value is the instance itself. */\n  protected Map<Integer, Instance> instanceMap;\n\n  /** Constructor of AbstractMessageManager. */\n  public AbstractMessageManager(Map<Integer, Instance> instanceMap) {\n    this.instanceMap = instanceMap;\n  }\n\n  /**\n   * Find the next instance with the smallest ID.\n   *\n   * @return The next instance.\n   */\n  protected Instance findNextInstance(int currentId) {\n    Instance result = null;\n    var candidateList =\n        instanceMap.keySet().stream()\n            .filter((i) -> i > currentId && instanceMap.get(i).isAlive())\n            .sorted()\n            .toList();\n    if (candidateList.isEmpty()) {\n      var index =\n          instanceMap.keySet().stream()\n              .filter((i) -> instanceMap.get(i).isAlive())\n              .sorted()\n              .toList()\n              .get(0);\n      result = instanceMap.get(index);\n    } else {\n      var index = candidateList.get(0);\n      result = instanceMap.get(index);\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "leader-election/src/main/java/com/iluwatar/leaderelection/Instance.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection;\n\n/** Instance interface. */\npublic interface Instance {\n\n  /**\n   * Check if the instance is alive or not.\n   *\n   * @return {@code true} if the instance is alive.\n   */\n  boolean isAlive();\n\n  /**\n   * Set the health status of the certain instance.\n   *\n   * @param alive {@code true} for alive.\n   */\n  void setAlive(boolean alive);\n\n  /**\n   * Consume messages from other instances.\n   *\n   * @param message Message sent by other instances\n   */\n  void onMessage(Message message);\n}\n"
  },
  {
    "path": "leader-election/src/main/java/com/iluwatar/leaderelection/Message.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection;\n\nimport lombok.AllArgsConstructor;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n/** Message used to transport data between instances. */\n@Setter\n@Getter\n@EqualsAndHashCode\n@AllArgsConstructor\n@NoArgsConstructor\npublic class Message {\n\n  private MessageType type;\n  private String content;\n}\n"
  },
  {
    "path": "leader-election/src/main/java/com/iluwatar/leaderelection/MessageManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection;\n\n/** MessageManager interface. */\npublic interface MessageManager {\n\n  /**\n   * Send heartbeat message to leader instance to check whether the leader instance is alive.\n   *\n   * @param leaderId Instance ID of leader instance.\n   * @return {@code true} if leader instance is alive, or {@code false} if not.\n   */\n  boolean sendHeartbeatMessage(int leaderId);\n\n  /**\n   * Send election message to other instances.\n   *\n   * @param currentId Instance ID of which sends this message.\n   * @param content Election message content.\n   * @return {@code true} if the message is accepted by the target instances.\n   */\n  boolean sendElectionMessage(int currentId, String content);\n\n  /**\n   * Send new leader notification message to other instances.\n   *\n   * @param currentId Instance ID of which sends this message.\n   * @param leaderId Leader message content.\n   * @return {@code true} if the message is accepted by the target instances.\n   */\n  boolean sendLeaderMessage(int currentId, int leaderId);\n\n  /**\n   * Send heartbeat invoke message. This will invoke heartbeat task in the target instance.\n   *\n   * @param currentId Instance ID of which sends this message.\n   */\n  void sendHeartbeatInvokeMessage(int currentId);\n}\n"
  },
  {
    "path": "leader-election/src/main/java/com/iluwatar/leaderelection/MessageType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection;\n\n/** Message Type enum. */\npublic enum MessageType {\n\n  /** Start the election. The content of the message stores ID(s) of the candidate instance(s). */\n  ELECTION,\n\n  /** Nodify the new leader. The content of the message should be the leader ID. */\n  LEADER,\n\n  /** Check health of current leader instance. */\n  HEARTBEAT,\n\n  /** Inform target instance to start election. */\n  ELECTION_INVOKE,\n\n  /** Inform target instance to notify all the other instance that it is the new leader. */\n  LEADER_INVOKE,\n\n  /** Inform target instance to start heartbeat. */\n  HEARTBEAT_INVOKE\n}\n"
  },
  {
    "path": "leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyApp.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection.bully;\n\nimport com.iluwatar.leaderelection.Instance;\nimport com.iluwatar.leaderelection.Message;\nimport com.iluwatar.leaderelection.MessageType;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Example of how to use bully leader election. Initially 5 instances is created in the clould\n * system, and the instance with ID 1 is set as leader. After the system is started stop the leader\n * instance, and the new leader will be elected.\n */\npublic class BullyApp {\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n\n    Map<Integer, Instance> instanceMap = new HashMap<>();\n    var messageManager = new BullyMessageManager(instanceMap);\n\n    var instance1 = new BullyInstance(messageManager, 1, 1);\n    var instance2 = new BullyInstance(messageManager, 2, 1);\n    var instance3 = new BullyInstance(messageManager, 3, 1);\n    var instance4 = new BullyInstance(messageManager, 4, 1);\n    var instance5 = new BullyInstance(messageManager, 5, 1);\n\n    instanceMap.put(1, instance1);\n    instanceMap.put(2, instance2);\n    instanceMap.put(3, instance3);\n    instanceMap.put(4, instance4);\n    instanceMap.put(5, instance5);\n\n    instance4.onMessage(new Message(MessageType.HEARTBEAT_INVOKE, \"\"));\n\n    final var thread1 = new Thread(instance1);\n    final var thread2 = new Thread(instance2);\n    final var thread3 = new Thread(instance3);\n    final var thread4 = new Thread(instance4);\n    final var thread5 = new Thread(instance5);\n\n    thread1.start();\n    thread2.start();\n    thread3.start();\n    thread4.start();\n    thread5.start();\n\n    instance1.setAlive(false);\n  }\n}\n"
  },
  {
    "path": "leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyInstance.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection.bully;\n\nimport com.iluwatar.leaderelection.AbstractInstance;\nimport com.iluwatar.leaderelection.Message;\nimport com.iluwatar.leaderelection.MessageManager;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Impelemetation with bully algorithm. Each instance should have a sequential id and is able to\n * communicate with other instances in the system. Initially the instance with smallest (or largest)\n * ID is selected to be the leader. All the other instances send heartbeat message to leader\n * periodically to check its health. If one certain instance finds the server done, it will send an\n * election message to all the instances of which the ID is larger. If the target instance is alive,\n * it will return an alive message (in this sample return true) and then send election message with\n * its ID. If not, the original instance will send leader message to all the other instances.\n */\n@Slf4j\npublic class BullyInstance extends AbstractInstance {\n  private static final String INSTANCE = \"Instance \";\n\n  /** Constructor of BullyInstance. */\n  public BullyInstance(MessageManager messageManager, int localId, int leaderId) {\n    super(messageManager, localId, leaderId);\n  }\n\n  /**\n   * Process the heartbeat invoke message. After receiving the message, the instance will send a\n   * heartbeat to leader to check its health. If alive, it will inform the next instance to do the\n   * heartbeat. If not, it will start the election process.\n   */\n  @Override\n  protected void handleHeartbeatInvokeMessage() {\n    try {\n      boolean isLeaderAlive = messageManager.sendHeartbeatMessage(leaderId);\n      if (isLeaderAlive) {\n        LOGGER.info(INSTANCE + localId + \"- Leader is alive.\");\n        Thread.sleep(HEARTBEAT_INTERVAL);\n        messageManager.sendHeartbeatInvokeMessage(localId);\n      } else {\n        LOGGER.info(INSTANCE + localId + \"- Leader is not alive. Start election.\");\n        boolean electionResult =\n            messageManager.sendElectionMessage(localId, String.valueOf(localId));\n        if (electionResult) {\n          LOGGER.info(INSTANCE + localId + \"- Succeed in election. Start leader notification.\");\n          messageManager.sendLeaderMessage(localId, localId);\n        }\n      }\n    } catch (InterruptedException e) {\n      LOGGER.info(INSTANCE + localId + \"- Interrupted.\");\n    }\n  }\n\n  /**\n   * Process election invoke message. Send election message to all the instances with smaller ID. If\n   * any one of them is alive, do nothing. If no instance alive, send leader message to all the\n   * alive instance and restart heartbeat.\n   */\n  @Override\n  protected void handleElectionInvokeMessage() {\n    if (!isLeader()) {\n      LOGGER.info(INSTANCE + localId + \"- Start election.\");\n      boolean electionResult = messageManager.sendElectionMessage(localId, String.valueOf(localId));\n      if (electionResult) {\n        LOGGER.info(INSTANCE + localId + \"- Succeed in election. Start leader notification.\");\n        leaderId = localId;\n        messageManager.sendLeaderMessage(localId, localId);\n        messageManager.sendHeartbeatInvokeMessage(localId);\n      }\n    }\n  }\n\n  /** Process leader message. Update local leader information. */\n  @Override\n  protected void handleLeaderMessage(Message message) {\n    leaderId = Integer.parseInt(message.getContent());\n    LOGGER.info(INSTANCE + localId + \" - Leader update done.\");\n  }\n\n  private boolean isLeader() {\n    return localId == leaderId;\n  }\n\n  @Override\n  protected void handleLeaderInvokeMessage() {\n    // Not used in Bully Instance\n  }\n\n  @Override\n  protected void handleHeartbeatMessage(Message message) {\n    // Not used in Bully Instance\n  }\n\n  @Override\n  protected void handleElectionMessage(Message message) {\n    // Not used in Bully Instance\n  }\n}\n"
  },
  {
    "path": "leader-election/src/main/java/com/iluwatar/leaderelection/bully/BullyMessageManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection.bully;\n\nimport com.iluwatar.leaderelection.AbstractMessageManager;\nimport com.iluwatar.leaderelection.Instance;\nimport com.iluwatar.leaderelection.Message;\nimport com.iluwatar.leaderelection.MessageType;\nimport java.util.List;\nimport java.util.Map;\n\n/** Implementation of BullyMessageManager. */\npublic class BullyMessageManager extends AbstractMessageManager {\n\n  /** Constructor of BullyMessageManager. */\n  public BullyMessageManager(Map<Integer, Instance> instanceMap) {\n    super(instanceMap);\n  }\n\n  /**\n   * Send heartbeat message to current leader instance to check the health.\n   *\n   * @param leaderId leaderID\n   * @return {@code true} if the leader is alive.\n   */\n  @Override\n  public boolean sendHeartbeatMessage(int leaderId) {\n    var leaderInstance = instanceMap.get(leaderId);\n    return leaderInstance.isAlive();\n  }\n\n  /**\n   * Send election message to all the instances with smaller ID.\n   *\n   * @param currentId Instance ID of which sends this message.\n   * @param content Election message content.\n   * @return {@code true} if no alive instance has smaller ID, so that the election is accepted.\n   */\n  @Override\n  public boolean sendElectionMessage(int currentId, String content) {\n    var candidateList = findElectionCandidateInstanceList(currentId);\n    if (candidateList.isEmpty()) {\n      return true;\n    } else {\n      var electionMessage = new Message(MessageType.ELECTION_INVOKE, \"\");\n      candidateList.forEach((i) -> instanceMap.get(i).onMessage(electionMessage));\n      return false;\n    }\n  }\n\n  /**\n   * Send leader message to all the instances to notify the new leader.\n   *\n   * @param currentId Instance ID of which sends this message.\n   * @param leaderId Leader message content.\n   * @return {@code true} if the message is accepted.\n   */\n  @Override\n  public boolean sendLeaderMessage(int currentId, int leaderId) {\n    var leaderMessage = new Message(MessageType.LEADER, String.valueOf(leaderId));\n    instanceMap.keySet().stream()\n        .filter((i) -> i != currentId)\n        .forEach((i) -> instanceMap.get(i).onMessage(leaderMessage));\n    return false;\n  }\n\n  /**\n   * Send heartbeat invoke message to the next instance.\n   *\n   * @param currentId Instance ID of which sends this message.\n   */\n  @Override\n  public void sendHeartbeatInvokeMessage(int currentId) {\n    var nextInstance = this.findNextInstance(currentId);\n    var heartbeatInvokeMessage = new Message(MessageType.HEARTBEAT_INVOKE, \"\");\n    nextInstance.onMessage(heartbeatInvokeMessage);\n  }\n\n  /**\n   * Find all the alive instances with smaller ID than current instance.\n   *\n   * @param currentId ID of current instance.\n   * @return ID list of all the candidate instance.\n   */\n  private List<Integer> findElectionCandidateInstanceList(int currentId) {\n    return instanceMap.keySet().stream()\n        .filter((i) -> i < currentId && instanceMap.get(i).isAlive())\n        .toList();\n  }\n}\n"
  },
  {
    "path": "leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingApp.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection.ring;\n\nimport com.iluwatar.leaderelection.Instance;\nimport com.iluwatar.leaderelection.Message;\nimport com.iluwatar.leaderelection.MessageType;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Example of how to use ring leader election. Initially 5 instances is created in the clould\n * system, and the instance with ID 1 is set as leader. After the system is started stop the leader\n * instance, and the new leader will be elected.\n */\npublic class RingApp {\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n\n    Map<Integer, Instance> instanceMap = new HashMap<>();\n    var messageManager = new RingMessageManager(instanceMap);\n\n    var instance1 = new RingInstance(messageManager, 1, 1);\n    var instance2 = new RingInstance(messageManager, 2, 1);\n    var instance3 = new RingInstance(messageManager, 3, 1);\n    var instance4 = new RingInstance(messageManager, 4, 1);\n    var instance5 = new RingInstance(messageManager, 5, 1);\n\n    instanceMap.put(1, instance1);\n    instanceMap.put(2, instance2);\n    instanceMap.put(3, instance3);\n    instanceMap.put(4, instance4);\n    instanceMap.put(5, instance5);\n\n    instance2.onMessage(new Message(MessageType.HEARTBEAT_INVOKE, \"\"));\n\n    final var thread1 = new Thread(instance1);\n    final var thread2 = new Thread(instance2);\n    final var thread3 = new Thread(instance3);\n    final var thread4 = new Thread(instance4);\n    final var thread5 = new Thread(instance5);\n\n    thread1.start();\n    thread2.start();\n    thread3.start();\n    thread4.start();\n    thread5.start();\n\n    instance1.setAlive(false);\n  }\n}\n"
  },
  {
    "path": "leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingInstance.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection.ring;\n\nimport com.iluwatar.leaderelection.AbstractInstance;\nimport com.iluwatar.leaderelection.Message;\nimport com.iluwatar.leaderelection.MessageManager;\nimport java.util.Arrays;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Implementation with token ring algorithm. The instances in the system are organized as a ring.\n * Each instance should have a sequential id and the instance with smallest (or largest) id should\n * be the initial leader. All the other instances send heartbeat message to leader periodically to\n * check its health. If one certain instance finds the server done, it will send an election message\n * to the next alive instance in the ring, which contains its own ID. Then the next instance add its\n * ID into the message and pass it to the next. After all the alive instances' ID are add to the\n * message, the message is send back to the first instance, and it will choose the instance with the\n * smallest ID to be the new leader, and then send a leader message to other instances to inform the\n * result.\n */\n@Slf4j\npublic class RingInstance extends AbstractInstance {\n  private static final String INSTANCE = \"Instance \";\n\n  /** Constructor of RingInstance. */\n  public RingInstance(MessageManager messageManager, int localId, int leaderId) {\n    super(messageManager, localId, leaderId);\n  }\n\n  /**\n   * Process the heartbeat invoke message. After receiving the message, the instance will send a\n   * heartbeat to leader to check its health. If alive, it will inform the next instance to do the\n   * heartbeat. If not, it will start the election process.\n   */\n  @Override\n  protected void handleHeartbeatInvokeMessage() {\n    try {\n      var isLeaderAlive = messageManager.sendHeartbeatMessage(this.leaderId);\n      if (isLeaderAlive) {\n        LOGGER.info(INSTANCE + localId + \"- Leader is alive. Start next heartbeat in 5 second.\");\n        Thread.sleep(HEARTBEAT_INTERVAL);\n        messageManager.sendHeartbeatInvokeMessage(this.localId);\n      } else {\n        LOGGER.info(INSTANCE + localId + \"- Leader is not alive. Start election.\");\n        messageManager.sendElectionMessage(this.localId, String.valueOf(this.localId));\n      }\n    } catch (InterruptedException e) {\n      LOGGER.info(INSTANCE + localId + \"- Interrupted.\");\n    }\n  }\n\n  /**\n   * Process election message. If the local ID is contained in the ID list, the instance will select\n   * the alive instance with the smallest ID to be the new leader, and send the leader inform\n   * message. If not, it will add its local ID to the list and send the message to the next instance\n   * in the ring.\n   */\n  @Override\n  protected void handleElectionMessage(Message message) {\n    var content = message.getContent();\n    LOGGER.info(INSTANCE + localId + \" - Election Message: \" + content);\n    var candidateList =\n        Arrays.stream(content.trim().split(\",\")).map(Integer::valueOf).sorted().toList();\n    if (candidateList.contains(localId)) {\n      var newLeaderId = candidateList.get(0);\n      LOGGER.info(INSTANCE + localId + \" - New leader should be \" + newLeaderId + \".\");\n      messageManager.sendLeaderMessage(localId, newLeaderId);\n    } else {\n      content += \",\" + localId;\n      messageManager.sendElectionMessage(localId, content);\n    }\n  }\n\n  /**\n   * Process leader Message. The instance will set the leader ID to be the new one and send the\n   * message to the next instance until all the alive instance in the ring is informed.\n   */\n  @Override\n  protected void handleLeaderMessage(Message message) {\n    var newLeaderId = Integer.valueOf(message.getContent());\n    if (this.leaderId != newLeaderId) {\n      LOGGER.info(INSTANCE + localId + \" - Update leaderID\");\n      this.leaderId = newLeaderId;\n      messageManager.sendLeaderMessage(localId, newLeaderId);\n    } else {\n      LOGGER.info(INSTANCE + localId + \" - Leader update done. Start heartbeat.\");\n      messageManager.sendHeartbeatInvokeMessage(localId);\n    }\n  }\n\n  /** Not used in Ring instance. */\n  @Override\n  protected void handleLeaderInvokeMessage() {\n    // Not used in Ring instance.\n  }\n\n  @Override\n  protected void handleHeartbeatMessage(Message message) {\n    // Not used in Ring instance.\n  }\n\n  @Override\n  protected void handleElectionInvokeMessage() {\n    // Not used in Ring instance.\n  }\n}\n"
  },
  {
    "path": "leader-election/src/main/java/com/iluwatar/leaderelection/ring/RingMessageManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection.ring;\n\nimport com.iluwatar.leaderelection.AbstractMessageManager;\nimport com.iluwatar.leaderelection.Instance;\nimport com.iluwatar.leaderelection.Message;\nimport com.iluwatar.leaderelection.MessageType;\nimport java.util.Map;\n\n/** Implementation of RingMessageManager. */\npublic class RingMessageManager extends AbstractMessageManager {\n\n  /** Constructor of RingMessageManager. */\n  public RingMessageManager(Map<Integer, Instance> instanceMap) {\n    super(instanceMap);\n  }\n\n  /**\n   * Send heartbeat message to current leader instance to check the health.\n   *\n   * @param leaderId leaderID\n   * @return {@code true} if the leader is alive.\n   */\n  @Override\n  public boolean sendHeartbeatMessage(int leaderId) {\n    var leaderInstance = instanceMap.get(leaderId);\n    return leaderInstance.isAlive();\n  }\n\n  /**\n   * Send election message to the next instance.\n   *\n   * @param currentId currentID\n   * @param content list contains all the IDs of instances which have received this election\n   *     message.\n   * @return {@code true} if the election message is accepted by the target instance.\n   */\n  @Override\n  public boolean sendElectionMessage(int currentId, String content) {\n    var nextInstance = this.findNextInstance(currentId);\n    var electionMessage = new Message(MessageType.ELECTION, content);\n    nextInstance.onMessage(electionMessage);\n    return true;\n  }\n\n  /**\n   * Send leader message to the next instance.\n   *\n   * @param currentId Instance ID of which sends this message.\n   * @param leaderId Leader message content.\n   * @return {@code true} if the leader message is accepted by the target instance.\n   */\n  @Override\n  public boolean sendLeaderMessage(int currentId, int leaderId) {\n    var nextInstance = this.findNextInstance(currentId);\n    var leaderMessage = new Message(MessageType.LEADER, String.valueOf(leaderId));\n    nextInstance.onMessage(leaderMessage);\n    return true;\n  }\n\n  /**\n   * Send heartbeat invoke message to the next instance.\n   *\n   * @param currentId Instance ID of which sends this message.\n   */\n  @Override\n  public void sendHeartbeatInvokeMessage(int currentId) {\n    var nextInstance = this.findNextInstance(currentId);\n    var heartbeatInvokeMessage = new Message(MessageType.HEARTBEAT_INVOKE, \"\");\n    nextInstance.onMessage(heartbeatInvokeMessage);\n  }\n}\n"
  },
  {
    "path": "leader-election/src/test/java/com/iluwatar/leaderelection/MessageTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Message test case. */\nclass MessageTest {\n\n  @Test\n  void testGetType() {\n    var message = new Message(MessageType.HEARTBEAT, \"\");\n    assertEquals(MessageType.HEARTBEAT, message.getType());\n  }\n\n  @Test\n  void testGetContent() {\n    var content = \"test\";\n    var message = new Message(MessageType.HEARTBEAT, content);\n    assertEquals(content, message.getContent());\n  }\n}\n"
  },
  {
    "path": "leader-election/src/test/java/com/iluwatar/leaderelection/bully/BullyAppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection.bully;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** BullyApp unit test. */\nclass BullyAppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> BullyApp.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "leader-election/src/test/java/com/iluwatar/leaderelection/bully/BullyMessageManagerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection.bully;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nimport com.iluwatar.leaderelection.AbstractInstance;\nimport com.iluwatar.leaderelection.Instance;\nimport com.iluwatar.leaderelection.Message;\nimport com.iluwatar.leaderelection.MessageType;\nimport java.util.Map;\nimport java.util.Queue;\nimport org.junit.jupiter.api.Test;\n\n/** BullyMessageManager unit test. */\nclass BullyMessageManagerTest {\n\n  @Test\n  void testSendHeartbeatMessage() {\n    var instance1 = new BullyInstance(null, 1, 1);\n    Map<Integer, Instance> instanceMap = Map.of(1, instance1);\n    var messageManager = new BullyMessageManager(instanceMap);\n    assertTrue(messageManager.sendHeartbeatMessage(1));\n  }\n\n  @Test\n  void testSendElectionMessageNotAccepted() {\n    try {\n      var instance1 = new BullyInstance(null, 1, 1);\n      var instance2 = new BullyInstance(null, 1, 2);\n      var instance3 = new BullyInstance(null, 1, 3);\n      var instance4 = new BullyInstance(null, 1, 4);\n      Map<Integer, Instance> instanceMap =\n          Map.of(1, instance1, 2, instance2, 3, instance3, 4, instance4);\n      instance1.setAlive(false);\n      var messageManager = new BullyMessageManager(instanceMap);\n      var result = messageManager.sendElectionMessage(3, \"3\");\n      var instanceClass = AbstractInstance.class;\n      var messageQueueField = instanceClass.getDeclaredField(\"messageQueue\");\n      messageQueueField.setAccessible(true);\n      var message2 = ((Queue<Message>) messageQueueField.get(instance2)).poll();\n      var instance4QueueSize = ((Queue<Message>) messageQueueField.get(instance4)).size();\n      var expectedMessage = new Message(MessageType.ELECTION_INVOKE, \"\");\n      assertEquals(message2, expectedMessage);\n      assertEquals(instance4QueueSize, 0);\n      assertFalse(result);\n    } catch (IllegalAccessException | NoSuchFieldException e) {\n      fail(\"Error to access private field.\");\n    }\n  }\n\n  @Test\n  void testElectionMessageAccepted() {\n    var instance1 = new BullyInstance(null, 1, 1);\n    var instance2 = new BullyInstance(null, 1, 2);\n    var instance3 = new BullyInstance(null, 1, 3);\n    var instance4 = new BullyInstance(null, 1, 4);\n    Map<Integer, Instance> instanceMap =\n        Map.of(1, instance1, 2, instance2, 3, instance3, 4, instance4);\n    instance1.setAlive(false);\n    var messageManager = new BullyMessageManager(instanceMap);\n    var result = messageManager.sendElectionMessage(2, \"2\");\n    assertTrue(result);\n  }\n\n  @Test\n  void testSendLeaderMessage() {\n    try {\n      var instance1 = new BullyInstance(null, 1, 1);\n      var instance2 = new BullyInstance(null, 1, 2);\n      var instance3 = new BullyInstance(null, 1, 3);\n      var instance4 = new BullyInstance(null, 1, 4);\n      Map<Integer, Instance> instanceMap =\n          Map.of(1, instance1, 2, instance2, 3, instance3, 4, instance4);\n      instance1.setAlive(false);\n      var messageManager = new BullyMessageManager(instanceMap);\n      messageManager.sendLeaderMessage(2, 2);\n      var instanceClass = AbstractInstance.class;\n      var messageQueueField = instanceClass.getDeclaredField(\"messageQueue\");\n      messageQueueField.setAccessible(true);\n      var message3 = ((Queue<Message>) messageQueueField.get(instance3)).poll();\n      var message4 = ((Queue<Message>) messageQueueField.get(instance4)).poll();\n      var expectedMessage = new Message(MessageType.LEADER, \"2\");\n      assertEquals(message3, expectedMessage);\n      assertEquals(message4, expectedMessage);\n    } catch (IllegalAccessException | NoSuchFieldException e) {\n      fail(\"Error to access private field.\");\n    }\n  }\n\n  @Test\n  void testSendHeartbeatInvokeMessage() {\n    try {\n      var instance1 = new BullyInstance(null, 1, 1);\n      var instance2 = new BullyInstance(null, 1, 2);\n      var instance3 = new BullyInstance(null, 1, 3);\n      Map<Integer, Instance> instanceMap = Map.of(1, instance1, 2, instance2, 3, instance3);\n      var messageManager = new BullyMessageManager(instanceMap);\n      messageManager.sendHeartbeatInvokeMessage(2);\n      var message = new Message(MessageType.HEARTBEAT_INVOKE, \"\");\n      var instanceClass = AbstractInstance.class;\n      var messageQueueField = instanceClass.getDeclaredField(\"messageQueue\");\n      messageQueueField.setAccessible(true);\n      var messageSent = ((Queue<Message>) messageQueueField.get(instance3)).poll();\n      assertEquals(messageSent.getType(), message.getType());\n      assertEquals(messageSent.getContent(), message.getContent());\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Error to access private field.\");\n    }\n  }\n}\n"
  },
  {
    "path": "leader-election/src/test/java/com/iluwatar/leaderelection/bully/BullyinstanceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection.bully;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nimport com.iluwatar.leaderelection.AbstractInstance;\nimport com.iluwatar.leaderelection.Message;\nimport com.iluwatar.leaderelection.MessageType;\nimport java.util.Queue;\nimport org.junit.jupiter.api.Test;\n\n/** BullyInstance unit test. */\nclass BullyinstanceTest {\n\n  @Test\n  void testOnMessage() {\n    try {\n      final var bullyInstance = new BullyInstance(null, 1, 1);\n      var bullyMessage = new Message(MessageType.HEARTBEAT, \"\");\n      bullyInstance.onMessage(bullyMessage);\n      var instanceClass = AbstractInstance.class;\n      var messageQueueField = instanceClass.getDeclaredField(\"messageQueue\");\n      messageQueueField.setAccessible(true);\n      assertEquals(bullyMessage, ((Queue<Message>) messageQueueField.get(bullyInstance)).poll());\n    } catch (IllegalAccessException | NoSuchFieldException e) {\n      fail(\"fail to access messasge queue.\");\n    }\n  }\n\n  @Test\n  void testIsAlive() {\n    try {\n      final var bullyInstance = new BullyInstance(null, 1, 1);\n      var instanceClass = AbstractInstance.class;\n      var aliveField = instanceClass.getDeclaredField(\"alive\");\n      aliveField.setAccessible(true);\n      aliveField.set(bullyInstance, false);\n      assertFalse(bullyInstance.isAlive());\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Fail to access field alive.\");\n    }\n  }\n\n  @Test\n  void testSetAlive() {\n    final var bullyInstance = new BullyInstance(null, 1, 1);\n    bullyInstance.setAlive(false);\n    assertFalse(bullyInstance.isAlive());\n  }\n}\n"
  },
  {
    "path": "leader-election/src/test/java/com/iluwatar/leaderelection/ring/RingAppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection.ring;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** RingApp unit test. */\nclass RingAppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> RingApp.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "leader-election/src/test/java/com/iluwatar/leaderelection/ring/RingInstanceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection.ring;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nimport com.iluwatar.leaderelection.AbstractInstance;\nimport com.iluwatar.leaderelection.Message;\nimport com.iluwatar.leaderelection.MessageType;\nimport java.util.Queue;\nimport org.junit.jupiter.api.Test;\n\n/** RingInstance unit test. */\nclass RingInstanceTest {\n\n  @Test\n  void testOnMessage() {\n    try {\n      final var ringInstance = new RingInstance(null, 1, 1);\n      var ringMessage = new Message(MessageType.HEARTBEAT, \"\");\n      ringInstance.onMessage(ringMessage);\n      var ringInstanceClass = AbstractInstance.class;\n      var messageQueueField = ringInstanceClass.getDeclaredField(\"messageQueue\");\n      messageQueueField.setAccessible(true);\n      assertEquals(ringMessage, ((Queue<Message>) messageQueueField.get(ringInstance)).poll());\n    } catch (IllegalAccessException | NoSuchFieldException e) {\n      fail(\"fail to access messasge queue.\");\n    }\n  }\n\n  @Test\n  void testIsAlive() {\n    try {\n      final var ringInstance = new RingInstance(null, 1, 1);\n      var ringInstanceClass = AbstractInstance.class;\n      var aliveField = ringInstanceClass.getDeclaredField(\"alive\");\n      aliveField.setAccessible(true);\n      aliveField.set(ringInstance, false);\n      assertFalse(ringInstance.isAlive());\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Fail to access field alive.\");\n    }\n  }\n\n  @Test\n  void testSetAlive() {\n    final var ringInstance = new RingInstance(null, 1, 1);\n    ringInstance.setAlive(false);\n    assertFalse(ringInstance.isAlive());\n  }\n}\n"
  },
  {
    "path": "leader-election/src/test/java/com/iluwatar/leaderelection/ring/RingMessageManagerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderelection.ring;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nimport com.iluwatar.leaderelection.AbstractInstance;\nimport com.iluwatar.leaderelection.Instance;\nimport com.iluwatar.leaderelection.Message;\nimport com.iluwatar.leaderelection.MessageType;\nimport java.util.Map;\nimport java.util.Queue;\nimport org.junit.jupiter.api.Test;\n\n/** RingMessageManager unit test. */\nclass RingMessageManagerTest {\n\n  @Test\n  void testSendHeartbeatMessage() {\n    var instance1 = new RingInstance(null, 1, 1);\n    Map<Integer, Instance> instanceMap = Map.of(1, instance1);\n    var messageManager = new RingMessageManager(instanceMap);\n    assertTrue(messageManager.sendHeartbeatMessage(1));\n  }\n\n  @Test\n  void testSendElectionMessage() {\n    try {\n      var instance1 = new RingInstance(null, 1, 1);\n      var instance2 = new RingInstance(null, 1, 2);\n      var instance3 = new RingInstance(null, 1, 3);\n      Map<Integer, Instance> instanceMap = Map.of(1, instance1, 2, instance2, 3, instance3);\n      var messageManager = new RingMessageManager(instanceMap);\n      var messageContent = \"2\";\n      messageManager.sendElectionMessage(2, messageContent);\n      var ringMessage = new Message(MessageType.ELECTION, messageContent);\n      var instanceClass = AbstractInstance.class;\n      var messageQueueField = instanceClass.getDeclaredField(\"messageQueue\");\n      messageQueueField.setAccessible(true);\n      var ringMessageSent = ((Queue<Message>) messageQueueField.get(instance3)).poll();\n      assertEquals(ringMessageSent.getType(), ringMessage.getType());\n      assertEquals(ringMessageSent.getContent(), ringMessage.getContent());\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Error to access private field.\");\n    }\n  }\n\n  @Test\n  void testSendLeaderMessage() {\n    try {\n      var instance1 = new RingInstance(null, 1, 1);\n      var instance2 = new RingInstance(null, 1, 2);\n      var instance3 = new RingInstance(null, 1, 3);\n      Map<Integer, Instance> instanceMap = Map.of(1, instance1, 2, instance2, 3, instance3);\n      var messageManager = new RingMessageManager(instanceMap);\n      var messageContent = \"3\";\n      messageManager.sendLeaderMessage(2, 3);\n      var ringMessage = new Message(MessageType.LEADER, messageContent);\n      var instanceClass = AbstractInstance.class;\n      var messageQueueField = instanceClass.getDeclaredField(\"messageQueue\");\n      messageQueueField.setAccessible(true);\n      var ringMessageSent = ((Queue<Message>) messageQueueField.get(instance3)).poll();\n      assertEquals(ringMessageSent, ringMessage);\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Error to access private field.\");\n    }\n  }\n\n  @Test\n  void testSendHeartbeatInvokeMessage() {\n    try {\n      var instance1 = new RingInstance(null, 1, 1);\n      var instance2 = new RingInstance(null, 1, 2);\n      var instance3 = new RingInstance(null, 1, 3);\n      Map<Integer, Instance> instanceMap = Map.of(1, instance1, 2, instance2, 3, instance3);\n      var messageManager = new RingMessageManager(instanceMap);\n      messageManager.sendHeartbeatInvokeMessage(2);\n      var ringMessage = new Message(MessageType.HEARTBEAT_INVOKE, \"\");\n      var instanceClass = AbstractInstance.class;\n      var messageQueueField = instanceClass.getDeclaredField(\"messageQueue\");\n      messageQueueField.setAccessible(true);\n      var ringMessageSent = ((Queue<Message>) messageQueueField.get(instance3)).poll();\n      assertEquals(ringMessageSent.getType(), ringMessage.getType());\n      assertEquals(ringMessageSent.getContent(), ringMessage.getContent());\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Error to access private field.\");\n    }\n  }\n}\n"
  },
  {
    "path": "leader-followers/README.md",
    "content": "---\ntitle: \"Leader-Followers Pattern in Java: Enhancing Efficiency with Dynamic Worker Allocation\"\nshortTitle: Leader-Followers\ndescription: \"Discover the Leader-Followers design pattern for efficient thread management and synchronization. Learn how to optimize resource usage and improve system performance with detailed examples and applications.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Decoupling\n  - Performance\n  - Synchronization\n  - Thread management\n---\n\n## Intent of Leader/Followers Design Pattern\n\nTo efficiently manage a set of worker threads, the Leader-Followers pattern enables multiple threads to take turns sharing a set of event sources, optimizing resource utilization and improving performance compared to a one-thread-per-source approach.\n\n## Detailed Explanation of Leader/Followers Pattern with Real-World Examples\n\nReal-world Example\n\n> Imagine managing a busy restaurant with multiple servers and a single host. The host acts as the \"leader\" and is responsible for greeting guests, managing the waitlist, and seating guests. Once the guests are seated, the host returns to the entrance to manage new arrivals. The servers, or \"followers,\" wait for the host to assign them tables. This assignment is done on a rotational basis where the next available server takes the next group of guests. This system ensures that the host efficiently handles the incoming flow of guests while servers focus on providing service, similar to how the Leader and Followers pattern manages threads and tasks in a software system. This approach optimizes resource utilization (in this case, staff) and ensures smooth operations during peak times, much like it optimizes thread usage in computing environments.\n\nIn plain words\n\n> The Leader-Followers design pattern utilizes a single leader thread to distribute work among multiple follower threads, effectively managing task delegation, thread synchronization, and improving resource efficiency in concurrent programming.\n\n[martinfowler.com](https://martinfowler.com/articles/patterns-of-distributed-systems/leader-follower.html) says\n\n> Select one server in the cluster as a leader. The leader is responsible for taking decisions on behalf of the entire cluster and propagating the decisions to all the other servers.\n\nSequence diagram\n\n![Leader-Followers Sequence Diagram](./etc/leader-followers-sequence-diagram.png)\n\n## Programmatic Example of Leader-Followers Pattern in Java\n\nThe Leader-Followers pattern is a concurrency design pattern where one thread (the leader) waits for work to arrive, de-multiplexes, dispatches, and processes the work, thereby enhancing CPU cache affinity and reducing event dispatching latency. Once the leader finishes processing the work, it promotes one of the follower threads to be the new leader. This pattern is useful for enhancing CPU cache affinity, minimizing locking overhead, and reducing event dispatching latency.\n\nIn the provided code, we have a `WorkCenter` class that manages a group of `Worker` threads. One of these workers is designated as the leader and is responsible for receiving and processing tasks. Once a task is processed, the leader promotes a new leader from the remaining workers.\n\n```java\n// WorkCenter class\npublic class WorkCenter {\n\n  @Getter\n  private Worker leader;\n  private final List<Worker> workers = new CopyOnWriteArrayList<>();\n\n  // Method to create workers and set the initial leader\n  public void createWorkers(int numberOfWorkers, TaskSet taskSet, TaskHandler taskHandler) {\n    for (var id = 1; id <= numberOfWorkers; id++) {\n      var worker = new Worker(id, this, taskSet, taskHandler);\n      workers.add(worker);\n    }\n    promoteLeader();\n  }\n\n  // Method to promote a new leader\n  public void promoteLeader() {\n    Worker leader = null;\n    if (!workers.isEmpty()) {\n      leader = workers.get(0);\n    }\n    this.leader = leader;\n  }\n}\n```\n\nIn the `Worker` class, each worker is a thread that waits for tasks to process. If the worker is the leader, it processes the task and then promotes a new leader.\n\n```java\n// Worker class\npublic class Worker implements Runnable {\n\n  private final long id;\n  private final WorkCenter workCenter;\n  private final TaskSet taskSet;\n  private final TaskHandler taskHandler;\n\n  @Override\n  public void run() {\n    while (!Thread.interrupted()) {\n      try {\n        if (workCenter.getLeader() != null && !workCenter.getLeader().equals(this)) {\n          synchronized (workCenter) {\n            if (workCenter.getLeader() != null && !workCenter.getLeader().equals(this)) {\n              workCenter.wait();\n              continue;\n            }\n          }\n        }\n        final Task task = taskSet.getTask();\n        synchronized (workCenter) {\n          workCenter.removeWorker(this);\n          workCenter.promoteLeader();\n          workCenter.notifyAll();\n        }\n        taskHandler.handleTask(task);\n        workCenter.addWorker(this);\n      } catch (InterruptedException e) {\n        Thread.currentThread().interrupt();\n        return;\n      }\n    }\n  }\n}\n```\n\nIn the `App` class, we create a `WorkCenter`, add tasks to a `TaskSet`, and then start the workers. The leader worker will start processing the tasks, and once it finishes a task, it will promote a new leader.\n\n```java\n// App class\npublic class App {\n\n  public static void main(String[] args) throws InterruptedException {\n    var taskSet = new TaskSet();\n    var taskHandler = new TaskHandler();\n    var workCenter = new WorkCenter();\n    workCenter.createWorkers(4, taskSet, taskHandler);\n    addTasks(taskSet);\n    startWorkers(workCenter);\n  }\n\n  private static void addTasks(TaskSet taskSet) throws InterruptedException {\n    var rand = new SecureRandom();\n    for (var i = 0; i < 5; i++) {\n      var time = Math.abs(rand.nextInt(1000));\n      taskSet.addTask(new Task(time));\n    }\n  }\n\n  private static void startWorkers(WorkCenter workCenter) throws InterruptedException {\n    var workers = workCenter.getWorkers();\n    var exec = Executors.newFixedThreadPool(workers.size());\n    workers.forEach(exec::submit);\n    exec.awaitTermination(2, TimeUnit.SECONDS);\n    exec.shutdownNow();\n  }\n}\n```\n\nThis is a basic example of the Leader/Followers pattern. The leader worker processes tasks and promotes a new leader once it finishes a task. The new leader then starts processing the next task, and the cycle continues.\n\n## When to Use the Leader/Followers Pattern in Java\n\n* The Leader-Followers pattern is useful in scenarios requiring efficient handling of multiple services on a single thread, avoiding resource thrashing, and improving scalability in concurrent programming environments.\n* Applicable in server environments where multiple client requests must be handled concurrently with minimal resource consumption.\n\n## Real-World Applications of Leader-Followers Pattern in Java\n\n* Network servers handling multiple incoming connections.\n* Event-driven applications that manage a large number of input/output sources.\n\n## Benefits and Trade-offs of Leader/Followers Pattern\n\nBenefits:\n\n* Reduces the number of threads and context switching, leading to better performance and lower resource utilization.\n* Improves system scalability and responsiveness.\n\nTrade-offs:\n\n* Increased complexity in managing the synchronization between leader and followers.\n* Potential for underutilization of resources if not correctly implemented.\n\n## Related Java Design Patterns\n\n* [Half-Sync/Half-Async](https://java-design-patterns.com/patterns/half-sync-half-async/): Leader and Followers can be seen as a variation where the synchronization aspect is divided between the leader (synchronous handling) and followers (waiting asynchronously).\n* [Thread Pool](https://java-design-patterns.com/patterns/thread-pool/): Both patterns manage a pool of worker threads, but Thread Pool assigns tasks to any available thread rather than using a leader to distribute work.\n\n## References and Credits\n\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n* [Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects](https://amzn.to/3UgC24V)\n"
  },
  {
    "path": "leader-followers/etc/leader-followers.urm.puml",
    "content": "@startuml\npackage com.iluwatar.leaderfollowers {\n  class App {\n    + App()\n    - addTasks(taskSet : TaskSet) {static}\n    - execute(workCenter : WorkCenter, taskSet : TaskSet) {static}\n    + main(args : String[]) {static}\n  }\n  class Task {\n    - finished : boolean\n    - time : int\n    + Task(time : int)\n    + getTime() : int\n    + isFinished() : boolean\n    + setFinished()\n  }\n  class TaskHandler {\n    + TaskHandler()\n    + handleTask(task : Task)\n  }\n  class TaskSet {\n    - queue : BlockingQueue<Task>\n    + TaskSet()\n    + addTask(task : Task)\n    + getSize() : int\n    + getTask() : Task\n  }\n  class WorkCenter {\n    - leader : Worker\n    - workers : List<Worker>\n    + WorkCenter()\n    + addWorker(worker : Worker)\n    + createWorkers(numberOfWorkers : int, taskSet : TaskSet, taskHandler : TaskHandler)\n    + getLeader() : Worker\n    + getWorkers() : List<Worker>\n    + promoteLeader()\n    + removeWorker(worker : Worker)\n  }\n  class Worker {\n    - id : long\n    - taskHandler : TaskHandler\n    - taskSet : TaskSet\n    - workCenter : WorkCenter\n    + Worker(id : long, workCenter : WorkCenter, taskSet : TaskSet, taskHandler : TaskHandler)\n    + equals(o : Object) : boolean\n    + hashCode() : int\n    + run()\n  }\n}\nWorker -->  \"-taskSet\" TaskSet\nWorker -->  \"-taskHandler\" TaskHandler\nTaskSet -->  \"-queue\" Task\nWorker -->  \"-workCenter\" WorkCenter\n@enduml"
  },
  {
    "path": "leader-followers/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>leader-followers</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.leaderfollowers.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "leader-followers/src/main/java/com/iluwatar/leaderfollowers/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderfollowers;\n\nimport java.security.SecureRandom;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\n\n@Slf4j\npublic class App {\n\n  public static void main(String[] args) throws InterruptedException {\n    var taskSet = new TaskSet();\n    var taskHandler = new TaskHandler();\n    var workCenter = new WorkCenter();\n    workCenter.createWorkers(4, taskSet, taskHandler);\n    execute(workCenter, taskSet);\n  }\n\n  private static void execute(WorkCenter workCenter, TaskSet taskSet) throws InterruptedException {\n    var workers = workCenter.getWorkers();\n    var exec = Executors.newFixedThreadPool(workers.size());\n\n    try {\n      workers.forEach(exec::submit);\n      Thread.sleep(1000);\n      addTasks(taskSet);\n      boolean terminated = exec.awaitTermination(2, TimeUnit.SECONDS);\n      if (!terminated) {\n        LOGGER.warn(\"Executor did not terminate in the given time.\");\n      }\n    } finally {\n      exec.shutdownNow();\n    }\n  }\n\n  private static void addTasks(TaskSet taskSet) throws InterruptedException {\n    var rand = new SecureRandom();\n    for (var i = 0; i < 5; i++) {\n      var time = Math.abs(rand.nextInt(1000));\n      taskSet.addTask(new Task(time));\n    }\n  }\n}\n"
  },
  {
    "path": "leader-followers/src/main/java/com/iluwatar/leaderfollowers/Task.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderfollowers;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** A unit of work to be processed by the Workers. */\npublic class Task {\n\n  @Getter private final int time;\n\n  @Getter @Setter private boolean finished;\n\n  public Task(int time) {\n    this.time = time;\n  }\n}\n"
  },
  {
    "path": "leader-followers/src/main/java/com/iluwatar/leaderfollowers/TaskHandler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderfollowers;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** The TaskHandler is used by the {@link Worker} to process the newly arrived task. */\n@Slf4j\npublic class TaskHandler {\n\n  /** This interface handles one task at a time. */\n  public void handleTask(Task task) throws InterruptedException {\n    var time = task.getTime();\n    Thread.sleep(time);\n    LOGGER.info(\"It takes \" + time + \" milliseconds to finish the task\");\n    task.setFinished(true);\n  }\n}\n"
  },
  {
    "path": "leader-followers/src/main/java/com/iluwatar/leaderfollowers/TaskSet.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderfollowers;\n\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.BlockingQueue;\n\n/** A TaskSet is a collection of the tasks, the leader receives task from here. */\npublic class TaskSet {\n\n  private final BlockingQueue<Task> queue = new ArrayBlockingQueue<>(100);\n\n  public void addTask(Task task) throws InterruptedException {\n    queue.put(task);\n  }\n\n  public Task getTask() throws InterruptedException {\n    return queue.take();\n  }\n\n  public int getSize() {\n    return queue.size();\n  }\n}\n"
  },
  {
    "path": "leader-followers/src/main/java/com/iluwatar/leaderfollowers/WorkCenter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderfollowers;\n\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport lombok.Getter;\n\n/**\n * A WorkCenter contains a leader and a list of idle workers. The leader is responsible for\n * receiving work when it arrives. This class also provides a mechanism to promote a new leader. A\n * worker once he completes his task will add himself back to the center.\n */\npublic class WorkCenter {\n\n  @Getter private Worker leader;\n  private final List<Worker> workers = new CopyOnWriteArrayList<>();\n\n  /** Create workers and set leader. */\n  public void createWorkers(int numberOfWorkers, TaskSet taskSet, TaskHandler taskHandler) {\n    for (var id = 1; id <= numberOfWorkers; id++) {\n      var worker = new Worker(id, this, taskSet, taskHandler);\n      workers.add(worker);\n    }\n    promoteLeader();\n  }\n\n  public void addWorker(Worker worker) {\n    workers.add(worker);\n  }\n\n  public void removeWorker(Worker worker) {\n    workers.remove(worker);\n  }\n\n  /** Promote a leader. */\n  public void promoteLeader() {\n    Worker leader = null;\n    if (!workers.isEmpty()) {\n      leader = workers.get(0);\n    }\n    this.leader = leader;\n  }\n\n  public List<Worker> getWorkers() {\n    return workers;\n  }\n}\n"
  },
  {
    "path": "leader-followers/src/main/java/com/iluwatar/leaderfollowers/Worker.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderfollowers;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Worker class that takes work from work center. */\n@EqualsAndHashCode(onlyExplicitlyIncluded = true)\n@Slf4j\npublic class Worker implements Runnable {\n\n  @EqualsAndHashCode.Include private final long id;\n  private final WorkCenter workCenter;\n  private final TaskSet taskSet;\n  private final TaskHandler taskHandler;\n\n  /** Constructor to create a worker which will take work from the work center. */\n  public Worker(long id, WorkCenter workCenter, TaskSet taskSet, TaskHandler taskHandler) {\n    super();\n    this.id = id;\n    this.workCenter = workCenter;\n    this.taskSet = taskSet;\n    this.taskHandler = taskHandler;\n  }\n\n  /**\n   * The leader thread listens for task. When task arrives, it promotes one of the followers to be\n   * the new leader. Then it handles the task and add himself back to work center.\n   */\n  @Override\n  public void run() {\n    while (!Thread.interrupted()) {\n      try {\n        if (workCenter.getLeader() != null && !workCenter.getLeader().equals(this)) {\n          synchronized (workCenter) {\n            if (workCenter.getLeader() != null && !workCenter.getLeader().equals(this)) {\n              workCenter.wait();\n              continue;\n            }\n          }\n        }\n        final Task task = taskSet.getTask();\n        synchronized (workCenter) {\n          workCenter.removeWorker(this);\n          workCenter.promoteLeader();\n          workCenter.notifyAll();\n        }\n        taskHandler.handleTask(task);\n        LOGGER.info(\"The Worker with the ID \" + id + \" completed the task\");\n        workCenter.addWorker(this);\n      } catch (InterruptedException e) {\n        LOGGER.warn(\"Worker interrupted\");\n        Thread.currentThread().interrupt();\n        return;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "leader-followers/src/test/java/com/iluwatar/leaderfollowers/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderfollowers;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "leader-followers/src/test/java/com/iluwatar/leaderfollowers/TaskHandlerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderfollowers;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests for TaskHandler */\nclass TaskHandlerTest {\n\n  @Test\n  void testHandleTask() throws InterruptedException {\n    var taskHandler = new TaskHandler();\n    var handle = new Task(100);\n    taskHandler.handleTask(handle);\n    assertTrue(handle.isFinished());\n  }\n}\n"
  },
  {
    "path": "leader-followers/src/test/java/com/iluwatar/leaderfollowers/TaskSetTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderfollowers;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests for TaskSet */\nclass TaskSetTest {\n\n  @Test\n  void testAddTask() throws InterruptedException {\n    var taskSet = new TaskSet();\n    taskSet.addTask(new Task(10));\n    assertEquals(1, taskSet.getSize());\n  }\n\n  @Test\n  void testGetTask() throws InterruptedException {\n    var taskSet = new TaskSet();\n    taskSet.addTask(new Task(100));\n    Task task = taskSet.getTask();\n    assertEquals(100, task.getTime());\n    assertEquals(0, taskSet.getSize());\n  }\n}\n"
  },
  {
    "path": "leader-followers/src/test/java/com/iluwatar/leaderfollowers/WorkCenterTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.leaderfollowers;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests for WorkCenter */\nclass WorkCenterTest {\n\n  @Test\n  void testCreateWorkers() {\n    var taskSet = new TaskSet();\n    var taskHandler = new TaskHandler();\n    var workCenter = new WorkCenter();\n    workCenter.createWorkers(5, taskSet, taskHandler);\n    assertEquals(5, workCenter.getWorkers().size());\n    assertEquals(workCenter.getWorkers().get(0), workCenter.getLeader());\n  }\n\n  @Test\n  void testNullLeader() {\n    var workCenter = new WorkCenter();\n    workCenter.promoteLeader();\n    assertNull(workCenter.getLeader());\n  }\n\n  @Test\n  void testPromoteLeader() {\n    var taskSet = new TaskSet();\n    var taskHandler = new TaskHandler();\n    var workCenter = new WorkCenter();\n    workCenter.createWorkers(5, taskSet, taskHandler);\n    workCenter.removeWorker(workCenter.getLeader());\n    workCenter.promoteLeader();\n    assertEquals(4, workCenter.getWorkers().size());\n    assertEquals(workCenter.getWorkers().get(0), workCenter.getLeader());\n  }\n}\n"
  },
  {
    "path": "lgpl-3.0.txt",
    "content": "====\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n====\n\n                   GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\n  This version of the GNU Lesser General Public License incorporates\nthe terms and conditions of version 3 of the GNU General Public\nLicense, supplemented by the additional permissions listed below.\n\n  0. Additional Definitions.\n\n  As used herein, \"this License\" refers to version 3 of the GNU Lesser\nGeneral Public License, and the \"GNU GPL\" refers to version 3 of the GNU\nGeneral Public License.\n\n  \"The Library\" refers to a covered work governed by this License,\nother than an Application or a Combined Work as defined below.\n\n  An \"Application\" is any work that makes use of an interface provided\nby the Library, but which is not otherwise based on the Library.\nDefining a subclass of a class defined by the Library is deemed a mode\nof using an interface provided by the Library.\n\n  A \"Combined Work\" is a work produced by combining or linking an\nApplication with the Library.  The particular version of the Library\nwith which the Combined Work was made is also called the \"Linked\nVersion\".\n\n  The \"Minimal Corresponding Source\" for a Combined Work means the\nCorresponding Source for the Combined Work, excluding any source code\nfor portions of the Combined Work that, considered in isolation, are\nbased on the Application, and not on the Linked Version.\n\n  The \"Corresponding Application Code\" for a Combined Work means the\nobject code and/or source code for the Application, including any data\nand utility programs needed for reproducing the Combined Work from the\nApplication, but excluding the System Libraries of the Combined Work.\n\n  1. Exception to Section 3 of the GNU GPL.\n\n  You may convey a covered work under sections 3 and 4 of this License\nwithout being bound by section 3 of the GNU GPL.\n\n  2. Conveying Modified Versions.\n\n  If you modify a copy of the Library, and, in your modifications, a\nfacility refers to a function or data to be supplied by an Application\nthat uses the facility (other than as an argument passed when the\nfacility is invoked), then you may convey a copy of the modified\nversion:\n\n   a) under this License, provided that you make a good faith effort to\n   ensure that, in the event an Application does not supply the\n   function or data, the facility still operates, and performs\n   whatever part of its purpose remains meaningful, or\n\n   b) under the GNU GPL, with none of the additional permissions of\n   this License applicable to that copy.\n\n  3. Object Code Incorporating Material from Library Header Files.\n\n  The object code form of an Application may incorporate material from\na header file that is part of the Library.  You may convey such object\ncode under terms of your choice, provided that, if the incorporated\nmaterial is not limited to numerical parameters, data structure\nlayouts and accessors, or small macros, inline functions and templates\n(ten or fewer lines in length), you do both of the following:\n\n   a) Give prominent notice with each copy of the object code that the\n   Library is used in it and that the Library and its use are\n   covered by this License.\n\n   b) Accompany the object code with a copy of the GNU GPL and this license\n   document.\n\n  4. Combined Works.\n\n  You may convey a Combined Work under terms of your choice that,\ntaken together, effectively do not restrict modification of the\nportions of the Library contained in the Combined Work and reverse\nengineering for debugging such modifications, if you also do each of\nthe following:\n\n   a) Give prominent notice with each copy of the Combined Work that\n   the Library is used in it and that the Library and its use are\n   covered by this License.\n\n   b) Accompany the Combined Work with a copy of the GNU GPL and this license\n   document.\n\n   c) For a Combined Work that displays copyright notices during\n   execution, include the copyright notice for the Library among\n   these notices, as well as a reference directing the user to the\n   copies of the GNU GPL and this license document.\n\n   d) Do one of the following:\n\n       0) Convey the Minimal Corresponding Source under the terms of this\n       License, and the Corresponding Application Code in a form\n       suitable for, and under terms that permit, the user to\n       recombine or relink the Application with a modified version of\n       the Linked Version to produce a modified Combined Work, in the\n       manner specified by section 6 of the GNU GPL for conveying\n       Corresponding Source.\n\n       1) Use a suitable shared library mechanism for linking with the\n       Library.  A suitable mechanism is one that (a) uses at run time\n       a copy of the Library already present on the user's computer\n       system, and (b) will operate properly with a modified version\n       of the Library that is interface-compatible with the Linked\n       Version.\n\n   e) Provide Installation Information, but only if you would otherwise\n   be required to provide such information under section 6 of the\n   GNU GPL, and only to the extent that such information is\n   necessary to install and execute a modified version of the\n   Combined Work produced by recombining or relinking the\n   Application with a modified version of the Linked Version. (If\n   you use option 4d0, the Installation Information must accompany\n   the Minimal Corresponding Source and Corresponding Application\n   Code. If you use option 4d1, you must provide the Installation\n   Information in the manner specified by section 6 of the GNU GPL\n   for conveying Corresponding Source.)\n\n  5. Combined Libraries.\n\n  You may place library facilities that are a work based on the\nLibrary side by side in a single library together with other library\nfacilities that are not Applications and are not covered by this\nLicense, and convey such a combined library under terms of your\nchoice, if you do both of the following:\n\n   a) Accompany the combined library with a copy of the same work based\n   on the Library, uncombined with any other library facilities,\n   conveyed under the terms of this License.\n\n   b) Give prominent notice with the combined library that part of it\n   is a work based on the Library, and explaining where to find the\n   accompanying uncombined form of the same work.\n\n  6. Revised Versions of the GNU Lesser General Public License.\n\n  The Free Software Foundation may publish revised and/or new versions\nof the GNU Lesser General Public License from time to time. Such new\nversions will be similar in spirit to the present version, but may\ndiffer in detail to address new problems or concerns.\n\n  Each version is given a distinguishing version number. If the\nLibrary as you received it specifies that a certain numbered version\nof the GNU Lesser General Public License \"or any later version\"\napplies to it, you have the option of following the terms and\nconditions either of that published version or of any later version\npublished by the Free Software Foundation. If the Library as you\nreceived it does not specify a version number of the GNU Lesser\nGeneral Public License, you may choose any version of the GNU Lesser\nGeneral Public License ever published by the Free Software Foundation.\n\n  If the Library as you received it specifies that a proxy can decide\nwhether future versions of the GNU Lesser General Public License shall\napply, that proxy's public statement of acceptance of any version is\npermanent authorization for you to choose that version for the\nLibrary.\n"
  },
  {
    "path": "localization/ar/README.md",
    "content": "# أنماط التصميم بلغة برمجة الجافا \n\n![Java CI with Maven](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI%20with%20Maven/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns) \n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-148-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n\n# مقدمة \n\nأنماط التصميم هي أفضل التدريبات التي يمكن للمبرمج استخدامها لحل المشكلات الشائعة عند تصميم تطبيق أو نظام.\nيمكن لأنماط التصميم تسريع عملية التطوير من خلال توفير نماذج تطوير مجربة ومثبتة ومفيدة.\nتساعد إعادة استخدام أنماط التصميم في منع المشكلات الدقيقة التي تسبب مشكلات كبيرة ، كما تعمل على تحسين قابلية قراءة الكود للمهندسين البرمجيات الذين هم على دراية بالأنماط.\n\n# البدء في التعلم\n\nيعرض هذا الموقع أنماط تصميم جافا. تم تطوير الحلول من قبل المبرمجين والمهندسين ذوي الخبرة من مجتمع المصادر المفتوحة. يمكن تصفح الأنماط من خلال أوصافها عالية المستوى أو بالنظر إلى كود المصدر الخاص بها. تم كتابة الشرح على أمثلة الكود المصدري جيدًا ويمكن اعتبارها برامج تعليمية حول كيفية تنفيذ نمط معين. نحن نستخدم تقنيات Java مفتوحة المصدر الأكثر شيوعًا والتي أثبتت جدارتها في مشاريع الجافا. \nقبل الغوص في المادة ، يجب أن تكون على دراية [بمبادئ تصميم البرامج المختلفة](https://java-design-patterns.com/principles/).\n\nيجب أن تكون جميع التصميمات بسيطة قدر الإمكان. يجب أن تبدأ بـ KISS و YAGNI وافعل أبسط شيء يمكن أن يعمل بهذه المبادىء. يجب إستخدام الأنماط فقط عند الحاجة إليها من أجل تمديد البرنامج بشكل عملي.\n\nبمجرد أن تصبح معتادًا على هذه المفاهيم ، يمكنك البدء في التعمق في  [أنماط التصميم المتاحة](https://java-design-patterns.com/patterns/) من خلال أي من الأساليب التالية\n\nابحث عن نمط محدد بالاسم. لا يمكنك العثور على واحد؟ الرجاء الإبلاغ عن نمط جديد [هنا](https://github.com/iluwatar/java-design-patterns/issues).\nاستخدام علامات مثل Performance أو Gang of Four أو الوصول إلى البيانات.\nاستخدام فئات الأنماط و Creational, Behavioral وغيرها.\n\nنأمل أن تجد الحلول الموجهة للكائنات المعروضة على هذا الموقع مفيدة في مشاريعك البرمجية وأن تستمتع بتعلمها بقدر ما قمنا بتطويرها.\n\n\n# كيف تساهم؟ \n\nإذا كنت على استعداد للمساهمة في المشروع ، فستجد المعلومات ذات الصلة في [ويكي المطور الخاص بنا](https://github.com/iluwatar/java-design-patterns/wiki). سنساعدك ونجيب على أسئلتك في  [غرفة الدردشة Gitter](https://gitter.im/iluwatar/java-design-patterns).\n\n\n# الترخيص\n\nهذا المشروع مرخص بموجب شروط ترخيص MIT.\n\n"
  },
  {
    "path": "localization/ar/abstract-document/README.md",
    "content": "---\ntitle: Abstract Document\nshortTitle: Abstract Document\ncategory: Structural\nlanguage: ar\ntag:\n  - Extensibility\n---\n\n\n## الهدف\n\nاستخدام الخصائص الديناميكية والحصول على مرونة اللغات غير المتغيرة مع الحفاظ على أمان الأنواع.\n\n## التوضيح\n\nيتيح استخدام نمط الوثيقة المجردة إدارة الخصائص غير الثابتة الإضافية. يستخدم هذا النمط مفهوم \nالسمات لتمكين أمان الأنواع وخصائص مفصولة من فئات مختلفة في مجموعة من الواجهات.\n\nمثال من العالم الحقيقي\n\n> خذ على سبيل المثال سيارة مكونة من العديد من الأجزاء. ومع ذلك، لا نعرف إذا كانت السيارة تحتوي على جميع الأجزاء أو جزء منها فقط. سياراتنا ديناميكية ومرنة للغاية.\n\nبصيغة أخرى\n\n> يسمح نمط الوثيقة المجردة بإضافة خصائص إلى الكائنات دون أن تكون هذه الكائنات على دراية بذلك.\n\nحسب ويكيبيديا\n\n> نمط تصميم هيكلي موجه للكائنات لتنظيم الكائنات في حاويات من نوع مفتاح-قيمة بشكل فضفاض مع نوعية غير محددة، وكشف البيانات باستخدام طرق عرض مهيكلة. الهدف من هذا النمط هو تحقيق درجة عالية من المرونة بين المكونات في لغة قوية النوع حيث يمكن إضافة خصائص جديدة إلى شجرة الكائنات أثناء العمل دون فقدان دعم أمان الأنواع. يستخدم النمط السمات لفصل خصائص مختلفة للفئة إلى واجهات متعددة.\n\n**مثال برمجي**\n\nأولاً، دعونا نعرف الفئات الأساسية `Document` و `AbstractDocument`. في الأساس، تجعل الكائن يحتوي على خريطة من الخصائص وأي عدد من الكائنات الفرعية.\n\n\n```java\npublic interface Document {\n\n  Void put(String key, Object value);\n\n  Object get(String key);\n\n  <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);\n}\n\npublic abstract class AbstractDocument implements Document {\n\n  private final Map<String, Object> properties;\n\n  protected AbstractDocument(Map<String, Object> properties) {\n    Objects.requireNonNull(properties, \"properties map is required\");\n    this.properties = properties;\n  }\n\n  @Override\n  public Void put(String key, Object value) {\n    properties.put(key, value);\n    return null;\n  }\n\n  @Override\n  public Object get(String key) {\n    return properties.get(key);\n  }\n\n  @Override\n  public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {\n    return Stream.ofNullable(get(key))\n        .filter(Objects::nonNull)\n        .map(el -> (List<Map<String, Object>>) el)\n        .findAny()\n        .stream()\n        .flatMap(Collection::stream)\n        .map(constructor);\n  }\n  ...\n}\n```\n\nبعد ذلك، نعرف `enum` لـ `Property` ومجموعة من الواجهات للنمط، السعر، النموذج، والأجزاء. هذا يتيح لنا إنشاء واجهات تظهر بشكل ثابت لفئة `Car`.\n\n\n```java\npublic enum Property {\n\n  PARTS, TYPE, PRICE, MODEL\n}\n\npublic interface HasType extends Document {\n\n  default Optional<String> getType() {\n    return Optional.ofNullable((String) get(Property.TYPE.toString()));\n  }\n}\n\npublic interface HasPrice extends Document {\n\n  default Optional<Number> getPrice() {\n    return Optional.ofNullable((Number) get(Property.PRICE.toString()));\n  }\n}\npublic interface HasModel extends Document {\n\n  default Optional<String> getModel() {\n    return Optional.ofNullable((String) get(Property.MODEL.toString()));\n  }\n}\n\npublic interface HasParts extends Document {\n\n  default Stream<Part> getParts() {\n    return children(Property.PARTS.toString(), Part::new);\n  }\n}\n```\n\nAhora estamos listos para introducir el Coche `Car`.\n\n```java\npublic class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {\n\n  public Car(Map<String, Object> properties) {\n    super(properties);\n  }\n}\n```\n\nوأخيرًا، هكذا نبني ونستخدم السيارة `Car` في مثال كامل.\n\n\n```java\n    LOGGER.info(\"Constructing parts and car\");\n\n    var wheelProperties = Map.of(\n        Property.TYPE.toString(), \"wheel\",\n        Property.MODEL.toString(), \"15C\",\n        Property.PRICE.toString(), 100L);\n\n    var doorProperties = Map.of(\n        Property.TYPE.toString(), \"door\",\n        Property.MODEL.toString(), \"Lambo\",\n        Property.PRICE.toString(), 300L);\n\n    var carProperties = Map.of(\n        Property.MODEL.toString(), \"300SL\",\n        Property.PRICE.toString(), 10000L,\n        Property.PARTS.toString(), List.of(wheelProperties, doorProperties));\n\n    var car = new Car(carProperties);\n\n    LOGGER.info(\"Here is our car:\");\n    LOGGER.info(\"-> model: {}\", car.getModel().orElseThrow());\n    LOGGER.info(\"-> price: {}\", car.getPrice().orElseThrow());\n    LOGGER.info(\"-> parts: \");\n    car.getParts().forEach(p -> LOGGER.info(\"\\t{}/{}/{}\",\n        p.getType().orElse(null),\n        p.getModel().orElse(null),\n        p.getPrice().orElse(null))\n    );\n\n    // Constructing parts and car\n    // Here is our car:\n    // model: 300SL\n    // price: 10000\n    // parts: \n    // wheel/15C/100\n    // door/Lambo/300\n```\n\n## Diagrama de clases\n\n![alt text](./etc/abstract-document.png \"Abstract Document Traits and Domain\")\n\n## التطبيق\n\nاستخدم نمط الوثيقة المجردة عندما:\n\n* يوجد حاجة لإضافة خصائص أثناء العمل.\n* ترغب في طريقة مرنة لتنظيم النطاق في هيكل مشابه لشجرة.\n* ترغب في نظام أقل ترابطًا.\n\n## الحقوق\n\n\n* [Wikipedia: Abstract Document Pattern](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)\n* [Martin Fowler: Dealing with properties](http://martinfowler.com/apsupp/properties.pdf)\n* [Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4)](https://www.amazon.com/gp/product/0470059028/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0470059028&linkId=e3aacaea7017258acf184f9f3283b492)"
  },
  {
    "path": "localization/ar/abstract-factory/README.md",
    "content": "---\ntitle: Abstract Factory\nshortTitle: Abstract Factory\ncategory: Creational\nlanguage: ar\ntag:\n - Gang of Four\n---\n## يُعرف أيضًا باسم\n\nKit\n\n## الهدف\n\nتوفير واجهة لإنشاء عائلات من الكائنات المرتبطة المعتمدة دون تحديد فئتها المحددة.\n\n## التوضيح\n\nمثال من العالم الحقيقي\n\n> لإنشاء مملكة نحتاج إلى كائنات بموضوع مشترك. المملكة الإلفية تحتاج إلى ملك إلفي، وقلعة إلفية، وجيش إلفي، بينما المملكة الأوركية تحتاج إلى ملك أوركي، وقلعة أوركية، وجيش أوركي. هناك اعتماد بين كائنات المملكة.\n\nبصيغة أخرى\n\n> مصنع للمصانع؛ مصنع يجمع بين مصانع فردية ولكنها مرتبطة/معتمدة دون تحديد فئتها المحددة.\n\nحسب ويكيبيديا\n\n> يوفر نمط المصنع المجرد طريقة لتغليف مجموعة من المصانع الفردية التي لها موضوع مشترك دون تحديد فئاتها المحددة.\n\n**مثال برمجي**\n\nترجمة المثال السابق حول الممالك. أولاً لدينا بعض الواجهات والتنفيذات لكائنات `Castle`.\n\n\n```java\npublic interface Castle {\n  String getDescription();\n}\n\npublic interface King {\n  String getDescription();\n}\n\npublic interface Army {\n  String getDescription();\n}\n\n// Elven implementations ->\npublic class ElfCastle implements Castle {\n  static final String DESCRIPTION = \"This is the elven castle!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfKing implements King {\n  static final String DESCRIPTION = \"This is the elven king!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfArmy implements Army {\n  static final String DESCRIPTION = \"This is the elven Army!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\n// التنفيذات Orcish بطريقة مشابهة\n-> ...\n\n```\n\nثم لدينا التجريد والتنفيذ لمصنع المملكة `KingdomFactory`.\n\n\n```java\npublic interface KingdomFactory {\n  Castle createCastle();\n  King createKing();\n  Army createArmy();\n}\n\npublic class ElfKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new ElfCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new ElfKing();\n  }\n\n  @Override\n  public Army createArmy() {\n    return new ElfArmy();\n  }\n}\n\npublic class OrcKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new OrcCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new OrcKing();\n  }\n  \n  @Override\n  public Army createArmy() {\n    return new OrcArmy();\n  }\n}\n```\n\nالآن لدينا المصنع المجرد الذي يسمح لنا بإنشاء عائلات من الكائنات المرتبطة. على سبيل المثال، مصنع المملكة الإلفية `ElfKingdomFactory` يقوم بإنشاء القلعة `castle`، الملك `king`، والجيش `army`، إلخ.\n\n\n\n```java\nvar factory = new ElfKingdomFactory();\nvar castle = factory.createCastle();\nvar king = factory.createKing();\nvar army = factory.createArmy();\n\ncastle.getDescription();\nking.getDescription();\narmy.getDescription();\n```\n\nناتج البرنامج:\n\n\n```java\nThis is the elven castle!\nThis is the elven king!\nThis is the elven Army!\n```\n\nالآن يمكننا تصميم مصنع لمصانع الممالك الخاصة بنا. في هذا المثال، قمنا بإنشاء `FactoryMaker`، المسؤول عن إعادة نسخة من `ElfKingdomFactory` أو `OrcKingdomFactory`.  \nيمكن للعميل استخدام `FactoryMaker` لإنشاء مصنع محدد، والذي بدوره سينتج كائنات محددة مختلفة (مشتقة من `Army` و `King` و `Castle`).  \nفي هذا المثال نستخدم أيضًا `enum` لتمرير نوع مصنع المملكة الذي سيطلبه العميل.\n\n\n```java\npublic static class FactoryMaker {\n\n    public enum KingdomType {\n        ELF, ORC\n    }\n\n    public static KingdomFactory makeFactory(KingdomType type) {\n        return switch (type) {\n            case ELF -> new ElfKingdomFactory();\n            case ORC -> new OrcKingdomFactory();\n            default -> throw new IllegalArgumentException(\"KingdomType not supported.\");\n        };\n    }\n}\n\n    public static void main(String[] args) {\n        var app = new App();\n\n        LOGGER.info(\"Elf Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));\n        LOGGER.info(app.getArmy().getDescription());\n        LOGGER.info(app.getCastle().getDescription());\n        LOGGER.info(app.getKing().getDescription());\n\n        LOGGER.info(\"Orc Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));\n        --similar use of the orc factory\n    }\n```\n\n## مخطط الفئات\n\n![alt text](./etc/abstract-factory.urm.png \"Diagrama de Clases de Abstract Factory\")\n\n\n## التطبيق\n\nاستخدم نمط المصنع المجرد عندما:\n\n* يجب أن يكون النظام غير متحيز حول كيفية إنشاء وتركيب وتمثيل كائناته.\n* يجب تكوين النظام مع إحدى عائلات المنتجات المتعددة.\n* تم تصميم عائلة الكائنات المرتبطة لتستخدم معًا وتحتاج إلى فرض هذا الافتراض.\n* ترغب في توفير مكتبة من المنتجات ولا تريد الكشف عن تنفيذاتها، بل واجهاتها فقط.\n* العمر الافتراضي للاعتماد هو مفهومًا أقصر من عمر العميل.\n* تحتاج إلى قيمة في وقت التشغيل لبناء الاعتماد.\n* تريد تحديد أي منتج من العائلة يتم استدعاؤه في وقت التشغيل.\n* تحتاج إلى توفير واحد أو أكثر من المعلمات المعروفة فقط في وقت التشغيل قبل أن تتمكن من حل الاعتماد.\n* تحتاج إلى الاتساق بين المنتجات.\n* لا تريد تغيير الكود الموجود عند إضافة منتجات أو عائلات جديدة من المنتجات إلى البرنامج.\n\nأمثلة على حالات الاستخدام\n\n* اختيار استدعاء التنفيذ الصحيح لـ FileSystemAcmeService أو DatabaseAcmeService أو NetworkAcmeService في وقت التشغيل.\n* كتابة الاختبارات الوحدوية تصبح أسهل بكثير.\n* أدوات واجهة المستخدم (UI) لأنظمة تشغيل مختلفة (SO).\n\n## العواقب\n\n* إخفاء حقن الاعتمادات في جافا داخل كائنات الخدمة قد يؤدي إلى أخطاء في وقت التشغيل كان يمكن تجنبها في وقت الترجمة.\n* بينما يكون النمط جيدًا في إنشاء كائنات محددة مسبقًا، قد يكون من الصعب إضافة الجديدة.\n* الكود يصبح أكثر تعقيدًا مما ينبغي لأنه يتم إضافة العديد من الواجهات والفئات الجديدة جنبًا إلى جنب مع النمط.\n\n## الدروس التعليمية\n\n* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java) \n\n## الاستخدامات المعروفة\n\n* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)\n* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)\n* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)\n\n## الأنماط المتعلقة\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n\n## الحقوق\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/ar/active-object/README.md",
    "content": "---\ntitle: Active Object\nshortTitle: Active Object\ncategory: Concurrency\nlanguage: ar\ntag:\n - Performance\n---\n\n\n## الهدف\nيفصل نمط التصميم الكائن النشط بين تنفيذ الطريقة واستدعائها للكائنات التي تعمل في خيط تحكم خاص بها. الهدف هو إدخال التزامن باستخدام استدعاءات الطرق غير المتزامنة وجدولة لإدارة الطلبات.\n\n## التوضيح\n\nستحتوي الفئة التي تنفذ نمط التصميم الكائن النشط على آلية مزامنة ذاتية دون استخدام الطرق المتزامنة (synchronized).\n\nمثال من العالم الحقيقي\n\n> الأورك معروفون بوحشيتهم وفلسفتهم في عدم العمل الجماعي. بناءً على هذا السلوك، يمكن القول إن لديهم خيط تحكم خاص بهم.\n\nيمكننا استخدام نمط الكائن النشط لتنفيذ مخلوق لديه خيط تحكم خاص به ويعرض واجهة برمجة التطبيقات (API) الخاصة به، ولكن ليس التنفيذ نفسه.\n\n**مثال برمجي**\n\n\n```java\npublic abstract class ActiveCreature{\n  private final Logger logger = LoggerFactory.getLogger(ActiveCreature.class.getName());\n\n  private BlockingQueue<Runnable> requests;\n  \n  private String name;\n  \n  private Thread thread;\n\n  public ActiveCreature(String name) {\n    this.name = name;\n    this.requests = new LinkedBlockingQueue<Runnable>();\n    thread = new Thread(new Runnable() {\n        @Override\n        public void run() {\n          while (true) {\n            try {\n              requests.take().run();\n            } catch (InterruptedException e) { \n              logger.error(e.getMessage());\n            }\n          }\n        }\n      }\n    );\n    thread.start();\n  }\n  \n  public void eat() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} is eating!\",name());\n          logger.info(\"{} has finished eating!\",name());\n        }\n      }\n    );\n  }\n\n  public void roam() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} has started to roam the wastelands.\",name());\n        }\n      }\n    );\n  }\n  \n  public String name() {\n    return this.name;\n  }\n}\n```\nيمكننا أن نرى أن أي فئة تمتد من ActiveCreature سيكون لديها خيط تحكم خاص بها لاستدعاء وتنفيذ الطرق.\n\nعلى سبيل المثال، الفئة Orc:\n\n```java\npublic class Orc extends ActiveCreature {\n\n  public Orc(String name) {\n    super(name);\n  }\n\n}\n```\nالآن يمكننا إنشاء مخلوقات متعددة مثل الأورك، نطلب منهم الأكل والتجول، وسيفعلون ذلك في خيط التحكم الخاص بهم:\n\n```java\n  public static void main(String[] args) {  \n    var app = new App();\n    app.run();\n  }\n  \n  @Override\n  public void run() {\n    ActiveCreature creature;\n    try {\n      for (int i = 0;i < creatures;i++) {\n        creature = new Orc(Orc.class.getSimpleName().toString() + i);\n        creature.eat();\n        creature.roam();\n      }\n      Thread.sleep(1000);\n    } catch (InterruptedException e) {\n      logger.error(e.getMessage());\n    }\n    Runtime.getRuntime().exit(1);\n  }\n```\n\n## مخطط الفئات  \n\n![alt text](./etc/active-object.urm.png \"Active Object class diagram\")\n\n## الدروس التعليمية\n\n* [Android and Java Concurrency: The Active Object Pattern](https://www.youtube.com/watch?v=Cd8t2u5Qmvc)"
  },
  {
    "path": "localization/ar/acyclic-visitor/README.md",
    "content": "---\ntitle: Acyclic Visitor\nshortTitle: Acyclic Visitor\ncategory: Behavioral\nlanguage: ar\ntag:\n - Extensibility\n---\n## الهدف\n\nالسماح بإضافة وظائف جديدة إلى تسلسلات الفئات الموجودة دون التأثير عليها، ودون إنشاء الدوائر المعتمدة المزعجة التي هي جزء من نمط GoF (Gang of Four) للزائر (Visitor).\n\n## التوضيح\n\nمثال من العالم الحقيقي\n\n> لدينا تسلسل فئات مودم. يجب أن تتم زيارة المودمات في هذه التسلسلات بواسطة خوارزمية خارجية بناءً على بعض الفلاتر (هل المودم متوافق مع Unix أو DOS؟).\n\nبصيغة أخرى\n\n> يتيح نمط Acyclic Visitor إضافة وظائف إلى تسلسلات الفئات الموجودة دون تعديلها.\n\n[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) يقول\n\n> يسمح نمط Acyclic Visitor بإضافة وظائف جديدة إلى تسلسلات الفئات الموجودة دون التأثير عليها، ودون إنشاء الدوائر المعتمدة التي هي جزء من نمط الزائر (Visitor Pattern) في GangOfFour.\n\n**مثال برمجي**\n\nهنا لدينا تسلسل `Modem`.\n\n\n```java\npublic abstract class Modem {\n  public abstract void accept(ModemVisitor modemVisitor);\n}\n\npublic class Zoom extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof ZoomVisitor) {\n      ((ZoomVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only ZoomVisitor is allowed to visit Zoom modem\");\n    }\n  }\n}\n\npublic class Hayes extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof HayesVisitor) {\n      ((HayesVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only HayesVisitor is allowed to visit Hayes modem\");\n    }\n  }\n}\n```\n\nبعد ذلك، لدينا تسلسل `ModemVisitor`.\n\n\n```java\npublic interface ModemVisitor {\n}\n\npublic interface HayesVisitor extends ModemVisitor {\n  void visit(Hayes hayes);\n}\n\npublic interface ZoomVisitor extends ModemVisitor {\n  void visit(Zoom zoom);\n}\n\npublic interface AllModemVisitor extends ZoomVisitor, HayesVisitor {\n}\n\npublic class ConfigureForDosVisitor implements AllModemVisitor {\n  ...\n  @Override\n  public void visit(Hayes hayes) {\n    LOGGER.info(hayes + \" used with Dos configurator.\");\n  }\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Dos configurator.\");\n  }\n}\n\npublic class ConfigureForUnixVisitor implements ZoomVisitor {\n  ...\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Unix configurator.\");\n  }\n}\n```\n\nوأخيرًا، هنا \"الزوار\" في العمل.\n\n\n```java\n    var conUnix = new ConfigureForUnixVisitor();\n    var conDos = new ConfigureForDosVisitor();\n    var zoom = new Zoom();\n    var hayes = new Hayes();\n    hayes.accept(conDos);\n    zoom.accept(conDos);\n    hayes.accept(conUnix);\n    zoom.accept(conUnix);   \n```\n\nناتج البرنامج:\n\n\n```\n    // Hayes modem used with Dos configurator.\n    // Zoom modem used with Dos configurator.\n    // Only HayesVisitor is allowed to visit Hayes modem\n    // Zoom modem used with Unix configurator.\n```\n\n\n## مخطط الفئات\n\n![alt text](./etc/acyclic-visitor.png \"Acyclic Visitor\")\n\n## التطبيق\n\nيمكن استخدام هذا النمط في الحالات التالية:\n\n* عندما تحتاج إلى إضافة وظيفة جديدة إلى تسلسل فئات دون التأثير عليها أو تعديلها.\n* عندما توجد وظائف تعمل على التسلسل ولكنها لا تنتمي إلى التسلسل بحد ذاته. على سبيل المثال، الفئات `ConfigureForDOS` و `ConfigureForUnix` و `ConfigureForX`.\n* عندما تحتاج إلى تنفيذ عمليات مختلفة تمامًا على كائن اعتمادًا على نوعه.\n* عندما يكون من المتوقع توسيع التسلسل الزائر بشكل متكرر باستخدام مشتقات من فئة العنصر.\n* عندما يكون عملية إعادة التجميع، الربط، الاختبار أو توزيع المشتقات من فئة العنصر مرهقة جدًا.\n\n## الدروس التعليمية\n\n* [Acyclic Visitor Pattern Example](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html)\n\n## العواقب\n\nالجوانب الجيدة:\n\n* لا توجد دوائر اعتماد بين التسلسلات.\n* لا حاجة لإعادة تجميع جميع الزوار إذا تم إضافة زائر جديد.\n* لا يسبب أخطاء في الترجمة في الزوار الموجودين إذا كانت التسلسل تحتوي على عضو جديد.\n\nالجوانب السيئة:\n\n\n* ينتهك [مبدأ الاستبدال في ليسكوف](https://java-design-patterns.com/principles/#liskov-substitution-principle) من خلال إظهار أنه يمكن قبول جميع الزوار مع الاهتمام بزائر واحد فقط.\n* يجب إنشاء تسلسل زوار موازٍ لجميع الأعضاء في التسلسل الذي يمكن زيارته.\n\n## الأنماط المتعلقة\n\n* [Visitor Pattern](https://java-design-patterns.com/patterns/visitor/)\n\n\n## الحقوق\n\n\n* [Acyclic Visitor by Robert C. Martin](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf)\n* [Acyclic Visitor in WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor)\n"
  },
  {
    "path": "localization/ar/adapter/README.md",
    "content": "---\ntitle: Adapter\nshortTitle: Adapter\ncategory: Structural\nlanguage: ar\ntag:\n - Gang of Four\n---\n\n## أيضًا معروف بـ\nالغطاء (Wrapper)\n\n## الهدف\nتحويل واجهة فئة إلى واجهة أخرى يتوقعها العميل. يتيح نمط المحول (Adapter) للفئات العمل مع فئات أخرى التي لا يمكنها العمل معها في الظروف العادية بسبب مشاكل التوافق.\n\n## التوضيح\n\nمثال من العالم الحقيقي\n\n> تخيل أنك تمتلك بعض الصور في بطاقة ذاكرة وتريد نقلها إلى جهاز الكمبيوتر الخاص بك. لنقل الصور، تحتاج إلى نوع من المحول الذي يتوافق مع منافذ جهاز الكمبيوتر الخاص بك ويسمح لك بإدخال البطاقة. في هذه الحالة، قارئ البطاقات هو محول (Adapter).\n> مثال آخر هو محول التيار الكهربائي؛ إذا كان هناك قابس بثلاثة دبابيس ولا يمكن توصيله بمنفذ كهربائي به ثقبين، فإنه يحتاج إلى محول لجعله متوافقًا مع المنفذ.\n> مثال آخر هو مترجم يترجم كلمات من شخص لآخر.\n\nبصيغة أخرى\n\n> يتيح نمط المحول (Adapter) تغليف كائن داخل محول لجعله متوافقًا مع فئة سيكون غير متوافق معها بطريقة أخرى.\n\nحسب ويكيبيديا\n\n> في هندسة البرمجيات، نمط المحول هو نمط تصميم برمجي يسمح باستخدام واجهة فئة موجودة كواجهة مختلفة. وغالبًا ما يُستخدم لجعل الفئات الموجودة تعمل مع فئات أخرى دون الحاجة إلى تعديل كود المصدر الخاص بها.\n\n**مثال برمجي**\n\nخذ على سبيل المثال قبطان يمكنه فقط استخدام القوارب التي تعمل بالمجاديف ولا يمكنه الإبحار على الإطلاق.\n\nأولاً، لدينا الواجهات `RowingBoat` (قارب المجاديف) و `FishingBoat` (قارب الصيد).\n\n```java\npublic interface RowingBoat {\n  void row();\n}\n\n@Slf4j\npublic class FishingBoat {\n  public void sail() {\n    LOGGER.info(\"The fishing boat is sailing\");\n  }\n}\n```\n\nويتوقع القبطان تنفيذ واجهة `RowingBoat` (قارب المجاديف) ليتمكن من التحرك.\n\n\n```java\npublic class Captain {\n\n  private final RowingBoat rowingBoat;\n  // default constructor and setter for rowingBoat\n  public Captain(RowingBoat rowingBoat) {\n    this.rowingBoat = rowingBoat;\n  }\n\n  public void row() {\n    rowingBoat.row();\n  }\n}\n```\n\nالآن لنفترض أن مجموعة من القراصنة قد جاءت ويجب على قائدنا الهروب، ولكن هناك فقط قارب صيد. نحتاج إلى إنشاء محول يسمح للقائد باستخدام قارب الصيد مع مهاراته لاستخدام القوارب التي تعمل بالمجاديف.\n\n\n```java\n@Slf4j\npublic class FishingBoatAdapter implements RowingBoat {\n\n  private final FishingBoat boat;\n\n  public FishingBoatAdapter() {\n    boat = new FishingBoat();\n  }\n\n  @Override\n  public void row() {\n    boat.sail();\n  }\n}\n```\n\nوالآن يمكن لـ `Captain` (القائد) استخدام `FishingBoat` (قارب الصيد) للهروب من القراصنة.\n\n\n```java\nvar captain = new Captain(new FishingBoatAdapter());\ncaptain.row();\n```\n\n## مخطط الفئات\n![alt text](./etc/adapter.urm.png \"Adapter class diagram\")\n\n## التطبيق\nاستخدم نمط المحول (Adapter) عندما:\n\n* تريد استخدام فئة موجودة وواجهتها لا تتناسب مع ما تحتاجه.\n* تريد إنشاء فئة قابلة لإعادة الاستخدام تتعاون مع فئات غير مرتبطة أو لم يكن من المخطط تعاونها معًا، أي فئات ليس لديها بالضرورة واجهات متوافقة.\n* تحتاج إلى استخدام عدة فئات فرعية موجودة، ولكن من غير العملي تعديل واجهتها عن طريق إنشاء فئات فرعية لكل واحدة. يمكن للمحول تعديل واجهة الفئة الأصلية.\n* العديد من التطبيقات التي تستخدم مكتبات طرف ثالث تستخدم المحولات كطبقات وسيطة بين التطبيق والمكتبة لفصل التطبيق عن المكتبة. إذا كان من الضروري استخدام مكتبة أخرى، يكفي إنشاء محول للمكتبة الجديدة دون الحاجة إلى تعديل كود التطبيق.\n\n## الدروس\n\n\n* [Dzone](https://dzone.com/articles/adapter-design-pattern-in-java)\n* [Refactoring Guru](https://refactoring.guru/design-patterns/adapter/java/example)\n* [Baeldung](https://www.baeldung.com/java-adapter-pattern)\n\n## العواقب\nالمحولات بين الفئات والكائنات لها خصائص مختلفة. محول الفئات\n\n* يقوم بإجراء التكيف ويرتبط بفئة محددة. كنتيجة لذلك، لن يعمل محول الفئات عندما نريد تكيف فئة وفئاتها الفرعية.\n* يسمح للمحول بتعديل سلوك الفئة المتكيفة لأن المحول هو فئة فرعية من الفئة المتكيفة.\n* يستخدم كائنًا واحدًا ولا يحتاج إلى استخدام مؤشرات إضافية للإشارة إلى الفئة المتكيفة.\n\nمحوّل الكائنات\n\n* يسمح للمحول الواحد بالعمل مع العديد من الفئات، أي مع الفئة المتكيفة وكل الفئات الفرعية لها (إذا كانت موجودة). يمكن للمحول أيضًا إضافة وظائف إلى جميع الفئات المتكيفة في نفس الوقت.\n* يجعل من الصعب تعديل سلوك الفئة المتكيفة. سيكون من الضروري إنشاء فئة فرعية للفئة المتكيفة وجعل المحول يشير إلى الفئة الفرعية بدلاً من الفئة الأصلية.\n\n## أمثلة من العالم الواقعي\n\n\n* [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)\n* [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)\n* [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-)\n* [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-)\n\n\n## الشكر\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/ar/aggregator-microservices/README.md",
    "content": "---\ntitle: Aggregator Microservices\nshortTitle: Aggregator Microservices\ncategory: Architectural\nlanguage: ar\ntag:\n- Cloud distributed\n- Decoupling\n- Microservices\n---\n\n## الهدف\n\nيقوم المستخدم بإجراء مكالمة واحدة إلى خدمة المجمع، ومن ثم يقوم المجمع بالاتصال بكل خدمة ميكروسيرفيس ذات صلة.\n\n## الشرح\n\nمثال من العالم الواقعي\n\n> يحتاج سوقنا الإلكتروني إلى معلومات حول المنتجات والمخزون الحالي. يقوم بإجراء مكالمة إلى خدمة المجمع التي بدورها تتصل بخدمة ميكروسيرفيس المعلومات الخاصة بالمنتج وخدمة ميكروسيرفيس المخزون للمنتج التي تعيد المعلومات مجمعة.\n\nببساطة\n\n> يقوم ميكروسيرفيس المجمع بجمع البيانات من عدة ميكروسيرفيسات ويعيد النتيجة مجمعة لمعالجتها.\n\nيقول StackOverflow\n\n> يقوم ميكروسيرفيس المجمع بالاتصال بعدة خدمات لتحقيق الوظيفة المطلوبة من التطبيق.\n\n**مثال برمجي**\n\nلنبدأ بنموذج البيانات. هنا هو `Product`.\n\n\n```java\npublic class Product {\n  private String title;\n  private int productInventories;\n  // getters and setters ->\n  ...\n}\n```\n\nبعد ذلك، يمكننا تقديم ميكروسيرفيسنا `Aggregator` (مجمع الميكروسيرفيسات). يحتوي على `ProductInformationClient` (عميل معلومات المنتج) و\n`ProductInventoryClient` (عميل مخزون المنتج) للاتصال بالميكروسيرفيسات المعنية.\n\n\n```java\n@RestController\npublic class Aggregator {\n\n  @Resource\n  private ProductInformationClient informationClient;\n\n  @Resource\n  private ProductInventoryClient inventoryClient;\n\n  @RequestMapping(path = \"/product\", method = RequestMethod.GET)\n  public Product getProduct() {\n\n    var product = new Product();\n    var productTitle = informationClient.getProductTitle();\n    var productInventory = inventoryClient.getProductInventories();\n\n    //Fallback to error message\n    product.setTitle(requireNonNullElse(productTitle, \"Error: Fetching Product Title Failed\"));\n\n    //Fallback to default error inventory\n    product.setProductInventories(requireNonNullElse(productInventory, -1));\n\n    return product;\n  }\n}\n```\n\nهذه هي جوهر تنفيذ الميكروسيرفيسات للمعلومات. ميكروسيرفيس المخزون مشابه، ببساطة يعيد\nعدد المخزون.\n\n\n```java\n@RestController\npublic class InformationController {\n  @RequestMapping(value = \"/information\", method = RequestMethod.GET)\n  public String getProductTitle() {\n    return \"The Product Title.\";\n  }\n}\n```\n\nالآن عند استدعاء واجهة برمجة التطبيقات REST الخاصة بنا `Aggregator` تُرجع معلومات المنتج.\n\n\n```bash\ncurl http://localhost:50004/product\n{\"title\":\"The Product Title.\",\"productInventories\":5}\n```\n\n## مخطط الفئة\n\n![alt text](./aggregator-service/etc/aggregator-service.png \"Aggregator Microservice\")\n\n## قابلية التطبيق\n\nاستخدم نمط تجميع الميكروسيرفيسات (Aggregator Microservices) عندما تحتاج إلى واجهة برمجة تطبيقات موحدة لعدة ميكروسيرفيسات، بغض النظر عن جهاز العميل.\n\n\n## الشكر\n\n* [أنماط تصميم الميكروسيرفيس](http://web.archive.org/web/20190705163602/http://blog.arungupta.me/microservice-design-patterns/)\n* [أنماط الميكروسيرفيس: مع أمثلة في Java](https://www.amazon.com/gp/product/1617294543/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617294543&linkId=8b4e570267bc5fb8b8189917b461dc60)\n* [أنماط العمارة: اكتشاف الأنماط الأساسية في أكثر المجالات ضرورة في العمارة المؤسسية](https://www.amazon.com/gp/product/B077T7V8RC/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=B077T7V8RC&linkId=c34d204bfe1b277914b420189f09c1a4)\n"
  },
  {
    "path": "localization/ar/ambassador/README.md",
    "content": "---\ntitle: Ambassador\nshortTitle: Ambassador\ncategory: Structural\nlanguage: ar\ntag:\n  - Decoupling\n  - Cloud distributed\n---\n\n## الهدف\n\nتوفير مثيل من الخدمة المساعدة للعميل وتفويض الوظائف المشتركة لها من مصدر مشترك.\n\n## الشرح\n\nمثال واقعي\n\n> خدمة بعيدة تحتوي على العديد من العملاء الذين يصلون إلى وظيفة تقدمها هذه الخدمة. الخدمة هي تطبيق قديم ومن\n> المستحيل تحديثها. عدد كبير من الطلبات من قبل المستخدمين تسبب مشاكل في الاتصال. يجب تنفيذ قواعد جديدة\n> بشأن تكرار الطلبات جنبًا إلى جنب مع فحوصات التأخير والسجلات من جانب العميل.\n\nبكلمات أخرى\n\n> باستخدام نمط Ambassador، يمكننا تنفيذ تقليل تكرار الطلبات من العملاء جنبًا إلى جنب مع فحوصات التأخير\n> والسجلات.\n\nوفقًا لوثائق مايكروسوفت\n\n> يمكن اعتبار خدمة Ambassador وكأنها وكيل خارج العملية يتواجد جنبًا إلى جنب مع العميل.\n>\n> يمكن أن يكون هذا النمط مفيدًا لتفريغ المهام المشتركة في الاتصال من العميل مثل المراقبة، السجلات، التوجيه،\n> الأمان (مثل TLS) وأنماط المقاومة (*) بطريقة مستقلة عن اللغة. غالبًا ما يُستخدم مع التطبيقات القديمة،\n> أو التطبيقات الأخرى التي يصعب تعديلها، بهدف توسيع قدراتها في الشبكات. يمكنه أيضًا\n> تمكين فريق متخصص لتنفيذ هذه الميزات.\n\n**مثال على الكود**\n\nمع المقدمة السابقة في الاعتبار، سنقوم بمحاكاة وظيفتها في المثال التالي. لدينا واجهة يتم تنفيذها\nمن قبل الخدمة البعيدة وكذلك خدمة Ambassador:\n\n```java\ninterface RemoteServiceInterface {\n    long doRemoteFunction(int value) throws Exception;\n}\n```\n\n## خدمة بعيدة ممثلة كـ Singleton (مثيل واحد).\n\n```java\n@Slf4j\npublic class RemoteService implements RemoteServiceInterface {\n    private static RemoteService service = null;\n\n    static synchronized RemoteService getRemoteService() {\n        if (service == null) {\n            service = new RemoteService();\n        }\n        return service;\n    }\n\n    private RemoteService() {}\n\n    @Override\n    public long doRemoteFunction(int value) {\n        long waitTime = (long) Math.floor(Math.random() * 1000);\n\n        try {\n            sleep(waitTime);\n        } catch (InterruptedException e) {\n            LOGGER.error(\"Thread sleep interrupted\", e);\n        }\n\n        return waitTime >= 200 ? value * 10 : -1;\n    }\n}\n```\n\n## خدمة السفير مع إضافة وظائف إضافية مثل السجلات والتحقق من الكمون\n\n```java\n@Slf4j\npublic class ServiceAmbassador implements RemoteServiceInterface {\n  private static final int RETRIES = 3;\n  private static final int DELAY_MS = 3000;\n\n  ServiceAmbassador() {\n  }\n\n  @Override\n  public long doRemoteFunction(int value) {\n    return safeCall(value);\n  }\n\n  private long checkLatency(int value) {\n    var startTime = System.currentTimeMillis();\n    var result = RemoteService.getRemoteService().doRemoteFunction(value);\n    var timeTaken = System.currentTimeMillis() - startTime;\n\n    LOGGER.info(\"Time taken (ms): \" + timeTaken);\n    return result;\n  }\n\n  private long safeCall(int value) {\n    var retries = 0;\n    var result = (long) FAILURE;\n\n    for (int i = 0; i < RETRIES; i++) {\n      if (retries >= RETRIES) {\n        return FAILURE;\n      }\n\n      if ((result = checkLatency(value)) == FAILURE) {\n        LOGGER.info(\"Failed to reach remote: (\" + (i + 1) + \")\");\n        retries++;\n        try {\n          sleep(DELAY_MS);\n        } catch (InterruptedException e) {\n          LOGGER.error(\"Thread sleep state interrupted\", e);\n        }\n      } else {\n        break;\n      }\n    }\n    return result;\n  }\n}\n```\n\nالعميل لديه خدمة سفير محلية تستخدم للتفاعل مع الخدمة البعيدة:\n\n\n```java\n@Slf4j\npublic class Client {\n  private final ServiceAmbassador serviceAmbassador = new ServiceAmbassador();\n\n  long useService(int value) {\n    var result = serviceAmbassador.doRemoteFunction(value);\n    LOGGER.info(\"Service result: \" + result);\n    return result;\n  }\n}\n```\n\nبعد ذلك، لدينا عميلان يستخدمان الخدمة:\n\n\n```java\npublic class App {\n  public static void main(String[] args) {\n    var host1 = new Client();\n    var host2 = new Client();\n    host1.useService(12);\n    host2.useService(73);\n  }\n}\n```\n\nهذه هي النتيجة التي سنحصل عليها بعد تنفيذ المثال:\n\n\n```java\nTime taken (ms): 111\nService result: 120\nTime taken (ms): 931\nFailed to reach remote: (1)\nTime taken (ms): 665\nFailed to reach remote: (2)\nTime taken (ms): 538\nFailed to reach remote: (3)\nService result: -1\n```\n\n## مخطط الفئات\n\n![alt text](./etc/ambassador.urm.png \"مخطط فئات Ambassador\")\n\n## التطبيقات\n\nيتم تطبيق نمط Ambassador عندما نعمل مع خدمة بعيدة قديمة لا يمكن تعديلها أو أنه سيكون من الصعب للغاية تعديلها. يمكن تنفيذ خصائص الاتصال في العميل دون الحاجة إلى إجراء تغييرات على الخدمة البعيدة.\n\n* يوفر Ambassador واجهة محلية لخدمة بعيدة.\n* يوفر Ambassador سجلات، انقطاع الدائرة، إعادة المحاولات، والأمان في العميل.\n\n## حالات الاستخدام النموذجية\n\n* التحكم في الوصول إلى كائن آخر\n* تنفيذ السجلات أو السجلات\n* تنفيذ انقطاع الدائرة\n* تفويض مهام الخدمات البعيدة\n* تسهيل الاتصال بالشبكة\n\n## الاستخدامات المعروفة\n\n* [بوابة API المدمجة مع Kubernetes للخدمات الصغيرة](https://github.com/datawire/ambassador)\n\n## الأنماط ذات الصلة\n\n* [الوكيل (Proxy)](https://java-design-patterns.com/patterns/proxy/)\n\n## الشكر\n\n* [نمط Ambassador (وثائق Microsoft باللغة الإنجليزية)](https://docs.microsoft.com/en-us/azure/architecture/patterns/ambassador)\n* [تصميم الأنظمة الموزعة: الأنماط والمفاهيم للخدمات القابلة للتوسع وموثوقة](https://www.amazon.com/s?k=designing+distributed+systems&sprefix=designing+distri%2Caps%2C156&linkCode=ll2&tag=javadesignpat-20&linkId=a12581e625462f9038557b01794e5341&language=en_US&ref_=as_li_ss_tl)\n\n## ملاحظات المترجم\n(*) تشير النسخة الأصلية بالإنجليزية من وثائق Microsoft إلى مصطلح المرونة\nوفي الترجمة الإسبانية يتم ترجمته إلى المقاومة، على الرغم من ربطه بالقسم الخاص بنمط الموثوقية. انظر:\n* [نسخة الوثائق الخاصة بنمط Ambassador من Microsoft باللغة الإسبانية.](https://learn.microsoft.com/es-es/azure/architecture/patterns/ambassador)\n"
  },
  {
    "path": "localization/ar/api-gateway/README.md",
    "content": "---\ntitle: API Gateway\nshortTitle: API Gateway\ncategory: Architectural\nlanguage: ar\ntag:\n  - Cloud distributed\n  - Decoupling\n  - Microservices\n---\n\n## الهدف\n\nإضافة استدعاءات إلى الخدمات الصغيرة في نفس المكان، بوابة API (API Gateway). يقوم المستخدم \nبإجراء استدعاء بسيط إلى بوابة API، وتقوم بوابة API بدورها باستدعاء كل خدمة صغيرة ذات صلة.\n\n## الشرح\n\nمع نمط الخدمات الصغيرة، قد يحتاج العميل إلى بيانات من عدة خدمات صغيرة. إذا كان \nالعميل سيستدعي كل خدمة صغيرة بشكل مباشر، فقد يؤدي ذلك إلى أوقات تحميل طويلة، حيث \nيجب على العميل إجراء طلب شبكة لكل خدمة صغيرة يتم استدعاؤها. بالإضافة إلى ذلك، وجود \nاستدعاء العميل لكل خدمة صغيرة يربط العميل مباشرة بتلك الخدمة الصغيرة - إذا حدث تغيير داخلي \nفي الخدمات الصغيرة (على سبيل المثال، إذا تم دمج خدمتين صغيرتين في وقت ما في المستقبل) أو إذا تغير الموقع (الخادم والمنفذ) لأحد الخدمات الصغيرة، فإن كل \nعميل يستخدم تلك الخدمات الصغيرة يجب تحديثه.\n\nالهدف من نمط بوابة API هو تخفيف بعض هذه المشاكل. في نمط بوابة API، يتم وضع كيان إضافي \n(بوابة API) بين العميل والخدمات الصغيرة. \nمهمة بوابة API هي إضافة استدعاءات إلى الخدمات الصغيرة. بدلاً من أن يقوم العميل \nبإجراء استدعاء لكل خدمة صغيرة على حدة، يقوم العميل باستدعاء بوابة API مرة واحدة فقط. ثم تقوم بوابة \nAPI باستدعاء كل واحدة من الخدمات الصغيرة التي يحتاجها العميل.\n\nمثال واقعي\n\n> نحن نطبق نظام خدمات صغيرة وبوابة API لموقع تجارة إلكترونية. في هذا \n> النظام تقوم بوابة API بإجراء استدعاءات إلى خدمات Image و Price. (الصورة والسعر)\n\nبمعنى آخر\n\n> في نظام يتم تنفيذه باستخدام بنية خدمات صغيرة، تعتبر بوابة API هي النقطة \n> الوحيدة للوصول التي تجمع استدعاءات الخدمات الصغيرة الفردية.\n\nتقول ويكيبيديا\n\n> بوابة API هي خادم يعمل كواجهة أمامية لـ API، يستقبل طلبات API، ويطبق \n> حدودًا وسياسات الأمان، ويرسل الطلبات إلى الخدمة الخلفية ثم يعيد \n> الاستجابة إلى الطالب. غالبًا ما تشمل بوابة API محركًا للتحويل لتنظيم \n> وتعديل الطلبات والاستجابات أثناء سير العملية. يمكن أن توفر بوابة \n> API أيضًا وظائف مثل جمع تحليلات البيانات والتخزين المؤقت. قد \n> توفر بوابة API وظائف لدعم المصادقة، والتفويض، والأمان، \n> والتدقيق، والامتثال.\n\n**كود المثال**\n\nيوضح هذا التنفيذ كيف قد يبدو نمط بوابة API لموقع تجارة إلكترونية. تقوم \n`ApiGateway` بإجراء استدعاءات إلى خدمات Image و Price باستخدام \n`ImageClientImpl` و `PriceClientImpl` على التوالي. العملاء الذين يشاهدون الموقع \nعلى جهاز مكتبي يمكنهم مشاهدة معلومات الأسعار وصورة المنتج، لذلك تقوم `ApiGateway` \nبإجراء استدعاء إلى الخدمات الصغيرة وجمع البيانات في نموذج `DesktopProduct`. \nومع ذلك، فإن مستخدمي الأجهزة المحمولة يرون فقط معلومات الأسعار، ولا يشاهدون صورة المنتج. \nبالنسبة لمستخدمي الأجهزة المحمولة، تقوم `ApiGateway` فقط \nبالحصول على معلومات الأسعار، والتي تستخدم لإكمال `MobileProduct`.\n\nإليك تنفيذ خدمة الصورة (Image).\n\n\n```java\npublic interface ImageClient {\n  String getImagePath();\n}\n\npublic class ImageClientImpl implements ImageClient {\n  @Override\n  public String getImagePath() {\n    var httpClient = HttpClient.newHttpClient();\n    var httpGet = HttpRequest.newBuilder()\n        .GET()\n        .uri(URI.create(\"http://localhost:50005/image-path\"))\n        .build();\n\n    try {\n      var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n      return httpResponse.body();\n    } catch (IOException | InterruptedException e) {\n      e.printStackTrace();\n    }\n\n    return null;\n  }\n}\n```\n\nإليك تنفيذ خدمة المصغرة للسعر (Price).\n\n```java\npublic interface PriceClient {\n  String getPrice();\n}\n\npublic class PriceClientImpl implements PriceClient {\n\n  @Override\n  public String getPrice() {\n    var httpClient = HttpClient.newHttpClient();\n    var httpGet = HttpRequest.newBuilder()\n        .GET()\n        .uri(URI.create(\"http://localhost:50006/price\"))\n        .build();\n\n    try {\n      var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n      return httpResponse.body();\n    } catch (IOException | InterruptedException e) {\n      e.printStackTrace();\n    }\n\n    return null;\n  }\n}\n```\n\nهنا يمكننا أن نرى كيف تقوم بوابة الـ API بتوجيه الطلبات إلى الخدمات المصغرة.\n\n```java\npublic class ApiGateway {\n\n  @Resource\n  private ImageClient imageClient;\n\n  @Resource\n  private PriceClient priceClient;\n\n  @RequestMapping(path = \"/desktop\", method = RequestMethod.GET)\n  public DesktopProduct getProductDesktop() {\n    var desktopProduct = new DesktopProduct();\n    desktopProduct.setImagePath(imageClient.getImagePath());\n    desktopProduct.setPrice(priceClient.getPrice());\n    return desktopProduct;\n  }\n\n  @RequestMapping(path = \"/mobile\", method = RequestMethod.GET)\n  public MobileProduct getProductMobile() {\n    var mobileProduct = new MobileProduct();\n    mobileProduct.setPrice(priceClient.getPrice());\n    return mobileProduct;\n  }\n}\n```\n\n## مخطط الفئة\n\n![alt text](./etc/api-gateway.png \"API Gateway\")\n\n## التطبيقات\n\nاستخدم نمط API Gateway عندما\n\n* تكون تستخدم بنية ميكروسيرفيسز وتحتاج إلى نقطة تجميع واحدة لاستدعاءات الميكروسيرفيسز.\n\n## الدروس التعليمية\n\n* [Exploring the New Spring Cloud Gateway](https://www.baeldung.com/spring-cloud-gateway)\n* [Spring Cloud - Gateway](https://www.tutorialspoint.com/spring_cloud/spring_cloud_gateway.htm)\n* [Getting Started With Spring Cloud Gateway](https://dzone.com/articles/getting-started-with-spring-cloud-gateway)\n\n## الشكر\n\n* [microservices.io - API Gateway](http://microservices.io/patterns/apigateway.html)\n* [NGINX - Building Microservices: Using an API Gateway](https://www.nginx.com/blog/building-microservices-using-an-api-gateway/)\n* [Microservices Patterns: With examples in Java](https://www.amazon.com/gp/product/1617294543/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617294543&linkId=ac7b6a57f866ac006a309d9086e8cfbd)\n* [Building Microservices: Designing Fine-Grained Systems](https://www.amazon.com/gp/product/1491950358/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1491950358&linkId=4c95ca9831e05e3f0dadb08841d77bf1)\n"
  },
  {
    "path": "localization/ar/arrange-act-assert/README.md",
    "content": "---\ntitle: Arrange/Act/Assert\nshortTitle: Arrange/Act/Assert\ncategory: Idiom\nlanguage: ar\ntag:\n - Testing\n---\n\n## أيضا معروف بـ\n\nDado/Cuando/Entonces\n\n## الغرض\n\nArrange/Act/Assert (AAA) هو نمط لتنظيم اختبارات الوحدة.\nيقسم اختبارات الوحدة إلى ثلاث خطوات واضحة ومميزة:\n\n1. Arrange(تنظيم): قم بإعداد التهيئة والتهيئة اللازمة للاختبار.\n2. Act(العمل): اتخذ التدابير اللازمة للاختبار.\n3. Assert(التأكيد): تحقق من نتائج الاختبار.\n\n## الشرح\n\nلهذا النمط العديد من الفوائد الكبيرة. فهو يخلق فصلًا واضحًا بين إعدادات الاختبار، العمليات والنتائج. هذا الهيكل يجعل الكود أسهل في القراءة والفهم. إذا\nوضعت الخطوات بالترتيب وصيغت الكود بطريقة تفصلها، يمكنك مسح الاختبار وفهمه بسرعة.\n\nكما أنه يفرض درجة معينة من الانضباط عند كتابة اختبارات الوحدة. يجب أن تكون قادرًا على تصور\nبوضوح الخطوات الثلاث التي سيقوم بها اختبارك. هذا يجعل الاختبارات أكثر بديهية للكتابة مع الحفاظ على هيكل واضح.\n\nمثال يومي\n\n> نحتاج إلى كتابة مجموعة من اختبارات الوحدة كاملة وواضحة لفئة.\n\nبعبارة أخرى\n\n> Arrange/Act/Assert هو نمط اختبار ينظم الاختبارات إلى ثلاث خطوات واضحة لتسهيل\n> الصيانة.\n\nWikiWikiWeb يقول\n\n> Arrange/Act/Assert هو نمط لتنظيم وتنسيق الكود في طرق اختبار الوحدة.\n\n**كود المثال**\n\nلنلقِ نظرة أولاً على فئتنا `Cash` التي سيتم اختبارها.\n\n\n```java\npublic class Cash {\n\n  private int amount;\n\n  Cash(int amount) {\n    this.amount = amount;\n  }\n\n  void plus(int addend) {\n    amount += addend;\n  }\n\n  boolean minus(int subtrahend) {\n    if (amount >= subtrahend) {\n      amount -= subtrahend;\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  int count() {\n    return amount;\n  }\n}\n```\n\nثم نكتب اختبارات الوحدة الخاصة بنا بناءً على نمط Arrange/Act/Assert. لاحظ بوضوح الفصل بين الخطوات لكل اختبار وحدة.\n\n\n```java\nclass CashAAATest {\n\n  @Test\n  void testPlus() {\n    //Arrange\n    var cash = new Cash(3);\n    //Act\n    cash.plus(4);\n    //Assert\n    assertEquals(7, cash.count());\n  }\n\n  @Test\n  void testMinus() {\n    //Arrange\n    var cash = new Cash(8);\n    //Act\n    var result = cash.minus(5);\n    //Assert\n    assertTrue(result);\n    assertEquals(3, cash.count());\n  }\n\n  @Test\n  void testInsufficientMinus() {\n    //Arrange\n    var cash = new Cash(1);\n    //Act\n    var result = cash.minus(6);\n    //Assert\n    assertFalse(result);\n    assertEquals(1, cash.count());\n  }\n\n  @Test\n  void testUpdate() {\n    //Arrange\n    var cash = new Cash(5);\n    //Act\n    cash.plus(6);\n    var result = cash.minus(3);\n    //Assert\n    assertTrue(result);\n    assertEquals(8, cash.count());\n  }\n}\n```\n\n## القابلية للتطبيق\n\nاستخدم نمط Arrange/Act/Assert عندما\n\n* تحتاج إلى تنظيم اختبارات الوحدة الخاصة بك لتكون أسهل في القراءة والصيانة والتحسين.\n\n## الشكر\n\n* [Arrange, Act, Assert: ¿Qué son las pruebas AAA?](https://blog.ncrunch.net/post/arrange-act-assert-aaa-testing.aspx)\n* [Bill Wake: 3A – Arrange, Act, Assert](https://xp123.com/articles/3a-arrange-act-assert/)\n* [Martin Fowler: DadoCuandoEntonces](https://martinfowler.com/bliki/GivenWhenThen.html)\n* [Patrones de prueba xUnit: Refactorizando Código de prueba](https://www.amazon.com/gp/product/0131495054/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0131495054&linkId=99701e8f4af2f63d0bcf50)\n* [Principios, prácticas y patrones UnitTesting](https://www.amazon.com/gp/product/1617296279/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617296279&linkId=74c75cfae3a5aaccae3a5a)\n* [Desarrollo basado en pruebas: Ejemplo](https://www.amazon.com/gp/product/0321146530/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0321146530&linkId=5c63a93d8c1175b47caef50875)\n"
  },
  {
    "path": "localization/ar/async-method-invocation/README.md",
    "content": "---\ntitle: Async Method Invocation\nshortTitle: Async Method Invocation\ncategory: Concurrency\nlanguage: ar\ntag:\n - Reactive\n---\n\n## الغرض\n\nالاستدعاء غير المتزامن للطرق (invocación de método asincrónico) هو نمط حيث لا يتم حظر الخيط أو العملية التي تستدعي الطريقة أثناء انتظار النتائج. يوفر النمط معالجة متوازية للمهام المستقلة المتعددة ويسترجع النتائج عبر\nالتعريفات الراجعة (callbacks) أو بالانتظار حتى ينتهي الإجراء.\n\n## الشرح\n\nمثال يومي\n\n> إطلاق الصواريخ الفضائية هو عمل مثير. يعطي قائد المهمة أمر الإطلاق و\n> بعد فترة غير محددة من الوقت، يتم إطلاق الصاروخ بنجاح أو يفشل بشكل كارثي.\n\nبعبارة أخرى\n\n> يستدعي الاستدعاء غير المتزامن للطرق الإجراء ويعود فورًا قبل أن تنتهي المهمة\n> يتم إرجاع نتائج الإجراء لاحقًا إلى الاستدعاء (callback).\n\nحسب ويكيبيديا\n\n> في البرمجة متعددة العمليات، يعتبر استدعاء الطريقة غير المتزامن (AMI)، المعروف أيضًا بـ\n> الاستدعاءات غير المتزامنة أو النمط غير المتزامن هو نمط تصميم حيث لا يتم حظر مكان الاستدعاء\n> أثناء انتظار انتهاء الكود المستدعى. بدلاً من ذلك، يتم إخطار خيط الاستدعاء عندما تصل الاستجابة. الاستطلاع للحصول على إجابة هو خيار غير مرغوب فيه.\n\n**مثال برمجي**\n\nفي هذا المثال، نحن نطلق صواريخ فضائية وننشر مركبات قمرية.\n\nتُظهر التطبيق ما يفعله نمط الاستدعاء غير المتزامن للطريقة. الأجزاء الرئيسية للنمط هي\n`AsyncResult` الذي يعد حاوية وسيطة لقيمة تم تقييمها بشكل غير متزامن،\n`AsyncCallback` الذي يمكن توفيره ليتم تنفيذه عند اكتمال المهمة و `AsyncExecutor` الذي\nيدير تنفيذ المهام غير المتزامنة.\n\n\n```java\npublic interface AsyncResult<T> {\n  boolean isCompleted();\n  T getValue() throws ExecutionException;\n  void await() throws InterruptedException;\n}\n```\n\n```java\npublic interface AsyncCallback<T> {\n  void onComplete(T value, Optional<Exception> ex);\n}\n```\n\n```java\npublic interface AsyncExecutor {\n  <T> AsyncResult<T> startProcess(Callable<T> task);\n  <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback);\n  <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException;\n}\n```\n\n`ThreadAsyncExecutor` هو تنفيذ لـ `AsyncExecutor`. يتم تسليط الضوء على بعض من أجزائه الرئيسية أدناه.\n\n\n```java\npublic class ThreadAsyncExecutor implements AsyncExecutor {\n\n  @Override\n  public <T> AsyncResult<T> startProcess(Callable<T> task) {\n    return startProcess(task, null);\n  }\n\n  @Override\n  public <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback) {\n    var result = new CompletableResult<>(callback);\n    new Thread(\n            () -> {\n              try {\n                result.setValue(task.call());\n              } catch (Exception ex) {\n                result.setException(ex);\n              }\n            },\n            \"executor-\" + idx.incrementAndGet())\n        .start();\n    return result;\n  }\n\n  @Override\n  public <T> T endProcess(AsyncResult<T> asyncResult)\n      throws ExecutionException, InterruptedException {\n    if (!asyncResult.isCompleted()) {\n      asyncResult.await();\n    }\n    return asyncResult.getValue();\n  }\n}\n```\n\nالآن كل شيء جاهز لإطلاق بعض الصواريخ لرؤية كيف يعمل كل شيء.\n\n\n```java\npublic static void main(String[] args) throws Exception {\n  // الآن كل شيء جاهز لإطلاق بعض الصواريخ لرؤية كيف يعمل كل شيء.\n\n  var executor = new ThreadAsyncExecutor();\n\n // يبدأ بعض المهام غير المتزامنة بأوقات معالجة مختلفة، اثنان من الأخيرين مع محركات استرجاع (callback handlers)\n\n  final var asyncResult1 = executor.startProcess(lazyval(10, 500));\n  final var asyncResult2 = executor.startProcess(lazyval(\"test\", 300));\n  final var asyncResult3 = executor.startProcess(lazyval(50L, 700));\n  final var asyncResult4 = executor.startProcess(lazyval(20, 400), callback(\"Desplegando el rover lunar\"));\n  final var asyncResult5 =\n      executor.startProcess(lazyval(\"devolución de llamada callback\", 600), callback(\"Desplegando el rover lunar\"));\n\n // يحاكي المعالجة في الخيط أو العملية الحالية بينما يتم تنفيذ المهام غير المتزامنة في خيوط أو عملياتها الخاصة\n\n  Subproceso.dormir(350); // هيه، نحن نعمل بجد هنا\n\n  log(\"قائد المهمة يشرب القهوة\n\");\n\n // ينتظر حتى اكتمال المهام\n\n  final var result1 = executor.endProcess(asyncResult1);\n  final var result2 = executor.endProcess(asyncResult2);\n  final var result3 = executor.endProcess(asyncResult3);\n  asyncResult4.await();\n  asyncResult5.await();\n\n// يسجل نتائج المهام، يتم تسجيل الاسترجاعات فور اكتمالها\nlog(\"الصاروخ الفضائي <\" + resultado1 + \"> أكمل إطلاقه\");\nlog(\"الصاروخ الفضائي <\" + resultado2 + \"> أكمل إطلاقه\");\nlog(\"الصاروخ الفضائي <\" + result3 + \"> أكمل إطلاقه\");\n\n}\n```\n\nHere is the output from the program console.\n\n```java\n21:47:08.227 [executor-2] INFO com.iluwatar.async.method.invocation.App - الصاروخ الفضائي <prueba> تم إطلاقه بنجاح\n21:47:08.269 [main] INFO com.iluwatar.async.method.invocation.App - قائد المهمة يشرب القهوة\n21:47:08.318 [executor-4] INFO com.iluwatar.async.method.invocation.App - الصاروخ الفضائي <20> تم إطلاقه بنجاح\n21:47:08.335 [executor-4] INFO com.iluwatar.async.method.invocation.App - نشر الروفر القمري <20>\n21:47:08.414 [executor-1] INFO com.iluwatar.async.method.invocation.App  - الصاروخ الفضائي <10> تم إطلاقه بنجاح\n21:47:08.519 [executor-5] INFO com.iluwatar.async.method.invocation.App - الصاروخ الفضائي <devolución de llamada callback> تم إطلاقه بنجاح\n21:47:08.519 [executor-5] INFO com.iluwatar.async.method.invocation.App - تنفيذ المركبة القمرية <devolución de llamada callback>\n21:47:08.616 [executor-3] INFO com.iluwatar.async.method.invocation.App - الصاروخ الفضائي <50> تم إطلاقه بنجاح\n21:47:08.617 [main] INFO com.iluwatar.async.method.invocation.App - إطلاق الصاروخ الفضائي <10> تم\n21:47:08.617 [main] INFO com.iluwatar.async.method.invocation.App - إطلاق الصاروخ الفضائي <prueba> تم\n21:47:08.618 [main] INFO com.iluwatar.async.method.invocation.App - إطلاق الصاروخ الفضائي <50> تم\n\n```\n\n# مخطط الفئة\n\n![texto alternativo](./etc/async-method-invocation.png \"Invocación de método asíncrono\")\n\n## القابلية للتطبيق\n\nاستخدم نمط استدعاء الطريقة غير المتزامنة عندما\n\n* يكون لديك مهام مستقلة متعددة يمكن تنفيذها بشكل متوازٍ\n* تحتاج إلى تحسين أداء مجموعة من المهام المتسلسلة\n* لديك قدرة معالجة محدودة أو مهام تنفيذ طويلة الأمد ولا ينبغي أن تنتظر الدعوة حتى تصبح المهام جاهزة\n\n## أمثلة يومية\n\n* [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html)\n* [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)\n* [ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html)\n* [Patrón asíncrono basado en tareas](https://msdn.microsoft.com/en-us/library/hh873175.aspx)\n"
  },
  {
    "path": "localization/ar/balking/README.md",
    "content": "---\ntitle: Balking\nshortTitle: Balking\ncategory: Concurrency\nlanguage: ar\ntag:\n - Decoupling\n---\n\n## الغرض\n\nيتم استخدام نمط _Balking_ لمنع كائن من تنفيذ كود معين إذا كان في حالة غير مكتملة أو غير مناسبة.\n\n## الشرح\n\nمثال من الحياة الواقعية\n\n> في غسالة الملابس هناك زر بدء لتشغيل غسل الملابس. عندما تكون الغسالة غير نشطة، يعمل الزر كما هو متوقع، ولكن إذا كانت الغسالة تغسل بالفعل، فإن الزر لا يفعل شيئًا.\n\nبمعنى آخر\n\n> باستخدام نمط _Balking_، يتم تنفيذ كود معين فقط إذا كان الكائن في حالة معينة.\n\nتقول ويكيبيديا\n\n> نمط _Balking_ هو نمط تصميم برمجي ينفذ إجراء على كائن فقط عندما يكون الكائن في حالة معينة. على سبيل المثال، إذا كان الكائن يقرأ ملفات ZIP واستدعى أسلوب _get_ على الكائن عندما لا يكون الملف ZIP مفتوحًا، فإن الكائن \"يرفض\" (_balk_) الطلب.\n\n**مثال برمجي**\n\nفي هذا المثال من التنفيذ، `WashingMachine` هو كائن له حالتان يمكن أن يكونا: _ENABLED_ و _WASHING_ (مفعل و يغسل على التوالي). إذا كانت الغسالة في حالة _ENABLED_، فإن الحالة تتغير إلى _WASHING_ باستخدام طريقة آمنة ضد الخيوط (thread-safe). من ناحية أخرى، إذا كانت الغسالة بالفعل تغسل وأي خيط آخر ينفذ `wash()`، فلن يتم تغيير الحالة وتنتهي تنفيذ الطريقة دون القيام بأي شيء.\n\nإليك الأجزاء ذات الصلة من فئة `WashingMachine`.\n\n\n```java\n@Slf4j\npublic class WashingMachine {\n\n    private final DelayProvider delayProvider;\n    private WashingMachineState washingMachineState;\n\n    public WashingMachine(DelayProvider delayProvider) {\n        this.delayProvider = delayProvider;\n        this.washingMachineState = WashingMachineState.ENABLED;\n    }\n\n    public WashingMachineState getWashingMachineState() {\n        return washingMachineState;\n    }\n    \n    public void wash() {\n        synchronized (this) {\n            var machineState = getWashingMachineState();\n            LOGGER.info(\"{}: Actual machine state: {}\", Thread.currentThread().getName(), machineState);\n            if (this.washingMachineState == WashingMachineState.WASHING) {\n                LOGGER.error(\"Cannot wash if the machine has been already washing!\");\n                return;\n            }\n            this.washingMachineState = WashingMachineState.WASHING;\n        }\n        LOGGER.info(\"{}: Doing the washing\", Thread.currentThread().getName());\n        this.delayProvider.executeAfterDelay(50, TimeUnit.MILLISECONDS, this::endOfWashing);\n    }\n    \n    public synchronized void endOfWashing() {\n        washingMachineState = WashingMachineState.ENABLED;\n        LOGGER.info(\"{}: Washing completed.\", Thread.currentThread().getId());\n    }\n}\n```\n\nهنا الواجهة البسيطة `DelayProvider` المستخدمة من قبل `WashingMachine`.\n\n\n```java\npublic interface DelayProvider {\n    void executeAfterDelay(long interval, TimeUnit timeUnit, Runnable task);\n}\n```\n\nالآن نقدم التطبيق باستخدام `WashingMachine`.\n\n\n```java\npublic static void main(String... args) {\n    final var washingMachine = new WashingMachine();\n    var executorService = Executors.newFixedThreadPool(3);\n    for (int i = 0; i < 3; i++) {\n        executorService.execute(washingMachine::wash);\n    }\n    executorService.shutdown();\n    try {\n        executorService.awaitTermination(10, TimeUnit.SECONDS);    \n    } catch (InterruptedException ie) {\n        LOGGER.error(\"ERROR: Waiting on executor service shutdown!\");\n        Thread.currentThread().interrupt();\n    }\n}\n```\n\nإليك مخرجات التطبيق في وحدة التحكم.\n\n\n```\n14:02:52.268 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Actual machine state: ENABLED\n14:02:52.272 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Doing the washing\n14:02:52.272 [pool-1-thread-3] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-3: Actual machine state: WASHING\n14:02:52.273 [pool-1-thread-3] ERROR com.iluwatar.balking.WashingMachine - Cannot wash if the machine has been already washing!\n14:02:52.273 [pool-1-thread-1] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-1: Actual machine state: WASHING\n14:02:52.273 [pool-1-thread-1] ERROR com.iluwatar.balking.WashingMachine - Cannot wash if the machine has been already washing!\n14:02:52.324 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - 14: Washing completed.\n```\n\n## مخطط الفئات\n\n\n![alt text](./etc/balking.png \"Balking\")\n\n## القابلية للتطبيق\n\nاستخدم نمط _Balking_ عندما\n\n* يجب على كائن تنفيذ كود معين فقط عندما يكون في حالة معينة.\n* الكائنات في حالة معرضة للتوقف مؤقتًا، ولكن لفترة زمنية غير محددة.\n\n## الأنماط ذات الصلة\n\n\n* [Guarded Suspension Pattern](https://java-design-patterns.com/patterns/guarded-suspension/)\n* [Double Checked Locking Pattern](https://java-design-patterns.com/patterns/double-checked-locking/)\n\n## المراجع\n\n\n* [Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML, 2nd Edition, Volume 1](https://www.amazon.com/gp/product/0471227293/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0471227293&linkId=0e39a59ffaab93fb476036fecb637b99)\n"
  },
  {
    "path": "localization/ar/bridge/README.md",
    "content": "---\ntitle: Bridge\nshortTitle: Bridge\ncategory: Structural\nlanguage: ar\ntag:\n  - Gang of Four\n---\n\n## أيضًا معروف باسم\n\nHandle/Body\n\n## الهدف\n\nفصل التجريد عن تنفيذه بحيث يمكن لكل منهما التغيير بشكل مستقل.\n\n## الشرح\n\nمثال من الحياة الواقعية\n\n> تخيل أن لديك سلاحًا مع تعاويذ مختلفة، ومن المفترض أن تسمح بخلط أسلحة مختلفة مع تعاويذ مختلفة. ماذا ستفعل؟ هل ستقوم بإنشاء نسخ متعددة من كل سلاح لكل تعويذة من التعاويذ أو ببساطة تقوم بإنشاء تعويذة منفصلة وتحددها للسلاح حسب الحاجة؟ نمط Bridge يتيح لك القيام بالأمر الثاني.\n\nببساطة\n\n> يتعلق نمط Bridge بتفضيل التركيب على الوراثة. يتم دفع تفاصيل التنفيذ من هرم إلى كائن آخر مع هرم منفصل.\n\nتقول ويكيبيديا\n\n> نمط Bridge هو نمط تصميم يستخدم في هندسة البرمجيات يهدف إلى \"فصل التجريد عن تنفيذه بحيث يمكن لكل منهما التغيير بشكل مستقل.\"\n\n**مثال برمجي**\n\nنقلًا لمثال السلاح المذكور أعلاه. هنا لدينا واجهة السلاح `Weapon`:\n\n\n```java\npublic interface Weapon {\n  void wield();\n  void swing();\n  void unwield();\n  Enchantment getEnchantment();\n}\n\npublic class Sword implements Weapon {\n\n  private final Enchantment enchantment;\n\n  public Sword(Enchantment enchantment) {\n    this.enchantment = enchantment;\n  }\n\n  @Override\n  public void wield() {\n    LOGGER.info(\"The sword is wielded.\");\n    enchantment.onActivate();\n  }\n\n  @Override\n  public void swing() {\n    LOGGER.info(\"The sword is swinged.\");\n    enchantment.apply();\n  }\n\n  @Override\n  public void unwield() {\n    LOGGER.info(\"The sword is unwielded.\");\n    enchantment.onDeactivate();\n  }\n\n  @Override\n  public Enchantment getEnchantment() {\n    return enchantment;\n  }\n}\n\npublic class Hammer implements Weapon {\n\n  private final Enchantment enchantment;\n\n  public Hammer(Enchantment enchantment) {\n    this.enchantment = enchantment;\n  }\n\n  @Override\n  public void wield() {\n    LOGGER.info(\"The hammer is wielded.\");\n    enchantment.onActivate();\n  }\n\n  @Override\n  public void swing() {\n    LOGGER.info(\"The hammer is swinged.\");\n    enchantment.apply();\n  }\n\n  @Override\n  public void unwield() {\n    LOGGER.info(\"The hammer is unwielded.\");\n    enchantment.onDeactivate();\n  }\n\n  @Override\n  public Enchantment getEnchantment() {\n    return enchantment;\n  }\n}\n```\n\nإليك واجهة التعاويذ `Enchantment` المنفصلة:\n\n\n```java\npublic interface Enchantment {\n  void onActivate();\n  void apply();\n  void onDeactivate();\n}\n\npublic class FlyingEnchantment implements Enchantment {\n\n  @Override\n  public void onActivate() {\n    LOGGER.info(\"The item begins to glow faintly.\");\n  }\n\n  @Override\n  public void apply() {\n    LOGGER.info(\"The item flies and strikes the enemies finally returning to owner's hand.\");\n  }\n\n  @Override\n  public void onDeactivate() {\n    LOGGER.info(\"The item's glow fades.\");\n  }\n}\n\npublic class SoulEatingEnchantment implements Enchantment {\n\n  @Override\n  public void onActivate() {\n    LOGGER.info(\"The item spreads bloodlust.\");\n  }\n\n  @Override\n  public void apply() {\n    LOGGER.info(\"The item eats the soul of enemies.\");\n  }\n\n  @Override\n  public void onDeactivate() {\n    LOGGER.info(\"Bloodlust slowly disappears.\");\n  }\n}\n```\n\nإليك كلا الواجهتين في العمل:\n\n\n```java\nLOGGER.info(\"The knight receives an enchanted sword.\");\nvar enchantedSword = new Sword(new SoulEatingEnchantment());\nenchantedSword.wield();\nenchantedSword.swing();\nenchantedSword.unwield();\n\nLOGGER.info(\"The valkyrie receives an enchanted hammer.\");\nvar hammer = new Hammer(new FlyingEnchantment());\nhammer.wield();\nhammer.swing();\nhammer.unwield();\n```\n\nإليك مخرجات التطبيق في وحدة التحكم.\n\n\n```\nThe knight receives an enchanted sword.\nThe sword is wielded.\nThe item spreads bloodlust.\nThe sword is swung.\nThe item eats the soul of enemies.\nThe sword is unwielded.\nBloodlust slowly disappears.\nThe valkyrie receives an enchanted hammer.\nThe hammer is wielded.\nThe item begins to glow faintly.\nThe hammer is swung.\nThe item flies and strikes the enemies finally returning to owner's hand.\nThe hammer is unwielded.\nThe item's glow fades.\n```\n\n## مخطط الفئات\n\n\n![alt text](./etc/bridge.urm.png \"Bridge diagrama de clases\")\n\n## القابلية للتطبيق\n\nاستخدم نمط Bridge عندما\n\n* ترغب في تجنب الربط الدائم بين التجريد وتنفيذه. قد يكون هذا هو الحال، على سبيل المثال، عندما يجب اختيار أو تغيير التنفيذ في وقت التشغيل.\n* يجب أن تكون كل من التجريدات وتنفيذاتها قابلة للتوسيع عبر الوراثة. في هذه الحالة، يتيح لك نمط Bridge دمج التجريدات والتنفيذات المختلفة وتوسيعها بشكل مستقل.\n* يجب ألا تؤثر التغييرات في تنفيذ التجريد على العملاء؛ أي أنه لا يجب أن يحتاج الكود الخاص بهم إلى إعادة تجميع.\n* لديك تكاثر في الفئات. تشير مثل هذه الهرميات إلى الحاجة إلى تقسيم كائن إلى جزئين. يستخدم Rumbaugh مصطلح \"التعميمات المتداخلة\" للإشارة إلى مثل هذه الهرميات من الفئات.\n* ترغب في مشاركة تنفيذ بين عدة كائنات (ربما باستخدام عد مرجعي)، ويجب إخفاء هذه الحقيقة عن العميل. مثال بسيط هو فئة String لـ Coplien، حيث يمكن لعدة كائنات مشاركة نفس تمثيل السلسلة.\n\n## الدروس التعليمية\n\n* [Bridge Pattern Tutorial](https://www.journaldev.com/1491/bridge-design-pattern-java)\n\n## الاعتمادات\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/ar/builder/README.md",
    "content": "---\ntitle: Builder\nshortTitle: Builder\ncategory: Creational\nlanguage: ar\ntag:\n  - Gang of Four\n---\n\n## الهدف\n\nفصل بناء كائن معقد عن تمثيله بحيث يمكن لنفس عملية البناء إنشاء تمثيلات مختلفة.\n\n## الشرح\n\nمثال من الحياة الواقعية\n\n> تخيل مولد شخصيات للعبة تقمص أدوار. الخيار الأسهل هو السماح للكمبيوتر بإنشاء الشخصية نيابة عنك. إذا أردت تحديد تفاصيل الشخصية يدويًا مثل المهنة، الجنس، لون الشعر، إلخ، فإن إنشاء الشخصية يصبح عملية خطوة بخطوة تكتمل عندما تكون جميع الاختيارات جاهزة.\n\nببساطة\n\n> يسمح بإنشاء نكهات مختلفة من كائن دون تلويث الباني. مفيد عندما يمكن أن يكون هناك عدة نكهات لكائن ما، أو عندما تكون هناك العديد من الخطوات المعنية في إنشاء الكائن.\n\nتقول ويكيبيديا\n\n> نمط البناء هو نمط تصميم برمجي لإنشاء الكائنات بهدف إيجاد حل لمضاد النمط الخاص بالباني المنطقي.\n\nمع ذلك، دعني أضيف بعض المعلومات حول ما هو مضاد النمط للباني المنطقي. في وقت ما أو آخر، رأينا جميعًا بانيًا مثل التالي:\n\n\n```java\npublic Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) {\n}\n```\n\nكما ترى، قد يخرج عدد معلمات الباني عن السيطرة بسرعة، وقد يصبح من الصعب فهم ترتيب المعلمات. بالإضافة إلى ذلك، قد تستمر هذه القائمة في النمو إذا أردت إضافة المزيد من الخيارات في المستقبل. يسمى هذا مضاد النمط للباني المنطقي.\n\n**مثال برمجي**\n\nالبديل الحكيم هو استخدام نمط Builder. أولاً، لدينا بطلنا `Hero` الذي نريد إنشائه:\n\n\n```java\npublic final class Hero {\n  private final Profession profession;\n  private final String name;\n  private final HairType hairType;\n  private final HairColor hairColor;\n  private final Armor armor;\n  private final Weapon weapon;\n\n  private Hero(Builder builder) {\n    this.profession = builder.profession;\n    this.name = builder.name;\n    this.hairColor = builder.hairColor;\n    this.hairType = builder.hairType;\n    this.weapon = builder.weapon;\n    this.armor = builder.armor;\n  }\n}\n```\n\nثم لدينا الباني:\n\n\n```java\n  public static class Builder {\n    private final Profession profession;\n    private final String name;\n    private HairType hairType;\n    private HairColor hairColor;\n    private Armor armor;\n    private Weapon weapon;\n\n    public Builder(Profession profession, String name) {\n      if (profession == null || name == null) {\n        throw new IllegalArgumentException(\"profession and name can not be null\");\n      }\n      this.profession = profession;\n      this.name = name;\n    }\n\n    public Builder withHairType(HairType hairType) {\n      this.hairType = hairType;\n      return this;\n    }\n\n    public Builder withHairColor(HairColor hairColor) {\n      this.hairColor = hairColor;\n      return this;\n    }\n\n    public Builder withArmor(Armor armor) {\n      this.armor = armor;\n      return this;\n    }\n\n    public Builder withWeapon(Weapon weapon) {\n      this.weapon = weapon;\n      return this;\n    }\n\n    public Hero build() {\n      return new Hero(this);\n    }\n  }\n```\n\nإذن يمكن استخدامه كما يلي:\n\n\n```java\nvar mage = new Hero.Builder(Profession.MAGE, \"Riobard\").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();\n```\n\n## مخطط الفئات\n\n![alt text](./etc/builder.urm.png \"مخطط فئات Builder\")\n\n## القابلية للتطبيق\n\nاستخدم نمط Builder عندما\n\n* يجب أن يكون الخوارزمية لإنشاء كائن معقدة مستقلة عن الأجزاء التي تتكون منها الكائن وكيفية تجميعها.\n* يجب أن تسمح عملية البناء بتمثيلات مختلفة للكائن الذي يتم بناؤه.\n\n## الدروس التعليمية\n\n* [Refactoring Guru](https://refactoring.guru/design-patterns/builder)\n* [مدونة Oracle](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java)\n* [Journal Dev](https://www.journaldev.com/1425/builder-design-pattern-in-java)\n\n## الاستخدامات في العالم الواقعي\n\n* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)\n* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) بالإضافة إلى غيرها من المخازن المؤقتة مثل FloatBuffer و IntBuffer، إلخ.\n* [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-)\n* جميع التطبيقات من [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)\n* [بناة Apache Camel](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)\n* [Apache Commons Option.Builder](https://commons.apache.org/proper/commons-cli/apidocs/org/apache/commons/cli/Option.Builder.html)\n\n## الاعتمادات\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/ar/business-delegate/README.md",
    "content": "---\ntitle: Business Delegate\nshortTitle: Business Delegate\ncategory: Structural\nlanguage: ar\ntag:\n  - Decoupling\n---\n\n## الغرض\n\nنمط **Business Delegate** يضيف طبقة من التجريد بين مستويات العرض والأعمال. باستخدام هذا النمط، نحقق ارتباطًا مرنًا بين المستويات ونعزل المعرفة حول كيفية تحديد المواقع والاتصال والتفاعل مع الكائنات التجارية التي تشكل التطبيق.\n\n## أيضًا معروف باسم\n\nمُمثل الخدمة\n\n## الشرح\n\nمثال من العالم الحقيقي\n\n> تطبيق للهواتف المحمولة يعد ببث أي فيلم موجود إلى جهازك. يقوم التطبيق بالتقاط سلسلة البحث من المستخدم ويمررها إلى **Business Delegate**. يقوم **Business Delegate** باختيار خدمة البث الأكثر ملاءمة ويبدأ في تشغيل الفيديو.\n\nبكلمات أبسط\n\n> يضيف **Business Delegate** طبقة من التجريد بين مستويات العرض والأعمال.\n\nتقول ويكيبيديا\n\n> **Business Delegate** هو نمط تصميم في Java EE. هذا النمط يهدف إلى تقليل الترابط بين خدمات الأعمال ومستوى العرض المتصل، وإخفاء تفاصيل التنفيذ الخاصة بالخدمات (بما في ذلك البحث والوصول إلى بنية EJB). يعمل **Business Delegate** كـ **مهايئ** لاستدعاء كائنات الأعمال من طبقة العرض.\n\n**مثال برمجي**\n\nأولاً، لدينا تجريد لخدمات البث عبر الفيديو `VideoStreamingService` مع زوج من التطبيقات `NetflixService` و `YouTubeService`.\n\n\n```java\npublic interface VideoStreamingService {\n    void doProcessing();\n}\n\n@Slf4j\npublic class NetflixService implements VideoStreamingService {\n    @Override\n    public void doProcessing() {\n        LOGGER.info(\"NetflixService is now processing\");\n    }\n}\n\n@Slf4j\npublic class YouTubeService implements VideoStreamingService {\n    @Override\n    public void doProcessing() {\n        LOGGER.info(\"YouTubeService is now processing\");\n    }\n}\n```\n\nالتالي، لدينا خدمة البحث `BusinessLookup` التي تقرر أي خدمة بث الفيديو يجب استخدامها.\n\n\n```java\n\n@Setter\npublic class BusinessLookup {\n\n    private NetflixService netflixService;\n    private YouTubeService youTubeService;\n\n    public VideoStreamingService getBusinessService(String movie) {\n        if (movie.toLowerCase(Locale.ROOT).contains(\"die hard\")) {\n            return netflixService;\n        } else {\n            return youTubeService;\n        }\n    }\n}\n```\n\nيستخدم **Delegado de Negocio** `BusinessDelegate` بحث الأعمال لتوجيه طلبات تشغيل الأفلام إلى خدمة بث الفيديو المناسبة.\n\n\n```java\n\n@Setter\npublic class BusinessDelegate {\n\n    private BusinessLookup lookupService;\n\n    public void playbackMovie(String movie) {\n        VideoStreamingService videoStreamingService = lookupService.getBusinessService(movie);\n        videoStreamingService.doProcessing();\n    }\n}\n```\n\nالعميل المحمول `MobileClient` يستخدم **Business Delegate** لاستدعاء مستوى الأعمال.\n\n\n```java\npublic class MobileClient {\n\n    private final BusinessDelegate businessDelegate;\n\n    public MobileClient(BusinessDelegate businessDelegate) {\n        this.businessDelegate = businessDelegate;\n    }\n\n    public void playbackMovie(String movie) {\n        businessDelegate.playbackMovie(movie);\n    }\n}\n```\n\nأخيرًا، يمكننا عرض المثال الكامل أثناء التنفيذ.\n\n\n```java\n  public static void main(String[]args){\n\n        // preparar los objetos\n        var businessDelegate=new BusinessDelegate();\n        var businessLookup=new BusinessLookup();\n        businessLookup.setNetflixService(new NetflixService());\n        businessLookup.setYouTubeService(new YouTubeService());\n        businessDelegate.setLookupService(businessLookup);\n\n        // crear el cliente y utilizar el Business Delegate\n        var client=new MobileClient(businessDelegate);\n        client.playbackMovie(\"Die Hard 2\");\n        client.playbackMovie(\"Maradona: The Greatest Ever\");\n        }\n```\n\nإليك مخرجات وحدة التحكم.\n\n\n```\n21:15:33.790 [main] INFO com.iluwatar.business.delegate.NetflixService - NetflixService is now processing\n21:15:33.794 [main] INFO com.iluwatar.business.delegate.YouTubeService - YouTubeService is now processing\n```\n\n## مخطط الفئات\n\n![مخطط الفئات](./etc/business-delegate.urm.png \"Business Delegate\")\n\n## الأنماط ذات الصلة\n\n* [نمط تحديد الموقع للخدمات](https://java-design-patterns.com/patterns/service-locator/)\n\n## القابلية للتطبيق\n\nاستخدم نمط Business Delegate عندما\n\n* ترغب في تقليل الترابط بين مستويات العرض والأعمال.\n* ترغب في تنسيق المكالمات إلى خدمات أعمال متعددة.\n* ترغب في تجميع عمليات البحث والمكالمات إلى الخدمات.\n* من الضروري تجريد وتغليف الاتصال بين طبقة العميل وخدمات الأعمال.\n\n## دروس\n\n* [نمط Business Delegate في TutorialsPoint](https://www.tutorialspoint.com/design_pattern/business_delegate_pattern.htm)\n\n## الاستخدامات المعروفة\n\n* التطبيقات المؤسسية التي تستخدم Java EE (Java Platform, Enterprise Edition)\n* التطبيقات التي تتطلب الوصول عن بُعد إلى خدمات الأعمال\n\n## العواقب\n\nالفوائد:\n\n* فك الترابط بين مستويات العرض والأعمال: يسمح بمواصلة تطور مستوى العميل والخدمات المؤسسية بشكل مستقل.\n* شفافية الموقع: لا يتأثر العملاء بتغييرات الموقع أو التهيئة لخدمات الأعمال.\n* إعادة الاستخدام وقابلية التوسع: يمكن إعادة استخدام كائنات Business Delegate بواسطة عملاء متعددين، ويدعم النمط التوازن في الحمل وقابلية التوسع.\n\nالعيوب:\n\n* التعقيد: يضيف طبقات وتجريدات إضافية قد تزيد من التعقيد.\n* تحميل الأداء: قد يؤدي الإشارة الإضافية إلى خفض طفيف في الأداء.\n\n## الأنماط ذات الصلة\n\n* [محدد خدمات](https://java-design-patterns.com/patterns/service-locator/): يستخدم Delegado de Negocio (\n  Business Delegate) محدد خدمات (Service Locator) للعثور على خدمات الأعمال.\n* [واجهة الجلسة](https://java-design-patterns.com/patterns/session-facade/): يمكن لـ Delegado de Negocio (Business\n  Delegate) استخدام واجهة الجلسة (Session Facade) لتوفير واجهة موحدة لمجموعة من خدمات الأعمال.\n* [كائن مركب](https://java-design-patterns.com/patterns/composite-entity/): يمكن لـ Delegado de Negocio (Business Delegate)\n  استخدام الكائن المركب (Composite Entity) لإدارة حالة خدمات الأعمال.\n\n## الشكر\n\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://www.amazon.com/gp/product/0130648841/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0130648841&linkId=a0100de2b28c71ede8db1757fb2b5947)\n"
  },
  {
    "path": "localization/ar/bytecode/README.md",
    "content": "---\ntitle: Bytecode\nshortTitle: Bytecode\ncategory: Behavioral\nlanguage: ar\ntag:\n    - Game programming\n---\n\n## الغرض\n\nيسمح بترميز السلوك كتعليمات لجهاز افتراضي.\n\n## الشرح\n\nمثال من العالم الواقعي\n\n> فريق يعمل على لعبة جديدة حيث يتقاتل السحرة مع بعضهم البعض. يحتاج سلوك السحرة إلى تعديل دقيق وتجربة مئات المرات من خلال اختبارات اللعبة. ليس من المثالي أن يطلب من المبرمج إجراء تغييرات في كل مرة يريد فيها مصمم اللعبة تعديل السلوك، لذلك يتم تنفيذ سلوك الساحر كجهاز افتراضي يعتمد على البيانات.\n\nبكلمات بسيطة\n\n> نمط Bytecode يسمح بسلوك موجه بالبيانات بدلاً من الكود.\n\n[Gameprogrammingpatterns.com](https://gameprogrammingpatterns.com/bytecode.html) يوضح الوثائق:\n\n> مجموعة من التعليمات تحدد العمليات منخفضة المستوى التي يمكن تنفيذها. يتم ترميز سلسلة من التعليمات كدورة من البايتات. يقوم الجهاز الافتراضي بتنفيذ هذه التعليمات واحدة تلو الأخرى، باستخدام مكدس للقيم الوسيطة. يسمح الجمع بين التعليمات بتعريف سلوكيات معقدة وعالية المستوى.\n\n**مثال برمجي**\n\nأحد الكائنات الأكثر أهمية في اللعبة هو فئة ماغو `Wizard`.\n\n\n```java\n\n@AllArgsConstructor\n@Setter\n@Getter\n@Slf4j\npublic class Wizard {\n\n    private int health;\n    private int agility;\n    private int wisdom;\n    private int numberOfPlayedSounds;\n    private int numberOfSpawnedParticles;\n\n    public void playSound() {\n        LOGGER.info(\"Playing sound\");\n        numberOfPlayedSounds++;\n    }\n\n    public void spawnParticles() {\n        LOGGER.info(\"Spawning particles\");\n        numberOfSpawnedParticles++;\n    }\n}\n```\n\nبعد ذلك، نعرض التعليمات المتاحة لجهازنا الافتراضي. لكل تعليمات دلالتها الخاصة حول كيفية التعامل مع بيانات المكدس. على سبيل المثال، تقوم التعليمة ADD بأخذ العنصرين العلويين من المكدس، وتجمعهما، ثم تضع النتيجة في المكدس.\n\n\n```java\n\n@AllArgsConstructor\n@Getter\npublic enum Instruction {\n\n    LITERAL(1),         // e.g. \"LITERAL 0\", push 0 to stack\n    SET_HEALTH(2),      // e.g. \"SET_HEALTH\", pop health and wizard number, call set health\n    SET_WISDOM(3),      // e.g. \"SET_WISDOM\", pop wisdom and wizard number, call set wisdom\n    SET_AGILITY(4),     // e.g. \"SET_AGILITY\", pop agility and wizard number, call set agility\n    PLAY_SOUND(5),      // e.g. \"PLAY_SOUND\", pop value as wizard number, call play sound\n    SPAWN_PARTICLES(6), // e.g. \"SPAWN_PARTICLES\", pop value as wizard number, call spawn particles\n    GET_HEALTH(7),      // e.g. \"GET_HEALTH\", pop value as wizard number, push wizard's health\n    GET_AGILITY(8),     // e.g. \"GET_AGILITY\", pop value as wizard number, push wizard's agility\n    GET_WISDOM(9),      // e.g. \"GET_WISDOM\", pop value as wizard number, push wizard's wisdom\n    ADD(10),            // e.g. \"ADD\", pop 2 values, push their sum\n    DIVIDE(11);         // e.g. \"DIVIDE\", pop 2 values, push their division\n    // ...\n}\n```\n\nفي قلب مثالنا توجد فئة `VirtualMachine`. تأخذ التعليمات كمدخلات وتنفذها لتوفير سلوك كائن اللعبة.\n\n\n```java\n\n@Getter\n@Slf4j\npublic class VirtualMachine {\n\n    private final Stack<Integer> stack = new Stack<>();\n\n    private final Wizard[] wizards = new Wizard[2];\n\n    public VirtualMachine() {\n        wizards[0] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),\n                0, 0);\n        wizards[1] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),\n                0, 0);\n    }\n\n    public VirtualMachine(Wizard wizard1, Wizard wizard2) {\n        wizards[0] = wizard1;\n        wizards[1] = wizard2;\n    }\n\n    public void execute(int[] bytecode) {\n        for (var i = 0; i < bytecode.length; i++) {\n            Instruction instruction = Instruction.getInstruction(bytecode[i]);\n            switch (instruction) {\n                case LITERAL:\n                    // Read the next byte from the bytecode.\n                    int value = bytecode[++i];\n                    // Push the next value to stack\n                    stack.push(value);\n                    break;\n                case SET_AGILITY:\n                    var amount = stack.pop();\n                    var wizard = stack.pop();\n                    setAgility(wizard, amount);\n                    break;\n                case SET_WISDOM:\n                    amount = stack.pop();\n                    wizard = stack.pop();\n                    setWisdom(wizard, amount);\n                    break;\n                case SET_HEALTH:\n                    amount = stack.pop();\n                    wizard = stack.pop();\n                    setHealth(wizard, amount);\n                    break;\n                case GET_HEALTH:\n                    wizard = stack.pop();\n                    stack.push(getHealth(wizard));\n                    break;\n                case GET_AGILITY:\n                    wizard = stack.pop();\n                    stack.push(getAgility(wizard));\n                    break;\n                case GET_WISDOM:\n                    wizard = stack.pop();\n                    stack.push(getWisdom(wizard));\n                    break;\n                case ADD:\n                    var a = stack.pop();\n                    var b = stack.pop();\n                    stack.push(a + b);\n                    break;\n                case DIVIDE:\n                    a = stack.pop();\n                    b = stack.pop();\n                    stack.push(b / a);\n                    break;\n                case PLAY_SOUND:\n                    wizard = stack.pop();\n                    getWizards()[wizard].playSound();\n                    break;\n                case SPAWN_PARTICLES:\n                    wizard = stack.pop();\n                    getWizards()[wizard].spawnParticles();\n                    break;\n                default:\n                    throw new IllegalArgumentException(\"Invalid instruction value\");\n            }\n            LOGGER.info(\"Executed \" + instruction.name() + \", Stack contains \" + getStack());\n        }\n    }\n\n    public void setHealth(int wizard, int amount) {\n        wizards[wizard].setHealth(amount);\n    }\n    // other setters ->\n    // ...\n}\n```\n\nالآن يمكننا عرض المثال الكامل باستخدام الآلة الافتراضية.\n\n```java\n  public static void main(String[]args){\n\n        var vm=new VirtualMachine(\n        new Wizard(45,7,11,0,0),\n        new Wizard(36,18,8,0,0));\n\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"GET_HEALTH\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"GET_AGILITY\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"GET_WISDOM\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"ADD\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 2\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"DIVIDE\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"ADD\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"SET_HEALTH\"));\n        }\n```\n\nإليك مخرجات وحدة التحكم.\n\n\n```\n16:20:10.193 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0]\n16:20:10.196 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_HEALTH, Stack contains [0, 45]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_AGILITY, Stack contains [0, 45, 7]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 7, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_WISDOM, Stack contains [0, 45, 7, 11]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 45, 18]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 18, 2]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed DIVIDE, Stack contains [0, 45, 9]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 54]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed SET_HEALTH, Stack contains []\n```\n\n## مخطط الفئات\n\n\n![alt text](./etc/bytecode.urm.png \"Bytecode class diagram\")\n\n## القابلية للتطبيق\n\n\n## القابلية للتطبيق\n\nاستخدم نمط Bytecode عندما تحتاج إلى تعريف العديد من السلوكيات ولغة تنفيذ لعبتك ليست مناسبة لأن:\n\n* إنها منخفضة المستوى جدًا، مما يجعل البرمجة مملة أو عرضة للأخطاء.\n* التكرار فيها يستغرق وقتًا طويلًا بسبب بطء وقت الترجمة أو مشاكل أخرى في الأدوات.\n* إنها تحتوي على ثقة مفرطة. إذا كنت ترغب في التأكد من أن السلوك المحدد لا يمكن أن يتسبب في كسر اللعبة، يجب أن تفصله عن باقي قاعدة الكود.\n\n## الاستخدامات المعروفة\n\n* تستخدم Java Virtual Machine (JVM) bytecode لتمكين برامج Java من العمل على أي جهاز يحتوي على JVM.\n* تقوم Python بترجمة سكربتاتها إلى bytecode، الذي يتم تفسيره بعد ذلك بواسطة آلة افتراضية Python.\n* يستخدم .NET Framework نوعًا من bytecode يسمى Microsoft Intermediate Language (MSIL).\n\n## العواقب\n\n### المزايا:\n\n* القابلية للنقل: يمكن تنفيذ البرامج على أي منصة تحتوي على آلة افتراضية متوافقة.\n* الأمان: يمكن للآلة الافتراضية تطبيق ضوابط أمان على كود البايت.\n* الأداء: يمكن للمترجمات JIT تحسين كود البايت في وقت التشغيل، مما يحسن الأداء المحتمل مقارنة بالكود المفسر.\n\n### العيوب:\n\n* الحمل الزائد: تنفيذ bytecode يتضمن عادةً مزيدًا من الحمل الزائد مقارنةً بتنفيذ الكود الأصلي، مما قد يؤثر على الأداء.\n* التعقيد: تنفيذ وصيانة آلة افتراضية يضيف تعقيدًا للنظام.\n\n## الأنماط المرتبطة\n\n* [مترجم](https://java-design-patterns.com/patterns/interpreter/) يستخدم غالبًا داخل تنفيذ آلات افتراضية لتفسير تعليمات bytecode.\n* [أمر](https://java-design-patterns.com/patterns/command/): يمكن اعتبار تعليمات bytecode أوامر يتم تنفيذها بواسطة الآلة الافتراضية.\n* [طريقة المصنع](https://java-design-patterns.com/patterns/factory-method/): قد تستخدم الآلات الافتراضية طرق المصنع لإنشاء العمليات أو التعليمات المحددة في bytecode.\n\n## الشكر\n\n* [أنماط برمجة الألعاب](http://gameprogrammingpatterns.com/bytecode.html)\n* [برمجة لغات البرمجة](https://amzn.to/49Tusnn)\n"
  },
  {
    "path": "localization/ar/chain-of-responsibility/README.md",
    "content": "---\ntitle: Chain of responsibility\nshortTitle: Chain of responsibility\ncategory: Behavioral\nlanguage: ar\ntag:\n    - Gang of Four\n    - Decoupling\n---\n\n## أيضًا معروف بـ\n\n* سلسلة الأوامر\n* سلسلة الكائنات\n* سلسلة المسؤولية\n\n## الغرض\n\nيمنع ربط مُرسل الطلب بمستقبله من خلال إعطاء أكثر من كائن الفرصة لإدارة الطلب. يربط الكائنات المستقبلية معًا ويمرر الطلب عبر السلسلة حتى يتمكن أحد الكائنات من معالجته.\n\n## الشرح\n\nمثال من الحياة الواقعية\n\n> الملك الأورك يعطي أوامر بصوت عالٍ لجيشه. أقرب شخص للرد هو القائد، ثم الضابط، ثم الجندي. القائد، الضابط، والجندي يشكلون سلسلة من المسؤولية.\n\nبكلمات بسيطة\n\n> يساعد في بناء سلسلة من الكائنات. يدخل الطلب من طرف ويتنقل عبر كائنات متعددة حتى يجد مديرًا مناسبًا.\n\nتقول ويكيبيديا\n\n> في التصميم الموجه للكائنات، نمط سلسلة المسؤولية هو نمط تصميم يتكون من مصدر لأوامر الكائنات وسلسلة من كائنات المعالجة. يحتوي كل كائن معالجة على منطق يحدد أنواع أوامر الكائنات التي يمكنه التعامل معها؛ يتم تمرير البقية إلى كائن المعالجة التالي في السلسلة.\n\n**مثال برمجي**\n\nترجمة لمثالنا مع الأورك أعلاه. أولًا، لدينا الكلاس `Request`:\n\n\n```java\nimport lombok.Getter;\n\n@Getter\npublic class Request {\n\n    private final RequestType requestType;\n    private final String requestDescription;\n    private boolean handled;\n\n    public Request(final RequestType requestType, final String requestDescription) {\n        this.requestType = Objects.requireNonNull(requestType);\n        this.requestDescription = Objects.requireNonNull(requestDescription);\n    }\n\n    public void markHandled() {\n        this.handled = true;\n    }\n\n    @Override\n    public String toString() {\n        return getRequestDescription();\n    }\n}\n\npublic enum RequestType {\n    DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX\n}\n```\n\nأدناه، نعرض تسلسل هرم مدير الطلبات.\n\n\n```java\npublic interface RequestHandler {\n\n    boolean canHandleRequest(Request req);\n\n    int getPriority();\n\n    void handle(Request req);\n\n    String name();\n}\n\n@Slf4j\npublic class OrcCommander implements RequestHandler {\n    @Override\n    public boolean canHandleRequest(Request req) {\n        return req.getRequestType() == RequestType.DEFEND_CASTLE;\n    }\n\n    @Override\n    public int getPriority() {\n        return 2;\n    }\n\n    @Override\n    public void handle(Request req) {\n        req.markHandled();\n        LOGGER.info(\"{} handling request \\\"{}\\\"\", name(), req);\n    }\n\n    @Override\n    public String name() {\n        return \"Orc commander\";\n    }\n}\n\n// يتم تعريف OrcOfficer و OrcSoldier بطريقة مشابهة لـ OrcCommander\n\n\n```\n\nالملك أورك يعطي الأوامر ويشكل السلسلة.\n\n\n```java\npublic class OrcKing {\n\n    private List<RequestHandler> handlers;\n\n    public OrcKing() {\n        buildChain();\n    }\n\n    private void buildChain() {\n        handlers = Arrays.asList(new OrcCommander(), new OrcOfficer(), new OrcSoldier());\n    }\n\n    public void makeRequest(Request req) {\n        handlers\n                .stream()\n                .sorted(Comparator.comparing(RequestHandler::getPriority))\n                .filter(handler -> handler.canHandleRequest(req))\n                .findFirst()\n                .ifPresent(handler -> handler.handle(req));\n    }\n}\n```\n\nسلسلة المسؤولية في العمل.\n\n\n```java\nvar king=new OrcKing();\n        king.makeRequest(new Request(RequestType.DEFEND_CASTLE,\"defend castle\"));\n        king.makeRequest(new Request(RequestType.TORTURE_PRISONER,\"torture prisoner\"));\n        king.makeRequest(new Request(RequestType.COLLECT_TAX,\"collect tax\"));\n```\n\nإخراج وحدة التحكم.\n\n\n```\nOrc commander handling request \"defend castle\"\nOrc officer handling request \"torture prisoner\"\nOrc soldier handling request \"collect tax\"\n```\n\n## مخطط الفئات\n\n![alt text](./etc/chain-of-responsibility.urm.png \"مخطط الفئات لسلسلة المسؤولية\")\n\n## التطبيقية\n\nاستخدم سلسلة المسؤولية عندما\n\n* يمكن لعدة كائنات معالجة الطلب، ولا يتم التعرف على المعالج مسبقًا. يجب تحديد المعالج تلقائيًا.\n* ترغب في إرسال طلب إلى أحد الكائنات دون تحديد المستقبل بشكل صريح.\n* يجب تحديد مجموعة الكائنات التي يمكنها معالجة الطلب ديناميكيًا.\n\n## الاستخدامات المعروفة\n\n* التفاعل مع الأحداث في إطارات واجهات المستخدم الرسومية حيث يمكن معالجة الحدث في عدة مستويات من تسلسل مكونات واجهة المستخدم.\n* إطارات عمل الوسطاء حيث يمر الطلب عبر سلسلة من كائنات المعالجة.\n* أنظمة السجلات حيث يمكن أن تمر الرسائل عبر سلسلة من المسجلين، مع إمكانية معالجتها بطرق مختلفة.\n* [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29)\n* [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html)\n* [javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-)\n\n## العواقب\n\nالمزايا:\n\n* تقليل الترابط. لا يحتاج مُرسل الطلب إلى معرفة المعالج المحدد الذي سيعالج الطلب.\n* مرونة أكبر في تخصيص المسؤوليات للكائنات. يمكن إضافة أو تغيير المسؤوليات لإدارة الطلب عن طريق تغيير أعضاء وترتيب السلسلة.\n* يتيح تعيين معالج افتراضي إذا لم يكن هناك معالج محدد يمكنه معالجة الطلب.\n\nالعيوب:\n\n* قد يكون من الصعب تصحيح الأخطاء وفهم التدفق، خاصة إذا كانت السلسلة طويلة ومعقدة.\n* قد يبقى الطلب دون معالجة إذا كانت السلسلة لا تحتوي على معالج \"التقاط الكل\".\n* قد تنشأ مشكلات في الأداء بسبب إمكانية مرور الطلب عبر عدة معالجات قبل العثور على المعالج المناسب، أو عدم العثور عليه على الإطلاق.\n\n## الأنماط ذات الصلة\n\n* [الأمر](https://java-design-patterns.com/patterns/command/): يمكن استخدامه لتغليف طلب ككائن، يمكن تمريره عبر السلسلة.\n* [التركيب](https://java-design-patterns.com/patterns/composite/): غالبًا ما يتم تطبيق نمط سلسلة المسؤولية مع نمط التركيب.\n* [الزخرفة](https://java-design-patterns.com/patterns/decorator/): يمكن ربط الزخارف بشكل مشابه للمسؤوليات في نمط سلسلة المسؤولية.\n\n## الاعتمادات\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/3PAJUg5)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n* [Pattern languages of program design 3](https://amzn.to/4a4NxTH)\n"
  },
  {
    "path": "localization/ar/client-session/README.md",
    "content": "---\ntitle: Client Session\nshortTitle: Client Session\ncategory: Behavioral\nlanguage: ar\ntags:\n    - Session management\n    - Web development\n---\n\n## أيضًا معروف باسم\n\n* جلسة المستخدم\n\n## الهدف\n\nيهدف نمط التصميم \"جلسة العميل\" إلى الحفاظ على حالة وبيانات المستخدم عبر طلبات متعددة ضمن تطبيق ويب، مما يضمن تجربة مستخدم مستمرة وشخصية.\n\n## الشرح\n\nمثال واقعي\n\n> ترغب في إنشاء تطبيق لإدارة البيانات يسمح للمستخدمين بإرسال طلبات إلى الخادم لتعديل وإجراء تغييرات على البيانات المخزنة على أجهزتهم. هذه الطلبات صغيرة والبيانات فردية لكل مستخدم، مما يلغي الحاجة إلى تنفيذ قاعدة بيانات واسعة النطاق. باستخدام نمط جلسة العميل، يمكن إدارة عدة طلبات في نفس الوقت، مع تحقيق توازن في تحميل العملاء عبر خوادم مختلفة بسهولة لأن الخوادم تظل بدون حالة. كما يتم القضاء على الحاجة إلى تخزين معرفات الجلسة على الخادم لأن العملاء يقدمون كل المعلومات التي يحتاجها الخادم لمعالجة طلباتهم.\n\nبإيجاز\n\n> بدلاً من تخزين معلومات عن العميل الحالي والمعلومات التي يتم الوصول إليها على الخادم، يتم الاحتفاظ بها فقط على جانب العميل. يجب على العميل إرسال بيانات الجلسة مع كل طلب إلى الخادم ويجب عليه إرسال حالة محدثة مرة أخرى إلى العميل، التي يتم تخزينها على جهاز العميل. لا يتعين على الخادم تخزين معلومات العميل. ([مرجع](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-client))\n\n**مثال برمجي**\n\nإليك كود مثال لوصف نمط جلسة العميل. في الكود التالي، نقوم أولاً بإنشاء مثيل للخادم. سيتم استخدام هذا المثيل بعد ذلك للحصول على كائنات الجلسة لعميلين. كما ترى في الكود التالي، يمكن استخدام كائن الجلسة لتخزين أي معلومات ذات صلة يحتاجها الخادم لمعالجة طلب العميل. سيتم تمرير هذه الكائنات مع كل طلب إلى الخادم. سيتضمن الطلب كائن الجلسة الذي يخزن التفاصيل ذات الصلة بالعميل مع البيانات المطلوبة لمعالجة الطلب. تساعد معلومات الجلسة في كل طلب الخادم في التعرف على العميل ومعالجة الطلب بناءً على ذلك.\n\n\n```java\npublic class App {\n\n    public static void main(String[] args) {\n        var server = new Server(\"localhost\", 8080);\n        var session1 = server.getSession(\"Session1\");\n        var session2 = server.getSession(\"Session2\");\n        var request1 = new Request(\"Data1\", session1);\n        var request2 = new Request(\"Data2\", session2);\n        server.process(request1);\n        server.process(request2);\n    }\n}\n\n@Data\n@AllArgsConstructor\npublic class Session {\n\n    /**\n     * Session id.\n     */\n    private String id;\n\n    /**\n     * Client name.\n     */\n    private String clientName;\n\n}\n\n@Data\n@AllArgsConstructor\npublic class Request {\n\n    private String data;\n\n    private Session session;\n\n}\n```\n\n## مخطط الهيكلية\n\n![alt text](./etc/session_state_pattern.png \"نمط حالة الجلسة\")\n\n## قابلية التطبيق\n\nاستخدم نمط حالة الجلسة عندما:\n\n* التطبيقات الويب التي تتطلب مصادقة وتفويض المستخدم.\n* التطبيقات التي تحتاج إلى تتبع أنشطة وتفضيلات المستخدم عبر طلبات أو زيارات متعددة.\n* الأنظمة التي يحتاج فيها موارد الخادم إلى التحسين عن طريق تحميل إدارة الحالة إلى جانب العميل.\n\n## الاستخدامات المعروفة\n\n* مواقع التجارة الإلكترونية لتتبع محتويات سلة التسوق عبر الجلسات.\n* المنصات عبر الإنترنت التي تقدم محتوى مخصص بناءً على تفضيلات وسجل المستخدم.\n* تطبيقات الويب التي تتطلب تسجيل دخول المستخدم للوصول إلى المحتوى المخصص أو الآمن.\n\n## العواقب\n\nالفوائد:\n\n* تحسين أداء الخادم من خلال تقليل الحاجة لتخزين حالة المستخدم على الخادم.\n* تحسين تجربة المستخدم من خلال المحتوى المخصص والتنقل السلس عبر أجزاء التطبيق المختلفة.\n* مرونة في إدارة الجلسات من خلال عدة آليات تخزين على جانب العميل (مثل الكوكيز، Web Storage API).\n\nالعيوب:\n\n* مخاطر محتملة للأمان إذا تم تخزين معلومات حساسة في جلسات العميل دون التشفير والتحقق المناسب.\n* الاعتماد على قدرات وضبط العميل، مثل سياسات الكوكيز التي قد تختلف حسب المتصفح وإعدادات المستخدم.\n* زيادة التعقيد في منطق إدارة الجلسات، خاصة في إدارة انتهاء الصلاحية، التجديد ومزامنة الجلسات عبر الأجهزة أو النوافذ المتعددة.\n\n## الأنماط ذات الصلة\n\n* جلسة الخادم: غالباً ما يُستخدم جنباً إلى جنب مع نمط جلسة العميل لتوفير توازن بين كفاءة جانب العميل والتحكم في جانب الخادم.\n* [سينجلتون](https://java-design-patterns.com/patterns/singleton/): ضمان وجود مثيل واحد فقط من جلسة المستخدم في التطبيق بأكمله.\n* [حالة](https://java-design-patterns.com/patterns/state/): إدارة تحولات الحالة في الجلسة مثل الحالات المصادق عليها، الضيف أو المنتهية.\n\n## الفضل\n\n* [DZone - Practical PHP patterns](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-client)\n* [نمط حالة جلسة العميل - Ram N Java](https://www.youtube.com/watch?v=ycOSj9g41pc)\n* [Java الاحترافي لتطبيقات الويب](https://amzn.to/4aazY59)\n* [تأمين تطبيقات الويب باستخدام Spring Security](https://amzn.to/3PCCEA1)\n"
  },
  {
    "path": "localization/ar/collecting-parameter/README.md",
    "content": "---\ntitle: Collecting Parameter\nshortTitle: Collecting Parameter\ncategory: Behavioral\nlanguage: ar\ntag:\n    - Accumulation\n    - Generic\n---\n\n## أيضًا يُعرف بـ\n\n* جامع\n* مُجمّع\n\n## الهدف\n\nيهدف إلى تبسيط الطرق التي تجمع المعلومات من خلال تمرير كائن جمع واحد عبر عدة استدعاءات للطرق، مما يسمح لها بإضافة النتائج إلى هذه المجموعة بدلاً من أن يقوم كل طريقة بإنشاء مجموعة خاصة بها.\n\n## الشرح\n\n### مثال من العالم الحقيقي\n\nداخل مبنى تجاري كبير، توجد طابعات مُشتركة تعد مجموعة من جميع وظائف الطباعة المعلقة حاليًا. تحتوي الطوابق المختلفة على طرز مختلفة من الطابعات، ولكل منها سياسة طباعة مختلفة. يجب علينا بناء برنامج يمكنه إضافة مهام الطباعة المناسبة بشكل مستمر إلى مجموعة تسمى *معامل الجمع*.\n\n### ببساطة\n\nبدلاً من وجود دالة ضخمة تحتوي على العديد من السياسات لجمع المعلومات في متغير، يمكننا إنشاء العديد من الدوال الصغيرة التي تأخذ كل معلم، وتضيف معلومات جديدة. يمكننا تمرير المعامل إلى كل من هذه الدوال الصغيرة وفي النهاية، سيكون لدينا ما أردناه في الأصل. في هذه المرة، يكون الكود أنظف وأسهل في الفهم. نظرًا لأن الدالة الكبيرة قد تم تقسيمها، فإن الكود أيضًا أسهل في التعديل حيث يتم تحديد التغييرات في الدوال الصغيرة.\n\n### تقول ويكيبيديا\n\nفي اصطلاح المعاملات الجامعية، يتم تمرير مجموعة (قائمة، خريطة، إلخ) بشكل متكرر كمعامل إلى دالة تضيف العناصر إلى المجموعة.\n\n### مثال برمجي\n\nبتشفير مثالنا السابق، يمكننا استخدام مجموعة `النتيجة` كمعامل جامع. يتم تنفيذ القيود التالية:\n\n- إذا كان ورق A4 ملونًا، يجب أن يكون أيضًا من جهة واحدة. يتم قبول جميع الأوراق غير الملونة الأخرى.\n- لا يجب أن يكون ورق A3 ملونًا ويجب أن يكون من جهة واحدة.\n- يجب أن يكون ورق A2 من صفحة واحدة، من جهة واحدة وغير ملون.\n\n\n```java\npackage com.iluwatar.collectingparameter;\n\nimport java.util.LinkedList;\nimport java.util.Queue;\n\npublic class App {\n    static PrinterQueue printerQueue = PrinterQueue.getInstance();\n\n    /**\n     * Program entry point.\n     *\n     * @param args command line args\n     */\n    public static void main(String[] args) {\n    /*\n      Initialising the printer queue with jobs\n    */\n        printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A4, 5, false, false));\n        printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A3, 2, false, false));\n        printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A2, 5, false, false));\n\n    /*\n      This variable is the collecting parameter.\n    */\n        var result = new LinkedList<PrinterItem>();\n\n        /*\n         * Using numerous sub-methods to collaboratively add information to the result collecting parameter\n         */\n        addA4Papers(result);\n        addA3Papers(result);\n        addA2Papers(result);\n    }\n}\n```\n\nنستخدم الطرق `addA4Paper` و `addA3Paper` و `addA2Paper` لملء معامل الجمع `النتيجة` بالوظائف المناسبة للطباعة وفقًا للسياسة الموصوفة سابقًا. يتم ترميز السياسات الثلاث كما يلي:\n\n\n```java\npublic class App {\n    static PrinterQueue printerQueue = PrinterQueue.getInstance();\n\n    /**\n     * Adds A4 document jobs to the collecting parameter according to some policy that can be whatever the client\n     * (the print center) wants.\n     *\n     * @param printerItemsCollection the collecting parameter\n     */\n    public static void addA4Papers(Queue<PrinterItem> printerItemsCollection) {\n    /*\n      Iterate through the printer queue, and add A4 papers according to the correct policy to the collecting parameter,\n      which is 'printerItemsCollection' in this case.\n     */\n        for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n            if (nextItem.paperSize.equals(PaperSizes.A4)) {\n                var isColouredAndSingleSided =\n                        nextItem.isColour && !nextItem.isDoubleSided;\n                if (isColouredAndSingleSided) {\n                    printerItemsCollection.add(nextItem);\n                } else if (!nextItem.isColour) {\n                    printerItemsCollection.add(nextItem);\n                }\n            }\n        }\n    }\n\n    /**\n     * Adds A3 document jobs to the collecting parameter according to some policy that can be whatever the client\n     * (the print center) wants. The code is similar to the 'addA4Papers' method. The code can be changed to accommodate\n     * the wants of the client.\n     *\n     * @param printerItemsCollection the collecting parameter\n     */\n    public static void addA3Papers(Queue<PrinterItem> printerItemsCollection) {\n        for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n            if (nextItem.paperSize.equals(PaperSizes.A3)) {\n\n                // Encoding the policy into a Boolean: the A3 paper cannot be coloured and double-sided at the same time\n                var isNotColouredAndSingleSided =\n                        !nextItem.isColour && !nextItem.isDoubleSided;\n                if (isNotColouredAndSingleSided) {\n                    printerItemsCollection.add(nextItem);\n                }\n            }\n        }\n    }\n\n    /**\n     * Adds A2 document jobs to the collecting parameter according to some policy that can be whatever the client\n     * (the print center) wants. The code is similar to the 'addA4Papers' method. The code can be changed to accommodate\n     * the wants of the client.\n     *\n     * @param printerItemsCollection the collecting parameter\n     */\n    public static void addA2Papers(Queue<PrinterItem> printerItemsCollection) {\n        for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n            if (nextItem.paperSize.equals(PaperSizes.A2)) {\n\n                // Encoding the policy into a Boolean: the A2 paper must be single page, single-sided, and non-coloured.\n                var isNotColouredSingleSidedAndOnePage =\n                        nextItem.pageCount == 1 &&\n                                !nextItem.isDoubleSided\n                                && !nextItem.isColour;\n                if (isNotColouredSingleSidedAndOnePage) {\n                    printerItemsCollection.add(nextItem);\n                }\n            }\n        }\n    }\n}\n```\n\nكل طريقة تأخذ كمعامل معلمة جمع. بعد ذلك، تضيف العناصر، المأخوذة من متغير عالمي، إلى هذه المعلمة إذا كانت كل عنصر يفي بمعيار معين. يمكن أن تحتوي هذه الطرق على السياسة التي يرغب فيها العميل.\n\nفي هذا المثال البرمجي، يتم إضافة ثلاث مهام طباعة إلى الطابور. فقط أول مهمتين للطباعة يجب إضافتهما إلى معلمة الجمع وفقًا للسياسة. العناصر في متغير `النتيجة` بعد التنفيذ هي:\n\n| حجم الورق | عدد الصفحات | مزدوج الوجه | ملون |\n|-----------|-------------|-------------|------|\n| A4        | 5           | false       | false |\n| A3        | 2           | false       | false |\n\nوهذا هو ما توقعناه.\n\n## مخطط الفئات\n\n![alt text](./etc/collecting-parameter.urm.png \"معامل الجمع\")\n\n## قابلية التطبيق\n\nاستخدم نمط التصميم جمع المعاملات عندما:\n\n- عندما تنتج عدة طرق مجموعة من النتائج وتريد إضافة هذه النتائج بطريقة موحدة.\n- في السيناريوهات حيث يمكن أن يحسن تقليل عدد المجموعات التي يتم إنشاؤها بواسطة الطرق من كفاءة الذاكرة والأداء.\n- عند إعادة هيكلة الطرق الكبيرة التي تقوم بعدة مهام، بما في ذلك جمع النتائج من عمليات متعددة.\n\n## الدروس التعليمية\n\nالدروس التعليمية لهذه الطريقة موجودة في:\n\n- [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf) بواسطة Joshua Kerivsky\n- [Smalltalk Best Practice Patterns](https://ptgmedia.pearsoncmg.com/images/9780134769042/samplepages/013476904X.pdf) بواسطة Kent Beck\n\n## الاستخدامات المعروفة\n\nيوضح Joshua Kerivsky مثالًا واقعيًا في كتابه 'Refactoring to Patterns'. يقدم مثالًا لاستخدام نمط التصميم \"جمع المعاملات\" لإنشاء طريقة `toString()` لشجرة XML. بدون استخدام هذا النمط، سيحتاج ذلك إلى وظيفة ضخمة تحتوي على شروط ودمج النصوص مما سيزيد من صعوبة قراءة الشيفرة. يمكن تقسيم مثل هذه الطريقة إلى طرق أصغر، حيث يضيف كل منها مجموعة خاصة من المعلومات إلى معلمة الجمع. انظر إلى هذا في [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf).\n\nأمثلة أخرى هي:\n\n- إضافة رسائل الخطأ أو فشل التحقق في عملية تحقق معقدة.\n- جمع العناصر أو المعلومات أثناء التنقل في هيكل بيانات معقد.\n- إعادة هيكلة الوظائف المعقدة للتقارير حيث يتم إنشاء أجزاء متعددة من التقرير باستخدام طرق مختلفة.\n\n## العواقب\n\nالمزايا:\n\n- يقلل من تكرار الشيفرة من خلال تجميع معالجة المجموعات في مكان واحد.\n- يحسن الوضوح وقابلية الصيانة من خلال توضيح مكان وكيفية جمع النتائج.\n- يحسن الأداء عن طريق تقليل إنشاء وإدارة كائنات جمع متعددة.\n\nالعيوب:\n\n- يزيد من الترابط بين المنادي والطرق المنادى عليها، حيث يجب أن يتفقوا على المجموعة المستخدمة.\n- قد يقدم آثار جانبية في الطرق إذا لم تتم إدارتها بعناية، حيث لم تعد الطرق مستقلة في إدارة النتائج.\n\n## الأنماط ذات الصلة\n\n- [Composite](https://java-design-patterns.com/patterns/composite/): يمكن استخدامه مع جمع المعاملات عند العمل مع الهياكل الهرمية، مما يسمح بجمع النتائج عبر هيكل مركب.\n- [Visitor](https://java-design-patterns.com/patterns/visitor/): يستخدم غالبًا معًا، حيث يتولى Visitor المرور وإجراء العمليات في هيكل، بينما يقوم جمع المعاملات بتراكم النتائج.\n- [Command](https://java-design-patterns.com/patterns/command/): يمكن للأوامر استخدام معلمة الجمع لإضافة نتائج عدة عمليات يتم تنفيذها بواسطة كائنات الأمر.\n\n## الشكر\n\n- [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf) بواسطة Joshua Kerivsky\n- [Smalltalk Best Practice Patterns](https://ptgmedia.pearsoncmg.com/images/9780134769042/samplepages/013476904X.pdf) بواسطة Kent Beck\n- [Wiki](https://wiki.c2.com/?CollectingParameter)\n- [Refactoring: Improving the Design of Existing Code](https://amzn.to/3TVEgaB)\n- [Clean Code: A Handbook of Agile Software Craftsmanship](https://amzn.to/4aApLP0)\n"
  },
  {
    "path": "localization/ar/command/README.md",
    "content": "---\ntitle: Command\nshortTitle: Command\ncategory: Behavioral\nlanguage: ar\ntag:\n    - Gang of Four\n---\n\n## أيضًا يعرف بـ\n\n* إجراء\n* معاملة\n\n## الهدف\n\nيُغلف نمط التصميم Command الطلب ككائن، مما يسمح بتمرير العملاء مع قوائم الانتظار، الطلبات، والعمليات. كما يدعم أيضًا التراجع عن العمليات.\n\n## الشرح\n\n### مثال واقعي\n\n> يوجد ساحر يلقي تعويذات على عفريت. يتم تنفيذ التعويذات على العفريت واحدة تلو الأخرى. التعويذة الأولى تصغر العفريت والتعويذة الثانية تجعله غير مرئي. بعد ذلك، يقوم الساحر بالتراجع عن التعويذات واحدة تلو الأخرى. كل تعويذة هي كائن أمر يمكن التراجع عنها.\n\n### بكلمات بسيطة:\n\n> تخزين الطلبات ككائنات أمر يسمح بتنفيذ الإجراء أو التراجع عنه في وقت لاحق.\n\n### تقول ويكيبيديا:\n\n> في البرمجة الكائنية التوجه، نمط الأمر هو نمط تصميم سلوكي حيث يتم استخدام كائن لتغليف كافة المعلومات اللازمة لتنفيذ إجراء أو تحفيز حدث في وقت لاحق.\n\n### مثال برمجي\n\nإليك الكود البرمجي مع الساحر `Wizard` والعفريت `Goblin`. دعونا نبدأ بفئة الساحر `Wizard`.\n\n\n```java\n\n@Slf4j\npublic class Wizard {\n\n    private final Deque<Runnable> undoStack = new LinkedList<>();\n    private final Deque<Runnable> redoStack = new LinkedList<>();\n\n    public Wizard() {\n    }\n\n    public void castSpell(Runnable runnable) {\n        runnable.run();\n        undoStack.offerLast(runnable);\n    }\n\n    public void undoLastSpell() {\n        if (!undoStack.isEmpty()) {\n            var previousSpell = undoStack.pollLast();\n            redoStack.offerLast(previousSpell);\n            previousSpell.run();\n        }\n    }\n\n    public void redoLastSpell() {\n        if (!redoStack.isEmpty()) {\n            var previousSpell = redoStack.pollLast();\n            undoStack.offerLast(previousSpell);\n            previousSpell.run();\n        }\n    }\n\n    @Override\n    public String toString() {\n        return \"Wizard\";\n    }\n}\n```\n\n### التالي، لدينا العفريت `Goblin` الذي هو الهدف `Target` للتعويذات.\n\n\n```java\n\n@Slf4j\npublic abstract class Target {\n\n    private Size size;\n\n    private Visibility visibility;\n\n    public Size getSize() {\n        return size;\n    }\n\n    public void setSize(Size size) {\n        this.size = size;\n    }\n\n    public Visibility getVisibility() {\n        return visibility;\n    }\n\n    public void setVisibility(Visibility visibility) {\n        this.visibility = visibility;\n    }\n\n    @Override\n    public abstract String toString();\n\n    public void printStatus() {\n        LOGGER.info(\"{}, [size={}] [visibility={}]\", this, getSize(), getVisibility());\n    }\n}\n\npublic class Goblin extends Target {\n\n    public Goblin() {\n        setSize(Size.NORMAL);\n        setVisibility(Visibility.VISIBLE);\n    }\n\n    @Override\n    public String toString() {\n        return \"Goblin\";\n    }\n\n    public void changeSize() {\n        var oldSize = getSize() == Size.NORMAL ? Size.SMALL : Size.NORMAL;\n        setSize(oldSize);\n    }\n\n    public void changeVisibility() {\n        var visible = getVisibility() == Visibility.INVISIBLE\n                ? Visibility.VISIBLE : Visibility.INVISIBLE;\n        setVisibility(visible);\n    }\n}\n```\n\n### أخيرًا، لدينا الساحر في الدالة الرئيسية وهو يلقي التعويذات.\n\n\n```java\npublic static void main(String[]args){\n        var wizard=new Wizard();\n        var goblin=new Goblin();\n\n        // casts shrink/unshrink spell\n        wizard.castSpell(goblin::changeSize);\n\n        // casts visible/invisible spell\n        wizard.castSpell(goblin::changeVisibility);\n\n        // undo and redo casts\n        wizard.undoLastSpell();\n        wizard.redoLastSpell();\n```\n\n### هذا هو المثال قيد التنفيذ.\n\n\n```java\nvar wizard=new Wizard();\n        var goblin=new Goblin();\n\n        goblin.printStatus();\n        wizard.castSpell(goblin::changeSize);\n        goblin.printStatus();\n\n        wizard.castSpell(goblin::changeVisibility);\n        goblin.printStatus();\n\n        wizard.undoLastSpell();\n        goblin.printStatus();\n\n        wizard.undoLastSpell();\n        goblin.printStatus();\n\n        wizard.redoLastSpell();\n        goblin.printStatus();\n\n        wizard.redoLastSpell();\n        goblin.printStatus();\n```\n\n### إليك مخرجات البرنامج:\n\n\n```java\nGoblin,[size=normal][visibility=visible]\n        Goblin,[size=small][visibility=visible]\n        Goblin,[size=small][visibility=invisible]\n        Goblin,[size=small][visibility=visible]\n        Goblin,[size=normal][visibility=visible]\n        Goblin,[size=small][visibility=visible]\n        Goblin,[size=small][visibility=invisible]\n```\n\n## تطبيق\n\nاستخدم نمط الأمر (Command) في الحالات التالية:\n\n* لتحديد كائنات باستخدام إجراء لتنفيذه. يمكنك التعبير عن هذه التحديدات باستخدام لغة إجراء مع دالة رد اتصال، أي دالة يتم تسجيلها في مكان ما ليتم استدعاؤها في وقت لاحق. الأوامر هي بديل موجه للكائنات لردود الاتصال.\n* لتحديد، وضع في طابور وتنفيذ الطلبات في أوقات مختلفة. يمكن أن يكون لكائن الأمر حياة مستقلة عن الطلب الأصلي. إذا كان يمكن تمثيل مستلم الطلب بطريقة مستقلة عن مساحة العناوين، فيمكنك نقل كائن الأمر للطلب إلى عملية مختلفة وتنفيذ الطلب هناك.\n* دعم الإلغاء. يمكن لعملية تنفيذ الأمر تخزين الحالة لإلغاء تأثيراتها في نفس الأمر. يجب أن تحتوي واجهة الأمر على عملية إضافية لإلغاء التنفيذ التي تعيد تأثيرات استدعاء سابق لتنفيذ. يتم تخزين الأوامر التي تم تنفيذها في قائمة تاريخ. يمكن تحقيق وظيفة التراجع وإعادة التنفيذ بشكل غير محدود من خلال استعراض هذه القائمة للأمام والخلف عن طريق استدعاء إلغاء التنفيذ والتنفيذ، على التوالي.\n* دعم تسجيل التغييرات بحيث يمكن تطبيقها مرة أخرى في حال حدوث عطل في النظام. من خلال إضافة عمليات تحميل وتخزين إلى واجهة الأوامر، يمكنك الاحتفاظ بسجل مستمر للتغييرات. يتطلب استعادة العطل إعادة تحميل الأوامر المسجلة من القرص وتنفيذها مرة أخرى باستخدام عملية التنفيذ.\n* هيكلة النظام حول عمليات عالية المستوى مبنية على عمليات بدائية. هذه الهيكلة شائعة في أنظمة المعلومات التي تدعم المعاملات. المعاملة تحتوي على مجموعة من التغييرات في البيانات. يوفر نمط الأمر طريقة لنمذجة المعاملات. تحتوي الأوامر على واجهة مشتركة تسمح باستدعاء جميع المعاملات بنفس الطريقة. كما يسهل النمط توسيع النظام مع معاملات جديدة.\n* الحفاظ على سجل من الطلبات.\n* تنفيذ وظيفة رد الاتصال.\n* تنفيذ وظيفة التراجع.\n\n## الاستخدامات المعروفة\n\n* الأزرار في واجهة المستخدم الرسومية وعناصر القائمة في تطبيقات سطح المكتب.\n* العمليات في أنظمة قواعد البيانات والأنظمة المعاملاتية التي تدعم التراجع (rollback).\n* تسجيل الماكرو في التطبيقات مثل محرري النصوص وجداول البيانات.\n* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)\n* [org.junit.runners.model.Statement](https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/runners/model/Statement.java)\n* [Netflix Hystrix](https://github.com/Netflix/Hystrix/wiki)\n* [javax.swing.Action](http://docs.oracle.com/javase/8/docs/api/javax/swing/Action.html)\n\n## العواقب\n\nالمزايا:\n\n* يفصل الكائن الذي يستدعي العملية عن الكائن الذي يعرف كيفية تنفيذها.\n* من السهل إضافة أوامر جديدة، لأنه لا يتعين عليك تغيير الفئات الموجودة.\n* يمكنك تجميع مجموعة من الأوامر في أمر مركب.\n\nالعيوب:\n\n* يزيد عدد الفئات لكل أمر فردي.\n* قد يعقد التصميم عند إضافة طبقات متعددة بين المرسلين والمستلمين.\n\n## الأنماط ذات الصلة\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): يمكن تجميع الأوامر باستخدام نمط المركب لإنشاء أوامر كبيرة.\n* [Memento](https://java-design-patterns.com/patterns/memento/): يمكن استخدامه لتنفيذ آليات التراجع.\n* [Observer](https://java-design-patterns.com/patterns/observer/): يمكن ملاحظة النمط لتغييرات التي تفعّل الأوامر.\n\n## المصادر\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n* [Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/3PFUqSY)\n"
  },
  {
    "path": "localization/ar/commander/README.md",
    "content": "---\ntitle: Commander\nshortTitle: Commander\ncategory: Behavioral\nlanguage: ar\ntag:\n    - Cloud distributed\n    - Microservices\n    - Transactions\n---\n\n## أيضا يُعرف باسم\n\n* منسق المعاملات الموزعة\n* منسق المعاملات\n\n## الهدف\n\nالهدف من نمط \"المنسق\" في سياق المعاملات الموزعة هو إدارة وتنسيق المعاملات المعقدة عبر العديد من المكونات أو الخدمات الموزعة، مما يضمن التناسق والنزاهة للمعاملة العالمية. يقوم بتغليف أوامر المعاملات ومنطق التنسيق، مما يسهل تنفيذ بروتوكولات المعاملات الموزعة مثل الالتزام ذو المرحلتين أو ساغا.\n\n## الشرح\n\nمثال حقيقي\n\n> تخيل أنك تنظم مهرجان موسيقي دولي كبير، حيث من المقرر أن تؤدي عدة فرق من جميع أنحاء العالم. وصول كل فرقة، واختبار الصوت، والأداء، كل منها يعد معاملة فردية في نظام موزع. يتصرف منظم المهرجان كـ \"منسق\"، منسقًا هذه المعاملات لضمان أنه إذا تأخر طيران إحدى الفرق (مثل فشل المعاملة)، فهناك خطة احتياطية مثل إعادة جدولة أو تبادل الفترات الزمنية مع فرقة أخرى (إجراءات تعويضية)، للحفاظ على سير البرنامج العام. تعكس هذه الإعدادات نمط المنسق في المعاملات الموزعة، حيث يجب تنسيق العديد من المكونات لتحقيق نتيجة مرضية رغم الفشل الفردي.\n\nبكلمات بسيطة\n\n> يقوم نمط \"المنسق\" بتحويل الطلب إلى كائن مستقل، مما يسمح بمعلمة الأوامر، ووضع الإجراءات في طابور، وتنفيذ عمليات التراجع.\n\n**مثال برمجي**\n\nإدارة المعاملات عبر خدمات مختلفة في نظام موزع، مثل منصة للتجارة الإلكترونية تحتوي على خدمات منفصلة للدفع والشحن، تتطلب تنسيقًا دقيقًا لتجنب المشكلات. عندما يقدم المستخدم طلبًا ولكن خدمة واحدة (مثل الدفع) غير متوفرة بينما الخدمة الأخرى (مثل الشحن) جاهزة، نحتاج إلى حل قوي للتعامل مع هذا التفاوت.\n\nإحدى الاستراتيجيات لحل هذه المشكلة هي استخدام مكون منسق لتنظيم العملية. في البداية، تتم معالجة الطلب من قبل الخدمة المتاحة (الشحن في هذه الحالة). ثم يحاول المنسق مزامنة الطلب مع الخدمة غير المتوفرة في ذلك الوقت (الدفع) من خلال تخزين تفاصيل الطلب في قاعدة بيانات أو وضعه في طابور للمعالجة في المستقبل. يجب أن يأخذ هذا النظام في الحسبان الفشل المحتمل عند إضافة الطلبات إلى الطابور.\n\nيحاول المنسق بشكل متكرر معالجة الطلبات في الطابور لضمان أن تعكس جميع الخدمات أخيرًا نفس بيانات المعاملة. يتضمن هذا العملية ضمان التكرارية، مما يعني أنه حتى إذا تم إجراء نفس طلب مزامنة الطلبات عدة مرات، فسيتم تنفيذه مرة واحدة فقط، مما يمنع المعاملات المكررة. الهدف هو تحقيق التناسق النهائي بين الخدمات، حيث تتزامن جميع الأنظمة بمرور الوقت على الرغم من الفشل أو التأخير الأولي.\n\nفي الكود المقدم، يُستخدم نمط المنسق لإدارة المعاملات الموزعة عبر العديد من الخدمات (خدمة الدفع، خدمة الشحن، خدمة الرسائل، إدارة الموظفين). كل خدمة تحتوي على قاعدة بيانات خاصة بها ويمكن أن تُطلق استثناءات لمحاكاة الفشل.\n\nفئة المنسق هي الجزء المركزي من هذا النمط. تأخذ الفئة المنسق مثيلات لجميع الخدمات وقواعد بياناتها، جنبًا إلى جنب مع بعض معلمات التكوين. تُستخدم دالة placeOrder في فئة المنسق لتنفيذ الطلب، مما يتطلب التفاعل مع جميع الخدمات.\n\n\n```java\npublic class Commander {\n    // ... constructor and other methods ...\n\n    public void placeOrder(Order order) {\n        // ... implementation ...\n    }\n}\n```\n\nتمثل الفئات \"المستخدم\" و \"الطلب\" مستخدمًا وطلبًا على التوالي. يتم إجراء الطلب بواسطة المستخدم.\n\n\n```java\npublic class User {\n    // ... constructor and other methods ...\n}\n\npublic class Order {\n    // ... constructor and other methods ...\n}\n```\n\nكل خدمة (على سبيل المثال، خدمة الدفع، خدمة الشحن، خدمة الرسائل، إدارة الموظفين) لديها قاعدة بيانات خاصة بها ويمكن أن تُطلق استثناءات لمحاكاة الأعطال. على سبيل المثال، قد تقوم خدمة الدفع بإطلاق استثناء DatabaseUnavailableException إذا كانت قاعدة بياناتها غير متاحة.\n\n\n```java\npublic class PaymentService {\n    // ... constructor and other methods ...\n}\n```\n\nتمثل الفئات DatabaseUnavailableException و ItemUnavailableException و ShippingNotPossibleException أنواعًا مختلفة من الاستثناءات التي قد تحدث.\n\n\n```java\npublic class DatabaseUnavailableException extends Exception {\n    // ... constructor and other methods ...\n}\n\npublic class ItemUnavailableException extends Exception {\n    // ... constructor and other methods ...\n}\n\npublic class ShippingNotPossibleException extends Exception {\n    // ... constructor and other methods ...\n}\n```\n\nفي الطريقة الرئيسية لكل فئة (AppQueueFailCases و AppShippingFailCases)، يتم محاكاة سيناريوهات مختلفة عن طريق إنشاء مثيلات من فئة Commander مع تكوينات مختلفة واستدعاء طريقة placeOrder.\n\n## مخطط الفئات\n\n![alt text](./etc/commander.urm.png \"مخطط فئة Commander\")\n\n## قابلية التطبيق\n\nاستخدم نمط Commander للمعاملات الموزعة عندما:\n\n* تحتاج إلى ضمان اتساق البيانات بين الخدمات الموزعة في حالة حدوث فشل جزئي في النظام.\n* تشمل المعاملات عدة خدمات ميكروسيرفيس أو مكونات موزعة تتطلب commit أو rollback منسق.\n* تقوم بتنفيذ معاملات طويلة الأجل تتطلب إجراءات تعويضية للإلغاء.\n\n## الاستخدامات المعروفة\n\n* بروتوكولات Two-Phase Commit (2PC): التنسيق بين commit أو rollback عبر قواعد البيانات أو الخدمات الموزعة.\n* تنفيذات نمط Saga: إدارة عمليات الأعمال طويلة الأجل التي تشمل العديد من الميكروسيرفيس، مع وجود إجراء تعويضي لكل خطوة للإلغاء.\n* المعاملات الموزعة في بنية الميكروسيرفيس: تنسيق العمليات المعقدة بين الميكروسيرفيس مع الحفاظ على تكامل البيانات واتساقها.\n\n## العواقب\n\nالفوائد:\n\n* يوفر آلية واضحة لإدارة المعاملات الموزعة المعقدة، مما يحسن موثوقية النظام.\n* يسمح بتنفيذ المعاملات التعويضية، وهي ضرورية للحفاظ على التناسق في المعاملات طويلة الأجل.\n* يسهل دمج الأنظمة المتجانسة في سياق المعاملات.\n\nالعيوب:\n\n* يزيد من التعقيد، خاصة في حالات الفشل، بسبب الحاجة إلى آليات التراجع المنسقة.\n* قد يؤثر على الأداء بسبب الحمل الزائد للتنسيق وفحوصات التناسق.\n* قد تؤدي التنفيذات المعتمدة على Saga إلى زيادة التعقيد في فهم سير العملية التجارية العامة.\n\n## الأنماط المرتبطة\n\n[Nمط Saga](https://java-design-patterns.com/patterns/saga/): غالبًا ما يتم مناقشته مع نمط Commander للمعاملات الموزعة، مع التركيز على المعاملات طويلة الأجل مع إجراءات تعويضية.\n\n## الشكر\n\n* [المعاملات الموزعة: جبال الجليد في الميكروسيرفيس](https://www.grahamlea.com/2016/08/distributed-transactions-microservices-icebergs/)\n* [أنماط الميكروسيرفيس: مع أمثلة في جافا](https://amzn.to/4axjnYW)\n* [تصميم التطبيقات المعتمدة على البيانات: الأفكار الكبيرة وراء الأنظمة القابلة للاعتماد، القابلة للتوسع، والقابلة للصيانة](https://amzn.to/4axHwOV)\n* [أنماط تكامل المؤسسات: تصميم وبناء ونشر حلول الرسائل](https://amzn.to/4aATcRe)\n"
  },
  {
    "path": "localization/ar/composite/README.md",
    "content": "---\ntitle: Composite\nshortTitle: Composite\ncategory: Structural\nlanguage: ar\ntag:\n  - Gang of Four\n  - Object composition\n  - Recursion\n---\n\n## أيضًا يُعرف بـ\n\n* شجرة الكائنات\n* الهيكل المركب\n\n## الهدف\n\nتركيب الكائنات في هياكل شجرية لتمثيل التسلسل الهرمي \"جزء-كامل\". يسمح نمط المركب للعملاء بمعاملة الكائنات الفردية وتركيبات الكائنات بطريقة موحدة.\n\n## الشرح\n\nمثال واقعي\n\n> تتكون كل جملة من كلمات، وكل كلمة تتكون بدورها من أحرف. كل واحد من هذه الكائنات قابل للطباعة ويمكن أن يكون له شيء مطبوع قبله أو بعده، مثلًا الجملة دائمًا تنتهي بنقطة، والكلمة دائمًا تملك مسافة قبلها.\n\nبكلمات بسيطة\n\n> يسمح نمط المركب للعملاء بمعاملة الكائنات الفردية بطريقة موحدة.\n\nتقول ويكيبيديا\n\n> في هندسة البرمجيات، نمط المركب هو نمط تصميم تقسيمي. يصف هذا النمط أنه يجب معاملة مجموعة من الكائنات بنفس الطريقة التي يتم بها معاملة كائن واحد. الهدف من المركب هو \"تركيب\" الكائنات في هياكل شجرية لتمثيل التسلسل الهرمي \"جزء-كامل\". يسمح تنفيذ نمط التركيب للعملاء بمعاملة الكائنات الفردية وتركيبات الكائنات بطريقة موحدة.\n\n**مثال برمجي**\n\nباستخدام مثالنا السابق، هنا لدينا الفئة الأساسية `LetterComposite` وأنواع مختلفة من الكائنات القابلة للطباعة مثل `Letter`, `Word`, و `Sentence`.\n\n\n```java\npublic abstract class LetterComposite {\n\n    private final List<LetterComposite> children = new ArrayList<>();\n\n    public void add(LetterComposite letter) {\n        children.add(letter);\n    }\n\n    public int count() {\n        return children.size();\n    }\n\n    protected void printThisBefore() {\n    }\n\n    protected void printThisAfter() {\n    }\n\n    public void print() {\n        printThisBefore();\n        children.forEach(LetterComposite::print);\n        printThisAfter();\n    }\n}\n\npublic class Letter extends LetterComposite {\n\n    private final char character;\n\n    public Letter(char c) {\n        this.character = c;\n    }\n\n    @Override\n    protected void printThisBefore() {\n        System.out.print(character);\n    }\n}\n\npublic class Word extends LetterComposite {\n\n    public Word(List<Letter> letters) {\n        letters.forEach(this::add);\n    }\n\n    public Word(char... letters) {\n        for (char letter : letters) {\n            this.add(new Letter(letter));\n        }\n    }\n\n    @Override\n    protected void printThisBefore() {\n        System.out.print(\" \");\n    }\n}\n\npublic class Sentence extends LetterComposite {\n\n    public Sentence(List<Word> words) {\n        words.forEach(this::add);\n    }\n\n    @Override\n    protected void printThisAfter() {\n        System.out.print(\".\");\n    }\n}\n```\n\n## لدينا الآن مرسل لنقل الرسائل:\n\n```java\npublic class Messenger {\n\n    LetterComposite messageFromOrcs() {\n\n        var words = List.of(\n                new Word('W', 'h', 'e', 'r', 'e'),\n                new Word('t', 'h', 'e', 'r', 'e'),\n                new Word('i', 's'),\n                new Word('a'),\n                new Word('w', 'h', 'i', 'p'),\n                new Word('t', 'h', 'e', 'r', 'e'),\n                new Word('i', 's'),\n                new Word('a'),\n                new Word('w', 'a', 'y')\n        );\n\n        return new Sentence(words);\n\n    }\n\n    LetterComposite messageFromElves() {\n\n        var words = List.of(\n                new Word('M', 'u', 'c', 'h'),\n                new Word('w', 'i', 'n', 'd'),\n                new Word('p', 'o', 'u', 'r', 's'),\n                new Word('f', 'r', 'o', 'm'),\n                new Word('y', 'o', 'u', 'r'),\n                new Word('m', 'o', 'u', 't', 'h')\n        );\n\n        return new Sentence(words);\n\n    }\n\n}\n```\n\n## وبالتالي يمكن استخدامه كالتالي:\n\n```java\nvar messenger=new Messenger();\n\n        LOGGER.info(\"Message from the orcs: \");\n        messenger.messageFromOrcs().print();\n\n        LOGGER.info(\"Message from the elves: \");\n        messenger.messageFromElves().print();\n```\n\n## مخرجات وحدة التحكم:\n\n\n\n```\nMessage from the orcs: \n Where there is a whip there is a way.\nMessage from the elves: \n Much wind pours from your mouth.\n```\n\n## Diagrama de clases\n\n![alt text](./etc/composite.urm.png \"Diagrama de clases compuestas\")\n\n## Applicabilidad\n\nاستخدم نمط **Composite** عندما:\n\n* ترغب في تمثيل الهياكل الجزئية للأشياء.\n* ترغب في أن يتجاهل العملاء الفرق بين تراكيب الأشياء والأشياء الفردية. سيعالج العملاء جميع الكائنات في الهيكل المركب بشكل موحد.\n\n## الاستخدامات المعروفة\n\n* واجهات المستخدم الرسومية حيث يمكن للمكونات أن تحتوي على مكونات أخرى (مثل الألواح التي تحتوي على أزرار، تسميات، وألواح أخرى).\n* تمثيلات أنظمة الملفات حيث يمكن للأدلة أن تحتوي على ملفات وأدلة أخرى.\n* الهياكل التنظيمية حيث يمكن للقسم أن يحتوي على أقسام فرعية وموظفين.\n* [java.awt.Container](http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html)\n  و [java.awt.Component](http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html)\n* شجرة المكونات [Apache Wicket](https://github.com/apache/wicket)،\n  انظر [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java)\n  و [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)\n\n## العواقب\n\n### الفوائد:\n\n* يبسط الكود الخاص بالعميل، حيث يمكنه التعامل مع الهياكل المركبة والأشياء الفردية بشكل موحد.\n* يسهل إضافة أنواع جديدة من المكونات، حيث لا يتعين تعديل الكود الموجود.\n\n### العيوب:\n\n* قد يجعل التصميم عامًا جدًا. قد يكون من الصعب تقييد مكونات المركب.\n* قد يصعب تحديد أنواع المكونات في المركب.\n\n## الأنماط المتعلقة\n\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): يمكن لـ Composite استخدام Flyweight لمشاركة\n  مثيلات المكونات بين عدة مركبات.\n* [Iterador](https://java-design-patterns.com/patterns/iterator/): يمكن استخدامه لتصفح الهياكل المركبة.\n* [Visitante](https://java-design-patterns.com/patterns/visitor/): يمكن تطبيق عملية على الهيكل المركب.\n\n## الائتمانات\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n* [Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/3xoLAmi)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3vBKXWb)\n"
  },
  {
    "path": "localization/ar/composite-entity/README.md",
    "content": "---\ntitle: Composite Entity\nshortTitle: Composite Entity\ncategory: Structural\nlanguage: ar\ntag:\n  - Client-server\n  - Data access\n  - Enterprise patterns\n---\n\n## أيضا يُعرف بـ\n\n* الكيان ذو الحبيبات الخشنة\n\n## الهدف\n\nهدف نمط التصميم **الكيان المركب** هو إدارة مجموعة من الكائنات المستمرة المترابطة كما لو كانت كيانًا واحدًا. يتم استخدامه عادة في سياق **Enterprise JavaBeans (EJB)** وأطر العمل التجارية المماثلة لتمثيل الهياكل البيانية للبيانات ضمن نماذج الأعمال، مما يتيح للعملاء التعامل معها كوحدة واحدة.\n\n## الشرح\n\nمثال واقعي\n\n> في وحدة التحكم، قد يكون هناك العديد من الواجهات التي تحتاج إلى إدارة ومراقبة. باستخدام نمط الكيان المركب، يمكن دمج الكائنات المعتمدة مثل الرسائل والإشارات والسيطرة عليها باستخدام كائن واحد.\n\nبكلمات بسيطة\n\n> نمط الكيان المركب يسمح بتمثيل وإدارة مجموعة من الكائنات المرتبطة من خلال كائن موحد.\n\n**مثال برمجي**\n\nنحتاج إلى حل عام للمشكلة. لذلك، سنقدم نمطًا عامًا للكيان المركب.\n\n\n```java\npublic abstract class DependentObject<T> {\n\n    T data;\n\n    public void setData(T message) {\n        this.data = message;\n    }\n\n    public T getData() {\n        return data;\n    }\n}\n\npublic abstract class CoarseGrainedObject<T> {\n\n    DependentObject<T>[] dependentObjects;\n\n    public void setData(T... data) {\n        IntStream.range(0, data.length).forEach(i -> dependentObjects[i].setData(data[i]));\n    }\n\n    public T[] getData() {\n        return (T[]) Arrays.stream(dependentObjects).map(DependentObject::getData).toArray();\n    }\n}\n\n```\n\nالكائن المركب المتخصص `consola` يرث من هذه الفئة الأساسية بالطريقة التالية.\n\n\n```java\npublic class MessageDependentObject extends DependentObject<String> {\n\n}\n\npublic class SignalDependentObject extends DependentObject<String> {\n\n}\n\npublic class ConsoleCoarseGrainedObject extends CoarseGrainedObject<String> {\n\n    @Override\n    public String[] getData() {\n        super.getData();\n        return new String[] {\n                dependentObjects[0].getData(), dependentObjects[1].getData()\n        };\n    }\n\n    public void init() {\n        dependentObjects = new DependentObject[] {\n                new MessageDependentObject(), new SignalDependentObject()};\n    }\n}\n\npublic class CompositeEntity {\n\n    private final ConsoleCoarseGrainedObject console = new ConsoleCoarseGrainedObject();\n\n    public void setData(String message, String signal) {\n        console.setData(message, signal);\n    }\n\n    public String[] getData() {\n        return console.getData();\n    }\n}\n```\n\nإدارة الآن تخصيص كائنات الرسالة والإشارة مع الكائن المركب `consola`.\n\n\n```java\nvar console=new CompositeEntity();\n        console.init();\n        console.setData(\"No Danger\",\"Green Light\");\n        Arrays.stream(console.getData()).forEach(LOGGER::info);\n        console.setData(\"Danger\",\"Red Light\");\n        Arrays.stream(console.getData()).forEach(LOGGER::info);\n```\n\n## مخطط الفئات\n\n![alt text](./etc/composite_entity.urm.png \"نمط الكائن المركب\")\n\n## القابلية للتطبيق\n\n* مفيد في التطبيقات التجارية حيث تكون الكائنات التجارية معقدة وتنطوي على عدة كائنات مترابطة.\n* مثالي للسيناريوهات التي يحتاج فيها العملاء للعمل مع واجهة موحدة لمجموعة من الكائنات بدلاً من الكائنات الفردية.\n* قابل للتطبيق في الأنظمة التي تتطلب عرضًا مبسطًا لنموذج بيانات معقد للعملاء أو الخدمات الخارجية.\n\n## الاستخدامات المعروفة\n\n* التطبيقات التجارية ذات النماذج التجارية المعقدة، وخاصة تلك التي تستخدم EJB أو أطر عمل تجارية مشابهة.\n* الأنظمة التي تتطلب تجريدًا فوق مخططات قواعد بيانات معقدة لتبسيط التفاعلات مع العملاء.\n* التطبيقات التي تحتاج إلى تعزيز التناسق أو المعاملات عبر عدة كائنات في كائن تجاري واحد.\n\n## العواقب\n\nالفوائد:\n\n* يبسط تفاعلات العميل مع النماذج الكائنية المعقدة من خلال توفير واجهة موحدة.\n* يعزز إعادة الاستخدام والصيانة في طبقة الأعمال عن طريق فصل كود العميل عن المكونات الداخلية المعقدة للكائنات التجارية.\n* يسهل إدارة المعاملات وتطبيق التناسق في مجموعة من الكائنات المترابطة.\n\nالسلبيات:\n\n* قد يقدم مستوى من الاستدلال الذي قد يؤثر على الأداء.\n* قد يؤدي إلى واجهات ذات حبوب خشنة جدًا قد لا تكون مرنة لجميع احتياجات العملاء.\n* يتطلب تصميمًا دقيقًا لتجنب الكائنات المركبة المتضخمة التي يصعب إدارتها.\n\n## الأنماط ذات الصلة\n\n* [الزخرفة](https://java-design-patterns.com/patterns/decorator/): لإضافة سلوك ديناميكي للكائنات الفردية داخل الكائن المركب دون التأثير على الهيكل.\n* [الواجهة](https://java-design-patterns.com/patterns/facade/): يوفر واجهة مبسطة لنظام فرعي معقد، بشكل مشابه لكيفية تبسيط الكائن المركب الوصول إلى مجموعة من الكائنات.\n* [الوزن الخفيف](https://java-design-patterns.com/patterns/flyweight/): مفيد لإدارة الكائنات المشتركة داخل الكائن المركب لتقليل بصمة الذاكرة.\n\n## الاعتمادات\n\n* [نمط الكائن المركب في ويكيبيديا](https://en.wikipedia.org/wiki/Composite_entity_pattern)\n* [أفضل الممارسات واستراتيجيات التصميم في الأنماط الأساسية لـ J2EE](https://amzn.to/4cAbDap)\n* [أنماط المؤسسة و MDA: بناء البرمجيات الأفضل باستخدام أنماط الأركيتايب و UML](https://amzn.to/49mslqS)\n* [أنماط بنية التطبيقات المؤسسية](https://amzn.to/3xjKdpe)\n"
  },
  {
    "path": "localization/ar/composite-view/README.md",
    "content": "---\ntitle: Composite View\nshortTitle: Composite View\ncategory: Structural\nlanguage: ar\ntag:\n  - Enterprise patterns\n  - Presentation\n---\n\n## الغرض\n\nالهدف الرئيسي من نمط التصميم \"عرض مركب\" هو تكوين الكائنات في هياكل شجرية لتمثيل الهيراركية جزء-كامل. هذا يتيح للعملاء التعامل مع الكائنات الفردية وتركيبات الكائنات بشكل موحد، مما يبسط إدارة الهياكل المعقدة.\n\n## التفسير\n\nمثال من العالم الحقيقي\n\n> موقع إخباري يريد عرض التاريخ الحالي والأخبار لعدة مستخدمين بناءً على تفضيلات كل مستخدم. سيستبدل الموقع في مكونات تغذية الأخبار المختلفة حسب اهتمامات المستخدم، مع الأخبار المحلية كافتراضي.\n\nبإيجاز\n\n> نمط العرض المركب يتكون من عرض رئيسي مكون من عروض فرعية أصغر. يعتمد تصميم هذا العرض المركب على قالب. ثم يقرر مدير العرض أي العروض الفرعية يجب تضمينها في هذا القالب.\n\nتقول ويكيبيديا\n\n> العروض المركبة التي تتكون من العديد من العروض الفرعية الذرية. يمكن تضمين كل مكون من القالب ديناميكيًا في المجموعة ويمكن إدارة تصميم الصفحة بشكل مستقل عن المحتوى. يتيح هذا الحل إنشاء عرض مركب استنادًا إلى تضمين واستبدال أجزاء قابلة لإعادة الاستخدام من القوالب الديناميكية والثابتة. يعزز التصميم المعياري من خلال تشجيع إعادة استخدام أجزاء الذرة من العرض.\n\n**مثال برمجي**\n\nنظرًا لأن هذا نمط تطوير ويب، فإن الخادم مطلوب لعرضه. يستخدم هذا المثال Tomcat 10.0.13 لتشغيل السيرفلت، ولن يعمل هذا المثال البرمجي إلا مع Tomcat 10+.\n\nأولاً، يوجد `AppServlet` الذي هو `HttpServlet` يعمل في Tomcat 10+.\n\n\n```java\npublic class AppServlet extends HttpServlet {\n    private String msgPartOne = \"<h1>This Server Doesn't Support\";\n    private String msgPartTwo = \"Requests</h1>\\n\"\n            + \"<h2>Use a GET request with boolean values for the following parameters<h2>\\n\"\n            + \"<h3>'name'</h3>\\n<h3>'bus'</h3>\\n<h3>'sports'</h3>\\n<h3>'sci'</h3>\\n<h3>'world'</h3>\";\n\n    private String destination = \"newsDisplay.jsp\";\n\n    public AppServlet() {\n\n    }\n\n    @Override\n    public void doGet(HttpServletRequest req, HttpServletResponse resp)\n            throws ServletException, IOException {\n        RequestDispatcher requestDispatcher = req.getRequestDispatcher(destination);\n        ClientPropertiesBean reqParams = new ClientPropertiesBean(req);\n        req.setAttribute(\"properties\", reqParams);\n        requestDispatcher.forward(req, resp);\n    }\n\n    @Override\n    public void doPost(HttpServletRequest req, HttpServletResponse resp)\n            throws ServletException, IOException {\n        resp.setContentType(\"text/html\");\n        PrintWriter out = resp.getWriter();\n        out.println(msgPartOne + \" Post \" + msgPartTwo);\n\n    }\n\n    @Override\n    public void doDelete(HttpServletRequest req, HttpServletResponse resp)\n            throws ServletException, IOException {\n        resp.setContentType(\"text/html\");\n        PrintWriter out = resp.getWriter();\n        out.println(msgPartOne + \" Delete \" + msgPartTwo);\n\n    }\n\n    @Override\n    public void doPut(HttpServletRequest req, HttpServletResponse resp)\n            throws ServletException, IOException {\n        resp.setContentType(\"text/html\");\n        PrintWriter out = resp.getWriter();\n        out.println(msgPartOne + \" Put \" + msgPartTwo);\n\n    }\n}\n\n```\n\nهذا السيرفلت لا يشكل جزءًا من النمط، ويقوم ببساطة بإعادة توجيه طلبات GET إلى JSP الصحيح. الطلبات PUT و POST و DELETE غير مدعومة وستعرض ببساطة رسالة خطأ.\n\nإدارة العرض في هذا المثال تتم من خلال فئة javabean: `ClientPropertiesBean`، التي تخزن تفضيلات المستخدم.\n\n\n```java\npublic class ClientPropertiesBean implements Serializable {\n\n    private static final String WORLD_PARAM = \"world\";\n    private static final String SCIENCE_PARAM = \"sci\";\n    private static final String SPORTS_PARAM = \"sport\";\n    private static final String BUSINESS_PARAM = \"bus\";\n    private static final String NAME_PARAM = \"name\";\n\n    private static final String DEFAULT_NAME = \"DEFAULT_NAME\";\n    private boolean worldNewsInterest;\n    private boolean sportsInterest;\n    private boolean businessInterest;\n    private boolean scienceNewsInterest;\n    private String name;\n\n    public ClientPropertiesBean() {\n        worldNewsInterest = true;\n        sportsInterest = true;\n        businessInterest = true;\n        scienceNewsInterest = true;\n        name = DEFAULT_NAME;\n\n    }\n\n    public ClientPropertiesBean(HttpServletRequest req) {\n        worldNewsInterest = Boolean.parseBoolean(req.getParameter(WORLD_PARAM));\n        sportsInterest = Boolean.parseBoolean(req.getParameter(SPORTS_PARAM));\n        businessInterest = Boolean.parseBoolean(req.getParameter(BUSINESS_PARAM));\n        scienceNewsInterest = Boolean.parseBoolean(req.getParameter(SCIENCE_PARAM));\n        String tempName = req.getParameter(NAME_PARAM);\n        if (tempName == null || tempName == \"\") {\n            tempName = DEFAULT_NAME;\n        }\n        name = tempName;\n    }\n    // getters and setters generated by Lombok \n}\n```\n\nهذا السيرفلت لا يشكل جزءًا من النمط، ويقوم ببساطة بإعادة توجيه طلبات GET إلى JSP الصحيح. الطلبات PUT و POST و DELETE غير مدعومة وستعرض ببساطة رسالة خطأ.\n\nإدارة العرض في هذا المثال تتم من خلال فئة javabean: `ClientPropertiesBean`، التي تخزن تفضيلات المستخدم.\n\n\n```html\n\n<html>\n<head>\n    <style>\n        h1 {\n            text-align: center;\n        }\n\n        h2 {\n            text-align: center;\n        }\n\n        h3 {\n            text-align: center;\n        }\n\n        .centerTable {\n            margin-left: auto;\n            margin-right: auto;\n        }\n\n        table {\n            border: 1px solid black;\n        }\n\n        tr {\n            text-align: center;\n        }\n\n        td {\n            text-align: center;\n        }\n    </style>\n</head>\n<body>\n<%ClientPropertiesBean propertiesBean = (ClientPropertiesBean) request.getAttribute(\"properties\");%>\n<h1>Welcome <%= propertiesBean.getName()%></h1>\n<jsp:include page=\"header.jsp\"></jsp:include>\n<table class=\"centerTable\">\n\n    <tr>\n        <td></td>\n        <% if(propertiesBean.isWorldNewsInterest()) { %>\n        <td><%@include file=\"worldNews.jsp\"%></td>\n        <% } else { %>\n        <td><%@include file=\"localNews.jsp\"%></td>\n        <% } %>\n        <td></td>\n    </tr>\n    <tr>\n        <% if(propertiesBean.isBusinessInterest()) { %>\n        <td><%@include file=\"businessNews.jsp\"%></td>\n        <% } else { %>\n        <td><%@include file=\"localNews.jsp\"%></td>\n        <% } %>\n        <td></td>\n        <% if(propertiesBean.isSportsInterest()) { %>\n        <td><%@include file=\"sportsNews.jsp\"%></td>\n        <% } else { %>\n        <td><%@include file=\"localNews.jsp\"%></td>\n        <% } %>\n    </tr>\n    <tr>\n        <td></td>\n        <% if(propertiesBean.isScienceNewsInterest()) { %>\n        <td><%@include file=\"scienceNews.jsp\"%></td>\n        <% } else { %>\n        <td><%@include file=\"localNews.jsp\"%></td>\n        <% } %>\n        <td></td>\n    </tr>\n</table>\n</body>\n</html>\n```\n\nهذه الصفحة JSP هي القالب. تقوم بإعلان جدول يحتوي على ثلاث صفوف، مع مكون في الصف الأول، واثنين من المكونات في الصف الثاني، ومكون واحد في الصف الثالث.\n\nتعتبر السكربتات في الملف جزءًا من استراتيجية إدارة العرض التي تتضمن مختلف العناصر الفرعية الذرية بناءً على تفضيلات المستخدم في الجافابين.\n\nفيما يلي مثالان على العناصر الفرعية الذرية المُحاكاة المستخدمة في التكوين: `businessNews.jsp`.\n\n\n```html\n\n<html>\n<head>\n    <style>\n        h2 {\n            text-align: center;\n        }\n\n        table {\n            border: 1px solid black;\n        }\n\n        tr {\n            text-align: center;\n        }\n\n        td {\n            text-align: center;\n        }\n    </style>\n</head>\n<body>\n<h2>\n    Generic Business News\n</h2>\n<table style=\"margin-right: auto; margin-left: auto\">\n    <tr>\n        <td>Stock prices up across the world</td>\n        <td>New tech companies to invest in</td>\n    </tr>\n    <tr>\n        <td>Industry leaders unveil new project</td>\n        <td>Price fluctuations and what they mean</td>\n    </tr>\n</table>\n</body>\n</html>\n```\n\n`localNews.jsp`\n\n```html\n\n<html>\n<body>\n<div style=\"text-align: center\">\n    <h3>\n        Generic Local News\n    </h3>\n    <ul style=\"list-style-type: none\">\n        <li>\n            Mayoral elections coming up in 2 weeks\n        </li>\n        <li>\n            New parking meter rates downtown coming tomorrow\n        </li>\n        <li>\n            Park renovations to finish by the next year\n        </li>\n        <li>\n            Annual marathon sign ups available online\n        </li>\n    </ul>\n</div>\n</body>\n</html>\n```\n\nالنتائج هي كما يلي:\n\n1) وضع المستخدم اسمه كـ `Tammy` في معلمات الطلب ولم يضع أي تفضيلات: ![alt text](./etc/images/noparam.png)\n2) وضع المستخدم اسمه كـ `Johnny` في معلمات الطلب ولديه تفضيل للأخبار عن العالم، الأعمال والعلوم: ![alt text](./etc/images/threeparams.png)\n\nيتم تضمين العناصر الفرعية المختلفة مثل `worldNews.jsp`، `businessNews.jsp`، وغيرها بشكل مشروط بناءً على معلمات الطلب.\n\n**كيفية الاستخدام**\n\nلاختبار هذا المثال، تأكد من أن لديك Tomcat 10+ مثبتًا. قم بتكوين IDE الخاص بك لإنشاء ملف WAR من الوحدة ونشر هذا الملف على الخادم.\n\nIntelliJ:\n\nفي `تشغيل` و `تحرير التكوينات` تأكد من أن خادم Tomcat هو أحد تكوينات التنفيذ. اذهب إلى تبويب النشر وتأكد من أنه يتم بناء artifact يسمى `composite-view:war exploded`. إذا لم يكن موجودًا، أضف واحدًا.\n\nتأكد من أن artifact يتم بناؤه من محتويات مجلد `web` ونتائج تجميع الوحدة. وجه مخرجات artifact إلى مكان مناسب. نفذ التكوين وشاهد الصفحة المستهدفة، واتبع التعليمات في تلك الصفحة للمتابعة.\n\n## مخطط الفئات\n\n![alt text](./etc/composite_view.png)\n\nيُظهر مخطط الفئات هنا الجافابين الذي يُعتبر مدير العرض. العروض هي ملفات JSP داخل مجلد الويب.\n\n## القابلية للتطبيق:\n\nاستخدم نمط التصميم Composite View عندما:\n\n## تريد تمثيل الهياكل الجزئية للأشياء.\n\n* تتوقع أن الهياكل المركبة قد تتضمن مكونات جديدة في المستقبل.\n* ترغب في أن يتمكن العملاء من تجاهل الفرق بين تكوينات الكائنات والكائنات الفردية. سيتعامل العملاء مع جميع الكائنات في الهيكل المركب بشكل موحد.\n\n## الاستخدامات المعروفة\n\n* واجهات المستخدم الرسومية (GUI) التي يمكن أن تحتوي فيها الأدوات على أدوات أخرى (على سبيل المثال، نافذة تحتوي على لوحات وأزرار وحقول نصية).\n* هياكل الوثائق، مثل تمثيل الجداول التي تحتوي على صفوف، تحتوي هذه الصفوف بدورها على خلايا، والتي يمكن معالجتها جميعًا كعناصر في تسلسل هرمي موحد.\n\n## العواقب\n\nالفوائد:\n\n* مرونة كبيرة في إضافة مكونات جديدة: بما أن المكونات المركبة والعقد الورقية يتم التعامل معها بشكل موحد، يكون من الأسهل إضافة أنواع جديدة من المكونات.\n* تبسيط الشيفرة البرمجية للعملاء: يمكن للعملاء التعامل مع الهياكل المركبة والعناصر الفردية بشكل موحد، مما يقلل من تعقيد الشيفرة البرمجية للعملاء.\n\nالعيوب:\n\n* التعميم المفرط: قد يصبح تصميم النظام أكثر تعقيدًا إذا جعلت كل شيء مركبًا، خاصة إذا كانت تطبيقك لا يتطلب ذلك.\n* صعوبة تطبيق القيود: قد يكون من الأصعب تقييد مكونات المركب لتكون من أنواع معينة فقط.\n\n## الأنماط ذات الصلة\n\n* [المزخرف](https://java-design-patterns.com/patterns/decorator/): بينما يستخدم مزخرف لإضافة مسؤوليات إلى الكائنات، يتم تصميم Composite لبناء هياكل كائنات.\n* [الوزن الخفيف](https://java-design-patterns.com/patterns/flyweight/): يمكن دمج Composite غالبًا مع Flyweight لتنفيذ العقد الورقية المشتركة في هيكل مركب، مما يقلل من بصمة الذاكرة.\n* [سلسلة المسؤولية](https://java-design-patterns.com/patterns/chain-of-responsibility/): يمكن استخدامها مع Composite للسماح للمكونات بتمرير الطلبات عبر التسلسل الهرمي.\n* [المركب](https://java-design-patterns.com/patterns/composite/)\n* [مساعد العرض](https://www.oracle.com/java/technologies/viewhelper.html)\n\n## الاعتمادات\n\n* [Core J2EE Patterns - Composite View](https://www.oracle.com/java/technologies/composite-view.html)\n* [Composite View Design Pattern – Core J2EE Patterns](https://www.dineshonjava.com/composite-view-design-pattern/)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/49jpQG3)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/3xfntGJ)\n"
  },
  {
    "path": "localization/ar/context-object/README.md",
    "content": "---\ntitle: Context object\nshortTitle: Context object\ncategory: Creational\nlanguage: ar\ntags:\n  - Data access\n---\n\n## الاسم / التصنيف\n\nكائن السياق\n\n## يعرف أيضًا باسم\n\nالسياق، تجميع السياق\n\n## الغرض\n\nفصل البيانات عن الفئات الخاصة بالبروتوكول وتخزين بيانات السياق في كائن مستقل عن التكنولوجيا الخاصة بالبروتوكول الأساسي.\n\n## الشرح\n\nمثال من العالم الواقعي\n\n> يحتوي هذا التطبيق على طبقات مختلفة موسومة مثل A وB وC، كل واحدة منها تستخرج معلومات محددة من سياق مشابه لاستخدامها لاحقًا في البرنامج. تمرير كل قطعة من المعلومات بشكل فردي سيكون غير فعال، لذا هناك حاجة إلى طريقة لتخزين وتمرير المعلومات بشكل فعال.\n> بكلمات بسيطة\n\n> أنشئ كائنًا وخزن البيانات هناك، ثم مرر هذا الكائن حيثما كان مطلوبًا.\n\n[Core J2EE Patterns](http://corej2eepatterns.com/ContextObject.htm) يقول\n\n> استخدم كائن السياق (Context Object) لتغليف الحالة بطريقة مستقلة عن البروتوكول ليتم مشاركتها عبر تطبيقك.\n\n**مثال برمجي**\n\nنحدد البيانات التي يحتوي عليها كائن السياق (Context Object) للخدمة `ServiceContext`.\n\n\n```Java\npublic class ServiceContext {\n\n    String ACCOUNT_SERVICE, SESSION_SERVICE, SEARCH_SERVICE;\n\n    public void setACCOUNT_SERVICE(String ACCOUNT_SERVICE) {\n        this.ACCOUNT_SERVICE = ACCOUNT_SERVICE;\n    }\n\n    public void setSESSION_SERVICE(String SESSION_SERVICE) {\n        this.SESSION_SERVICE = SESSION_SERVICE;\n    }\n\n    public void setSEARCH_SERVICE(String SEARCH_SERVICE) {\n        this.SEARCH_SERVICE = SEARCH_SERVICE;\n    }\n\n    public String getACCOUNT_SERVICE() {\n        return ACCOUNT_SERVICE;\n    }\n\n    public String getSESSION_SERVICE() {\n        return SESSION_SERVICE;\n    }\n\n    public String getSEARCH_SERVICE() {\n        return SEARCH_SERVICE;\n    }\n    \n    public String toString() { return ACCOUNT_SERVICE + \" \" + SESSION_SERVICE + \" \" + SEARCH_SERVICE;}\n}\n```\n\nيتم إنشاء واجهة `ServiceContextFactory` تُستخدم في أجزاء من التطبيق لإنشاء كائنات السياق.\n\n\n```Java\npublic class ServiceContextFactory {\n\n    public static ServiceContext createContext() {\n        return new ServiceContext();\n    }\n}\n```\n\nإنشاء كائن السياق في الطبقة الأولى `LayerA` والطبقة المجاورة `LayerB` حتى يتم استدعاء السياق في الطبقة الحالية `LayerC`، التي تقوم بترتيب الكائن.\n\n\n```Java\npublic class LayerA {\n\n    private static ServiceContext context;\n\n    public LayerA() {\n        context = ServiceContextFactory.createContext();\n    }\n\n    public static ServiceContext getContext() {\n        return context;\n    }\n\n    public void addAccountInfo(String accountService) {\n        context.setACCOUNT_SERVICE(accountService);\n    }\n}\n\npublic class LayerB {\n\n    private static ServiceContext context;\n\n    public LayerB(LayerA layerA) {\n        this.context = layerA.getContext();\n    }\n\n    public static ServiceContext getContext() {\n        return context;\n    }\n\n    public void addSessionInfo(String sessionService) {\n        context.setSESSION_SERVICE(sessionService);\n    }\n}\n\npublic class LayerC {\n\n    public static ServiceContext context;\n\n    public LayerC(LayerB layerB) {\n        this.context = layerB.getContext();\n    }\n\n    public static ServiceContext getContext() {\n        return context;\n    }\n\n    public void addSearchInfo(String searchService) {\n        context.setSEARCH_SERVICE(searchService);\n    }\n}\n```\n\nإليك كائن السياق والطبقات قيد التنفيذ.\n\n\n```Java\nvar layerA = new LayerA();\nlayerA.addAccountInfo(SERVICE);\nLOGGER.info(\"Context = {}\",layerA.getContext());\nvar layerB = new LayerB(layerA);\nlayerB.addSessionInfo(SERVICE);\nLOGGER.info(\"Context = {}\",layerB.getContext());\nvar layerC = new LayerC(layerB);\nlayerC.addSearchInfo(SERVICE);\nLOGGER.info(\"Context = {}\",layerC.getContext());\n```\n\nإخراج البرنامج:\n\n\n```Java\nContext = SERVICE null null\nContext = SERVICE SERVICE null\nContext = SERVICE SERVICE SERVICE\n```\n\n## رسم توضيحي للفئات\n\n![alt text](./etc/context-object.png \"كائن السياق\")\n\n## القابلية للتطبيق\n\nاستخدم نمط كائن السياق (Context Object) لـ:\n\n* مشاركة المعلومات بين الطبقات المختلفة للنظام.\n* فصل البيانات عن السياقات المحددة للبروتوكولات.\n* عرض واجهات البرمجة ذات الصلة فقط ضمن السياق.\n\n## الاستخدامات المعروفة\n\n* [Spring: ApplicationContext](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html)\n* [Oracle: SecurityContext](https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/SecurityContext.html)\n* [Oracle: ServletContext](https://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html)\n\n## الفضل\n\n* [Core J2EE Design Patterns](https://amzn.to/3IhcY9w)\n* [موقع Core J2EE Design Patterns - كائن السياق](http://corej2eepatterns.com/ContextObject.htm)\n* [Allan Kelly - نمط تجميع السياق](https://accu.org/journals/overload/12/63/kelly_246/)\n* [Arvid S. Krishna وآخرون - كائن السياق](https://www.dre.vanderbilt.edu/~schmidt/PDF/Context-Object-Pattern.pdf)\n"
  },
  {
    "path": "localization/ar/converter/README.md",
    "content": "---\ntitle: Converter\nshortTitle: Converter\ncategory: Creational\nlanguage: ar\ntag:\n  - Decoupling\n---\n\n## الهدف\n\nالهدف من نمط المحول (Converter) هو توفير وسيلة عامة وشائعة للتحويل الثنائي الاتجاه بين الأنواع المقابلة، مما يتيح تنفيذًا نظيفًا حيث لا يحتاج الأنواع إلى معرفة بعضها البعض. علاوة على ذلك، يقدم نمط المحول تعيينًا ثنائي الاتجاه للمجموعات الثنائية الاتجاه، مما يقلل من الكود المكرر إلى الحد الأدنى.\n\n## الشرح\n\nمثال من الحياة الواقعية\n\n> في التطبيقات الواقعية، غالبًا ما يحدث أن يتكون طبقة قاعدة البيانات من كيانات تحتاج إلى أن يتم تحويلها إلى DTO لاستخدامها في طبقة منطق الأعمال. يتم إجراء تحويل مشابه لعدد potentially ضخم من الفئات ونحتاج إلى طريقة عامة لتحقيق ذلك.\n\nببساطة\n\n> يسهل نمط التحويل (Converter) تعيين الكائنات من فئة إلى كائنات من فئة أخرى.\n\n**مثال برمجي**\n\nنحتاج إلى حل عام لمشكلة التعيين. لذلك، دعونا نقدم محولًا عامًا.\n\n\n```java\npublic class Converter<T, U> {\n\n  private final Function<T, U> fromDto;\n  private final Function<U, T> fromEntity;\n\n  public Converter(final Function<T, U> fromDto, final Function<U, T> fromEntity) {\n    this.fromDto = fromDto;\n    this.fromEntity = fromEntity;\n  }\n\n  public final U convertFromDto(final T dto) {\n    return fromDto.apply(dto);\n  }\n\n  public final T convertFromEntity(final U entity) {\n    return fromEntity.apply(entity);\n  }\n\n  public final List<U> createFromDtos(final Collection<T> dtos) {\n    return dtos.stream().map(this::convertFromDto).collect(Collectors.toList());\n  }\n\n  public final List<T> createFromEntities(final Collection<U> entities) {\n    return entities.stream().map(this::convertFromEntity).collect(Collectors.toList());\n  }\n}\n```\n\n## المحولات المتخصصة ترث من هذه الفئة الأساسية كما يلي.\n\n\n```java\npublic class UserConverter extends Converter<UserDto, User> {\n\n  public UserConverter() {\n    super(UserConverter::convertToEntity, UserConverter::convertToDto);\n  }\n\n  private static UserDto convertToDto(User user) {\n    return new UserDto(user.getFirstName(), user.getLastName(), user.isActive(), user.getUserId());\n  }\n\n  private static User convertToEntity(UserDto dto) {\n    return new User(dto.getFirstName(), dto.getLastName(), dto.isActive(), dto.getEmail());\n  }\n\n}\n```\n\nالآن يصبح التحويل بين `User` و `UserDto` أمرًا تافهًا.\n\n\n```java\nvar userConverter = new UserConverter();\nvar dtoUser = new UserDto(\"John\", \"Doe\", true, \"whatever[at]wherever.com\");\nvar user = userConverter.convertFromDto(dtoUser);\n```\n\n## مخطط الفئات\n\n![alt text](./etc/converter.png \"نمط المحول\")\n\n## القابلية للتطبيق\n\nاستخدم نمط المحول في الحالات التالية:\n\n* عندما يكون لديك أنواع تتطابق منطقيًا مع بعضها البعض وتحتاج إلى تحويل الكيانات بينهما.\n* عندما ترغب في توفير أشكال مختلفة لتحويل الأنواع اعتمادًا على السياق.\n* كلما قدمت كائن نقل البيانات (DTO)، من المحتمل أن تحتاج إلى تحويله إلى معادله في المجال.\n\n## الاعتمادات\n\n* [نمط المحول في Java 8](http://www.xsolve.pl/blog/converter-pattern-in-java-8/)\n"
  },
  {
    "path": "localization/ar/crtp/README.md",
    "content": "---\ntitle: Curiously Recurring Template Pattern\nlanguage: ar\ncategory: Structural\ntag:\n- Extensibility\n- Instantiation\n---\n\n## الاسم / التصنيف\n\nنمط القالب المتكرر بغرابة\n\n## المعروف أيضًا باسم\n\nالحدود النوعية المتكررة، الجينيريك المتكرر\n\n## الهدف\n\nالسماح للمكونات المشتقة بالوراثة من بعض الوظائف من مكون أساسي تكون متوافقة مع النوع المشتق.\n\n## الشرح\n\nمثال حقيقي\n\n> لتنظيم حدث للفنون القتالية المختلطة، من المهم التأكد من أن المباريات تتم بين رياضيين في نفس فئة الوزن. هذا يضمن تجنب المواجهات بين مقاتلين من أحجام مختلفة للغاية، مثل الوزن الثقيل ضد الوزن الخفيف.\n\nببساطة\n\n> جعل بعض الطرق داخل نوع ما تقبل المعاملات الخاصة بأنواعه الفرعية.\n\nتقول ويكيبيديا\n\n> نمط القالب المتكرر بغرابة (CRTP) هو أسلوب برمجي، بدأ في C++، حيث تقوم فئة X بالاشتقاق من تطبيق قالب فئة باستخدام X نفسها كحجة للقالب.\n\n**مثال برمجي**\n\nلنحدد الواجهة العامة Fighter\n\n\n```java\npublic interface Fighter<T> {\n\n  void fight(T t);\n\n}\n```\n\nتستخدم فئة `MMAFighter` لإنشاء مقاتلين يتميزون بفئة وزنهم.\n\n\n```java\npublic class MmaFighter<T extends MmaFighter<T>> implements Fighter<T> {\n\n  private final String name;\n  private final String surname;\n  private final String nickName;\n  private final String speciality;\n\n  public MmaFighter(String name, String surname, String nickName, String speciality) {\n    this.name = name;\n    this.surname = surname;\n    this.nickName = nickName;\n    this.speciality = speciality;\n  }\n\n  @Override\n  public void fight(T opponent) {\n    LOGGER.info(\"{} is going to fight against {}\", this, opponent);\n  }\n\n  @Override\n  public String toString() {\n    return name + \" \\\"\" + nickName + \"\\\" \" + surname;\n  }\n}\n```\n\nفيما يلي بعض الأنواع الفرعية لـ `MMAFighter`:\n\n\n```java\nclass MmaBantamweightFighter extends MmaFighter<MmaBantamweightFighter> {\n\n  public MmaBantamweightFighter(String name, String surname, String nickName, String speciality) {\n    super(name, surname, nickName, speciality);\n  }\n\n}\n\npublic class MmaHeavyweightFighter extends MmaFighter<MmaHeavyweightFighter> {\n\n  public MmaHeavyweightFighter(String name, String surname, String nickName, String speciality) {\n    super(name, surname, nickName, speciality);\n  }\n\n}\n```\n\nيمكن للمقاتل أن يواجه خصمًا من نفس فئة الوزن، وإذا كان الخصم من فئة وزن مختلفة يحدث خطأ.\n\n\n```java\nMmaBantamweightFighter fighter1 = new MmaBantamweightFighter(\"Joe\", \"Johnson\", \"The Geek\", \"Muay Thai\");\nMmaBantamweightFighter fighter2 = new MmaBantamweightFighter(\"Ed\", \"Edwards\", \"The Problem Solver\", \"Judo\");\nfighter1.fight(fighter2); // This is fine\n\nMmaHeavyweightFighter fighter3 = new MmaHeavyweightFighter(\"Dave\", \"Davidson\", \"The Bug Smasher\", \"Kickboxing\");\nMmaHeavyweightFighter fighter4 = new MmaHeavyweightFighter(\"Jack\", \"Jackson\", \"The Pragmatic\", \"Brazilian Jiu-Jitsu\");\nfighter3.fight(fighter4); // This is fine too\n\nfighter1.fight(fighter3); // This will raise a compilation error\n```\n\n## Diagrama de clases\n\n![alt text](./etc/crtp.png \"Diagrama de clases CRTP\")\n\n## قابلية التطبيق\n\nاستخدم نمط \"القالب المتكرر بشكل غريب\" عندما:\n\n* تواجه تعارضات في الأنواع عند ربط الأساليب في هيكل الكائنات\n* ترغب في استخدام طريقة من الفئة معلمة يمكن أن تقبل الفئات الفرعية كوسائط، مما يسمح بتطبيقها على الكائنات التي ترث من هذه الفئة\n* ترغب في أن تعمل بعض الأساليب فقط مع كائنات من نفس النوع، على سبيل المثال، لتحقيق المقارنة المتبادلة.\n\n## دروس تعليمية\n\n* [مدونة NuaH](https://nuah.livejournal.com/328187.html)\n* إجابة من Yogesh Umesh Vaity على [ماذا يعني \"الحدود التكرارية للنوع\" في الأنواع العامة؟](https://stackoverflow.com/questions/7385949/what-does-recursive-type-bound-in-generics-mean)\n\n## الاستخدامات المعروفة\n\n* [java.lang.Enum](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Enum.html)\n\n## الاعتمادات\n\n* [كيف أفك تشفير \"Enum<E extends Enum\\<E>>\"؟](http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ106)\n* الفصل 5 Generics، العنصر 30 في [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n"
  },
  {
    "path": "localization/ar/data-locality/README.md",
    "content": "---\ntitle: Data Locality\nshortTitle: Data Locality\ncategory: Behavioral\nlanguage: ar\ntag:\n - Game programming\n - Performance\n---\n\n## الهدف\nيُسرع الوصول إلى الذاكرة من خلال تنظيم البيانات للاستفادة من ذاكرة التخزين المؤقت في وحدة المعالجة المركزية.\n\nتحتوي وحدات المعالجة المركزية الحديثة على ذاكرات تخزين مؤقت لتسريع الوصول إلى الذاكرة. يمكنها الوصول بسرعة أكبر إلى الذاكرة المجاورة لذاكرة تم الوصول إليها مؤخرًا. استفد من ذلك لتحسين الأداء عن طريق زيادة محلية البيانات، من خلال الحفاظ عليها في ذاكرة متجاورة بالترتيب الذي تعالجها فيه.\n\n## مخطط الفئات\n![alt text](./etc/data-locality.urm.png \"Data Locality pattern class diagram\")\n\n## قابلية التطبيق\n\n* كما هو الحال مع معظم التحسينات، القاعدة الأولى لاستخدام نمط \"محلية البيانات\" هي عندما يكون لديك مشكلة في الأداء.\n* مع هذا النمط بشكل خاص، ستحتاج أيضًا إلى التأكد من أن مشاكل الأداء ناتجة عن فقدان الذاكرة المؤقتة.\n\n## مثال من العالم الحقيقي\n\n* محرك الألعاب [Artemis](http://gamadu.com/artemis/) هو واحد من أولى وأكثر الأطر شهرة التي تستخدم معرفات بسيطة لكائنات اللعبة.\n\n## الاعتمادات\n\n* [أنماط برمجة الألعاب - أنماط التحسين: محلية البيانات](http://gameprogrammingpatterns.com/data-locality.html)\n"
  },
  {
    "path": "localization/ar/decorator/README.md",
    "content": "---\ntitle: Decorator\nshortTitle: Decorator\ncategory: Structural\nlanguage: ar\ntag:\n  - Gang of Four\n  - Extensibility\n---\n\n## المعروف أيضا باسم\n\nالتغليف\n\n## الهدف\n\nإضافة مسؤوليات إضافية إلى كائن بطريقة ديناميكية. يوفر الزخرفة بديلاً مرنًا للوراثة لتوسيع الوظائف.\n\n## الشرح\n\nمثال من العالم الحقيقي\n\n> في التلال القريبة يعيش تيرول غاضب. عادة ما يكون يده عارية، ولكن في بعض الأحيان يحمل سلاحًا. لتسليح التيرول لا يتطلب الأمر إنشاء تيرول جديد بل تزيينه ديناميكيًا بسلاح مناسب.\n\nببساطة\n\n> يتيح لك نمط الزخرفة تغيير سلوك كائن ديناميكيًا أثناء وقت التشغيل من خلال تغليفه في كائن من فئة الزخرفة.\n\nيقول Wikipedia\n\n> في البرمجة الكائنية التوجه، يعتبر نمط الزخرفة نمط تصميم يسمح بإضافة سلوك إلى كائن فردي، سواء بطريقة ثابتة أو ديناميكية، دون التأثير على سلوك الكائنات الأخرى من نفس الفئة. يُعتبر نمط الزخرفة مفيدًا للامتثال لمبدأ المسؤولية الفردية، حيث يسمح بتقسيم الوظائف بين الفئات ذات مجالات الاهتمام الفريدة، وكذلك لمبدأ الانفتاح-الإغلاق، من خلال السماح بتمديد وظائف الفئة دون تعديلها.\n\n**مثال برمجي**\n\nلنأخذ مثال التيرول. في البداية لدينا `SimpleTroll` الذي ينفذ الواجهة `Troll`:\n\n\n```java\npublic interface Troll {\n  void atacar();\n  int getPoderAtaque();\n  void huirBatalla();\n}\n\n@Slf4j\npublic class SimpleTroll implements Troll {\n\n  @Override\n  public void atacar() {\n    LOGGER.info(\"¡El troll intenta atraparte!\");\n  }\n\n  @Override\n  public int getPoderAtaque() {\n    return 10;\n  }\n\n  @Override\n  public void huirBatalla() {\n    LOGGER.info(\"¡El troll chilla de horror y huye!\");\n  }\n}\n```\n\nبعد ذلك، نريد إضافة عصا للتيرول. يمكننا فعل ذلك بشكل ديناميكي باستخدام الزخرفة:\n\n\n```java\n@Slf4j\npublic class TrollConGarrote implements Troll {\n\n  private final Troll decorado;\n\n  public TrollConGarrote(Troll decorado) {\n    this.decorado = decorado;\n  }\n\n  @Override\n  public void atacar() {\n    decorado.atacar();\n    LOGGER.info(\"¡El troll te golpea con un garrote!\");\n  }\n\n  @Override\n  public int getPoderAtaque() {\n    return decorado.getPoderAtaque() + 10;\n  }\n\n  @Override\n  public void huirBatalla() {\n    decorado.huirBatalla();\n  }\n}\n```\n\nإليك التيرول في العمل:\n\n\n```java\n// التيرول البسيط\nLOGGER.info(\"تيرول ذو مظهر بسيط يقترب.\");\nvar troll = new SimpleTroll();\ntroll.atacar();\ntroll.huirBatalla();\nLOGGER.info(\"قوة التيرول البسيط: {}.\\n\", troll.getPoderAtaque());\n\n// تغيير سلوك التيرول البسيط عن طريق إضافة ديكور\nLOGGER.info(\"تيرول يحمل عصا ضخمة يفاجئك.\");\nvar trollConGarrote = new TrollConGarrote(troll);\ntrollConGarrote.atacar();\ntrollConGarrote.huirBatalla();\nLOGGER.info(\"قوة التيرول مع العصا: {}.\\n\", trollConGarrote.getPoderAtaque());\n\n```\n\nنتيجة البرنامج:\n\n```java\nتيرول ذو مظهر بسيط يقترب.\n!التيرول يحاول الإمساك بك!\n!التيرول يصرخ من الرعب ويهرب!\nقوة التيرول البسيط: 10.\n\nتيرول يحمل عصا ضخمة يفاجئك.\n!التيرول يحاول الإمساك بك!\n!التيرول يضربك بعصا ضخمة!\n!التيرول يصرخ من الرعب ويهرب!\nقوة التيرول مع العصا: 20.\n\n```\n\n## مخطط الفئات\n\n![alt text](./etc/decorator.urm.png \"مخطط فئات نمط الديكور\")\n\n## القابلية للتطبيق\n\nيُستخدم نمط الديكور لـ:\n\n* إضافة مسؤوليات إلى كائنات فردية بشكل ديناميكي وشفاف، أي دون التأثير على الكائنات الأخرى.\n* للمسؤوليات التي يمكن إزالتها.\n* عندما يكون التوسيع بواسطة الفئات الفرعية غير عملي. في بعض الأحيان، قد يكون من الممكن إضافة عدد كبير من الامتدادات المستقلة التي قد تؤدي إلى انفجار في الفئات الفرعية لدعم كل مجموعة من التركيبات. أو قد تكون تعريفات الفئات مخفية أو غير متاحة للفئات الفرعية.\n\n## الدروس التعليمية\n\n* [دورة نمط الديكور](https://www.journaldev.com/1540/decorator-design-pattern-in-java-example)\n\n## الاستخدامات المعروفة\n\n* [java.io.InputStream](http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html)، [java.io.OutputStream](http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html)،\n  [java.io.Reader](http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html)\n  و [java.io.Writer](http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html)\n* [java.util.Collections#synchronizedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedCollection-java.util.Collection-)\n* [java.util.Collections#unmodifiableXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableCollection-java.util.Collection-)\n* [java.util.Collections#checkedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedCollection-java.util.Collection-java.lang.Class-)\n\n## الاعتمادات\n\n* [تصميم الأنماط: عناصر البرمجيات القابلة لإعادة الاستخدام](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [البرمجة الوظيفية في جافا: تسخير قوة تعبيرات لامبدا في جافا 8](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b)\n* [أنماط تصميم J2EE](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [رأس الأنماط: دليل سهل الفهم](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [إعادة الهيكلة إلى الأنماط](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n* [أنماط تصميم J2EE](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n"
  },
  {
    "path": "localization/ar/delegation/README.md",
    "content": "---\ntitle: Delegation\nshortTitle: Delegation\ncategory: Structural\nlanguage: ar\ntag:\n  - Decoupling\n---\n\n## يُعرف أيضًا بـ\n\nنمط الوكيل (Proxy Pattern)\n\n## الهدف\n\nهي تقنية يتم من خلالها أن يعبر كائن عن سلوك معين للخارج ولكنه في الواقع يفوض مسؤولية تنفيذ ذلك السلوك إلى كائن مرتبط.\n\n## الشرح\n\nمثال من الواقع\n\n> لنتخيل أن لدينا مغامرين يقاتلون ضد وحوش بأسلحة مختلفة حسب مهاراتهم وقدراتهم. يجب أن نكون قادرين على تجهيزهم بأسلحة مختلفة دون الحاجة لتعديل الشيفرة المصدرية لكل سلاح. يقوم نمط التفويض بهذا من خلال تفويض العمل بشكل ديناميكي إلى كائن معين يقوم بتنفيذ واجهة بها الطرق ذات الصلة.\n\nيقول ويكيبيديا\n\n> في البرمجة الشيئية، يشير التفويض إلى تقييم أحد الأعضاء (خاصية أو طريقة) لكائن (المستقبل) في سياق كائن آخر أصلي (المرسل). يمكن أن يتم التفويض بشكل صريح، عن طريق تمرير الكائن المرسل إلى الكائن المستقبل، وهو ما يمكن القيام به في أي لغة برمجة موجهة للكائنات؛ أو ضمنيًا، من خلال قواعد البحث عن الأعضاء في اللغة، وهو ما يتطلب دعم اللغة لهذه الوظيفة.\n\n**مثال برمجي**\n\nلدينا واجهة `Printer` وثلاثة تطبيقات هي `CanonPrinter`، `EpsonPrinter` و `HpPrinter`.\n\n```java\npublic interface Printer {\n  void print(final String message);\n}\n\n@Slf4j\npublic class CanonPrinter implements Printer {\n  @Override\n  public void print(String message) {\n    LOGGER.info(\"Canon Printer : {}\", message);\n  }\n}\n\n@Slf4j\npublic class EpsonPrinter implements Printer {\n  @Override\n  public void print(String message) {\n    LOGGER.info(\"Epson Printer : {}\", message);\n  }\n}\n\n@Slf4j\npublic class HpPrinter implements Printer {\n  @Override\n  public void print(String message) {\n    LOGGER.info(\"HP Printer : {}\", message);\n  }\n}\n```\n\nEl `PrinterController` puede ser utilizado como un `Printer` delegando cualquier trabajo manejado por este\na un objeto que la implemente.\n\n```java\npublic class PrinterController implements Printer {\n  \n  private final Printer printer;\n  \n  public PrinterController(Printer printer) {\n    this.printer = printer;\n  }\n  \n  @Override\n  public void print(String message) {\n    printer.print(message);\n  }\n}\n```\n\nالآن في شفرة العميل، يمكن لوحدات تحكم الطابعة طباعة الرسائل بطرق مختلفة اعتمادًا على الكائن الذي يتم تفويض العمل إليه.\n\n\n```java\nprivate static final String MESSAGE_TO_PRINT = \"hello world\";\n\nvar hpPrinterController = new PrinterController(new HpPrinter());\nvar canonPrinterController = new PrinterController(new CanonPrinter());\nvar epsonPrinterController = new PrinterController(new EpsonPrinter());\n\nhpPrinterController.print(MESSAGE_TO_PRINT);\ncanonPrinterController.print(MESSAGE_TO_PRINT);\nepsonPrinterController.print(MESSAGE_TO_PRINT)\n```\n\nمخرجات البرنامج:\n\n\n```java\nHP Printer : hello world\nCanon Printer : hello world\nEpson Printer : hello world\n```\n\n## مخطط الفئات\n\n![alt text](./etc/delegation.png \"Delegate\")\n\n## القابلية للتطبيق\n\nاستخدم نمط التفويض لتحقيق ما يلي:\n\n* تقليل ارتباط الأساليب بالفئة الخاصة بها\n* مكونات تتصرف بشكل متطابق، مع مراعاة أن هذا الوضع قد يتغير في المستقبل.\n\n## الاعتمادات\n\n* [نمط التفويض: ويكيبيديا](https://en.wikipedia.org/wiki/Delegation_pattern)\n* [نمط الوكيل: ويكيبيديا](https://en.wikipedia.org/wiki/Proxy_pattern)\n"
  },
  {
    "path": "localization/ar/dependency-injection/README.md",
    "content": "---\ntitle: Dependency Injection\nshortTitle: Dependency Injection\ncategory: Creational\nlanguage: ar\ntag:\n  - Decoupling\n---\n\n## الغرض\n\nحقن التبعيات هو نمط تصميم برمجي يتم فيه حقن واحدة أو أكثر من التبعيات (أو الخدمات) إلى كائن تابع (أو عميل) وتصبح جزءاً من حالة العميل. يفصل النمط بين إنشاء التبعيات للعميل وسلوكه الخاص، مما يسمح بتصاميم برامج منخفضة الارتباط وتلتزم بمبادئ عكس التحكم والمسؤولية الواحدة.\n\n## الشرح\n\nمثال من العالم الحقيقي\n\n> يحب الساحر العجوز ملء غليونه والتدخين من وقت لآخر. ومع ذلك، لا يريد أن يعتمد على علامة تجارية واحدة من التبغ، بل يحب أن يتمكن من الاستمتاع بها جميعاً بشكل قابل للتبادل.\n\nبكلمات بسيطة\n\n> حقن التبعيات يفصل إنشاء التبعيات للعميل عن سلوكه الخاص.\n\nتقول ويكيبيديا\n\n> في هندسة البرمجيات، حقن التبعيات هو تقنية يحصل فيها كائن على كائنات أخرى يعتمد عليها. تُسمى هذه الكائنات الأخرى بالتبعيات.\n\n**مثال برمجي**\n\nلنقم أولاً بتقديم واجهة التبغ `Tobacco` والعلامات التجارية المحددة.\n\n\n```java\n@Slf4j\npublic abstract class Tobacco {\n\n  public void smoke(Wizard wizard) {\n    LOGGER.info(\"{} smoking {}\", wizard.getClass().getSimpleName(),\n        this.getClass().getSimpleName());\n  }\n}\n\npublic class SecondBreakfastTobacco extends Tobacco {\n}\n\npublic class RivendellTobacco extends Tobacco {\n}\n\npublic class OldTobyTobacco extends Tobacco {\n}\n```\n\nالتالي هو واجهة `Wizard` وتنفيذها.\n\n\n```java\npublic interface Wizard {\n\n  void smoke();\n}\n\npublic class AdvancedWizard implements Wizard {\n\n  private final Tobacco tobacco;\n\n  public AdvancedWizard(Tobacco tobacco) {\n    this.tobacco = tobacco;\n  }\n\n  @Override\n  public void smoke() {\n    tobacco.smoke(this);\n  }\n}\n```\n\nوأخيراً يمكننا أن نثبت مدى سهولة إعطاء التبغ `Tobacco` لأي علامة تجارية قديمة للساحر.\n\n\n```java\n    var advancedWizard = new AdvancedWizard(new SecondBreakfastTobacco());\n    advancedWizard.smoke();\n```\n\n## Class Diagram\n\n![alt text](./etc/dependency-injection.png \"Dependency Injection\")\n\n## Applicability\n\nUse the Dependency Injection pattern when:\n\n* You need to eliminate the knowledge of the concrete implementation of the object.\n* To allow unit testing of classes in isolation using mock objects or stubs.\n\n## Credits\n\n* [Dependency Injection Principles, Practices, and Patterns](https://www.amazon.com/gp/product/161729473X/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=161729473X&linkId=57079257a5c7d33755493802f3b884bd)\n* [Clean Code: A Handbook of Agile Software Craftsmanship](https://www.amazon.com/gp/product/0132350882/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0132350882&linkCode=as2&tag=javadesignpat-20&linkId=2c390d89cc9e61c01b9e7005c7842871)\n* [Java 9 Dependency Injection: Write loosely coupled code with Spring 5 and Guice](https://www.amazon.com/gp/product/1788296257/ref=as_li_tl?ie=UTF8&tag=javadesignpat-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=1788296257&linkId=4e9137a3bf722a8b5b156cce1eec0fc1)\n* [Google Guice: Agile Lightweight Dependency Injection Framework](https://www.amazon.com/gp/product/1590599977/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1590599977&linkId=3b10c90b7ba480a1b7777ff38000f956)\n"
  },
  {
    "path": "localization/ar/dirty-flag/README.md",
    "content": "---\ntitle: Dirty Flag\nshortTitle: Dirty Flag\ncategory: Behavioral\nlanguage: ar\ntag:\n - Game programming\n - Performance\n---\n\n## Also known as\n* IsDirty pattern\n\n## Purpose\nAvoid the costly re-acquisition of resources. Resources retain their identity, are stored in some fast-access storage, and are reused to avoid having to acquire them again.\n\n## Class Diagram\n![alt text](./etc/dirty-flag.png \"Dirty Flag\")\n\n## Applicability\nUse the Dirty Flag pattern when\n\n* The repetitive acquisition, initialization, and release of the same resource causes unnecessary performance overhead.\n\n## Credits\n\n* [Design Patterns: Dirty Flag](https://www.takeupcode.com/podcast/89-design-patterns-dirty-flag/)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n"
  },
  {
    "path": "localization/ar/double-buffer/README.md",
    "content": "---\ntitle: Double Buffer\nshortTitle: Double Buffer\ncategory: Behavioral\nlanguage: ar\ntag:\n    - Performance\n    - Game programming  \n---\n\n## الهدف\n\nالذاكرة المزدوجة هي مصطلح يُستخدم لوصف جهاز يحتوي على مخزنين. استخدام المخازن المتعددة يزيد من الأداء العام للجهاز ويساعد في تجنب الاختناقات. يُظهر هذا المثال استخدام الذاكرة المزدوجة في الرسومات. يُستخدم لعرض صورة أو إطار بينما يتم تخزين إطار آخر في المخزن ليتم عرضه لاحقًا. هذه الطريقة تجعل الرسوم المتحركة والألعاب تبدو أكثر واقعية مقارنة بتلك التي تُعرض باستخدام الذاكرة الفردية.\n\n## الشرح\n\nمثال من الحياة الواقعية\n> مثال نموذجي، ويجب أن تتعامل معه جميع محركات الألعاب، هو التقديم. عندما يرسم اللعبة العالم الذي يراه المستخدمون، تقوم بذلك قطعة قطعة: الجبال البعيدة، التلال المتدحرجة، الأشجار، كل منها على حدة. إذا رأى المستخدم كيف يتم رسم العرض بشكل تدريجي، فسوف تنكسر الوهم لعالم متماسك. يجب تحديث المشهد بسلاسة وسرعة، مع عرض سلسلة من الإطارات المكتملة، يظهر كل منها فورًا. يحل التقديم المزدوج هذه المشكلة.\n\nببساطة\n> يضمن حالة يتم عرضها بشكل صحيح بينما يتم تعديل تلك الحالة تدريجيًا. يتم استخدامه كثيرًا في الرسومات الحاسوبية.\n\nويكيبيديا تقول\n> في علوم الكمبيوتر، التخزين في الذاكرة المتعددة هو استخدام أكثر من مخزن واحد لحمل كتلة من البيانات، بحيث يرى \"القارئ\" نسخة كاملة (على الرغم من أنها قديمة) من البيانات، بدلاً من نسخة محدثة جزئيًا من البيانات التي يقوم \"الكاتب\" بإنشائها. يُستخدم ذلك كثيرًا في الصور الحاسوبية.\n\n**مثال برمجي**\n\nواجهة `Buffer` التي تضمن الوظائف الأساسية للمخزن.\n\n```java\n/**\n * Buffer interface.\n */\npublic interface Buffer {\n\n    /**\n     * Clear the pixel in (x, y).\n     *\n     * @param x X coordinate\n     * @param y Y coordinate\n     */\n    void clear(int x, int y);\n\n    /**\n     * Draw the pixel in (x, y).\n     *\n     * @param x X coordinate\n     * @param y Y coordinate\n     */\n    void draw(int x, int y);\n\n    /**\n     * Clear all the pixels.\n     */\n    void clearAll();\n\n    /**\n     * Get all the pixels.\n     *\n     * @return pixel list\n     */\n    Pixel[] getPixels();\n\n}\n```\n\nإحدى تطبيقات واجهة `Buffer`.\n\n\n```java\n/**\n * FrameBuffer implementation class.\n */\npublic class FrameBuffer implements Buffer {\n\n    public static final int WIDTH = 10;\n    public static final int HEIGHT = 8;\n\n    private final Pixel[] pixels = new Pixel[WIDTH * HEIGHT];\n\n    public FrameBuffer() {\n        clearAll();\n    }\n\n    @Override\n    public void clear(int x, int y) {\n        pixels[getIndex(x, y)] = Pixel.WHITE;\n    }\n\n    @Override\n    public void draw(int x, int y) {\n        pixels[getIndex(x, y)] = Pixel.BLACK;\n    }\n\n    @Override\n    public void clearAll() {\n        Arrays.fill(pixels, Pixel.WHITE);\n    }\n\n    @Override\n    public Pixel[] getPixels() {\n        return pixels;\n    }\n\n    private int getIndex(int x, int y) {\n        return x + WIDTH * y;\n    }\n}\n```\n\n```java\n/**\n * Pixel enum. Each pixel can be white (not drawn) or black (drawn).\n */\npublic enum Pixel {\n\n    WHITE, BLACK;\n}\n```\n\n`Scene` representa la escena del juego en la que ya se ha renderizado el búfer actual.\n\n```java\n/**\n * Scene class. Render the output frame.\n */\n@Slf4j\npublic class Scene {\n\n    private final Buffer[] frameBuffers;\n\n    private int current;\n\n    private int next;\n\n    /**\n     * Constructor of Scene.\n     */\n    public Scene() {\n        frameBuffers = new FrameBuffer[2];\n        frameBuffers[0] = new FrameBuffer();\n        frameBuffers[1] = new FrameBuffer();\n        current = 0;\n        next = 1;\n    }\n\n    /**\n     * Draw the next frame.\n     *\n     * @param coordinateList list of pixels of which the color should be black\n     */\n    public void draw(List<? extends Pair<Integer, Integer>> coordinateList) {\n        LOGGER.info(\"Start drawing next frame\");\n        LOGGER.info(\"Current buffer: \" + current + \" Next buffer: \" + next);\n        frameBuffers[next].clearAll();\n        coordinateList.forEach(coordinate -> {\n            var x = coordinate.getKey();\n            var y = coordinate.getValue();\n            frameBuffers[next].draw(x, y);\n        });\n        LOGGER.info(\"Swap current and next buffer\");\n        swap();\n        LOGGER.info(\"Finish swapping\");\n        LOGGER.info(\"Current buffer: \" + current + \" Next buffer: \" + next);\n    }\n\n    public Buffer getBuffer() {\n        LOGGER.info(\"Get current buffer: \" + current);\n        return frameBuffers[current];\n    }\n\n    private void swap() {\n        current = current ^ next;\n        next = current ^ next;\n        current = current ^ next;\n    }\n\n}\n```\n\n```java\npublic static void main(String[] args) {\n    final var scene = new Scene();\n    var drawPixels1 = List.of(new MutablePair<>(1, 1), new MutablePair<>(5, 6), new MutablePair<>(3, 2));\n    scene.draw(drawPixels1);\n    var buffer1 = scene.getBuffer();\n    printBlackPixelCoordinate(buffer1);\n\n    var drawPixels2 = List.of(new MutablePair<>(3, 7), new MutablePair<>(6, 1));\n    scene.draw(drawPixels2);\n    var buffer2 = scene.getBuffer();\n    printBlackPixelCoordinate(buffer2);\n}\n\nprivate static void printBlackPixelCoordinate(Buffer buffer) {\n    StringBuilder log = new StringBuilder(\"Black Pixels: \");\n    var pixels = buffer.getPixels();\n    for (var i = 0; i < pixels.length; ++i) {\n        if (pixels[i] == Pixel.BLACK) {\n            var y = i / FrameBuffer.WIDTH;\n            var x = i % FrameBuffer.WIDTH;\n            log.append(\" (\").append(x).append(\", \").append(y).append(\")\");\n        }\n    }\n    LOGGER.info(log.toString());\n}\n```\n\nمخرجات وحدة التحكم\n\n\n```text\n[main] INFO com.iluwatar.doublebuffer.Scene - Start drawing next frame\n[main] INFO com.iluwatar.doublebuffer.Scene - Current buffer: 0 Next buffer: 1\n[main] INFO com.iluwatar.doublebuffer.Scene - Swap current and next buffer\n[main] INFO com.iluwatar.doublebuffer.Scene - Finish swapping\n[main] INFO com.iluwatar.doublebuffer.Scene - Current buffer: 1 Next buffer: 0\n[main] INFO com.iluwatar.doublebuffer.Scene - Get current buffer: 1\n[main] INFO com.iluwatar.doublebuffer.App - Black Pixels:  (1, 1) (3, 2) (5, 6)\n[main] INFO com.iluwatar.doublebuffer.Scene - Start drawing next frame\n[main] INFO com.iluwatar.doublebuffer.Scene - Current buffer: 1 Next buffer: 0\n[main] INFO com.iluwatar.doublebuffer.Scene - Swap current and next buffer\n[main] INFO com.iluwatar.doublebuffer.Scene - Finish swapping\n[main] INFO com.iluwatar.doublebuffer.Scene - Current buffer: 0 Next buffer: 1\n[main] INFO com.iluwatar.doublebuffer.Scene - Get current buffer: 0\n[main] INFO com.iluwatar.doublebuffer.App - Black Pixels:  (6, 1) (3, 7)\n```\n\n## مخطط الفئات\n\n![alt text](./etc/double-buffer.urm.png \"مخطط فئة نمط المخزن المؤقت المزدوج\")\n\n## القابلية للتطبيق\n\nهذا النمط هو أحد الأنماط التي ستعرف متى تحتاج إليها. إذا كان لديك نظام يفتقر إلى المخزن المؤقت المزدوج، فمن المحتمل أن يبدو بشكل غير صحيح مرئيًا (تمزق الصورة، إلخ) أو سيعمل بشكل غير صحيح. ولكن قول \"ستعرف متى تحتاج إليه\" لا يعطي الكثير من التوضيح. بشكل أكثر تحديدًا، هذا النمط مناسب عندما يكون كل هذا صحيحًا:\n\n- لدينا حالة يتم تعديلها بشكل تدريجي.\n- يمكن الوصول إلى نفس الحالة في منتصف التعديل.\n- نريد تجنب أن يرى الكود الذي يصل إلى الحالة العمل الجاري.\n- نريد أن نتمكن من قراءة الحالة دون الحاجة إلى الانتظار أثناء الكتابة.\n\n## المصادر\n\n* [Game Programming Patterns - Double Buffer](http://gameprogrammingpatterns.com/double-buffer.html)\n\n"
  },
  {
    "path": "localization/ar/embedded-value/README.md",
    "content": "---\ntitle: Embedded Value\nshortTitle: Embedded Value\ncategory: Structural\nlanguage: ar\ntag:\n  - Data Access\n  - Enterprise Application Pattern\n---\n\n## معروف أيضًا باسم\n\nالتخصيص المدمج، المُركب\n\n## الهدف\n\nالعديد من الكائنات الصغيرة تكون منطقية في نظام البرمجة الكائنية ولا تكون منطقية كجداول في قاعدة بيانات. القيمة المدمجة تخصيص قيم كائن إلى حقول سجل الكائن المالك.\n\n## الشرح\n\nمثال من الواقع\n\n> بعض الأمثلة تشمل الكائنات النقدية والفترات الزمنية. على الرغم من أن التفكير الافتراضي هو تخزين كائن كجدول، إلا أنه لا أحد في عقله السليم يرغب في جدول للقيم النقدية.\n> مثال آخر هو الطلبات عبر الإنترنت التي تحتوي على عنوان الشحن مثل الشارع، المدينة، الدولة. نقوم بتخصيص هذه القيم من كائن عنوان الشحن إلى حقول سجل كائن الطلب.\n\nبكلمات بسيطة\n\n> يسمح نمط القيم المدمجة بتخصيص كائن لعدة حقول في جدول كائن آخر.\n\n**مثال برمجي**\n\nلنأخذ مثالًا من طلب عبر الإنترنت حيث لدينا تفاصيل العنصر المطلوب وعنوان الشحن. لدينا\nعنوان الشحن مدمج في كائن الطلب. ولكن في قاعدة البيانات نقوم بتخصيص قيم عنوان الشحن في سجل الطلب بدلاً من إنشاء جدول منفصل لعنوان الشحن واستخدام مفتاح خارجي للإشارة إلى كائن الطلب.\n\nأولاً، لدينا كائنات `Order` و `ShippingAddress`.\n\n\n```java\npublic class Order {\n\n    private int id;\n    private String item;\n    private String orderedBy;\n    private ShippingAddress ShippingAddress;\n\n    public Order(String item, String orderedBy, ShippingAddress           ShippingAddress) {\n        this.item = item;\n        this.orderedBy = orderedBy;\n        this.ShippingAddress = ShippingAddress;\n    }\n}\n```\n\n```java\npublic class ShippingAddress {\n\n    private String city;\n    private String state;\n    private String pincode;\n\n    public ShippingAddress(String city, String state, String pincode) {\n        this.city = city;\n        this.state = state;\n        this.pincode = pincode;\n    }\n}\n```\n\nالآن، علينا إنشاء جدول واحد فقط للطلب مع الحقول الخاصة بسمات عنوان الشحن.\n\n\n```Sql\nCREATE TABLE Orders (Id INT AUTO_INCREMENT, item VARCHAR(50) NOT NULL, orderedBy VARCHAR(50) city VARCHAR(50), state VARCHAR(50), pincode CHAR(6) NOT NULL, PRIMARY KEY(Id))\n```\n\nأثناء إجراء الاستفسارات والإدخالات في قاعدة البيانات، نقوم بتغليف وفك تغليف تفاصيل عناوين الشحن.\n\n\n```java\nfinal String INSERT_ORDER = \"INSERT INTO Orders (item, orderedBy, city, state, pincode) VALUES (?, ?, ?, ?, ?)\";\n\npublic boolean insertOrder(Order order) throws Exception {\n  var insertOrder = new PreparedStatement(INSERT_ORDER);\n  var address = order.getShippingAddress();\n  conn.setAutoCommit(false);\n  insertIntoOrders.setString(1, order.getItem());\n  insertIntoOrders.setString(2, order.getOrderedBy());\n  insertIntoOrders.setString(3, address.getCity());\n  insertIntoOrders.setString(4, address.getState());\n  insertIntoOrders.setString(5, address.getPincode());\n  \n  var affectedRows = insertIntoOrders.executeUpdate();\n  if(affectedRows == 1){\n    Logger.info(\"Inserted successfully\");\n  }else{\n    Logger.info(\"Couldn't insert \" + order);\n  }\n}\n```\n\n## مخطط الفئات\n\n![alt text](./etc/embedded-value.urm.png \"مخطط فئة القيمة المدمجة\")\n\n## القابلية للتطبيق\n\nاستخدم نمط القيمة المدمجة عندما:\n\n* تكون العديد من الكائنات الصغيرة ذات معنى في نظام OO ولكن ليس لها معنى كجداول في قاعدة بيانات.\n* الحالات الأبسط للقيمة المدمجة هي الكائنات ذات القيم الواضحة والبسيطة مثل المال ونطاق التواريخ.\n* إذا كنت تقوم بربط إلى مخطط موجود، يمكنك استخدام هذا النمط عندما تحتوي إحدى الجداول على بيانات ترغب في تقسيمها إلى أكثر من كائن في الذاكرة. قد يحدث هذا عندما ترغب في استخراج بعض السلوك في نموذج الكائنات.\n* في معظم الحالات، ستستخدم القيمة المدمجة فقط في كائن مرجعي عندما تكون العلاقة بينهما ذات قيمة واحدة في كلا الطرفين (علاقة واحد إلى واحد).\n\n## الدروس التعليمية\n\n* [Dzone](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-3)\n* [Ram N Java](https://ramj2ee.blogspot.com/2013/08/embedded-value-design-pattern.html)\n* [Five's Weblog](https://powerdream5.wordpress.com/2007/10/09/embedded-value/)\n\n## العواقب\n\n* الميزة الكبرى للقيمة المدمجة هي أنها تسمح بإجراء استفسارات SQL ضد قيم الكائن التابع.\n* الكائن ذو القيمة المدمجة ليس له سلوك استمرارية.\n* عند استخدام هذا، يجب أن تكون حذرًا من أن أي تغيير في التابع سيجعل المالك يعتبره \"متسخًا\" — وهو ما لا يمثل مشكلة مع الكائنات ذات القيمة التي يتم استبدالها في المالك.\n* مشكلة أخرى هي التحميل والحفظ. إذا كنت تقوم بتحميل ذاكرة الكائن المدمج فقط عندما تقوم بتحميل المالك، فهذا حجة لحفظ كلاهما في نفس الجدول.\n* قضية أخرى هي ما إذا كنت ترغب في الوصول إلى بيانات الكائنات المدمجة بشكل منفصل عبر SQL. قد يكون هذا مهمًا إذا كنت تقوم بإعداد تقارير عبر SQL وليس لديك قاعدة بيانات منفصلة للتقارير.\n\n## الائتمان\n\n* [Fowler, Martin - Patterns of enterprise application architecture-Addison-Wesley](https://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420)\n* [Ram N Java](https://ramj2ee.blogspot.com/2013/08/embedded-value-design-pattern.html)\n"
  },
  {
    "path": "localization/ar/event-aggregator/README.md",
    "content": "---\ntitle: Event Aggregator\nshortTitle: Event Aggregator\ncategory: Structural\nlanguage: ar\ntag:\n  - Reactive\n---\n\n## الاسم\n\nمجمع الأحداث\n\n## النية\n\nقد يصبح النظام الذي يحتوي على العديد من الكائنات معقدًا عندما يريد العميل الاشتراك في الأحداث. يجب على العميل\nالبحث والتسجيل في\nكل كائن على حدة، وإذا كان كل كائن يحتوي على العديد من الأحداث فإن كل حدث يتطلب اشتراكًا\nمنفصلًا. يعمل مجمع الأحداث كمصدر واحد\nللأحداث للعديد من الكائنات. يقوم بالتسجيل في جميع الأحداث للكائنات المتعددة مما يسمح للعملاء\nبالتسجيل فقط مع المجمع.\n\n## الشرح\n\nمثال واقعي\n\n> يجلس الملك جوفري على عرش الحديد ويحكم الممالك السبع في وينترفل. يحصل على معظم معلوماته الهامة من يد الملك،\n> وهو ثاني أقوى شخص في المملكة. يد الملك لديها العديد من المستشارين المقربين الذين يوفرون له معلومات هامة حول الأحداث التي تحدث في المملكة.\n\nبكلمات بسيطة\n\n> مجمع الأحداث هو وسيط للأحداث يقوم بجمع الأحداث من مصادر متعددة وتقديمها للمراقبين المسجلين.\n\n**مثال برمجي**\n\nفي مثالنا البرمجي، نعرض تنفيذ نمط مجمع الأحداث. بعض الكائنات\nهي مستمعون للأحداث، وبعضها الآخر هو مرسلو أحداث، والمجمع للأحداث يقوم بكلتا الوظيفتين.\n\n\n```java\npublic interface EventObserver {\n  void onEvent(Event e);\n}\n\npublic abstract class EventEmitter {\n\n  private final Map<Event, List<EventObserver>> observerLists;\n\n  public EventEmitter() {\n    observerLists = new HashMap<>();\n  }\n\n  public final void registerObserver(EventObserver obs, Event e) {\n    ...\n  }\n\n  protected void notifyObservers(Event e) {\n    ...\n  }\n}\n```\n\n`KingJoffrey` يستمع إلى أحداث `KingsHand`.\n\n\n```java\n@Slf4j\npublic class KingJoffrey implements EventObserver {\n  @Override\n  public void onEvent(Event e) {\n    LOGGER.info(\"Received event from the King's Hand: {}\", e.toString());\n  }\n}\n```\n\n`ReyMano` يستمع إلى الأحداث من مرؤوسيه `LordBaelish`، `LordVarys` و `Scout`.\nما يسمعه منهم، ينقله إلى \"الملك جوفري\".\n\n\n```java\npublic class KingsHand extends EventEmitter implements EventObserver {\n\n  public KingsHand() {\n  }\n\n  public KingsHand(EventObserver obs, Event e) {\n    super(obs, e);\n  }\n\n  @Override\n  public void onEvent(Event e) {\n    notifyObservers(e);\n  }\n}\n```\n\nعلى سبيل المثال، `LordVarys` يجد خائنًا كل يوم أحد ويقوم بإبلاغ `KingsHand`.\n\n\n```java\n@Slf4j\npublic class LordVarys extends EventEmitter implements EventObserver {\n  @Override\n  public void timePasses(Weekday day) {\n    if (day == Weekday.SATURDAY) {\n      notifyObservers(Event.TRAITOR_DETECTED);\n    }\n  }\n}\n```\n\nالجزء التالي يوضح كيفية بناء وربط الكائنات.\n\n\n```java\n    var kingJoffrey = new KingJoffrey();\n\n    var kingsHand = new KingsHand();\n    kingsHand.registerObserver(kingJoffrey, Event.TRAITOR_DETECTED);\n    kingsHand.registerObserver(kingJoffrey, Event.STARK_SIGHTED);\n    kingsHand.registerObserver(kingJoffrey, Event.WARSHIPS_APPROACHING);\n    kingsHand.registerObserver(kingJoffrey, Event.WHITE_WALKERS_SIGHTED);\n\n    var varys = new LordVarys();\n    varys.registerObserver(kingsHand, Event.TRAITOR_DETECTED);\n    varys.registerObserver(kingsHand, Event.WHITE_WALKERS_SIGHTED);\n\n    var scout = new Scout();\n    scout.registerObserver(kingsHand, Event.WARSHIPS_APPROACHING);\n    scout.registerObserver(varys, Event.WHITE_WALKERS_SIGHTED);\n\n    var baelish = new LordBaelish(kingsHand, Event.STARK_SIGHTED);\n\n    var emitters = List.of(\n        kingsHand,\n        baelish,\n        varys,\n        scout\n    );\n\n    Arrays.stream(Weekday.values())\n        .<Consumer<? super EventEmitter>>map(day -> emitter -> emitter.timePasses(day))\n        .forEachOrdered(emitters::forEach);\n```\n\nالناتج في وحدة التحكم بعد تنفيذ المثال.\n\n```\n18:21:52.955 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: Warships approaching\n18:21:52.960 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: White walkers sighted\n18:21:52.960 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: Stark sighted\n18:21:52.960 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: Traitor detected\n```\n\n## قابلية الاستخدام\n\nاستخدم نمط \"مجمّع الأحداث\" عندما\n\n* يعد مجمّع الأحداث خيارًا جيدًا عندما يكون لديك العديد من الكائنات التي تعد مصادر محتملة للأحداث. بدلاً من جعل المراقب يتعامل مع التسجيل مع كل منها، يمكنك مركزية منطق التسجيل في مجمّع الأحداث. بالإضافة إلى تبسيط التسجيل، يبسط مجمّع الأحداث أيضًا مشكلات إدارة الذاكرة في استخدام المراقبين.\n\n## الأنماط المتعلقة\n\n* [Observer](https://java-design-patterns.com/patterns/observer/)\n\n## الاعتمادات\n\n* [مارتن فاولر - مجمّع الأحداث](http://martinfowler.com/eaaDev/EventAggregator.html)\n"
  },
  {
    "path": "localization/ar/extension-objects/README.md",
    "content": "---\ntitle: Extension objects\nshortTitle: Extension objects\ncategory: Behavioral\nlanguage: ar\ntag:\n - Extensibility\n---\n\n# نمط كائنات التوسيع (Extension Objects Pattern)\n\n## الهدف\nالتنبؤ بأنه يجب توسيع واجهة كائن ما في المستقبل. يتم تعريف الواجهات الإضافية من خلال كائنات التوسيع (Extension objects).\n\n## الشرح\nمثال واقعي\n\n> افترض أنك تطور لعبة تعتمد على Java لعميل، وأثناء عملية التطوير، يُقترح عليك إضافة وظائف جديدة. يسمح لك نمط كائنات التوسيع بتكييف برنامجك مع التغييرات غير المتوقعة مع الحد الأدنى من إعادة الهيكلة، خاصة عند دمج وظائف إضافية في مشروعك.\n\nببساطة\n\n> يتم استخدام نمط كائنات التوسيع لإضافة وظائف ديناميكيًا إلى الكائنات دون تعديل فئاتها الرئيسية. إنه نمط تصميم سلوكي يستخدم لإضافة وظائف جديدة إلى الفئات والكائنات الموجودة داخل البرنامج. يوفر هذا النمط للمبرمجين القدرة على تمديد/تعديل وظائف الفئات دون الحاجة إلى إعادة هيكلة الكود المصدر الحالي.\n\nتقول ويكيبيديا\n\n> في البرمجة الكائنية التوجه، يعتبر نمط كائنات التوسيع نمط تصميم يضاف إلى كائن بعد أن يتم تجميع الكائن الأصلي. الكائن المعدل غالبًا ما يكون فئة أو نموذجًا أو نوعًا. تعتبر أنماط كائنات التوسيع سمة من سمات بعض لغات البرمجة الكائنية التوجه. لا يوجد فرق نحوي بين استدعاء طريقة توسيع وطريقة معرفة في تعريف النوع.\n\n**مثال برمجي**\n\nالهدف من استخدام نمط كائنات التوسيع (Extension objects) هو تنفيذ ميزات/وظائف جديدة دون الحاجة إلى إعادة هيكلة كل فئة.\nتوضح الأمثلة التالية استخدام هذا النمط في فئة \"العدو\" التي تمتد من \"الكيان\" داخل لعبة:\n\nالفئة الرئيسية للتطبيق التي يتم تشغيل برنامجنا منها.\n\n\n```java\npublic class App {\n    public static void main(String[] args) {\n        Entity enemy = new Enemy(\"Enemy\");\n        checkExtensionsForEntity(enemy);\n    }\n\n    private static void checkExtensionsForEntity(Entity entity) {\n        Logger logger = Logger.getLogger(App.class.getName());\n        String name = entity.getName();\n        Function<String, Runnable> func = (e) -> () -> logger.info(name + \" without \" + e);\n\n        String extension = \"EnemyExtension\";\n        Optional.ofNullable(entity.getEntityExtension(extension))\n                .map(e -> (EnemyExtension) e)\n                .ifPresentOrElse(EnemyExtension::extendedAction, func.apply(extension));\n    }\n}\n```\nفئة العدو مع الإجراءات الأولية والتوسعات.\n\n\n```java\nclass Enemy extends Entity {\n    public Enemy(String name) {\n        super(name);\n    }\n\n    @Override\n    protected void performInitialAction() {\n        super.performInitialAction();\n        System.out.println(\"Enemy wants to attack you.\");\n    }\n\n    @Override\n    public EntityExtension getEntityExtension(String extensionName) {\n        if (extensionName.equals(\"EnemyExtension\")) {\n            return Optional.ofNullable(entityExtension).orElseGet(EnemyExtension::new);\n        }\n        return super.getEntityExtension(extensionName);\n    }\n}\n```\n\nفئة EnemyExtension مع إعادة كتابة طريقة extendAction().\n\n\n```java\nclass EnemyExtension implements EntityExtension {\n    @Override\n    public void extendedAction() {\n        System.out.println(\"Enemy has advanced towards you!\");\n    }\n}\n```\n\nفئة الكائن التي سيتم توسيعها بواسطة العدو.\n\n\n```java\nclass Entity {\n    private String name;\n    protected EntityExtension entityExtension;\n\n    public Entity(String name) {\n        this.name = name;\n        performInitialAction();\n    }\n\n    protected void performInitialAction() {\n        System.out.println(name + \" performs the initial action.\");\n    }\n\n    public EntityExtension getEntityExtension(String extensionName) {\n        return null;\n    }\n\n    public String getName() {\n        return name;\n    }\n}\n```\nواجهة `EntityExtension` التي ستستخدم `EnemyExtension`.\n\n\n```java\ninterface EntityExtension {\n    void extendedAction();\n}\n```\nإخراج البرنامج:\n\n\n```markdown\nEnemy performs the initial action.\nEnemy wants to attack you.\nEnemy has advanced towards you!\n```\nفي هذا المثال، يسمح نمط \"كائنات التمديد\" (Extension Objects) لكي يقوم الكائن العدو بتنفيذ إجراءات مبدئية فريدة وإجراءات متقدمة عند تطبيق التمديدات الخاصة. يوفر هذا النمط مرونة وقابلية تمديد لقاعدة الشيفرة مع تقليل الحاجة إلى إجراء تغييرات كبيرة في الشيفرة.\n\n## مخطط الفئات\n![Extension_objects](./etc/extension_obj.png \"Extension objects\")\n\n## قابلية التطبيق\nاستخدم نمط \"كائنات التمديد\" (Extension objects) عندما:\n\n* تحتاج إلى دعم إضافة واجهات جديدة أو غير متوقعة إلى فئات موجودة ولا تريد التأثير على العملاء الذين لا يحتاجون إلى هذه الواجهة الجديدة. تتيح لك كائنات التمديد الاحتفاظ بالعمليات ذات الصلة معًا عن طريق تعريفها في فئة منفصلة.\n* فئة تمثل تجريدًا رئيسيًا تؤدي وظائف مختلفة لعملاء مختلفين. يجب أن يكون عدد الوظائف التي يمكن أن تؤديها الفئة غير محدود. من الضروري الحفاظ على التجريد الرئيسي نفسه. على سبيل المثال، يبقى كائن العميل كائن عميل رغم أن الأنظمة الفرعية المختلفة قد تراها بطريقة مختلفة.\n* يجب أن تكون الفئة قابلة للتمديد بسلوكيات جديدة دون الحاجة إلى تصنيفها منها.\n\n## أمثلة من العالم الحقيقي\n\n* [OpenDoc](https://en.wikipedia.org/wiki/OpenDoc)\n* [ربط الكائنات وإدماجها](https://en.wikipedia.org/wiki/Object_Linking_and_Embedding)\n"
  },
  {
    "path": "localization/ar/facade/README.md",
    "content": "---\ntitle: Facade\nshortTitle: Facade\ncategory: Structural\nlanguage: ar\ntag:\n  - Gang Of Four\n  - Decoupling\n---\n\n## الهدف\n\nتوفير واجهة موحدة لمجموعة من واجهات النظام الفرعي. تقوم الواجهة البسيطة بتحديد واجهة تسهل استخدام النظام الفرعي.\n\n## الشرح\n\nمثال واقعي\n\n> كيف يعمل منجم الذهب؟ \"حسنًا، ينزل العمال لاستخراج الذهب!\" تقول. هذا ما تعتقده لأنك تستخدم واجهة بسيطة يوفرها منجم الذهب، ولكن من الداخل يجب أن يقوم بالكثير من الأشياء لتحقيق ذلك. هذه الواجهة البسيطة للنظام الفرعي المعقد هي الواجهة الأمامية.\n\nبإيجاز\n\n> يوفر نمط الواجهة الأمامية واجهة مبسطة لنظام فرعي معقد.\n\nتقول ويكيبيديا\n\n> الواجهة الأمامية هي كائن يوفر واجهة مبسطة لجسم من الكود الأكبر، مثل مكتبة الفصول.\n\n**مثال برمجي**\n\nلنأخذ مثال منجم الذهب. هنا لدينا تسلسل عمال الأقزام في المنجم. أولاً، لدينا فئة أساسية `DwarvenMineWorker`:\n\n\n```java\n\n@Slf4j\npublic abstract class DwarvenMineWorker {\n\n    public void goToSleep() {\n        LOGGER.info(\"{} goes to sleep.\", name());\n    }\n\n    public void wakeUp() {\n        LOGGER.info(\"{} wakes up.\", name());\n    }\n\n    public void goHome() {\n        LOGGER.info(\"{} goes home.\", name());\n    }\n\n    public void goToMine() {\n        LOGGER.info(\"{} goes to the mine.\", name());\n    }\n\n    private void action(Action action) {\n        switch (action) {\n            case GO_TO_SLEEP -> goToSleep();\n            case WAKE_UP -> wakeUp();\n            case GO_HOME -> goHome();\n            case GO_TO_MINE -> goToMine();\n            case WORK -> work();\n            default -> LOGGER.info(\"Undefined action\");\n        }\n    }\n\n    public void action(Action... actions) {\n        Arrays.stream(actions).forEach(this::action);\n    }\n\n    public abstract void work();\n\n    public abstract String name();\n\n    enum Action {\n        GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK\n    }\n}\n```\n\nثم لدينا الفئات المحددة للأقزام `DwarvenTunnelDigger`، `DwarvenGoldDigger` و `DwarvenCartOperator`:\n\n\n```java\n@Slf4j\npublic class DwarvenTunnelDigger extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} creates another promising tunnel.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarven tunnel digger\";\n  }\n}\n\n@Slf4j\npublic class DwarvenGoldDigger extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} digs for gold.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarf gold digger\";\n  }\n}\n\n@Slf4j\npublic class DwarvenCartOperator extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} moves gold chunks out of the mine.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarf cart operator\";\n  }\n}\n\n```\n\nلإدارة جميع هؤلاء العمال في منجم الذهب، لدينا `FachadaDwarvenGoldmine`:\n\n\n```java\npublic class DwarvenGoldmineFacade {\n\n  private final List<DwarvenMineWorker> workers;\n\n  public DwarvenGoldmineFacade() {\n      workers = List.of(\n            new DwarvenGoldDigger(),\n            new DwarvenCartOperator(),\n            new DwarvenTunnelDigger());\n  }\n\n  public void startNewDay() {\n    makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE);\n  }\n\n  public void digOutGold() {\n    makeActions(workers, DwarvenMineWorker.Action.WORK);\n  }\n\n  public void endDay() {\n    makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);\n  }\n\n  private static void makeActions(Collection<DwarvenMineWorker> workers,\n      DwarvenMineWorker.Action... actions) {\n    workers.forEach(worker -> worker.action(actions));\n  }\n}\n```\n\nالآن سنستخدم الواجهة:\n\n\n```java\nvar facade = new DwarvenGoldmineFacade();\nfacade.startNewDay();\nfacade.digOutGold();\nfacade.endDay();\n```\n\nإخراج البرنامج:\n\n\n```java\n// Dwarf gold digger wakes up.\n// Dwarf gold digger goes to the mine.\n// Dwarf cart operator wakes up.\n// Dwarf cart operator goes to the mine.\n// Dwarven tunnel digger wakes up.\n// Dwarven tunnel digger goes to the mine.\n// Dwarf gold digger digs for gold.\n// Dwarf cart operator moves gold chunks out of the mine.\n// Dwarven tunnel digger creates another promising tunnel.\n// Dwarf gold digger goes home.\n// Dwarf gold digger goes to sleep.\n// Dwarf cart operator goes home.\n// Dwarf cart operator goes to sleep.\n// Dwarven tunnel digger goes home.\n// Dwarven tunnel digger goes to sleep.\n```\n\n## مخطط الفئات\n\n![alt text](./etc/facade.urm.png \"مخطط فئة نمط الواجهة\")\n\n## قابلية التطبيق\n\nاستخدم نمط الواجهة عندما:\n\n* ترغب في توفير واجهة بسيطة إلى نظام فرعي معقد. غالبًا ما تصبح الأنظمة الفرعية أكثر تعقيدًا مع تطورها. معظم الأنماط، عند تطبيقها، تؤدي إلى المزيد من الفئات الأصغر. هذا يجعل النظام الفرعي أكثر قابلية لإعادة الاستخدام وأسهل في التخصيص، ولكن أيضًا يصبح أكثر صعوبة في الاستخدام للعملاء الذين لا يحتاجون إلى تخصيصه. يمكن أن توفر الواجهة عرضًا بسيطًا افتراضيًا للنظام الفرعي الذي يكفي لمعظم العملاء. فقط العملاء الذين يحتاجون إلى مزيد من التخصيص سيضطرون للنظر إلى ما وراء الواجهة.\n* هناك العديد من الاعتمادات بين العملاء وفئات تنفيذ التجريد. إدخال واجهة لفصل النظام الفرعي عن العملاء والأنظمة الفرعية الأخرى، مما يعزز الاستقلالية وقابلية النقل للنظام الفرعي.\n* ترغب في تقسيم أنظمتك الفرعية. استخدم واجهة لتعريف نقطة دخول إلى كل مستوى من النظام الفرعي. إذا كانت الأنظمة الفرعية تعتمد على بعضها البعض، يمكنك تبسيط الاعتمادات بينها من خلال جعلها تتواصل مع بعضها البعض فقط من خلال واجهاتها.\n\n## الدروس التعليمية\n\n* [DigitalOcean](https://www.digitalocean.com/community/tutorials/facade-design-pattern-in-java)\n\n* [Refactoring Guru](https://refactoring.guru/design-patterns/facade)\n* [GeekforGeeks](https://www.geeksforgeeks.org/facade-design-pattern-introduction/)\n* [Tutorialspoint](https://www.tutorialspoint.com/design_pattern/facade_pattern.htm)\n\n## الاعتمادات\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/ar/factory/README.md",
    "content": "---\ntitle: Factory\nshortTitle: Factory\ncategory: Creational\nlanguage: ar\ntag:\n  - Gang of Four\n---\n\n## أيضًا معروف بـ\n\n* المصنع البسيط\n* طريقة المصنع الثابتة\n\n## الهدف\n\nتوفير طريقة ثابتة محاطة في فئة تسمى المصنع (Factory)، لإخفاء منطق التنفيذ وجعل شفرة العميل تركز على الاستخدام بدلاً من تهيئة الكائنات الجديدة.\n\n## الشرح\n\nمثال من الحياة الواقعية\n\n> تخيل كيميائيًا على وشك تصنيع العملات. يجب أن يكون الكيميائي قادرًا على إنشاء عملات ذهبية وكذلك عملات نحاسية، ويجب أن يكون من الممكن التبديل بينهما دون تعديل الكود المصدري الحالي. يجعل نمط المصنع هذا ممكنًا من خلال توفير طريقة بناء ثابتة يمكن استدعاؤها مع المعلمات ذات الصلة.\n\nتقول ويكيبيديا\n\n> المصنع (Factory) هو كائن لإنشاء كائنات أخرى: بشكل رسمي، المصنع هو دالة أو طريقة تُرجع كائنات من نموذج أو فئة متغيرة.\n\n**مثال برمجي**\n\nلدينا واجهة عملة `Coin` واثنان من تطبيقات العملة: عملة ذهبية `GoldCoin` وعملة نحاسية `CopperCoin`.\n\n\n```java\npublic interface Coin {\n  String getDescription();\n}\n\npublic class GoldCoin implements Coin {\n\n  static final String DESCRIPTION = \"This is a gold coin.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\npublic class CopperCoin implements Coin {\n   \n  static final String DESCRIPTION = \"This is a copper coin.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n```\n\nتُمثل التعداد التالي أنواع العملات التي نقبلها (`GoldCoin` و `CopperCoin`).\n\n\n```java\n@RequiredArgsConstructor\n@Getter\npublic enum CoinType {\n\n  COPPER(CopperCoin::new),\n  GOLD(GoldCoin::new);\n\n  private final Supplier<Coin> constructor;\n}\n```\n\nثم لدينا الطريقة الثابتة للحصول على العملة `getCoin` لإنشاء كائنات العملة مغلفة داخل فئة المصنع `CoinFactory`.\n\n\n```java\npublic class CoinFactory {\n\n  public static Coin getCoin(CoinType type) {\n    return type.getConstructor().get();\n  }\n}\n```\n\nالآن في كود العميل يمكننا إنشاء أنواع مختلفة من العملات باستخدام فئة المصنع.\n\n\n```java\nLOGGER.info(\"The alchemist begins his work.\");\nvar coin1 = CoinFactory.getCoin(CoinType.COPPER);\nvar coin2 = CoinFactory.getCoin(CoinType.GOLD);\nLOGGER.info(coin1.getDescription());\nLOGGER.info(coin2.getDescription());\n```\n\n### مخرجات البرنامج:\n\n\n```java\nThe alchemist begins his work.\nThis is a copper coin.\nThis is a gold coin.\n```\n\n## المخطط البياني للفئات\n\n![alt text](./etc/factory.urm.png \"Factory pattern diagrama de clases\")\n\n## قابلية الاستخدام\n\nاستخدم نمط المصنع (Factory) عندما يكون تركيزك على إنشاء الكائنات فقط دون القلق حول كيفية إنشائها وإدارتها.\n\n### المزايا\n\n* يسمح بجمع كل عمليات إنشاء الكائنات في مكان واحد وتجنب نشر الكلمة الأساسية 'new' عبر قاعدة الشيفرة.\n* يُمكنك من كتابة شيفرة منخفضة الارتباط. من بين مزاياه الرئيسية: قابلية أفضل للاختبار، شيفرة سهلة الفهم، مكونات قابلة للاستبدال، قابلية التوسع، وميزات معزولة.\n\n### العيوب\n\n* قد يصبح الشيفرة أكثر تعقيدًا مما ينبغي.\n\n## أمثلة استخدام معروفة\n\n* [java.util.Calendar#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)\n* [java.util.ResourceBundle#getBundle()](https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)\n* [java.text.NumberFormat#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)\n* [java.nio.charset.Charset#forName()](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)\n* [java.net.URLStreamHandlerFactory#createURLStreamHandler(String)](https://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html) \n  (يعيد كائنات Singleton مختلفة استنادًا إلى بروتوكول معين)\n* [java.util.EnumSet#of()](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of(E))\n* [javax.xml.bind.JAXBContext#createMarshaller()](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--)\n  وأيضًا طرق مشابهة أخرى.\n\n## الأنماط المرتبطة\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/)\n"
  },
  {
    "path": "localization/bn/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n\n     that smart and dearly wants an empty line before a heading to be able to\n\n     display it as such, e.g. website) -->\n\n# জাভাতে প্রয়োগ করা ডিজাইনের প্যাটার্ন\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n\n[![All Contributors](https://img.shields.io/badge/all_contributors-213-orange.svg?style=flat-square)](#contributors-)\n\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n<br/>\n\nবিভিন্ন ভাষায় পড়ুন : [**zh**](localization/zh/README.md), [**ko**](localization/ko/README.md), [**fr**](localization/fr/README.md), [**tr**](localization/tr/README.md), [**ar**](localization/ar/README.md), [**es**](localization/es/README.md), [**pt**](localization/pt/README.md), [**id**](localization/id/README.md), [**ru**](localization/ru/README.md), [**de**](localization/de/README.md), [**ja**](localization/ja/README.md), [**vi**](localization/vi/README.md), [**bn**](localization/bn/README.md)\n\n<br/>\n\n# ভূমিকা\n\nডিজাইন প্যাটার্ন হল সেরা, আনুষ্ঠানিক অনুশীলন যা একজন প্রোগ্রামার ব্যবহার করতে পারে\n\nএকটি অ্যাপ্লিকেশন বা সিস্টেম ডিজাইন করার সময় সাধারণ সমস্যাগুলি সমাধান করুন।\n\nডিজাইনের প্যাটার্নগুলি পরীক্ষিত, প্রমাণিত প্রদান করে উন্নয়ন প্রক্রিয়াকে ত্বরান্বিত করতে পারে\n\nউন্নয়ন দৃষ্টান্ত\n\nডিজাইন প্যাটার্নগুলি পুনঃব্যবহার করা সূক্ষ্ম সমস্যাগুলি প্রতিরোধ করতে সাহায্য করে যা প্রধান সমস্যাগুলির কারণ হয়\n\nসমস্যা, এবং এটি কোডার এবং স্থপতিদের জন্য কোড পাঠযোগ্যতাও উন্নত করে যারা\n\nনিদর্শনগুলির সাথে পরিচিত।\n\n# শুরু হচ্ছে\n\nএই সাইটটি জাভা ডিজাইন প্যাটার্ন প্রদর্শন করে। সমাধান উন্নত করা হয়েছে\n\nওপেন সোর্স সম্প্রদায়ের অভিজ্ঞ প্রোগ্রামার এবং স্থপতি দ্বারা। প্যাটার্নগুলি তাদের উচ্চ-স্তরের বর্ণনা দ্বারা বা তাদের দেখে ব্রাউজ করা যেতে পারে\n\nসোর্স কোড। কোড উদাহরণ ভাল মন্তব্য করা হয় এবং হিসাবে চিন্তা করা যেতে পারে\n\nপ্রোগ্রামিং টিউটোরিয়াল কিভাবে একটি নির্দিষ্ট প্যাটার্ন বাস্তবায়ন করতে হয়। আমরা সবচেয়ে বেশি ব্যবহার করি\n\nজনপ্রিয় ওপেন সোর্স জাভা প্রযুক্তি।\n\nআপনি উপাদান সম্পর্কে জানার আগে, আপনি বিভিন্ন সঙ্গে পরিচিত হতে হবে\n\n[Software Design Principles](https://java-design-patterns.com/principles/).\n\nসমস্ত ডিজাইন যতটা সম্ভব সহজ হওয়া উচিত। আপনার চুম্বন, যগ্নি দিয়ে শুরু করা উচিত,\n\nএবং সবচেয়ে সহজ জিনিসটি করুন যা সম্ভবত নীতিগুলি কাজ করতে পারে। জটিলতা এবং\n\nনিদর্শনগুলি কেবল তখনই চালু করা উচিত যখন সেগুলি ব্যবহারিক জন্য প্রয়োজন\n\nএক্সটেনসিবিলিটি\n\nএকবার আপনি এই ধারণাগুলির সাথে পরিচিত হয়ে গেলে আপনি ড্রিল করা শুরু করতে পারেন\n\n[available design patterns](https://java-design-patterns.com/patterns/) নিম্নলিখিত পন্থাগুলির যেকোনো একটি দ্বারা\n\n - নাম দ্বারা একটি নির্দিষ্ট প্যাটার্ন জন্য অনুসন্ধান করুন। একটি খুঁজে পাচ্ছেন না? একটি নতুন প্যাটার্ন রিপোর্ট করুন [here](https://github.com/iluwatar/java-design-patterns/issues).\n\n - ট্যাগ ব্যবহার করা যেমন `পারফরম্যান্স`, `গ্যাং অফ ফোর` বা `ডেটা অ্যাক্সেস`। \n\n - প্যাটার্ন বিভাগ, `সৃজনশীল`, `আচরণমূলক` এবং অন্যান্য ব্যবহার করে।\n\nআশা করি, আপনি এই সাইটে উপস্থাপিত অবজেক্ট-ওরিয়েন্টেড সমাধানগুলিকে আপনার আর্কিটেকচারে উপযোগী খুঁজে পাবেন এবং সেগুলিকে বিকাশ করার সময় আমরা সেগুলি শিখতে যতটা মজা পেয়েছি।\n\n# কিভাবে অবদান রাখতে হয়\n\nআপনি যদি প্রকল্পে অবদান রাখতে ইচ্ছুক হন তবে আপনি আমাদের প্রাসঙ্গিক তথ্য পাবেন [developer wiki](https://github.com/iluwatar/java-design-patterns/wiki). \n\nআমরা আপনাকে সাহায্য করব এবং আপনার প্রশ্নের উত্তর দেব [Gitter chatroom](https://gitter.im/iluwatar/java-design-patterns).\n\n# লাইসেন্স\n\nএই প্রকল্পটি MIT লাইসেন্সের শর্তাবলীর অধীনে লাইসেন্সপ্রাপ্ত।\n\n"
  },
  {
    "path": "localization/da/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n\n# Designmønstre implementeret i Java\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-267-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n<br/>\n\nLæs på andre sprog : [**zh**](localization/zh/README.md), [**ko**](localization/ko/README.md), [**fr**](localization/fr/README.md), [**tr**](localization/tr/README.md), [**ar**](localization/ar/README.md), [**es**](localization/es/README.md), [**pt**](localization/pt/README.md), [**id**](localization/id/README.md), [**ru**](localization/ru/README.md), [**de**](localization/de/README.md), [**ja**](localization/ja/README.md), [**vi**](localization/vi/README.md), [**bn**](localization/bn/README.md), [**np**](localization/ne/README.md), [**it**](localization/it/README.md)\n<br/>\n\n# Introduktion\n\nDesignmønstre er de bedste formaliserede praksisser, som en programmør kan anvende for at løse typiske problemer i forbindelse med design af en applikation eller et system.\n\nDesignmønstre kan øge udviklingsprocessen ved at give testede, dokumenterede udviklingsparadigmer. \n\nGenanvendelse af designmønstre hjælper med at forhindre diskrete problemer, som kan føre til større problemer, og det forbedrer også kodelæsbarheden for programmører og arkitekter, der er bekendte med mønstrene.\n\n# Kom godt i gang\n\nDenne side viser Designmønstre I Java. Løsningerne er udviklet af erfarne programmører og arkitekter fra open-source fællesskabet. Mønstrene kan blive udforsket efter deres beskrivelser eller ved at se på deres kildekode. Kildekodeeksemplerne er velkommenterede og kan blive betragtet som programmerings-vejledninger om, hvordan man implementerer et specifikt mønster. Vi bruger de mest populære, afprøvede open-source Java-teknologier.\n\nFør du dykker ned i materialet, burde du være bekendt med forskellige\n[Software Design Principper](https://java-design-patterns.com/principles/).\n\nAlle designs bør være så simple som muligt. Du bør starte med KISS, YAGNI, og Do The Simplest Thing That Could Possibly Work principperne. Kompleksitet og mønstre bør kun introduceres, når de er nødvendige for praktisk udvidelse. \n\nNår du først er bekendt med disse begreber, kan du begynde at bore ned i \n[tilgængelige designmønstre](https://java-design-patterns.com/patterns/) ved at anvende en af disse tilgange:\n\n - Søg efter et specifikt mønster ved navn. Kan du ikke finde et? Rapportér venligst et nyt mønster [her](https://github.com/iluwatar/java-design-patterns/issues).\n - Brug tags såsom `Performance`, `Gang of Four` eller `Data access`.\n - Brug mønsterkategorier, såsom `Creational`, `Behavioral`, og andre.\n\nForhåbentlig finder du de objektorienterede løsninger, der præsenteres på denne side, nyttige i dine arkitekturer og har lige så meget sjov med at lære dem, som vi havde, mens vi udviklede dem.\n\n# Hvordan man bidrager\n\nHvis du er villig til at bidrage til projektet, finder du relevante oplysninger i \nvores [developer wiki](https://github.com/iluwatar/java-design-patterns/wiki). Vi vil hjælpe dig og besvare dine spørgsmål i [Gitter chatroom](https://gitter.im/iluwatar/java-design-patterns).\n\n# Licens\n\nDette projekt er licenseret under vilkårene for MIT-licensen.\n"
  },
  {
    "path": "localization/de/README.md",
    "content": "# In Java implementierte Entwurfsmuster\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![Lizenz MIT](https://img.shields.io/badge/lizenz-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Codezeilen](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Abdeckung](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Chat beitreten unter https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-208-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n<br/>\n\nIn anderen Sprachen lesen: [**zh**](localization/zh/README.md), [**ko**](localization/ko/README.md), [**fr**](localization/fr/README.md), [**tr**](localization/tr/README.md), [**ar**](localization/ar/README.md), [**es**](localization/es/README.md), [**pt**](localization/pt/README.md), [**id**](localization/id/README.md), [**ru**](localization/ru/README.md), [**de**](localization/de/README.md), [**ja**](localization/ja/README.md)\n\n<br/>\n\n# Einführung\n\nEntwurfsmuster sind bewährte Lösungen, die Entwickler nutzen können, um häufige Probleme beim Entwurf von Anwendungen oder Systemen zu lösen.\n\nSie helfen dabei, den Entwicklungsprozess zu beschleunigen, indem sie erprobte und zuverlässige Ansätze bereitstellen.\n\nDie Wiederverwendung von Entwurfsmustern verhindert subtile Fehler, die zu größeren Problemen führen können, und verbessert die Lesbarkeit des Codes – besonders für Entwickler und Architekten, die mit diesen Mustern vertraut sind.\n\n# Erste Schritte\n\nDiese Seite stellt Java-Entwurfsmuster vor. Die Lösungen wurden von erfahrenen Entwicklern und Architekten aus der Open-Source-Community erstellt. Die Muster können entweder durch ihre Beschreibungen oder durch den Quellcode erkundet werden. Die Codebeispiele sind gut kommentiert und eignen sich als Tutorials, um die Muster zu verstehen und umzusetzen. Wir verwenden dabei bekannte und bewährte Open-Source-Java-Technologien.\n\nBevor Sie sich mit den Entwurfsmustern beschäftigen, sollten Sie sich mit den grundlegenden [Software-Entwurfsprinzipien](https://java-design-patterns.com/principles/) vertraut machen.\n\nEntwürfe sollten immer so einfach wie möglich gehalten werden. Beginnen Sie mit den Prinzipien KISS (Keep It Simple, Stupid), YAGNI (You Aren’t Gonna Need It) und \"Do The Simplest Thing That Could Possibly Work\". Komplexe Muster sollten nur dann verwendet werden, wenn sie wirklich notwendig sind.\n\nSobald Sie mit diesen Konzepten vertraut sind, können Sie sich die [verfügbaren Entwurfsmuster](https://java-design-patterns.com/patterns/) ansehen. Dafür gibt es verschiedene Ansätze:\n\n- Suchen Sie nach einem bestimmten Muster anhand des Namens. Fehlt ein Muster? Melden Sie es gerne [hier](https://github.com/iluwatar/java-design-patterns/issues).\n- Nutzen Sie Tags wie `Performance`, `Gang of Four` oder `Data access`.\n- Durchsuchen Sie die Muster nach Kategorien wie `Creational`, `Behavioral` und anderen.\n\nWir hoffen, dass Sie die hier vorgestellten Lösungen für Ihre Projekte nützlich finden und genauso viel Spaß beim Lernen haben, wie wir bei der Entwicklung hatten.\n\n# Mitwirken\n\nWenn Sie zum Projekt beitragen möchten, finden Sie alle notwendigen Informationen in unserem [Entwickler-Wiki](https://github.com/iluwatar/java-design-patterns/wiki). Bei Fragen helfen wir Ihnen gerne im [Gitter-Chatraum](https://gitter.im/iluwatar/java-design-patterns) weiter.\n\n# Lizenz\n\nDieses Projekt steht unter der MIT-Lizenz."
  },
  {
    "path": "localization/de/abstract-document/README.md",
    "content": "---\ntitle: \"Abstract Document Pattern in Java: Vereinfachung der Datenverwaltung mit Flexibilität\"\nshortTitle: Abstract Document\ndescription: \"Erkunden Sie das Abstract Document Design Pattern in Java. Lernen Sie seine Absicht, Erklärung, Anwendbarkeit, Vorteile kennen und sehen Sie reale Beispiele zur Implementierung flexibler und dynamischer Datenstrukturen.\"\ncategory: Strukturell\nlanguage: de\ntag:\n  - Abstraktion\n  - Entkopplung\n  - Dynamische Typisierung\n  - Kapselung\n  - Erweiterbarkeit\n  - Polymorphismus\n---\n\n## Absicht des Abstract Document Design Patterns\n\nDas Abstract Document Design Pattern in Java ist ein wichtiges strukturelles Design Pattern, das eine konsistente Möglichkeit bietet, hierarchische und baumartige Datenstrukturen zu handhaben, indem es eine gemeinsame Schnittstelle für verschiedene Dokumenttypen definiert. Es trennt die Kernstruktur des Dokuments von spezifischen Datenformaten und ermöglicht dynamische Aktualisierungen und vereinfachte Wartung.\n\n## Detaillierte Erklärung des Abstract Document Patterns mit realen Beispielen\n\nDas Abstract Document Design Pattern in Java ermöglicht die dynamische Handhabung nicht-statischer Eigenschaften. Dieses Pattern verwendet das Konzept der Traits, um Typsicherheit zu gewährleisten und Eigenschaften verschiedener Klassen in eine Menge von Schnittstellen zu trennen.\n\nReales Beispiel\n\n> Betrachten Sie ein Bibliothekssystem, das das Abstract Document Design Pattern in Java implementiert, wo Bücher verschiedene Formate und Attribute haben können: physische Bücher, eBooks und Hörbücher. Jedes Format hat einzigartige Eigenschaften, wie Seitenzahl für physische Bücher, Dateigröße für eBooks und Dauer für Hörbücher. Das Abstract Document Design Pattern ermöglicht es dem Bibliothekssystem, diese verschiedenen Formate flexibel zu verwalten. Durch die Verwendung dieses Patterns kann das System Eigenschaften dynamisch speichern und abrufen, ohne dass eine starre Struktur für jeden Buchtyp erforderlich ist, was es einfacher macht, neue Formate oder Attribute in der Zukunft hinzuzufügen, ohne dass wesentliche Änderungen am Codebase erforderlich sind.\n\nIn einfachen Worten\n\n> Das Abstract Document Pattern ermöglicht das Anhängen von Eigenschaften an Objekte, ohne dass diese davon wissen.\n\nWikipedia sagt\n\n> Ein objektorientiertes strukturelles Design Pattern zur Organisation von Objekten in schwach typisierten Schlüssel-Wert-Speichern und zur Bereitstellung der Daten über typisierte Ansichten. Der Zweck des Patterns besteht darin, einen hohen Grad an Flexibilität zwischen Komponenten in einer stark typisierten Sprache zu erreichen, in der neue Eigenschaften zur Objektstruktur dynamisch hinzugefügt werden können, ohne die Unterstützung der Typsicherheit zu verlieren. Das Pattern verwendet Traits, um verschiedene Eigenschaften einer Klasse in verschiedene Schnittstellen zu trennen.\n\n## Programmatisches Beispiel des Abstract Document Patterns in Java\n\nBetrachten Sie ein Auto, das aus mehreren Teilen besteht. Wir wissen jedoch nicht, ob das spezifische Auto wirklich alle Teile hat oder nur einige davon. Unsere Autos sind dynamisch und extrem flexibel.\n\nLassen Sie uns zunächst die Basisklassen `Document` und `AbstractDocument` definieren. Sie sorgen im Wesentlichen dafür, dass das Objekt eine Eigenschaftsmap und eine beliebige Anzahl von Kindobjekten enthält.\n\n```java\npublic interface Document {\n\n    Void put(String key, Object value);\n\n    Object get(String key);\n\n    <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);\n}\n\npublic abstract class AbstractDocument implements Document {\n\n    private final Map<String, Object> properties;\n\n    protected AbstractDocument(Map<String, Object> properties) {\n        Objects.requireNonNull(properties, \"properties map is required\");\n        this.properties = properties;\n    }\n\n    @Override\n    public Void put(String key, Object value) {\n        properties.put(key, value);\n        return null;\n    }\n\n    @Override\n    public Object get(String key) {\n        return properties.get(key);\n    }\n\n    @Override\n    public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {\n        return Stream.ofNullable(get(key))\n                .filter(Objects::nonNull)\n                .map(el -> (List<Map<String, Object>>) el)\n                .findAny()\n                .stream()\n                .flatMap(Collection::stream)\n                .map(constructor);\n    }\n    \n    // Andere Eigenschaften und Methoden...\n}\n```\nAls nächstes definieren wir ein Enum Property und eine Menge von Schnittstellen für Typ, Preis, Modell und Teile. Dies ermöglicht es uns, eine statisch aussehende Schnittstelle für unsere Car-Klasse zu erstellen.\n\n```java\npublic enum Property {\n\n    PARTS, TYPE, PRICE, MODEL\n}\n\npublic interface HasType extends Document {\n\n    default Optional<String> getType() {\n        return Optional.ofNullable((String) get(Property.TYPE.toString()));\n    }\n}\n\npublic interface HasPrice extends Document {\n\n    default Optional<Number> getPrice() {\n        return Optional.ofNullable((Number) get(Property.PRICE.toString()));\n    }\n}\n\npublic interface HasModel extends Document {\n\n    default Optional<String> getModel() {\n        return Optional.ofNullable((String) get(Property.MODEL.toString()));\n    }\n}\n\npublic interface HasParts extends Document {\n\n    default Stream<Part> getParts() {\n        return children(Property.PARTS.toString(), Part::new);\n    }\n}\n```\n\nJetzt sind wir bereit, das `Car` einzuführen.\n\n```java\n  public static void main(String[] args) {\n    LOGGER.info(\"Konstruktion von Teilen und Auto\");\n\n    var wheelProperties = Map.of(\n            Property.TYPE.toString(), \"wheel\",\n            Property.MODEL.toString(), \"15C\",\n            Property.PRICE.toString(), 100L);\n\n    var doorProperties = Map.of(\n            Property.TYPE.toString(), \"door\",\n            Property.MODEL.toString(), \"Lambo\",\n            Property.PRICE.toString(), 300L);\n\n    var carProperties = Map.of(\n            Property.MODEL.toString(), \"300SL\",\n            Property.PRICE.toString(), 10000L,\n            Property.PARTS.toString(), List.of(wheelProperties, doorProperties));\n\n    var car = new Car(carProperties);\n\n    LOGGER.info(\"Hier ist unser Auto:\");\n    LOGGER.info(\"-> Modell: {}\", car.getModel().orElseThrow());\n    LOGGER.info(\"-> Preis: {}\", car.getPrice().orElseThrow());\n    LOGGER.info(\"-> Teile: \");\n    car.getParts().forEach(p -> LOGGER.info(\"\\t{}/{}/{}\",\n            p.getType().orElse(null),\n            p.getModel().orElse(null),\n            p.getPrice().orElse(null))\n    );\n}\n```\nDie Programmausgabe:\n\n```\n07:21:57.391 [main] INFO com.iluwatar.abstractdocument.App -- Konstruktion von Teilen und Auto\n07:21:57.393 [main] INFO com.iluwatar.abstractdocument.App -- Hier ist unser Auto:\n07:21:57.393 [main] INFO com.iluwatar.abstractdocument.App -- -> Modell: 300SL\n07:21:57.394 [main] INFO com.iluwatar.abstractdocument.App -- -> Preis: 10000\n07:21:57.394 [main] INFO com.iluwatar.abstractdocument.App -- -> Teile: \n07:21:57.395 [main] INFO com.iluwatar.abstractdocument.App -- \tRad/15C/100\n07:21:57.395 [main] INFO com.iluwatar.abstractdocument.App -- \tTür/Lambo/300\n```\n## Abstract Document Pattern Klassendiagramm\n\n![Abstract Document](./etc/abstract-document.png \"Abstract Document Traits und Domain\")\n\n## Wann sollte das Abstract Document Pattern in Java verwendet werden?\n\nDas Abstract Document Design Pattern ist besonders vorteilhaft in Szenarien, die eine Verwaltung unterschiedlicher Dokumenttypen in Java erfordern, die einige gemeinsame Attribute oder Verhaltensweisen teilen, aber auch einzigartige Attribute oder Verhaltensweisen haben, die spezifisch für ihren Typ sind. Hier sind einige Szenarien, in denen das Abstract Document Design Pattern anwendbar ist:\n\n* **Content-Management-Systeme (CMS)**: In einem CMS könnten verschiedene Arten von Inhalten wie Artikel, Bilder, Videos usw. vorkommen. Jede Inhaltsart könnte gemeinsame Attribute wie Erstellungsdatum, Autor und Tags haben, aber auch spezifische Attribute wie Bildabmessungen für Bilder oder Videodauer für Videos.\n\n* **Dateisysteme**: Wenn Sie ein Dateisystem entwerfen, in dem unterschiedliche Dateitypen verwaltet werden müssen, wie Dokumente, Bilder, Audiodateien und Verzeichnisse, kann das Abstract Document Pattern helfen, eine konsistente Möglichkeit zum Zugriff auf Attribute wie Dateigröße, Erstellungsdatum usw. zu bieten, während spezifische Attribute wie Bildauflösung oder Audiodauer berücksichtigt werden.\n\n* **E-Commerce-Systeme**: Eine E-Commerce-Plattform könnte verschiedene Produkttypen haben, wie physische Produkte, digitale Downloads und Abonnements. Jeder Typ könnte gemeinsame Attribute wie Name, Preis und Beschreibung haben, aber auch einzigartige Attribute wie Versandgewicht für physische Produkte oder Download-Link für digitale Produkte.\n\n* **Medizinische Aufzeichnungssysteme**: Im Gesundheitswesen könnten Patientenakten verschiedene Datentypen enthalten, wie demografische Daten, medizinische Vorgeschichte, Testergebnisse und Rezepte. Das Abstract Document Pattern kann helfen, gemeinsame Attribute wie Patienten-ID und Geburtsdatum zu verwalten, während spezialisierte Attribute wie Testergebnisse oder verschriebene Medikamente berücksichtigt werden.\n\n* **Konfigurationsmanagement**: Bei der Verwaltung von Konfigurationseinstellungen für Softwareanwendungen gibt es möglicherweise verschiedene Arten von Konfigurationselementen, jedes mit einer eigenen Reihe von Attributen. Das Abstract Document Pattern kann verwendet werden, um diese Konfigurationselemente zu verwalten, während eine konsistente Möglichkeit zum Zugriff auf und Bearbeiten der Attribute sichergestellt wird.\n\n* **Bildungsplattformen**: Bildungssysteme könnten verschiedene Arten von Lernmaterialien wie textbasierte Inhalte, Videos, Quizze und Aufgaben haben. Gemeinsame Attribute wie Titel, Autor und Veröffentlichungsdatum können geteilt werden, während spezifische Attribute wie Videodauer oder Aufgabenfälligkeit für jeden Typ einzigartig sind.\n\n* **Projektmanagement-Tools**: In Projektmanagement-Anwendungen könnten unterschiedliche Aufgabenarten wie To-Do-Items, Meilensteine und Probleme vorliegen. Das Abstract Document Pattern könnte verwendet werden, um allgemeine Attribute wie Aufgabenname und Zuweisung zu handhaben, während spezifische Attribute wie Meilensteindaten oder Problemprioritäten zugelassen werden.\n\n* **Dokumente haben vielfältige und sich entwickelnde Attributstrukturen.**\n\n* **Dynamisches Hinzufügen neuer Eigenschaften ist eine häufige Anforderung.**\n\n* **Entkopplung des Datenzugriffs von spezifischen Formaten ist entscheidend.**\n\n* **Wartbarkeit und Flexibilität sind entscheidend für die Codebasis.**\n\nDie Hauptidee hinter dem Abstract Document Design Pattern ist es, eine flexible und erweiterbare Möglichkeit zur Verwaltung unterschiedlicher Dokumenttypen oder Entitäten mit gemeinsamen und spezifischen Attributen bereitzustellen. Durch die Definition einer gemeinsamen Schnittstelle und deren Implementierung über verschiedene Dokumenttypen hinweg können Sie einen besser organisierten und konsistenteren Ansatz zur Handhabung komplexer Datenstrukturen erreichen.\n\n## Vorteile und Abwägungen des Abstract Document Patterns\n\n**Vorteile:**\n\n* **Flexibilität**: Ermöglicht die Handhabung unterschiedlicher Dokumentstrukturen und -eigenschaften.\n* **Erweiterbarkeit**: Neue Attribute können dynamisch hinzugefügt werden, ohne bestehenden Code zu brechen.\n* **Wartbarkeit**: Fördert sauberen und anpassungsfähigen Code durch Trennung der Verantwortlichkeiten.\n* **Wiederverwendbarkeit**: Typspezifische Ansichten ermöglichen eine Wiederverwendung des Codes zum Zugriff auf bestimmte Attributtypen.\n\n**Abwägungen:**\n\n* **Komplexität**: Erfordert die Definition von Schnittstellen und Ansichten, was zu zusätzlichem Implementierungsaufwand führt.\n* **Leistung**: Kann im Vergleich zum direkten Datenzugriff zu leichtem Leistungsaufwand führen.\n\n## Quellen und Danksagungen\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n* [Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4)](https://amzn.to/49zRP4R)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Abstract Document Pattern (Wikipedia)](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)\n* [Dealing with Properties (Martin Fowler)](http://martinfowler.com/apsupp/properties.pdf)\n\n\n\n\n\n"
  },
  {
    "path": "localization/el/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n\n# Σχεδιαστικά μοτίβα για την Java\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-208-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n<br/>\n\n# Εισαγωγή\n\nΤα σχεδιαστικά μοτίβα είναι οι καλύτερες, επίσημες πρακτικές που μπορεί να χρησιμοποιήσει ένας προγραμματιστής την λύση κοινών προβλημάτων κατά το σχεδιασμό μιας εφαρμογής ή συστήματος.\n\nΤα σχεδιαστικά μοτίβα μπορούν να επιταχύνουν τη διαδικασία ανάπτυξης παρέχοντας δοκιμασμένα, αποδεδειγμένα παραδείγματα.\n\nΗ επαναχρησιμοποίηση σχεδιαστικών μοτίβων βοηθά στην αποφυγή λεπτών ζητημάτων που προκαλούν μεγάλα προβλήματα και βελτιώνει επίσης την αναγνωσιμότητα κώδικα για άτομα που είναι εξοικειωμένοι με τα μοτίβα αυτά.\n\n# Κάνοντας την αρχή\n\nΑυτός ο ιστότοπος παρουσιάζει σχεδιαστικά μοτίβα στην Java. Οι λύσεις έχουν αναπτυχθεί από έμπειρους προγραμματιστές και αρχιτέκτονες από την κοινότητα ανοιχτού κώδικα. Τα μοτίβα μπορούν να ελεγχθούν από τις περιγραφές υψηλού επιπέδου ή κοιτάζοντας τον πηγαίο κώδικα τους. Τα παραδείγματα του πηγαίου κώδικα είναι καλά σχολιασμένα και μπορούν να θεωρηθούν ως εκπαιδευτικά προγράμματα προγραμματισμού για τον τρόπο εφαρμογής ενός συγκεκριμένου μοτίβου. Χρησιμοποιούμε τις πιο δημοφιλείς τεχνολογίες Java ανοιχτού κώδικα, αποδεδειγμένα στη μάχη.\n\nΠριν ξεκινήσετε, θα πρέπει να είστε εξοικειωμένοι με διάφορες\n[Αρχές Σχεδιασμού Λογισμικού](https://java-design-patterns.com/principles/).\n\nΌλα τα σχέδια πρέπει να είναι όσο το δυνατόν πιο απλά. Θα πρέπει να ξεκινήσετε με τις αρχές KISS, YAGNI και Do The Simplet Thing That Could Possibly Work. Πολυπλοκότητα και μοτίβα θα πρέπει να εισάγονται μόνο όταν χρειάζονται για πρακτική επεκτασιμότητα.\n\nΜόλις εξοικειωθείτε με αυτές τις έννοιες, μπορείτε να αρχίσετε να εξετάζετε τα\n[τα διαθέσιμα σχεδιαστικά μοτίβα](https://java-design-patterns.com/patterns/) με οποιονδήποτε\nαπο τους παρακάτω τρόπους\n\n - Αναζητήστε ένα συγκεκριμένο μοτίβο με το όνομα του. Δεν μπορείτε να το βρείτε; Αναφέρετε ένα νέο μοτίβο [εδώ](https://github.com/iluwatar/java-design-patterns/issues).\n - Χρησιμοποιώντας ετικέτες όπως `Performance`, `Gang of Four` or `Data access`.\n - Χρησιμοποιώντας κατηγορίες μοτίβων, `Creational`, `Behavioral`, and others.\n\nΑς ελπίσουμε ότι θα βρείτε τις αντικειμενοστρεφείς λύσεις που παρουσιάζονται σε αυτόν τον ιστότοπο χρήσιμες στις αρχιτεκτονικές σας και θα διασκεδάσετε μαθαίνοντας τες όσο και εμείς κατά την ανάπτυξή τους.\n\n# Πως να συνεισφέρεις\n\nΕάν είστε πρόθυμοι να συνεισφέρετε στο έργο, θα βρείτε τις σχετικές πληροφορίες στο δικό μας [developer wiki](https://github.com/iluwatar/java-design-patterns/wiki). Θα σας βοηθήσουμε και θα απαντήσουμε στις ερωτήσεις σας στο [Gitter chatroom](https://gitter.im/iluwatar/java-design-patterns).\n\n# Άδεια\n\nΑυτό το έργο αδειοδοτείται σύμφωνα με τους όρους της άδειας MIT.\n\n# Συνεισφέροντες\n\n"
  },
  {
    "path": "localization/es/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n\n# Patrones de diseño implementados en Java\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-167-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n# Introducción\n\nLos patrones de diseño son las mejores prácticas formalizadas que un programador puede utilizar para resolver problemas comunes al diseñar una aplicación o sistema.\n\nLos patrones de diseño pueden acelerar el proceso de desarrollo al proporcionar paradigmas de desarrollo probados y comprobados.\n\nLa reutilización de patrones de diseño ayuda a prevenir problemas sutiles que causan errores importantes, y también mejora la legibilidad del código para desarrolladores y arquitectos que están familiarizados con los patrones.\n\n# Comenzar\n\nEste sitio presenta los patrones de diseño en Java. Las soluciones han sido desarrolladas por\nprogramadores y arquitectos experimentados de la comunidad de código abierto. Los patrones se pueden buscar por sus descripciones de alto nivel o mirando su código fuente. Los ejemplos de código fuente están bien comentados y pueden pensarse como tutoriales de programación sobre cómo implementar un patrón específico. Usamos las tecnologías Java de código abierto más populares.\n\nAntes de sumergirte en el material deberías estar familiarizado con varios\n[Principios de diseño de software](https://java-design-patterns.com/principles/).\n\nTodos los diseños deben ser lo más simples posible. Deberías comenzar con los principios KISS, YAGNI y hacer lo más simple que funcione. La complejidad y los patrones solo deben introducirse cuando sean necesarios para una extensibilidad práctica.\n\nUna vez que esté familiarizado con estos conceptos, puedes comenzar a profundizar con los\n[patrones de diseño disponibles](https://java-design-patterns.com/patterns/) por cualquiera de los siguientes enfoques\n\n - Buscar un patrón específico por su nombre. ¿No puedes encontrar uno? Informa de un nuevo patrón [aquí](https://github.com/iluwatar/java-design-patterns/issues).\n - Usando etiquetas como `Performance`, `Gang of Four` ó `Data access`.\n - Usando categorías de patrones, `Creational`, `Behavioral` y otras.\n\nEsperamos que las soluciones orientadas a objetos presentadas en este sitio te resulten útiles en sus arquitecturas y se divierta aprendiéndolas tanto como nosotros desarrollándolas.\n\n# Cómo contribuir\n\nSi estás dispuesto a contribuir al proyecto encontrarás la información relevante en nuestra [wiki del desarrollador](https://github.com/iluwatar/java-design-patterns/wiki). Te ayudaremos y responderemos tus preguntas en la [sala de chat de Gitter](https://gitter.im/iluwatar/java-design-patterns).\n\n# Licencia\n\nEste proyecto está licenciado de acuerdo con los términos de la licencia del MIT.\n\n"
  },
  {
    "path": "localization/es/abstract-document/README.md",
    "content": "---\ntitle: Abstract Document\nshortTitle: Abstract Document\ncategory: Structural\nlanguage: es\ntag:\n  - Extensibility\n---\n\n## Propósito\n\nUsar propiedades dinámicas y conseguir la flexibilidad de los lenguajes no tipados manteniendo la seguridad de tipos.\n\n## Explicación\n\nEl uso del patrón Abstract Document permite gestionar propiedades no estáticas adicionales. Este patrón usa el concepto\nde atributos para permitir seguridad de tipos y propiedades separadas de diferentes clases en un grupo de interfaces.\n\nEjemplo del mundo real\n\n> Toma como ejemplo un coche que está formado por muchas partes. Sin embargo, no sabemos si el coche tiene todas las\n> partes o solo una parte de ellas. Nuestros coches son dinámicos y extremadamente flexibles.\n\nDicho de otra forma\n\n> El patrón Abstract Document permite añadir propiedades a objetos sin que estos sean conscientes de ello.\n\nSegún Wikipedia\n\n> Un patrón de diseño estructural orientado a objetos para organizar objetos en contenedores clave-valor vagamente\n> tipados y exponiendo los datos usando vistas tipadas. El propósito del patrón es conseguir un alto grado de flexibilidad\n> entre componentes en un lenguaje de tipado fuerte donde nuevas propiedades pueden añadirse al árbol de objetos sobre la\n> marcha sin perder el soporte de la seguridad de tipos. El patrón hace uso de atributos para separar diferentes\n> propiedades de una clase en distintas interfaces.\n\n**Ejemplo Programático**\n\nPrimero definamos las clases base `Document` y `AbstractDocument`. Básicamente, hacen que el objeto contenga un mapa de\npropiedades y cualquier número de objetos hijo.\n\n```java\npublic interface Document {\n\n  Void put(String key, Object value);\n\n  Object get(String key);\n\n  <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);\n}\n\npublic abstract class AbstractDocument implements Document {\n\n  private final Map<String, Object> properties;\n\n  protected AbstractDocument(Map<String, Object> properties) {\n    Objects.requireNonNull(properties, \"properties map is required\");\n    this.properties = properties;\n  }\n\n  @Override\n  public Void put(String key, Object value) {\n    properties.put(key, value);\n    return null;\n  }\n\n  @Override\n  public Object get(String key) {\n    return properties.get(key);\n  }\n\n  @Override\n  public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {\n    return Stream.ofNullable(get(key))\n        .filter(Objects::nonNull)\n        .map(el -> (List<Map<String, Object>>) el)\n        .findAny()\n        .stream()\n        .flatMap(Collection::stream)\n        .map(constructor);\n  }\n  ...\n}\n```\n\nA continuación definimos un enum `Property` y un grupo de interfaces para tipo, precio, modelo y partes. Esto nos\npermite crear interfaces de apariencia estática para nuestra clase `Car`.\n\n```java\npublic enum Property {\n\n  PARTS, TYPE, PRICE, MODEL\n}\n\npublic interface HasType extends Document {\n\n  default Optional<String> getType() {\n    return Optional.ofNullable((String) get(Property.TYPE.toString()));\n  }\n}\n\npublic interface HasPrice extends Document {\n\n  default Optional<Number> getPrice() {\n    return Optional.ofNullable((Number) get(Property.PRICE.toString()));\n  }\n}\npublic interface HasModel extends Document {\n\n  default Optional<String> getModel() {\n    return Optional.ofNullable((String) get(Property.MODEL.toString()));\n  }\n}\n\npublic interface HasParts extends Document {\n\n  default Stream<Part> getParts() {\n    return children(Property.PARTS.toString(), Part::new);\n  }\n}\n```\n\nAhora estamos listos para introducir el Coche `Car`.\n\n```java\npublic class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {\n\n  public Car(Map<String, Object> properties) {\n    super(properties);\n  }\n}\n```\n\nY finalmente asi es como construimos y usamos el Coche `Car` en un ejemplo completo.\n\n```java\n    LOGGER.info(\"Constructing parts and car\");\n\n    var wheelProperties = Map.of(\n        Property.TYPE.toString(), \"wheel\",\n        Property.MODEL.toString(), \"15C\",\n        Property.PRICE.toString(), 100L);\n\n    var doorProperties = Map.of(\n        Property.TYPE.toString(), \"door\",\n        Property.MODEL.toString(), \"Lambo\",\n        Property.PRICE.toString(), 300L);\n\n    var carProperties = Map.of(\n        Property.MODEL.toString(), \"300SL\",\n        Property.PRICE.toString(), 10000L,\n        Property.PARTS.toString(), List.of(wheelProperties, doorProperties));\n\n    var car = new Car(carProperties);\n\n    LOGGER.info(\"Here is our car:\");\n    LOGGER.info(\"-> model: {}\", car.getModel().orElseThrow());\n    LOGGER.info(\"-> price: {}\", car.getPrice().orElseThrow());\n    LOGGER.info(\"-> parts: \");\n    car.getParts().forEach(p -> LOGGER.info(\"\\t{}/{}/{}\",\n        p.getType().orElse(null),\n        p.getModel().orElse(null),\n        p.getPrice().orElse(null))\n    );\n\n    // Constructing parts and car\n    // Here is our car:\n    // model: 300SL\n    // price: 10000\n    // parts: \n    // wheel/15C/100\n    // door/Lambo/300\n```\n\n## Diagrama de clases\n\n![alt text](./etc/abstract-document.png \"Abstract Document Traits and Domain\")\n\n## Aplicación\n\nUsar el patrón Abstract Document cuando\n\n* Existe la necesidad de añadir propiedades sobre la marcha.\n* Quieres una manera flexible de organizar el dominio en una estructura similar a un árbol.\n* Quieres un sistema menos acoplado.\n\n## Créditos\n\n* [Wikipedia: Abstract Document Pattern](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)\n* [Martin Fowler: Dealing with properties](http://martinfowler.com/apsupp/properties.pdf)\n* [Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4)](https://www.amazon.com/gp/product/0470059028/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0470059028&linkId=e3aacaea7017258acf184f9f3283b492)\n"
  },
  {
    "path": "localization/es/abstract-factory/README.md",
    "content": "---\ntitle: Abstract Factory\nshortTitle: Abstract Factory\ncategory: Creational\nlanguage: es\ntag:\n - Gang of Four\n---\n\n## También conocido como\n\nKit\n\n## Propósito\n\nProveer de una interfaz para crear familias de objetos relacionados dependientes sin especificar su clase concreta.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Para crear un reino necesitamos objetos con una temática común. El reino élfico necesita un rey elfo, un castillo élfico y un ejército élfico mientras que el reino orco necesita un rey orco, un castillo orco y un ejército orco. Hay una dependencia entre los objetos del reino.\n\nDicho de otra forma\n\n> Una factoría de factorías; una factoría que agrupa otras factorías individuales pero relacionadas/dependientes sin especificar su clase concreta.\n\nSegún Wikipedia\n\n> El patrón abstract factory provee una forma de encapsular un grupo de factorías individuales que tienen una temática común sin especificar sus clases concretas.\n\n**Ejemplo Programático**\n\nTraduciendo el ejemplo anterior sobre los reinos. Primero tenemos algunas interfaces e implementaciones de los objetos del `Castle`.\n\n```java\npublic interface Castle {\n  String getDescription();\n}\n\npublic interface King {\n  String getDescription();\n}\n\npublic interface Army {\n  String getDescription();\n}\n\n// Elven implementations ->\npublic class ElfCastle implements Castle {\n  static final String DESCRIPTION = \"This is the elven castle!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfKing implements King {\n  static final String DESCRIPTION = \"This is the elven king!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfArmy implements Army {\n  static final String DESCRIPTION = \"This is the elven Army!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\n// Orcish implementations similarly -> ...\n\n```\n\nLuego tenemos la abstracción e implementación de la factoría del reino `KingdomFactory`.\n\n```java\npublic interface KingdomFactory {\n  Castle createCastle();\n  King createKing();\n  Army createArmy();\n}\n\npublic class ElfKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new ElfCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new ElfKing();\n  }\n\n  @Override\n  public Army createArmy() {\n    return new ElfArmy();\n  }\n}\n\npublic class OrcKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new OrcCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new OrcKing();\n  }\n  \n  @Override\n  public Army createArmy() {\n    return new OrcArmy();\n  }\n}\n```\n\nAhora tenemos la factoría abstracta que nos permite hacer familias de objetos relacionados por ejemplo la factoría del reino élfico `ElfKingdomFactory` crea el castillo `castle`, rey `king` y ejército `army` etc.\n\n\n```java\nvar factory = new ElfKingdomFactory();\nvar castle = factory.createCastle();\nvar king = factory.createKing();\nvar army = factory.createArmy();\n\ncastle.getDescription();\nking.getDescription();\narmy.getDescription();\n```\n\nSalida del programa:\n\n```java\nThis is the elven castle!\nThis is the elven king!\nThis is the elven Army!\n```\n\nAhora podemos diseñar una factoría para nuestras factorías de reinos. En este ejemplo creamos  `FactoryMaker`, responsable de devolver una instancia de `ElfKingdomFactory` o `OrcKingdomFactory`.  \nEl cliente puede usar `FactoryMaker` para crear una factoría concreta, que a su vez, producirá diferentes objetos concretos (derivados de `Army`, `King`, `Castle`).  \nEn este ejemplo también usamos un enum para parametrizar el tipo de factoría de reinos pedirá el cliente.\n\n```java\npublic static class FactoryMaker {\n\n    public enum KingdomType {\n        ELF, ORC\n    }\n\n    public static KingdomFactory makeFactory(KingdomType type) {\n        return switch (type) {\n            case ELF -> new ElfKingdomFactory();\n            case ORC -> new OrcKingdomFactory();\n            default -> throw new IllegalArgumentException(\"KingdomType not supported.\");\n        };\n    }\n}\n\n    public static void main(String[] args) {\n        var app = new App();\n\n        LOGGER.info(\"Elf Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));\n        LOGGER.info(app.getArmy().getDescription());\n        LOGGER.info(app.getCastle().getDescription());\n        LOGGER.info(app.getKing().getDescription());\n\n        LOGGER.info(\"Orc Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));\n        --similar use of the orc factory\n    }\n```\n\n## Diagrama de clases\n\n![alt text](./etc/abstract-factory.urm.png \"Diagrama de Clases de Abstract Factory\")\n\n\n## Aplicación\n\nUsar el patrón Abstract Factory cuando\n\n* El sistema debe ser agnóstico a como se crean, componen y representan sus objetos.\n* El sistema debe ser configurado con una de las múltiples familias de productos.\n* La familia de objetos relacionados está diseñada para ser usada en conjunto y necesitas forzar esta premisa.\n* Quieres proveer de una librería de productos y solo quieres revelar sus interfaces, no su implementación.\n* El tiempo de vida de la dependencia es conceptualmente más corto que el del cliente.\n* Necesitas un valor en tiempo de ejecución para construir una dependencia.\n* Quieres decidir que producto de una familia llamar en tiempo de ejecución.\n* Necesitas proveer de uno o más parámetros solo conocidos en tiempo de ejecución antes de poder resolver la dependencia.\n* Necesitas consistencia entre productos.\n* No quieres cambiar el código existente al añadir nuevos productos o familias de productos al programa.\n\nEjemplos de casos de uso\n\n* Elegir llamar a la implementación correcta de FileSystemAcmeService o DatabaseAcmeService o NetworkAcmeService en tiempo de ejecución.\n* Escribir test unitarios se hace mucho más sencillo.\n* Herramientas UI (User Interface) para diferentes SO (Sistemas Operativos).\n\n## Consecuencias\n\n* La inyección de dependencias en java esconde las dependencias de la clase servicio lo que puede llevar a errores de ejecución que se podrían haber evitado al compilar.\n* Mientras que el patrón es muy bueno creando objetos predefinidos, añadir nuevos puede ser complicado.\n* El código es más complicado de lo que debería porque se añaden muchas interfaces y clases nuevas junto con el patrón.\n\n## Tutoriales\n\n* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java) \n\n## Usos conocidos\n\n* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)\n* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)\n* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)\n\n## Patrones relacionados\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/es/active-object/README.md",
    "content": "---\ntitle: Active Object\nshortTitle: Active Object\ncategory: Concurrency\nlanguage: es\ntag:\n - Performance\n---\n\n\n## Propósito\nEl patrón de diseño de objeto activo desacopla la ejecución del método de la invocación del método para los objetos que residen en su propio hilo de control. El objetivo es introducir la concurrencia mediante el uso de la invocación de métodos asíncronos y un planificador para manejar solicitudes.\n\n## Explicación\n\nLa clase que implementa el patrón de diseño de objeto activo contendrá un mecanismo de autosincronización sin utilizar métodos sincronizados (synchronized).\n\nEjemplo del mundo real\n\n> Los orcos son conocidos por su salvajismo y filosofía de no hacer equipo. Basándonos en este comportamiento se podría decir que tienen su propio hilo de control.\n\nPodemos usar el patrón Active Object para implementar una criatura que tiene su propio hilo de control y exponer su API pero no la ejecución como tal.\n\n\n**Ejemplo Programático**\n\n```java\npublic abstract class ActiveCreature{\n  private final Logger logger = LoggerFactory.getLogger(ActiveCreature.class.getName());\n\n  private BlockingQueue<Runnable> requests;\n  \n  private String name;\n  \n  private Thread thread;\n\n  public ActiveCreature(String name) {\n    this.name = name;\n    this.requests = new LinkedBlockingQueue<Runnable>();\n    thread = new Thread(new Runnable() {\n        @Override\n        public void run() {\n          while (true) {\n            try {\n              requests.take().run();\n            } catch (InterruptedException e) { \n              logger.error(e.getMessage());\n            }\n          }\n        }\n      }\n    );\n    thread.start();\n  }\n  \n  public void eat() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} is eating!\",name());\n          logger.info(\"{} has finished eating!\",name());\n        }\n      }\n    );\n  }\n\n  public void roam() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} has started to roam the wastelands.\",name());\n        }\n      }\n    );\n  }\n  \n  public String name() {\n    return this.name;\n  }\n}\n```\n\nPodemos ver que cualquier clase que extienda de ActiveCreature tendrá su propio hilo de control para invocar y ejecutar métodos.\n\nPor ejemplo, la clase Orc:\n\n```java\npublic class Orc extends ActiveCreature {\n\n  public Orc(String name) {\n    super(name);\n  }\n\n}\n```\n\nAhora podemos crear múltiples criaturas como los Orcos, diles que coman y deambulen y lo harán en su propio hilo de control:\n\n```java\n  public static void main(String[] args) {  \n    var app = new App();\n    app.run();\n  }\n  \n  @Override\n  public void run() {\n    ActiveCreature creature;\n    try {\n      for (int i = 0;i < creatures;i++) {\n        creature = new Orc(Orc.class.getSimpleName().toString() + i);\n        creature.eat();\n        creature.roam();\n      }\n      Thread.sleep(1000);\n    } catch (InterruptedException e) {\n      logger.error(e.getMessage());\n    }\n    Runtime.getRuntime().exit(1);\n  }\n```\n\n## Diagrama de clases\n\n![alt text](./etc/active-object.urm.png \"Active Object class diagram\")\n\n## Tutoriales\n\n* [Android and Java Concurrency: The Active Object Pattern](https://www.youtube.com/watch?v=Cd8t2u5Qmvc)"
  },
  {
    "path": "localization/es/acyclic-visitor/README.md",
    "content": "---\ntitle: Acyclic Visitor\nshortTitle: Acyclic Visitor\ncategory: Behavioral\nlanguage: es\ntag:\n - Extensibility\n---\n\n## Propósito\n\nPermitir añadir nuevas funciones a jerarquías de clases existentes sin que estas se vean afectadas, y sin crear los problemáticos círculos de dependencias que son inherentes al patrón GoF (Gang of Four) Visitor.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Tenemos una jerarquía de clases módem. Los modems de esta jerarquía deben ser visitados por un algoritmo externo basándose en unos filtros (el módem es compatible con Unix o DOS).\n\nEn otras palabras\n\n> Acyclic Visitor permite añadir funciones a jerarquías de clases existentes sin modificarlas.\n\n[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) dice\n\n> El patrón Acyclic Visitor permite que nuevas funciones sean añadidas a jerarquías de clases existentes sin afectar a las mismas, y sin crear los círculos de dependencias que son inherentes al patrón de visitante (Visitor Pattern) de GangOfFour.\n\n**Ejemplo Programático**\n\nAquí tenemos la jerarquía `Modem`.\n\n```java\npublic abstract class Modem {\n  public abstract void accept(ModemVisitor modemVisitor);\n}\n\npublic class Zoom extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof ZoomVisitor) {\n      ((ZoomVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only ZoomVisitor is allowed to visit Zoom modem\");\n    }\n  }\n}\n\npublic class Hayes extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof HayesVisitor) {\n      ((HayesVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only HayesVisitor is allowed to visit Hayes modem\");\n    }\n  }\n}\n```\n\nDespués tenemos la jerarquía `ModemVisitor`.\n\n```java\npublic interface ModemVisitor {\n}\n\npublic interface HayesVisitor extends ModemVisitor {\n  void visit(Hayes hayes);\n}\n\npublic interface ZoomVisitor extends ModemVisitor {\n  void visit(Zoom zoom);\n}\n\npublic interface AllModemVisitor extends ZoomVisitor, HayesVisitor {\n}\n\npublic class ConfigureForDosVisitor implements AllModemVisitor {\n  ...\n  @Override\n  public void visit(Hayes hayes) {\n    LOGGER.info(hayes + \" used with Dos configurator.\");\n  }\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Dos configurator.\");\n  }\n}\n\npublic class ConfigureForUnixVisitor implements ZoomVisitor {\n  ...\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Unix configurator.\");\n  }\n}\n```\n\nFinalmente, aquí están los \"visitors\" en acción.\n\n```java\n    var conUnix = new ConfigureForUnixVisitor();\n    var conDos = new ConfigureForDosVisitor();\n    var zoom = new Zoom();\n    var hayes = new Hayes();\n    hayes.accept(conDos);\n    zoom.accept(conDos);\n    hayes.accept(conUnix);\n    zoom.accept(conUnix);   \n```\n\nOutput del programa:\n\n```\n    // Hayes modem used with Dos configurator.\n    // Zoom modem used with Dos configurator.\n    // Only HayesVisitor is allowed to visit Hayes modem\n    // Zoom modem used with Unix configurator.\n```\n\n## Diagrama de clases\n\n![alt text](./etc/acyclic-visitor.png \"Acyclic Visitor\")\n\n## Aplicación\n\nEste patrón puede ser usado:\n\n* Cuando necesitas añadir una nueva función a una jerarquía de clases sin que esta se vea afectada o alterada.\n* Cuando hay funciones que operan sobre la jerarquía, pero no pertenecen a la jerarquía como tal. Las clases ConfigureForDOS / ConfigureForUnix / ConfigureForX por ejemplo.\n* Cuando necesitas ejecutar operaciones muy diferentes en un objeto dependiendo de su tipo.\n* Cuando la jerarquía visitada va a ser frecuentemente extendida con derivados de la clase elemento.\n* Cuando el proceso de volver a compilar, enlazar, probar o distribuir los derivados de la clase elemento es muy pesado.\n\n## Tutoriales\n\n* [Acyclic Visitor Pattern Example](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html)\n\n## Consecuencias\n\nBuenas:\n\n* No hay círculos de dependencias entre las jerarquías.\n* No es necesario compilar todos los visitantes si se añade uno nuevo.\n* No provoca errores de compilación en visitantes existentes si la jerarquía tiene un nuevo miembro.\n\nMalas:\n\n* Viola el [Principio de sustitución de Liskov](https://java-design-patterns.com/principles/#liskov-substitution-principle) al mostrar que puede aceptar todos los visitantes solamente estando interesado en uno en particular.\n* Hay que crear una jerarquía de visitantes paralela para todos los miembros de una jerarquía visitable.\n\n## Patrones relacionados\n\n* [Visitor Pattern](https://java-design-patterns.com/patterns/visitor/)\n\n## Créditos\n\n* [Acyclic Visitor by Robert C. Martin](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf)\n* [Acyclic Visitor in WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor)\n"
  },
  {
    "path": "localization/es/adapter/README.md",
    "content": "---\ntitle: Adapter\nshortTitle: Adapter\ncategory: Structural\nlanguage: es\ntag:\n - Gang of Four\n---\n\n## También conocido como\nWrapper\n\n## Propósito\nConvertir la interfaz de una clase en otra que espera el cliente. El patrón Adapter permite a clases funcionar en conjunto con otras clases con las que no podrían de otra forma por problemas de compatibilidad.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Imagina que tienes unas imágenes en una tarjeta de memoria y quieres transferirlas a tu ordenador. Para transferirlas necesitas algún tipo de adaptador compatible con los puertos de tu ordenador que te permita introducir tu tarjeta. En este caso el lector de tarjetas es un adaptador (adapter).\n> Otro ejemplo podría ser el famoso adaptador de corriente; un enchufe con tres patas no se puede conectar a una toma de corriente con dos agujeros, necesita un adaptador para hacerlo compatible con la toma de corriente.\n> Otro ejemplo más sería un traductor traduciendo palabras de una persona para otra.\n\nEn otras palabras\n\n> El patrón Adapter permite envolver un objeto en un adaptador para hacerlo compatible con una clase con la que sería incompatible de otra manera.\n\nSegún Wikipedia\n\n> En ingeniería de software el patrón Adapter es un patrón de diseño de software que permite usar la interfaz de una clase existente como otra interfaz diferente. A menudo es utilizado para hacer que clases existentes trabajen con otras clases sin necesidad de modificar su código fuente.\n\n**Ejemplo Programático**\n\nToma como ejemplo un capitán que solo puede usar botes de remo y no puede navegar en absoluto.\n\nPrimero tenemos las interfaces `RowingBoat` (bote de remo) y `FishingBoat` (bote de pesca).\n\n```java\npublic interface RowingBoat {\n  void row();\n}\n\n@Slf4j\npublic class FishingBoat {\n  public void sail() {\n    LOGGER.info(\"The fishing boat is sailing\");\n  }\n}\n```\n\nY el capitán espera una implementación de la interfaz `RowingBoat` (bote de remo) para poder moverse.\n\n```java\npublic class Captain {\n\n  private final RowingBoat rowingBoat;\n  // default constructor and setter for rowingBoat\n  public Captain(RowingBoat rowingBoat) {\n    this.rowingBoat = rowingBoat;\n  }\n\n  public void row() {\n    rowingBoat.row();\n  }\n}\n```\n\nAhora supongamos que viene un grupo de piratas y nuestro capitán tiene que escapar, pero solo hay un bote de pesca. Necesitamos crear un adaptador que permita al capitán usar el bote de pesca con sus habilidades para usar botes de remo.\n\n```java\n@Slf4j\npublic class FishingBoatAdapter implements RowingBoat {\n\n  private final FishingBoat boat;\n\n  public FishingBoatAdapter() {\n    boat = new FishingBoat();\n  }\n\n  @Override\n  public void row() {\n    boat.sail();\n  }\n}\n```\n\nY ahora el `Captain` (capitán) puede usar el `FishingBoat` (bote de pesca) para escapar de los piratas.\n\n```java\nvar captain = new Captain(new FishingBoatAdapter());\ncaptain.row();\n```\n\n## Diagrama de clases\n![alt text](./etc/adapter.urm.png \"Adapter class diagram\")\n\n## Aplicación\nUsa el patrón Adapter cuando\n\n* Quieres usar una clase existente y su interfaz no coincide con la que necesitas.\n* Quieres crear una clase reutilizable que coopere con clases que no están relacionadas o con las que su cooperación no estaba planeada, esto es, clases que no necesariamente tienen interfaces compatibles.\n* Necesitas usar varias subclases existentes, pero no es práctico adaptar su interfaz creando subclases para todas. Un adaptador puede adaptar la interfaz de la clase padre.\n* Muchas aplicaciones que usan librerías de terceros usan adaptadores como capas intermedias entre la aplicación y la librería para desacoplar la aplicación de la librería. Si es necesario usar otra librería solo hace falta crear un adaptador para la nueva librería sin necesidad de modificar el código de la aplicación.\n\n## Tutoriales\n\n* [Dzone](https://dzone.com/articles/adapter-design-pattern-in-java)\n* [Refactoring Guru](https://refactoring.guru/design-patterns/adapter/java/example)\n* [Baeldung](https://www.baeldung.com/java-adapter-pattern)\n\n## Consecuencias\nLos adaptadores de clases y objetos tienen distintas cualidades. Un adaptador de clases\n\n*\tHace la adaptación quedando enlazado a una clase adaptada concreta. Como consecuencia un adaptador de clases no funcionará cuando queramos adaptar una clase y sus subclases.\n*\tPermite al adaptador modificar el comportamiento de la clase adaptada porque el adaptador es una subclase de la clase adaptada.\n*\tUsa un solo objeto y no es necesario usar punteros adicionales para referenciar la clase adaptada.\n\nUn adaptador de objetos\n\n*\tPermite a un solo adaptador trabajar con varias clases, esto es, con la clase adaptada y todas sus subclases (si tiene alguna). El adaptador también puede añadir funcionalidad a todas las clases adaptadas a la vez.\n*\tHace más complicado modificar el comportamiento de la clase adaptada. Sería necesario hacer una subclase de la clase a adaptar y hacer que el adaptador referencie la subclase en lugar de la clase a adaptar.\n\n\n## Ejemplos del mundo real\n\n* [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)\n* [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)\n* [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-)\n* [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-)\n\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/es/aggregator-microservices/README.md",
    "content": "---\ntitle: Aggregator Microservices\nshortTitle: Aggregator Microservices\ncategory: Architectural\nlanguage: es\ntag:\n- Cloud distributed\n- Decoupling\n- Microservices\n---\n\n## Propósito\n\nEl usuario realiza una sola llamada al servicio del agregador y, a continuación, el agregador llama a cada microservicio relevante.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Nuestro mercado web necesita información sobre los productos y su inventario actual. Hace una llamada a un agregador\n> servicio que a su vez llama al microservicio de información del producto y al microservicio de inventario del producto que devuelve la\n> información combinada.\n\nEn palabras sencillas\n\n> Aggregator Microservice recopila datos de varios microservicios y devuelve un agregado para su procesamiento.\n\nStackOverflow dice\n\n> Aggregator Microservice invoca múltiples servicios para lograr la funcionalidad requerida por la aplicación.\n\n**Ejemplo programático**\n\nEmpecemos por el modelo de datos. Aquí está nuestro `Product`.\n\n```java\npublic class Product {\n  private String title;\n  private int productInventories;\n  // getters and setters ->\n  ...\n}\n```\n\nA continuación, podemos presentar nuestro microservicio `Aggregator` (Agregador de microservicios). Contiene él `ProductInformationClient` (Información del producto del cliente) y él\n`ProductInventoryClient` (Inventario del producto del cliente) de los clientes para llamar a los respectivos microservicios.\n\n```java\n@RestController\npublic class Aggregator {\n\n  @Resource\n  private ProductInformationClient informationClient;\n\n  @Resource\n  private ProductInventoryClient inventoryClient;\n\n  @RequestMapping(path = \"/product\", method = RequestMethod.GET)\n  public Product getProduct() {\n\n    var product = new Product();\n    var productTitle = informationClient.getProductTitle();\n    var productInventory = inventoryClient.getProductInventories();\n\n    //Fallback to error message\n    product.setTitle(requireNonNullElse(productTitle, \"Error: Fetching Product Title Failed\"));\n\n    //Fallback to default error inventory\n    product.setProductInventories(requireNonNullElse(productInventory, -1));\n\n    return product;\n  }\n}\n```\n\nEsta es la esencia de la implementación de microservicios de información. El microservicio de inventario es similar, simplemente regresa\nrecuentos de inventario.\n\n```java\n@RestController\npublic class InformationController {\n  @RequestMapping(value = \"/information\", method = RequestMethod.GET)\n  public String getProductTitle() {\n    return \"The Product Title.\";\n  }\n}\n```\n\nAhora llamando a nuestra REST API `Aggregator` devuelve la información del producto.\n\n```bash\ncurl http://localhost:50004/product\n{\"title\":\"The Product Title.\",\"productInventories\":5}\n```\n\n## Diagrama de clase\n\n![alt text](./aggregator-service/etc/aggregator-service.png \"Aggregator Microservice\")\n\n## Aplicabilidad\n\nUtilice el patrón Agregador de microservicios (Aggregator Microservices) cuando necesite una API unificada para varios microservicios, independientemente del dispositivo cliente.\n\n## Créditos\n\n* [Patrones de diseño de microservicios] (http://web.archive.org/web/20190705163602/http://blog.arungupta.me/microservice-design-patterns/)\n* [Patrones de microservicios: Con ejemplos en Java](https://www.amazon.com/gp/product/1617294543/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617294543&linkId=8b4e570267bc5fb8b8189917b461dc60)\n* [Patrones de arquitectura: Descubra patrones esenciales en el ámbito más indispensable de la arquitectura empresarial](https://www.amazon.com/gp/product/B077T7V8RC/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=B077T7V8RC&linkId=c34d204bfe1b277914b420189f09c1a4)\n"
  },
  {
    "path": "localization/es/ambassador/README.md",
    "content": "---\ntitle: Ambassador\nshortTitle: Ambassador\ncategory: Structural\nlanguage: es\ntag:\n  - Decoupling\n  - Cloud distributed\n---\n\n## Propósito\n\nProporcionar una instancia de servicio auxiliar a un cliente y delegar en ella las funcionalidades comunes de un recurso compartido.\n\n## Explicación\n\nEjemplo real\n\n> Un servicio remoto tiene muchos clientes accediendo a una función que este servicio proporciona. El servicio es una aplicación heredada y\n> es imposible actualizarla. Un gran número de solicitudes por parte de los usuarios están causando problemas de conectividad. Nuevas reglas\n> respecto a la frecuencia de solicitudes deberían implementarse junto con comprobaciones de latencia y registros del lado del cliente.\n\nEn otras palabras\n\n> Con el patrón Ambassador, podemos implementar una menor frecuencia en solicitudes de clientes junto con comprobaciones de latencia y\n> registros.\n\nSegún la Documentación de Microsoft\n\n> Un servicio de Ambassador puede considerarse como un proxy fuera de proceso que coexiste con el cliente.\n>\n> Este patrón puede ser útil para la descarga de tareas comunes de conectividad de cliente, como la supervisión, el registro, el enrutamiento,\n> la seguridad (por ejemplo, TLS) y los patrones de resistencia(*) de una manera independiente del lenguaje. A menudo se utiliza con aplicaciones heredadas,\n> u otras aplicaciones que son difíciles de modificar, con el fin de ampliar sus capacidades de red. También puede\n> habilitar un equipo especializado para implementar esas características.\n\n**Código de ejemplo**\n\nCon la introducción anterior en mente vamos a imitar su funcionalidad en el siguiente ejemplo. Tenemos una interface implementada\npor el servicio remoto así como el servicio ambassador:\n\n```java\ninterface RemoteServiceInterface {\n    long doRemoteFunction(int value) throws Exception;\n}\n```\n\nUn servicio remoto representado como un singleton (Instancia única).\n\n```java\n@Slf4j\npublic class RemoteService implements RemoteServiceInterface {\n    private static RemoteService service = null;\n\n    static synchronized RemoteService getRemoteService() {\n        if (service == null) {\n            service = new RemoteService();\n        }\n        return service;\n    }\n\n    private RemoteService() {}\n\n    @Override\n    public long doRemoteFunction(int value) {\n        long waitTime = (long) Math.floor(Math.random() * 1000);\n\n        try {\n            sleep(waitTime);\n        } catch (InterruptedException e) {\n            LOGGER.error(\"Thread sleep interrupted\", e);\n        }\n\n        return waitTime >= 200 ? value * 10 : -1;\n    }\n}\n```\n\nUn servicio ambassador añadiendo funcionalidades adicionales como registros, comprobación de latencia\n\n```java\n@Slf4j\npublic class ServiceAmbassador implements RemoteServiceInterface {\n  private static final int RETRIES = 3;\n  private static final int DELAY_MS = 3000;\n\n  ServiceAmbassador() {\n  }\n\n  @Override\n  public long doRemoteFunction(int value) {\n    return safeCall(value);\n  }\n\n  private long checkLatency(int value) {\n    var startTime = System.currentTimeMillis();\n    var result = RemoteService.getRemoteService().doRemoteFunction(value);\n    var timeTaken = System.currentTimeMillis() - startTime;\n\n    LOGGER.info(\"Time taken (ms): \" + timeTaken);\n    return result;\n  }\n\n  private long safeCall(int value) {\n    var retries = 0;\n    var result = (long) FAILURE;\n\n    for (int i = 0; i < RETRIES; i++) {\n      if (retries >= RETRIES) {\n        return FAILURE;\n      }\n\n      if ((result = checkLatency(value)) == FAILURE) {\n        LOGGER.info(\"Failed to reach remote: (\" + (i + 1) + \")\");\n        retries++;\n        try {\n          sleep(DELAY_MS);\n        } catch (InterruptedException e) {\n          LOGGER.error(\"Thread sleep state interrupted\", e);\n        }\n      } else {\n        break;\n      }\n    }\n    return result;\n  }\n}\n```\n\nUn cliente tiene un servicio ambassador local usado para interactuar con el servicio remoto:\n\n```java\n@Slf4j\npublic class Client {\n  private final ServiceAmbassador serviceAmbassador = new ServiceAmbassador();\n\n  long useService(int value) {\n    var result = serviceAmbassador.doRemoteFunction(value);\n    LOGGER.info(\"Service result: \" + result);\n    return result;\n  }\n}\n```\n\nA continuación dos clientes usando el servicio.\n\n```java\npublic class App {\n  public static void main(String[] args) {\n    var host1 = new Client();\n    var host2 = new Client();\n    host1.useService(12);\n    host2.useService(73);\n  }\n}\n```\n\nEsta es la salida que obtendremos tras ejecutar el ejemplo:\n\n```java\nTime taken (ms): 111\nService result: 120\nTime taken (ms): 931\nFailed to reach remote: (1)\nTime taken (ms): 665\nFailed to reach remote: (2)\nTime taken (ms): 538\nFailed to reach remote: (3)\nService result: -1\n```\n\n## Diagrama de clase\n\n![alt text](./etc/ambassador.urm.png \"Ambassador class diagram\")\n\n## Aplicaciones\n\nAmbassador es aplicable cuando trabajamos con un servicio remoto heredado que no puede ser modificado o que sería extremamente\ndifícil de modificar. Las características de conectividad pueden implementarse en el cliente sin necesidad de realizar cambios en el servicio\nremoto.\n\n* Ambassador proporciona una interface local para un servicio remoto.\n* Ambassador proporciona registros, interrupción de circuitos, reintentos y seguridad en el cliente.\n\n## Casos de uso típicos\n\n* Control de acceso a otro objeto\n* Implementación de registros o logs\n* Implementación de interrupciones de circuito\n* Delegar tareas de servicios remotos\n* Facilitar la conexión a la red\n\n## Usos conocidos\n\n* [Pasarela API Kubernetes-native para microservicios](https://github.com/datawire/ambassador)\n\n## Patrones relacionados\n\n* [Proxy](https://java-design-patterns.com/patterns/proxy/)\n\n## Créditos\n\n* [Ambassador Pattern (Documentación de Microsoft en inglés)](https://docs.microsoft.com/en-us/azure/architecture/patterns/ambassador)\n* [Designing Distributed Systems: Patterns and Paradigms for Scalable, Reliable Services](https://www.amazon.com/s?k=designing+distributed+systems&sprefix=designing+distri%2Caps%2C156&linkCode=ll2&tag=javadesignpat-20&linkId=a12581e625462f9038557b01794e5341&language=en_US&ref_=as_li_ss_tl)\n\n## Notas del traductor\n(*) La versión original en inglés de la documentación de Microsoft hace referencia al término resiliencia y\nen su traducción al español lo traduce como resistencia, aunque enlaza al apartado patrones de confiabilidad. Véase:\n* [Versión de la Documentación para el Patrón Ambassador de Microsoft en español.](https://learn.microsoft.com/es-es/azure/architecture/patterns/ambassador)\n"
  },
  {
    "path": "localization/es/api-gateway/README.md",
    "content": "---\ntitle: API Gateway\nshortTitle: API Gateway\ncategory: Architectural\nlanguage: es\ntag:\n  - Cloud distributed\n  - Decoupling\n  - Microservices\n---\n\n## Propósito\n\nAgregar llamadas a los microservicios en un mismo lugar, la puerta de enlace API (API Gateway). El usuario \nhace una llamada simple a la API Gateway, y la API Gateway hace la llamada a cada microservicio relevante.\n\n## Explicación\n\nCon el patrón de microservicios, el cliente puede necesitar datos de múltiples microservicios. Si el \ncliente llamara a cada microservicio de forma directe, podría ocasionar tiempos de carga largos, ya que\nel cliente tendría que hacer una solicitud de red para cada microservicio llamado. Además, tener\nla llamada del cliente a cada microservicio vincula directamente al cliente con ese microservicio - si la\nimplementacion interna del cambio de microservicios (por ejemplo, si dos microservicios se combinan en \nalgún momento en el futuro) o si la ubicación (host y puerto) de un microservicio cambia, entonces cada \ncliente que hace uso de esos microservicios debe ser actualizado.\n\nLa intención del patrón API Gateway es aliviar algunos de estos problemas. En el patrón API Gateway, \nse coloca una entidad adicional (la API Gateway) entre el cliente y los microservicios.\nEl trabajo de API Gateway es agregar las llamadas a los microservicios. En lugar de que el cliente\nllame a cada microservicio individualmente, el cliente llama a la API Gateway una sola vez. La API\nGateway luego llama a cada uno de los microservicios que necesita el cliente.\n\nEjemplo real\n\n> Estamos implementando un sistema de microservicios y API Gateway para un sitio e-commerce. En este\n> sistema API Gateway realiza llamadas a los microservicios Image y Price. (Imagen y Precio)\n\nEn otras palabras\n\n> Para un sistema implementado utilizando una arquitectura de microservicios, API Gateway es el único\n> punto de entrada que agrega las llamadas a los microservicios individuales.\n\nWikipedia dice\n\n> API Gateway es un servidor que actúa como un front-end de API, recibe solicitudes de API, aplica la \n> limitación y políticas de seguridad, pasa las solicitudes al servicio back-end y luego devuelve la \n> respuesta al solicitante. Una puerta de enlace a menudo incluye un motor de transformación para \n> orquestar y modificar las solicitudes y respuestas sobre la marcha. Una puerta de enlace también \n> puede proporcionar funciones como recopilar análisis de datos y almacenamiento en caché. La puerta \n> de enlace puede proporcionar funcionalidad para soportar autenticación, autorización, seguridad, \n> auditoría y cumplimiento normativo.\n\n**Código de ejemplo**\n\nEsta implementación muestra cómo podría verse el patrón API Gateway para un sitio de e-commerce. El\n`ApiGateway` hace llamadas a los microservicios Image y Price usando `ImageClientImpl` y`PriceClientImpl` \nrespectivamente. Los clientes que ven el sitio en un dispositivo de escritorio pueden ver la información\nde precio y una imagen de un producto, entonces `ApiGateway` llama a los microservicios y\nagrega los datos en el modelo `DesktopProduct`. Sin embargo, los usuarios de dispositivos móviles solo \nven información de precios, no ven una imagen del producto. Para usuarios móviles, `ApiGateway` solo \nrecupera el precio información, que utiliza para completar el `MobileProduct`.\n\nAquí está la implementación del microservicio de imagen (Image).\n\n```java\npublic interface ImageClient {\n  String getImagePath();\n}\n\npublic class ImageClientImpl implements ImageClient {\n  @Override\n  public String getImagePath() {\n    var httpClient = HttpClient.newHttpClient();\n    var httpGet = HttpRequest.newBuilder()\n        .GET()\n        .uri(URI.create(\"http://localhost:50005/image-path\"))\n        .build();\n\n    try {\n      var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n      return httpResponse.body();\n    } catch (IOException | InterruptedException e) {\n      e.printStackTrace();\n    }\n\n    return null;\n  }\n}\n```\n\nAquí está la implementación del microservicio de precio (Price).\n\n```java\npublic interface PriceClient {\n  String getPrice();\n}\n\npublic class PriceClientImpl implements PriceClient {\n\n  @Override\n  public String getPrice() {\n    var httpClient = HttpClient.newHttpClient();\n    var httpGet = HttpRequest.newBuilder()\n        .GET()\n        .uri(URI.create(\"http://localhost:50006/price\"))\n        .build();\n\n    try {\n      var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n      return httpResponse.body();\n    } catch (IOException | InterruptedException e) {\n      e.printStackTrace();\n    }\n\n    return null;\n  }\n}\n```\n\nAquí podemos ver cómo API Gateway asigna las solicitudes a los microservicios.\n\n```java\npublic class ApiGateway {\n\n  @Resource\n  private ImageClient imageClient;\n\n  @Resource\n  private PriceClient priceClient;\n\n  @RequestMapping(path = \"/desktop\", method = RequestMethod.GET)\n  public DesktopProduct getProductDesktop() {\n    var desktopProduct = new DesktopProduct();\n    desktopProduct.setImagePath(imageClient.getImagePath());\n    desktopProduct.setPrice(priceClient.getPrice());\n    return desktopProduct;\n  }\n\n  @RequestMapping(path = \"/mobile\", method = RequestMethod.GET)\n  public MobileProduct getProductMobile() {\n    var mobileProduct = new MobileProduct();\n    mobileProduct.setPrice(priceClient.getPrice());\n    return mobileProduct;\n  }\n}\n```\n\n## Diagrama de clase\n\n![alt text](./etc/api-gateway.png \"API Gateway\")\n\n## Aplicaciones\n\nUsa el patrón de API Gateway cuando\n\n* Estás usando una arquitectura de microservicios y necesites un único punto de agregación para las llamadas de microservicios.\n\n## Tutoriales\n\n* [Exploring the New Spring Cloud Gateway](https://www.baeldung.com/spring-cloud-gateway)\n* [Spring Cloud - Gateway](https://www.tutorialspoint.com/spring_cloud/spring_cloud_gateway.htm)\n* [Getting Started With Spring Cloud Gateway](https://dzone.com/articles/getting-started-with-spring-cloud-gateway)\n\n## Créditos\n\n* [microservices.io - API Gateway](http://microservices.io/patterns/apigateway.html)\n* [NGINX - Building Microservices: Using an API Gateway](https://www.nginx.com/blog/building-microservices-using-an-api-gateway/)\n* [Microservices Patterns: With examples in Java](https://www.amazon.com/gp/product/1617294543/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617294543&linkId=ac7b6a57f866ac006a309d9086e8cfbd)\n* [Building Microservices: Designing Fine-Grained Systems](https://www.amazon.com/gp/product/1491950358/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1491950358&linkId=4c95ca9831e05e3f0dadb08841d77bf1)\n"
  },
  {
    "path": "localization/es/arrange-act-assert/README.md",
    "content": "---\ntitle: Arrange/Act/Assert\nshortTitle: Arrange/Act/Assert\ncategory: Idiom\nlanguage: es\ntag:\n - Testing\n---\n\n## También conocido como\n\nDado/Cuando/Entonces\n\n## Propósito\n\nArrange/Act/Assert (AAA) es un patrón para organizar UnitTests.\nDivide las UnitTests en tres pasos claros y diferenciados:\n\n1. Arrange(Organizar): Realiza la configuración y la inicialización necesarias para el test.\n2. Act(Actuar): Toma las medidas necesarias para el test.\n3. Assert(Afirmar): Verifica los resultados del test.\n\n## Explicación\n\nEste patrón tiene varios beneficios significativos. Crea una clara separación entre la configuración, operaciones y resultados de un test. Esta estructura hace que el código sea más fácil de leer y comprender. Si\ncolocas los pasos en orden y formateas su código para separarlos, puedes escanear un test y\ncomprender rápidamente lo que hace.\n\nTambién impone un cierto grado de disciplina cuando escribes tus UnitTests. Tienes que visualizar\nclaramente los tres pasos que tu test realizará. Esto hace que los tests sean más intuitivos de escribir a la vez que tienes presente un esquema.\n\nEjemplo cotidiano\n\n> Necesitamos escribir un conjunto de UnitTests completo y claro para una clase.\n\nEn otras palabras\n\n> Arrange/Act/Assert es un patrón de testeo que organiza las pruebas en tres pasos claros para facilitar su\n> mantenimiento.\n\nWikiWikiWeb dice\n\n> Arrange/Act/Assert es un patrón para organizar y dar formato al código en los métodos UnitTest.\n\n**Código de ejemplo**\n\nVeamos primero nuestra clase `Cash` para que sea testeada.\n\n```java\npublic class Cash {\n\n  private int amount;\n\n  Cash(int amount) {\n    this.amount = amount;\n  }\n\n  void plus(int addend) {\n    amount += addend;\n  }\n\n  boolean minus(int subtrahend) {\n    if (amount >= subtrahend) {\n      amount -= subtrahend;\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  int count() {\n    return amount;\n  }\n}\n```\n\nLuego escribimos nuestras UnitTests en función del patrón Arrange/Act/Assert. Note claramente la separación de los pasos para cada UnitTest.\n\n```java\nclass CashAAATest {\n\n  @Test\n  void testPlus() {\n    //Arrange\n    var cash = new Cash(3);\n    //Act\n    cash.plus(4);\n    //Assert\n    assertEquals(7, cash.count());\n  }\n\n  @Test\n  void testMinus() {\n    //Arrange\n    var cash = new Cash(8);\n    //Act\n    var result = cash.minus(5);\n    //Assert\n    assertTrue(result);\n    assertEquals(3, cash.count());\n  }\n\n  @Test\n  void testInsufficientMinus() {\n    //Arrange\n    var cash = new Cash(1);\n    //Act\n    var result = cash.minus(6);\n    //Assert\n    assertFalse(result);\n    assertEquals(1, cash.count());\n  }\n\n  @Test\n  void testUpdate() {\n    //Arrange\n    var cash = new Cash(5);\n    //Act\n    cash.plus(6);\n    var result = cash.minus(3);\n    //Assert\n    assertTrue(result);\n    assertEquals(8, cash.count());\n  }\n}\n```\n\n## Aplicabilidad\n\nUtilice el patrón Arrange/Act/Assert cuando\n\n* Necesitas estructurar tus UnitTests para que sean más fáciles de leer, mantener y mejorar.\n\n## Créditos\n\n* [Arrange, Act, Assert: ¿Qué son las pruebas AAA?](https://blog.ncrunch.net/post/arrange-act-assert-aaa-testing.aspx)\n* [Bill Wake: 3A – Arrange, Act, Assert](https://xp123.com/articles/3a-arrange-act-assert/)\n* [Martin Fowler: DadoCuandoEntonces](https://martinfowler.com/bliki/GivenWhenThen.html)\n* [Patrones de prueba xUnit: Refactorizando Código de prueba](https://www.amazon.com/gp/product/0131495054/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0131495054&linkId=99701e8f4af2f63d0bcf50)\n* [Principios, prácticas y patrones UnitTesting](https://www.amazon.com/gp/product/1617296279/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617296279&linkId=74c75cfae3a5aaccae3a5a)\n* [Desarrollo basado en pruebas: Ejemplo](https://www.amazon.com/gp/product/0321146530/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0321146530&linkId=5c63a93d8c1175b47caef50875)\n"
  },
  {
    "path": "localization/es/async-method-invocation/README.md",
    "content": "---\ntitle: Async Method Invocation\nshortTitle: Async Method Invocation\ncategory: Concurrency\nlanguage: es\ntag:\n - Reactive\n---\n\n## Propósito\n\nAsynchronous method invocation (invocación de método asincrónico) es un patrón con el que el hilo o subproceso de llamada\nno se bloquea mientras espera resultados. El patrón proporciona procesamiento en paralelo de múltiples tareas independientes y recupera los resultados a través de\ndevoluciones de llamada (callbacks) o esperando hasta que termine el procedimiento.\n\n## Explicación\n\nEjemplo cotidiano\n\n> Lanzar cohetes espaciales es un negocio apasionante. El comandante de la misión da la orden de lanzamiento y\n> después de un tiempo indeterminado, el cohete se lanza con éxito o falla miserablemente.\n\nEn otras palabras\n\n> La invocación del método asíncrono inicia el procedimiento y vuelve inmediatamente antes de que la tarea termine\n> Los resultados del procedimiento se devuelven a la llamada posteriormente (callback).\n\nSegún Wikipedia\n\n> En la programación multiproceso, la invocación de método asíncrono (AMI), también conocida como\n> llamadas de método asíncrono o el patrón asíncrono es un patrón de diseño en el que el lugar de la llamada\n> no se bloquea mientras espera que termine el código llamado. En cambio, el hilo de llamada es\n> notificado cuando llega la respuesta. Sondear para obtener una respuesta es una opción no deseada.\n\n**Ejemplo programático**\n\nEn este ejemplo, estamos lanzando cohetes espaciales y desplegando vehículos lunares.\n\nLa aplicación demuestra lo que hace el patrón de invocación del método asíncrono. Las partes clave del patrón son\n`AsyncResult` que es un contenedor intermedio para un valor evaluado de forma asíncrona,\n`AsyncCallback` que se puede proporcionar para que se ejecute al finalizar la tarea y `AsyncExecutor` que\ngestiona la ejecución de las tareas asíncronas.\n\n```java\npublic interface AsyncResult<T> {\n  boolean isCompleted();\n  T getValue() throws ExecutionException;\n  void await() throws InterruptedException;\n}\n```\n\n```java\npublic interface AsyncCallback<T> {\n  void onComplete(T value, Optional<Exception> ex);\n}\n```\n\n```java\npublic interface AsyncExecutor {\n  <T> AsyncResult<T> startProcess(Callable<T> task);\n  <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback);\n  <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException;\n}\n```\n\n`ThreadAsyncExecutor` es una implementación de `AsyncExecutor`. Se destacan algunas de sus partes clave a continuación.\n\n```java\npublic class ThreadAsyncExecutor implements AsyncExecutor {\n\n  @Override\n  public <T> AsyncResult<T> startProcess(Callable<T> task) {\n    return startProcess(task, null);\n  }\n\n  @Override\n  public <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback) {\n    var result = new CompletableResult<>(callback);\n    new Thread(\n            () -> {\n              try {\n                result.setValue(task.call());\n              } catch (Exception ex) {\n                result.setException(ex);\n              }\n            },\n            \"executor-\" + idx.incrementAndGet())\n        .start();\n    return result;\n  }\n\n  @Override\n  public <T> T endProcess(AsyncResult<T> asyncResult)\n      throws ExecutionException, InterruptedException {\n    if (!asyncResult.isCompleted()) {\n      asyncResult.await();\n    }\n    return asyncResult.getValue();\n  }\n}\n```\n\nAhora está todo preparado para lanzar algunos cohetes y así poder ver cómo funciona todo.\n\n```java\npublic static void main(String[] args) throws Exception {\n  // construye un nuevo objeto executor que ejecutará tareas asíncronas\n  var executor = new ThreadAsyncExecutor();\n\n  // inicia algunas tareas asíncronas con diferentes tiempos de procesamiento, las dos últimas con controladores de devolución de llamada\n  final var asyncResult1 = executor.startProcess(lazyval(10, 500));\n  final var asyncResult2 = executor.startProcess(lazyval(\"test\", 300));\n  final var asyncResult3 = executor.startProcess(lazyval(50L, 700));\n  final var asyncResult4 = executor.startProcess(lazyval(20, 400), callback(\"Desplegando el rover lunar\"));\n  final var asyncResult5 =\n      executor.startProcess(lazyval(\"devolución de llamada callback\", 600), callback(\"Desplegando el rover lunar\"));\n\n  // emula el procesamiento en el hilo o subproceso actual mientras las tareas asíncronas se ejecutan en sus propios hilos o subprocesos\n  Subproceso.dormir(350); // Oye, estamos trabajando duro aquí\n  log(\"El comandante de la misión está bebiendo café\");\n\n  // espera a que se completen las tareas\n  final var result1 = executor.endProcess(asyncResult1);\n  final var result2 = executor.endProcess(asyncResult2);\n  final var result3 = executor.endProcess(asyncResult3);\n  asyncResult4.await();\n  asyncResult5.await();\n\n  // registra los resultados de las tareas, las devoluciones de las llamadas se registran inmediatamente cuando se completan\n  log(\"Cohete espacial <\" + resultado1 + \"> ha completado su lanzamiento\");\n  log(\"Cohete espacial <\" + resultado2 + \"> ha completado su lanzamiento\");\n  log(\"Cohete espacial <\" + result3 + \"> ha completado su lanzamiento\");\n}\n```\n\nAquí está la salida de la consola del programa.\n\n```java\n21:47:08.227 [executor-2] INFO com.iluwatar.async.method.invocation.App - Cohete espacial <prueba> lanzado con éxito\n21:47:08.269 [main] INFO com.iluwatar.async.method.invocation.App - El comandante de la misión está bebiendo café\n21:47:08.318 [executor-4] INFO com.iluwatar.async.method.invocation.App - Cohete espacial <20> lanzado con éxito\n21:47:08.335 [executor-4] INFO com.iluwatar.async.method.invocation.App Desplegando el rover lunar <20>\n21:47:08.414 [executor-1] INFO com.iluwatar.async.method.invocation.App  - Cohete espacial <10> lanzado con éxito\n21:47:08.519 [executor-5] INFO com.iluwatar.async.method.invocation.App - Cohete espacial <devolución de llamada callback> lanzado con éxito\n21:47:08.519 [executor-5] INFO com.iluwatar.async.method.invocation.App - Implementando el vehículo lunar <devolución de llamada callback>\n21:47:08.616 [executor-3] INFO com.iluwatar.async.method.invocation.App - Cohete espacial <50> lanzado con éxito\n21:47:08.617 [main] INFO com.iluwatar.async.method.invocation.App - Lanzamiento del cohete espacial <10> completado\n21:47:08.617 [main] INFO com.iluwatar.async.method.invocation.App - Lanzamiento de cohete espacial <prueba> completado\n21:47:08.618 [main] INFO com.iluwatar.async.method.invocation.App - Lanzamiento del cohete espacial <50> completado\n```\n\n# Diagrama de clase\n\n![texto alternativo](./etc/async-method-invocation.png \"Invocación de método asíncrono\")\n\n## Aplicabilidad\n\nUtiliza el patrón de invocación del método asíncrono cuando\n\n* Tienes múltiples tareas independientes que pueden ejecutarse en paralelo\n* Necesitas mejorar el desempeño de un grupo de tareas secuenciales\n* Tienes una cantidad limitada de capacidad de procesamiento o tareas de ejecución prolongada y la llamada no debe esperar a que las tareas estén listas\n\n## Ejemplos cotidianos\n\n* [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html)\n* [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)\n* [ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html)\n* [Patrón asíncrono basado en tareas](https://msdn.microsoft.com/en-us/library/hh873175.aspx)"
  },
  {
    "path": "localization/es/balking/README.md",
    "content": "---\ntitle: Balking\nshortTitle: Balking\ncategory: Concurrency\nlanguage: es\ntag:\n - Decoupling\n---\n\n## Propósito\n\nEl patrón _Balking_ se utiliza para prevenir que un objeto ejecute un código determinado si\neste se encuentra en un estado incompleto o inapropiado.\n\n## Explicación\n\nEjemplo del mundo real\n\n> En una lavadora hay un botón de arranque para iniciar el lavado de ropa. Cuando la lavadora\n> está inactiva el botón funciona como se espera, pero si ya está lavando entonces el botón no hace\n> nada.\n\nEn otras palabras\n\n> Usando el patrón _Balking_, un código determinado se ejecuta solo si el objeto está en un estado concreto.\n\nWikipedia dice\n\n> El patrón _Balking_ es un patrón de diseño de software que ejecuta una acción en un objeto solamente cuando\n> el objeto está en un estado concreto. Por ejemplo, si un objeto lee archivos ZIP y un método de llamada\n> invoca un método _get_ en el objeto cuando el archivo ZIP no está abierto, el objeto \"rechazaría\" (_balk_)\n> la petición.\n\n**Ejemplo Programático**\n\nEn este ejemplo de implementación, `WashingMachine` es un objeto que tiene dos estados los cuales pueden\nser: _ENABLED_ y _WASHING_ (ACTIVADA y LAVANDO respectivamente). Si la máquina está _ENABLED_, el estado\ncambia a _WASHING_ usando un método thread-safe a prueba de hilos. Por otra parte, si ya está lavando y\ncualquier otro hilo ejecuta `wash()` entonces no hará ningún cambio de estado y finalizará la ejecución del\nmétodo sin hacer nada.\n\nAquí están las partes relevantes de la clase `WashingMachine`.\n\n```java\n@Slf4j\npublic class WashingMachine {\n\n    private final DelayProvider delayProvider;\n    private WashingMachineState washingMachineState;\n\n    public WashingMachine(DelayProvider delayProvider) {\n        this.delayProvider = delayProvider;\n        this.washingMachineState = WashingMachineState.ENABLED;\n    }\n\n    public WashingMachineState getWashingMachineState() {\n        return washingMachineState;\n    }\n    \n    public void wash() {\n        synchronized (this) {\n            var machineState = getWashingMachineState();\n            LOGGER.info(\"{}: Actual machine state: {}\", Thread.currentThread().getName(), machineState);\n            if (this.washingMachineState == WashingMachineState.WASHING) {\n                LOGGER.error(\"Cannot wash if the machine has been already washing!\");\n                return;\n            }\n            this.washingMachineState = WashingMachineState.WASHING;\n        }\n        LOGGER.info(\"{}: Doing the washing\", Thread.currentThread().getName());\n        this.delayProvider.executeAfterDelay(50, TimeUnit.MILLISECONDS, this::endOfWashing);\n    }\n    \n    public synchronized void endOfWashing() {\n        washingMachineState = WashingMachineState.ENABLED;\n        LOGGER.info(\"{}: Washing completed.\", Thread.currentThread().getId());\n    }\n}\n```\n\nAquí la sencilla interfaz `DelayProvider` utilizada por `WashingMachine`.\n\n```java\npublic interface DelayProvider {\n    void executeAfterDelay(long interval, TimeUnit timeUnit, Runnable task);\n}\n```\n\nAhora introducimos la aplicación utilizando `WashingMachine`.\n\n```java\npublic static void main(String... args) {\n    final var washingMachine = new WashingMachine();\n    var executorService = Executors.newFixedThreadPool(3);\n    for (int i = 0; i < 3; i++) {\n        executorService.execute(washingMachine::wash);\n    }\n    executorService.shutdown();\n    try {\n        executorService.awaitTermination(10, TimeUnit.SECONDS);    \n    } catch (InterruptedException ie) {\n        LOGGER.error(\"ERROR: Waiting on executor service shutdown!\");\n        Thread.currentThread().interrupt();\n    }\n}\n```\n\nAquí está la salida en consola de la aplicación.\n\n```\n14:02:52.268 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Actual machine state: ENABLED\n14:02:52.272 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Doing the washing\n14:02:52.272 [pool-1-thread-3] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-3: Actual machine state: WASHING\n14:02:52.273 [pool-1-thread-3] ERROR com.iluwatar.balking.WashingMachine - Cannot wash if the machine has been already washing!\n14:02:52.273 [pool-1-thread-1] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-1: Actual machine state: WASHING\n14:02:52.273 [pool-1-thread-1] ERROR com.iluwatar.balking.WashingMachine - Cannot wash if the machine has been already washing!\n14:02:52.324 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - 14: Washing completed.\n```\n\n## Diagrama de clases\n\n![alt text](./etc/balking.png \"Balking\")\n\n## Aplicabilidad\n\nUsa el patrón _Balking_ cuando\n\n* Un objeto debe ejecutar un código determinado sólo cuando se encuentra en un estado concreto.\n* Los objetos están en un estado que es propenso a bloquearse temporalmente, pero durante una cantidad de tiempo indeterminada.\n\n## Patrones relacionados\n\n* [Guarded Suspension Pattern](https://java-design-patterns.com/patterns/guarded-suspension/)\n* [Double Checked Locking Pattern](https://java-design-patterns.com/patterns/double-checked-locking/)\n\n## Referencias\n\n* [Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML, 2nd Edition, Volume 1](https://www.amazon.com/gp/product/0471227293/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0471227293&linkId=0e39a59ffaab93fb476036fecb637b99)\n"
  },
  {
    "path": "localization/es/bridge/README.md",
    "content": "---\ntitle: Bridge\nshortTitle: Bridge\ncategory: Structural\nlanguage: es\ntag:\n  - Gang of Four\n---\n\n## También conocido como\n\nHandle/Body\n\n## Intención\n\nDesacoplar una abstracción de su implementación para que ambas puedan variar de forma independiente.\n\n## Explicación\n\nReal-world example\n\n> Imagina que tienes un arma con diferentes encantamientos, y se supone que debes permitir la mezcla de diferentes armas\n> con diferentes encantamientos. ¿Qué harías? ¿Crearías múltiples copias de cada una de las armas para cada uno de los\n> encantamientos o simplemente crearías un encantamiento separado y lo establecerías para el arma según sea necesario?\n> El\n> patrón Bridge te permite hacer lo segundo.\n\nEn palabras sencillas\n\n> El patrón Bridge se trata de preferir la composición sobre la herencia. Los detalles de implementación se empujan de\n> una jerarquía a otro objeto con una jerarquía separada.\n\nWikipedia dice\n\n> El patrón bridge es un patrón de diseño utilizado en ingeniería de software que tiene como objetivo \"desacoplar una\n> abstracción de su implementación para que las dos puedan variar independientemente\"\n\n**Ejemplo programático**\n\nTransladando nuestro ejemplo de arma de arriba. Aquí tenemos la interfaz arma `Weapon`:\n\n```java\npublic interface Weapon {\n  void wield();\n  void swing();\n  void unwield();\n  Enchantment getEnchantment();\n}\n\npublic class Sword implements Weapon {\n\n  private final Enchantment enchantment;\n\n  public Sword(Enchantment enchantment) {\n    this.enchantment = enchantment;\n  }\n\n  @Override\n  public void wield() {\n    LOGGER.info(\"The sword is wielded.\");\n    enchantment.onActivate();\n  }\n\n  @Override\n  public void swing() {\n    LOGGER.info(\"The sword is swinged.\");\n    enchantment.apply();\n  }\n\n  @Override\n  public void unwield() {\n    LOGGER.info(\"The sword is unwielded.\");\n    enchantment.onDeactivate();\n  }\n\n  @Override\n  public Enchantment getEnchantment() {\n    return enchantment;\n  }\n}\n\npublic class Hammer implements Weapon {\n\n  private final Enchantment enchantment;\n\n  public Hammer(Enchantment enchantment) {\n    this.enchantment = enchantment;\n  }\n\n  @Override\n  public void wield() {\n    LOGGER.info(\"The hammer is wielded.\");\n    enchantment.onActivate();\n  }\n\n  @Override\n  public void swing() {\n    LOGGER.info(\"The hammer is swinged.\");\n    enchantment.apply();\n  }\n\n  @Override\n  public void unwield() {\n    LOGGER.info(\"The hammer is unwielded.\");\n    enchantment.onDeactivate();\n  }\n\n  @Override\n  public Enchantment getEnchantment() {\n    return enchantment;\n  }\n}\n```\n\nAquí está la interfaz de encantamientos `Enchantment` separada:\n\n```java\npublic interface Enchantment {\n  void onActivate();\n  void apply();\n  void onDeactivate();\n}\n\npublic class FlyingEnchantment implements Enchantment {\n\n  @Override\n  public void onActivate() {\n    LOGGER.info(\"The item begins to glow faintly.\");\n  }\n\n  @Override\n  public void apply() {\n    LOGGER.info(\"The item flies and strikes the enemies finally returning to owner's hand.\");\n  }\n\n  @Override\n  public void onDeactivate() {\n    LOGGER.info(\"The item's glow fades.\");\n  }\n}\n\npublic class SoulEatingEnchantment implements Enchantment {\n\n  @Override\n  public void onActivate() {\n    LOGGER.info(\"The item spreads bloodlust.\");\n  }\n\n  @Override\n  public void apply() {\n    LOGGER.info(\"The item eats the soul of enemies.\");\n  }\n\n  @Override\n  public void onDeactivate() {\n    LOGGER.info(\"Bloodlust slowly disappears.\");\n  }\n}\n```\n\nAquí están ambas interfaces en acción:\n\n```java\nLOGGER.info(\"The knight receives an enchanted sword.\");\nvar enchantedSword = new Sword(new SoulEatingEnchantment());\nenchantedSword.wield();\nenchantedSword.swing();\nenchantedSword.unwield();\n\nLOGGER.info(\"The valkyrie receives an enchanted hammer.\");\nvar hammer = new Hammer(new FlyingEnchantment());\nhammer.wield();\nhammer.swing();\nhammer.unwield();\n```\n\nAquí está la salida en consola.\n\n```\nThe knight receives an enchanted sword.\nThe sword is wielded.\nThe item spreads bloodlust.\nThe sword is swung.\nThe item eats the soul of enemies.\nThe sword is unwielded.\nBloodlust slowly disappears.\nThe valkyrie receives an enchanted hammer.\nThe hammer is wielded.\nThe item begins to glow faintly.\nThe hammer is swung.\nThe item flies and strikes the enemies finally returning to owner's hand.\nThe hammer is unwielded.\nThe item's glow fades.\n```\n\n## Diagrama de Clases\n\n![alt text](./etc/bridge.urm.png \"Bridge diagrama de clases\")\n\n## Aplicabilidad\n\nUsa el patrón Bridge cuando\n\n* Quieres evitar una vinculación permanente entre una abstracción y su implementación. Este podría ser el caso, por\n  ejemplo, cuando la implementación debe ser seleccionada o cambiada en tiempo de ejecución.\n* Tanto las abstracciones como sus implementaciones deberían ser extensibles mediante la herencia. En este caso, el\n  patrón Bridge te permite combinar las diferentes abstracciones e implementaciones y extenderlas de forma\n  independiente.\n* Los cambios en la implementación de una abstracción no deberían tener impacto en los clientes; es decir, su código no\n  debería tener que ser recompilado.\n* Tienes una proliferación de clases. Tal jerarquía de clases indica la necesidad de dividir un objeto en dos partes.\n  Rumbaugh usa el término \"generalizaciones anidadas\" para referirse a tales jerarquías de clases.\n* Quieres compartir una implementación entre varios objetos (quizás usando conteo de referencias), y este hecho debería\n  ser ocultado al cliente. Un ejemplo simple es la clase String de Coplien, en la que varios objetos pueden compartir la\n  misma representación de cadena.\n\n## Tutoriales\n\n* [Bridge Pattern Tutorial](https://www.journaldev.com/1491/bridge-design-pattern-java)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)"
  },
  {
    "path": "localization/es/builder/README.md",
    "content": "---\ntitle: Builder\nshortTitle: Builder\ncategory: Creational\nlanguage: es\ntag:\n  - Gang of Four\n---\n\n## Propósito\n\nSeparar la construcción de un objeto complejo de su representación para que el mismo proceso de\nconstrucción pueda crear diferentes representaciones.\n\n## Explicación\n\nEjemplo real\n\n> Imagina un generador de personajes para un juego de rol. La opción más fácil es dejar que el ordenador\n> cree el personaje por ti. Si quieres seleccionar manualmente los detalles del personaje como\n> profesión, sexo, color de pelo, etc. la generación del personaje se convierte en un proceso paso a paso que\n> se completa cuando todas las selecciones están listas.\n\nEn pocas palabras\n\n> Permite crear diferentes sabores de un objeto evitando la contaminación del constructor. Útil\n> cuando puede haber varios sabores de un objeto. O cuando hay muchos pasos involucrados en la creación de un objeto.\n> creación de un objeto.\n\nWikipedia dice\n\n> El patrón constructor es un patrón de diseño de software de creación de objetos con la intención de encontrar\n> una solución al anti-patrón del constructor telescópico.\n\n\nDicho esto, permíteme agregar un poco sobre qué es el anti-patrón del constructor telescópico. En algún momento  \nu otro, todos hemos visto un constructor como el siguiente:\n\n```java\npublic Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) {\n}\n```\n\nComo puedes ver, el número de parámetros del constructor puede salirse rápidamente de control, y puede volverse difícil\nentender la disposición de los parámetros. Además, esta lista de parámetros podría seguir creciendo si quisieras agregar\nmás opciones en el futuro. A esto se le llama anti-patrón del constructor telescópico.\n\n**Ejemplo programático**\n\nLa alternativa sensata es utilizar el patrón Builder. En primer lugar, tenemos a nuestro héroe `Hero` que queremos\ncrear:\n\n```java\npublic final class Hero {\n  private final Profession profession;\n  private final String name;\n  private final HairType hairType;\n  private final HairColor hairColor;\n  private final Armor armor;\n  private final Weapon weapon;\n\n  private Hero(Builder builder) {\n    this.profession = builder.profession;\n    this.name = builder.name;\n    this.hairColor = builder.hairColor;\n    this.hairType = builder.hairType;\n    this.weapon = builder.weapon;\n    this.armor = builder.armor;\n  }\n}\n```\n\nLuego tenemos al constructor:\n\n```java\n  public static class Builder {\n    private final Profession profession;\n    private final String name;\n    private HairType hairType;\n    private HairColor hairColor;\n    private Armor armor;\n    private Weapon weapon;\n\n    public Builder(Profession profession, String name) {\n      if (profession == null || name == null) {\n        throw new IllegalArgumentException(\"profession and name can not be null\");\n      }\n      this.profession = profession;\n      this.name = name;\n    }\n\n    public Builder withHairType(HairType hairType) {\n      this.hairType = hairType;\n      return this;\n    }\n\n    public Builder withHairColor(HairColor hairColor) {\n      this.hairColor = hairColor;\n      return this;\n    }\n\n    public Builder withArmor(Armor armor) {\n      this.armor = armor;\n      return this;\n    }\n\n    public Builder withWeapon(Weapon weapon) {\n      this.weapon = weapon;\n      return this;\n    }\n\n    public Hero build() {\n      return new Hero(this);\n    }\n  }\n```\n\nEntonces se puede utilizar como:\n\n```java\nvar mage = new Hero.Builder(Profession.MAGE, \"Riobard\").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();\n```\n\n## Diagrama de clases\n\n![alt text](./etc/builder.urm.png \"Builder diagrama de clases\")\n\n## Aplicabilidad\n\nUtiliza el patrón Builder cuando\n\n* El algoritmo para crear un objeto complejo debe ser independiente de las partes que componen el objeto y cómo se\n  ensamblan.\n* El proceso de construcción debe permitir diferentes representaciones para el objeto que se construye.\n\n## Tutoriales\n\n* [Refactoring Guru](https://refactoring.guru/design-patterns/builder)\n* [Oracle Blog](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java)\n* [Journal Dev](https://www.journaldev.com/1425/builder-design-pattern-in-java)\n\n## Usos en el mundo real\n\n* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)\n* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) así como otros\n  buffers\n  como FloatBuffer, IntBuffer, etc.\n* [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-)\n* Todas las implementaciones\n  de [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)\n* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)\n* [Apache Commons Option.Builder](https://commons.apache.org/proper/commons-cli/apidocs/org/apache/commons/cli/Option.Builder.html)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/es/business-delegate/README.md",
    "content": "---\ntitle: Business Delegate\nshortTitle: Business Delegate\ncategory: Structural\nlanguage: es\ntag:\n  - Decoupling\n---\n\n## Propósito\n\nEl patrón Business Delegate añade una capa de abstracción entre los niveles de presentación y de negocio. Al utilizar\neste patrón, conseguimos un acoplamiento flexible entre los niveles y encapsulamos el conocimiento sobre cómo localizar,\nconectar e interactuar con los objetos de negocio que componen la aplicación.\n\n## También conocido como\n\nService Representative\n\n## Explicación\n\nEjemplo del mundo real\n\n> Una aplicación para teléfonos móviles promete transmitir a tu dispositivo cualquier película existente. Captura la\n> cadena de búsqueda del usuario y se la pasa al Delegado de Negocio. El Delegado de Negocio selecciona el\n> servicio de streaming de vídeo más adecuado y reproduce el vídeo.\n\nEn pocas palabras\n\n> Business Delegate añade una capa de abstracción entre los niveles de presentación y de negocio.\n\nWikipedia dice\n\n> Business Delegate es un patrón de diseño de Java EE. Este patrón está dirigido a reducir el acoplamiento entre los\n> servicios de negocio y el nivel de presentación conectado, y para ocultar los detalles de implementación de los\n> servicios (incluyendo la búsqueda y la accesibilidad de la arquitectura EJB). Los delegados de negocio actúan como un\n> adaptador para invocar objetos de negocio desde la capa de presentación.\n\n**Ejemplo programático**\n\nEn primer lugar, tenemos una abstracción para los servicios de streaming de vídeo `VideoStreamingService` y un par de\nimplementaciones `NetflixService` y `YouTubeService`.\n\n```java\npublic interface VideoStreamingService {\n    void doProcessing();\n}\n\n@Slf4j\npublic class NetflixService implements VideoStreamingService {\n    @Override\n    public void doProcessing() {\n        LOGGER.info(\"NetflixService is now processing\");\n    }\n}\n\n@Slf4j\npublic class YouTubeService implements VideoStreamingService {\n    @Override\n    public void doProcessing() {\n        LOGGER.info(\"YouTubeService is now processing\");\n    }\n}\n```\n\nA continuación, tenemos un servicio de búsqueda `BusinessLookup` que decide qué servicio de transmisión de vídeo\nutilizar.\n\n```java\n\n@Setter\npublic class BusinessLookup {\n\n    private NetflixService netflixService;\n    private YouTubeService youTubeService;\n\n    public VideoStreamingService getBusinessService(String movie) {\n        if (movie.toLowerCase(Locale.ROOT).contains(\"die hard\")) {\n            return netflixService;\n        } else {\n            return youTubeService;\n        }\n    }\n}\n```\n\nEl Delegado de Negocio `BusinessDelegate` utiliza una búsqueda de negocio para dirigir las solicitudes de reproducción\nde películas a un servicio de streaming de vídeo adecuado.\n\n```java\n\n@Setter\npublic class BusinessDelegate {\n\n    private BusinessLookup lookupService;\n\n    public void playbackMovie(String movie) {\n        VideoStreamingService videoStreamingService = lookupService.getBusinessService(movie);\n        videoStreamingService.doProcessing();\n    }\n}\n```\n\nEl cliente móvil `MobileClient` utiliza Business Delegate para llamar al nivel de negocio.\n\n```java\npublic class MobileClient {\n\n    private final BusinessDelegate businessDelegate;\n\n    public MobileClient(BusinessDelegate businessDelegate) {\n        this.businessDelegate = businessDelegate;\n    }\n\n    public void playbackMovie(String movie) {\n        businessDelegate.playbackMovie(movie);\n    }\n}\n```\n\nPor último, podemos demostrar el ejemplo completo en acción.\n\n```java\n  public static void main(String[]args){\n\n        // preparar los objetos\n        var businessDelegate=new BusinessDelegate();\n        var businessLookup=new BusinessLookup();\n        businessLookup.setNetflixService(new NetflixService());\n        businessLookup.setYouTubeService(new YouTubeService());\n        businessDelegate.setLookupService(businessLookup);\n\n        // crear el cliente y utilizar el Business Delegate\n        var client=new MobileClient(businessDelegate);\n        client.playbackMovie(\"Die Hard 2\");\n        client.playbackMovie(\"Maradona: The Greatest Ever\");\n        }\n```\n\nAquí está la salida de la consola.\n\n```\n21:15:33.790 [main] INFO com.iluwatar.business.delegate.NetflixService - NetflixService is now processing\n21:15:33.794 [main] INFO com.iluwatar.business.delegate.YouTubeService - YouTubeService is now processing\n```\n\n## Diagrama de clases\n\n![Diagrama de clases](./etc/business-delegate.urm.png \"Business Delegate\")\n\n## Patrones relacionados\n\n* [Patrón de localización de servicios](https://java-design-patterns.com/patterns/service-locator/)\n\n## Aplicabilidad\n\nUtilice el patrón Business Delegate cuando\n\n* Desea un acoplamiento flexible entre los niveles de presentación y de negocio.\n* Quieres orquestar llamadas a múltiples servicios de negocio\n* Se desea encapsular las búsquedas y llamadas a servicios.\n* Es necesario abstraer y encapsular la comunicación entre la capa cliente y los servicios de negocio.\n\n## Tutoriales\n\n* [Patrón Delegado de Negocio en TutorialsPoint](https://www.tutorialspoint.com/design_pattern/business_delegate_pattern.htm)\n\n## Usos conocidos\n\n* Aplicaciones empresariales que utilicen Java EE (Java Platform, Enterprise Edition)\n* Aplicaciones que requieren acceso remoto a servicios empresariales\n\n## Consecuencias\n\nVentajas:\n\n* Desacoplamiento de los niveles de presentación y de negocio: Permite que el nivel de cliente y los servicios\n  empresariales evolucionen de forma independiente.\n* Transparencia de ubicación: Los clientes no se ven afectados por cambios en la ubicación o la instanciación de los\n  servicios de negocio.\n* Reutilización y escalabilidad: Los objetos Business Delegate pueden ser reutilizados por múltiples clientes, y el\n  patrón soporta el equilibrio de carga y la escalabilidad.\n  carga y escalabilidad.\n\nContrapartidas:\n\n* Complejidad: Introduce capas y abstracciones adicionales que pueden aumentar la complejidad.\n* Sobrecarga de rendimiento: La indirección adicional puede suponer una ligera penalización en el rendimiento.\n\n## Patrones relacionados\n\n* [Localizador de servicios](https://java-design-patterns.com/patterns/service-locator/): El Delegado de Negocio (\n  Business Delegate) utiliza el Localizador de Servicios (Service Locator) para localizar servicios de negocio.\n* [Fachada de Sesión](https://java-design-patterns.com/patterns/session-facade/): El Delegado de Negocio (Business\n  Delegate) puede utilizar la Fachada de Sesión (Session Facade) para proporcionar una interfaz unificada a un conjunto\n  de servicios de negocio.\n* [Entidad Compuesta](https://java-design-patterns.com/patterns/composite-entity/): El Delegado (Business Delegate) de\n  Negocio puede utilizar Entidad Compuesta (Composite Entity) para gestionar el estado de los servicios de negocio.\n\n## Créditos\n\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://www.amazon.com/gp/product/0130648841/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0130648841&linkId=a0100de2b28c71ede8db1757fb2b5947)\n"
  },
  {
    "path": "localization/es/bytecode/README.md",
    "content": "---\ntitle: Bytecode\nshortTitle: Bytecode\ncategory: Behavioral\nlanguage: es\ntag:\n    - Game programming\n---\n\n## Propósito\n\nPermite codificar el comportamiento como instrucciones para una máquina virtual.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Un equipo está trabajando en un nuevo juego en el que los magos luchan entre sí. El comportamiento de los magos necesita ser cuidadosamente ajustado e iterado cientos de veces a través de pruebas de juego. No es óptimo pedir al programador que haga cambios cada vez que el diseñador del juego quiere variar el comportamiento, así que el comportamiento del mago se implementa como una máquina virtual basada en datos.\n\nEn palabras sencillas\n\n> El patrón Bytecode permite un comportamiento dirigido por datos en lugar de por código.\n\n[Gameprogrammingpatterns.com](https://gameprogrammingpatterns.com/bytecode.html) indica la documentación:\n\n> Un conjunto de instrucciones define las operaciones de bajo nivel que pueden realizarse. Una serie de instrucciones se codifica como una secuencia de bytes. Una máquina virtual ejecuta estas instrucciones de una en una, utilizando una pila para los valores intermedios. La combinación de instrucciones permite definir comportamientos complejos de alto nivel.\n\n**Ejemplo programático**\n\nUno de los objetos más importantes del juego es la clase Mago `Wizard`.\n\n```java\n\n@AllArgsConstructor\n@Setter\n@Getter\n@Slf4j\npublic class Wizard {\n\n    private int health;\n    private int agility;\n    private int wisdom;\n    private int numberOfPlayedSounds;\n    private int numberOfSpawnedParticles;\n\n    public void playSound() {\n        LOGGER.info(\"Playing sound\");\n        numberOfPlayedSounds++;\n    }\n\n    public void spawnParticles() {\n        LOGGER.info(\"Spawning particles\");\n        numberOfSpawnedParticles++;\n    }\n}\n```\n\nA continuación, mostramos las instrucciones disponibles para nuestra máquina virtual. Cada una de las instrucciones tiene su propia semántica sobre cómo opera con los datos de la pila. Por ejemplo, la instrucción ADD toma los dos elementos superiores de la pila, los suma y coloca el resultado en la pila.\n\n```java\n\n@AllArgsConstructor\n@Getter\npublic enum Instruction {\n\n    LITERAL(1),         // e.g. \"LITERAL 0\", push 0 to stack\n    SET_HEALTH(2),      // e.g. \"SET_HEALTH\", pop health and wizard number, call set health\n    SET_WISDOM(3),      // e.g. \"SET_WISDOM\", pop wisdom and wizard number, call set wisdom\n    SET_AGILITY(4),     // e.g. \"SET_AGILITY\", pop agility and wizard number, call set agility\n    PLAY_SOUND(5),      // e.g. \"PLAY_SOUND\", pop value as wizard number, call play sound\n    SPAWN_PARTICLES(6), // e.g. \"SPAWN_PARTICLES\", pop value as wizard number, call spawn particles\n    GET_HEALTH(7),      // e.g. \"GET_HEALTH\", pop value as wizard number, push wizard's health\n    GET_AGILITY(8),     // e.g. \"GET_AGILITY\", pop value as wizard number, push wizard's agility\n    GET_WISDOM(9),      // e.g. \"GET_WISDOM\", pop value as wizard number, push wizard's wisdom\n    ADD(10),            // e.g. \"ADD\", pop 2 values, push their sum\n    DIVIDE(11);         // e.g. \"DIVIDE\", pop 2 values, push their division\n    // ...\n}\n```\n\nEn el corazón de nuestro ejemplo está la clase `VirtualMachine`. Toma instrucciones como entrada y las ejecuta para proporcionar el comportamiento del objeto de juego.\n\n```java\n\n@Getter\n@Slf4j\npublic class VirtualMachine {\n\n    private final Stack<Integer> stack = new Stack<>();\n\n    private final Wizard[] wizards = new Wizard[2];\n\n    public VirtualMachine() {\n        wizards[0] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),\n                0, 0);\n        wizards[1] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),\n                0, 0);\n    }\n\n    public VirtualMachine(Wizard wizard1, Wizard wizard2) {\n        wizards[0] = wizard1;\n        wizards[1] = wizard2;\n    }\n\n    public void execute(int[] bytecode) {\n        for (var i = 0; i < bytecode.length; i++) {\n            Instruction instruction = Instruction.getInstruction(bytecode[i]);\n            switch (instruction) {\n                case LITERAL:\n                    // Read the next byte from the bytecode.\n                    int value = bytecode[++i];\n                    // Push the next value to stack\n                    stack.push(value);\n                    break;\n                case SET_AGILITY:\n                    var amount = stack.pop();\n                    var wizard = stack.pop();\n                    setAgility(wizard, amount);\n                    break;\n                case SET_WISDOM:\n                    amount = stack.pop();\n                    wizard = stack.pop();\n                    setWisdom(wizard, amount);\n                    break;\n                case SET_HEALTH:\n                    amount = stack.pop();\n                    wizard = stack.pop();\n                    setHealth(wizard, amount);\n                    break;\n                case GET_HEALTH:\n                    wizard = stack.pop();\n                    stack.push(getHealth(wizard));\n                    break;\n                case GET_AGILITY:\n                    wizard = stack.pop();\n                    stack.push(getAgility(wizard));\n                    break;\n                case GET_WISDOM:\n                    wizard = stack.pop();\n                    stack.push(getWisdom(wizard));\n                    break;\n                case ADD:\n                    var a = stack.pop();\n                    var b = stack.pop();\n                    stack.push(a + b);\n                    break;\n                case DIVIDE:\n                    a = stack.pop();\n                    b = stack.pop();\n                    stack.push(b / a);\n                    break;\n                case PLAY_SOUND:\n                    wizard = stack.pop();\n                    getWizards()[wizard].playSound();\n                    break;\n                case SPAWN_PARTICLES:\n                    wizard = stack.pop();\n                    getWizards()[wizard].spawnParticles();\n                    break;\n                default:\n                    throw new IllegalArgumentException(\"Invalid instruction value\");\n            }\n            LOGGER.info(\"Executed \" + instruction.name() + \", Stack contains \" + getStack());\n        }\n    }\n\n    public void setHealth(int wizard, int amount) {\n        wizards[wizard].setHealth(amount);\n    }\n    // other setters ->\n    // ...\n}\n```\n\nAhora podemos mostrar el ejemplo completo utilizando la máquina virtual.\n\n```java\n  public static void main(String[]args){\n\n        var vm=new VirtualMachine(\n        new Wizard(45,7,11,0,0),\n        new Wizard(36,18,8,0,0));\n\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"GET_HEALTH\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"GET_AGILITY\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"GET_WISDOM\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"ADD\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 2\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"DIVIDE\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"ADD\"));\n        vm.execute(InstructionConverterUtil.convertToByteCode(\"SET_HEALTH\"));\n        }\n```\n\nAquí está la salida de la consola.\n\n```\n16:20:10.193 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0]\n16:20:10.196 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_HEALTH, Stack contains [0, 45]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_AGILITY, Stack contains [0, 45, 7]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 7, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_WISDOM, Stack contains [0, 45, 7, 11]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 45, 18]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 18, 2]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed DIVIDE, Stack contains [0, 45, 9]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 54]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed SET_HEALTH, Stack contains []\n```\n\n## Diagrama de clases\n\n![alt text](./etc/bytecode.urm.png \"Bytecode class diagram\")\n\n## Aplicabilidad\n\nUtiliza el patrón Bytecode cuando tengas que definir muchos comportamientos y el lenguaje de implementación de tu juego no sea el adecuado porque:\n\n* Es demasiado de bajo nivel, por lo que es tedioso o propenso a errores para programar.\n* Iterar en él lleva demasiado tiempo debido a tiempos de compilación lentos u otros problemas de herramientas.\n* Tiene demasiada confianza. Si quieres asegurarte de que el comportamiento definido no puede romper el juego, necesitas separarlo del resto del código base.\n\n## Usos Conocidos\n\n* Java Virtual Machine (JVM) utiliza bytecode para permitir que los programas Java se ejecuten en cualquier dispositivo que tenga JVM instalado.\n* Python compila sus scripts a bytecode que luego es interpretado por la Máquina Virtual Python.\n* NET Framework utiliza una forma de bytecode llamada Microsoft Intermediate Language (MSIL).\n\n## Consecuencias\n\nVentajas:\n\n* Portabilidad: Los programas pueden ejecutarse en cualquier plataforma que disponga de una máquina virtual compatible.\n* Seguridad: La máquina virtual puede aplicar controles de seguridad al código de bytes.\n* Rendimiento: Los compiladores JIT pueden optimizar el código de bytes en tiempo de ejecución, mejorando potencialmente el rendimiento respecto al código interpretado.\n\nDesventajas:\n\n* Sobrecarga: Ejecutar bytecode normalmente implica más sobrecarga que ejecutar código nativo, lo que puede afectar al rendimiento.\n* Complejidad: Implementar y mantener una máquina virtual añade complejidad al sistema.\n\n## Patrones relacionados\n\n* [Intérprete](https://java-design-patterns.com/patterns/interpreter/) se utiliza a menudo dentro de la implementación de VMs para interpretar instrucciones bytecode.\n* [Comando](https://java-design-patterns.com/patterns/command/): Las instrucciones bytecode pueden ser vistas como comandos ejecutados por la VM.\n* [Método de fábrica](https://java-design-patterns.com/patterns/factory-method/): Las VMs pueden utilizar métodos de fábrica para instanciar operaciones o instrucciones definidas en el bytecode.\n\n## Créditos\n\n* [Game programming patterns](http://gameprogrammingpatterns.com/bytecode.html)\n* [Programming Language Pragmatics](https://amzn.to/49Tusnn)\n"
  },
  {
    "path": "localization/es/chain-of-responsibility/README.md",
    "content": "---\ntitle: Chain of responsibility\nshortTitle: Chain of responsibility\ncategory: Behavioral\nlanguage: es\ntag:\n    - Gang of Four\n    - Decoupling\n---\n\n## También conocido como\n\n* Chain of Command\n* Chain of Objects\n* Responsibility Chain\n\n## Propósito\n\nEvita acoplar el emisor de una petición a su receptor dando a más de un objeto la oportunidad de gestionar la petición. Encadena los objetos receptores y pasa la solicitud a lo largo de la cadena hasta que un objeto la gestione.\n\n## Explicación\n\nEjemplo real\n\n> El Rey Orco da órdenes en voz alta a su ejército. El más cercano a reaccionar es el comandante, luego un oficial y después un soldado. El comandante, el oficial y el soldado forman una cadena de responsabilidad.\n\nEn palabras sencillas\n\n> Ayuda a construir una cadena de objetos. Una solicitud entra por un extremo y sigue pasando de un objeto a otro hasta que encuentra un gestor adecuado.\n\nWikipedia dice\n\n> En diseño orientado a objetos, el patrón de cadena de responsabilidad es un patrón de diseño que consiste en una fuente de objetos de comando y una serie de objetos de procesamiento. Cada objeto de procesamiento contiene lógica que define los tipos de objetos de comando que puede manejar; el resto se pasa al siguiente objeto de procesamiento de la cadena.\n\n**Ejemplo programático**\n\nTraduciendo nuestro ejemplo con los orcos de arriba. Primero, tenemos la clase `Request`:\n\n```java\nimport lombok.Getter;\n\n@Getter\npublic class Request {\n\n    private final RequestType requestType;\n    private final String requestDescription;\n    private boolean handled;\n\n    public Request(final RequestType requestType, final String requestDescription) {\n        this.requestType = Objects.requireNonNull(requestType);\n        this.requestDescription = Objects.requireNonNull(requestDescription);\n    }\n\n    public void markHandled() {\n        this.handled = true;\n    }\n\n    @Override\n    public String toString() {\n        return getRequestDescription();\n    }\n}\n\npublic enum RequestType {\n    DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX\n}\n```\n\nA continuación, mostramos la jerarquía del gestor de peticiones.\n\n```java\npublic interface RequestHandler {\n\n    boolean canHandleRequest(Request req);\n\n    int getPriority();\n\n    void handle(Request req);\n\n    String name();\n}\n\n@Slf4j\npublic class OrcCommander implements RequestHandler {\n    @Override\n    public boolean canHandleRequest(Request req) {\n        return req.getRequestType() == RequestType.DEFEND_CASTLE;\n    }\n\n    @Override\n    public int getPriority() {\n        return 2;\n    }\n\n    @Override\n    public void handle(Request req) {\n        req.markHandled();\n        LOGGER.info(\"{} handling request \\\"{}\\\"\", name(), req);\n    }\n\n    @Override\n    public String name() {\n        return \"Orc commander\";\n    }\n}\n\n// OrcOfficer and OrcSoldier are defined similarly as OrcCommander\n\n```\n\nEl Rey Orco da las órdenes y forma la cadena.\n\n```java\npublic class OrcKing {\n\n    private List<RequestHandler> handlers;\n\n    public OrcKing() {\n        buildChain();\n    }\n\n    private void buildChain() {\n        handlers = Arrays.asList(new OrcCommander(), new OrcOfficer(), new OrcSoldier());\n    }\n\n    public void makeRequest(Request req) {\n        handlers\n                .stream()\n                .sorted(Comparator.comparing(RequestHandler::getPriority))\n                .filter(handler -> handler.canHandleRequest(req))\n                .findFirst()\n                .ifPresent(handler -> handler.handle(req));\n    }\n}\n```\n\nLa cadena de responsabilidad en acción.\n\n```java\nvar king=new OrcKing();\n        king.makeRequest(new Request(RequestType.DEFEND_CASTLE,\"defend castle\"));\n        king.makeRequest(new Request(RequestType.TORTURE_PRISONER,\"torture prisoner\"));\n        king.makeRequest(new Request(RequestType.COLLECT_TAX,\"collect tax\"));\n```\n\nLa salida de la consola.\n\n```\nOrc commander handling request \"defend castle\"\nOrc officer handling request \"torture prisoner\"\nOrc soldier handling request \"collect tax\"\n```\n\n## Diagrama de clases\n\n![alt text](./etc/chain-of-responsibility.urm.png \"Diagrama de clases de la cadena de responsabilidad\")\n\n## Aplicabilidad\n\nUtilice Cadena de Responsabilidad cuando\n\n* Más de un objeto puede gestionar una petición, y el gestor no se conoce a priori. El gestor debe determinarse automáticamente.\n* Se desea enviar una petición a uno de varios objetos sin especificar explícitamente el receptor.\n* El conjunto de objetos que pueden gestionar una solicitud debe especificarse dinámicamente.\n\n## Usos conocidos\n\n* Burbujeo de eventos en frameworks GUI donde un evento puede ser manejado en múltiples niveles de la jerarquía de un componente UI.\n* Frameworks de middleware en los que una petición pasa a través de una cadena de objetos de procesamiento.\n* Marcos de trabajo de registro donde los mensajes pueden pasar a través de una serie de registradores, cada uno posiblemente manejándolos de manera diferente.\n* [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29)\n* [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html)\n* [javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-)\n\n## Consecuencias\n\nVentajas:\n\n* Acoplamiento reducido. El emisor de una petición no necesita conocer el manejador concreto que procesará la petición.\n* Mayor flexibilidad a la hora de asignar responsabilidades a los objetos. Se pueden añadir o cambiar responsabilidades para gestionar una petición cambiando los miembros y el orden de la cadena.\n* Permite establecer un gestor por defecto si no hay ningún gestor concreto que pueda gestionar la solicitud.\n\nDesventajas:\n\n* Puede ser difícil depurar y entender el flujo, especialmente si la cadena es larga y compleja.\n* La petición puede quedar sin gestionar si la cadena no incluye un gestor \"catch-all\".\n* Pueden surgir problemas de rendimiento debido a la posibilidad de pasar por varios gestores antes de encontrar el correcto, o no encontrarlo en absoluto.\n\n## Patrones Relacionados\n\n* [Comando](https://java-design-patterns.com/patterns/command/): puede ser usado para encapsular una petición como un objeto, que puede ser pasado a lo largo de la cadena.\n* [Composite](https://java-design-patterns.com/patterns/composite/): la Cadena de Responsabilidad se aplica a menudo junto con el patrón Composite.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): los decoradores pueden encadenarse de forma similar a las responsabilidades en el patrón Cadena de responsabilidad.\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/3PAJUg5)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n* [Pattern languages of program design 3](https://amzn.to/4a4NxTH)\n"
  },
  {
    "path": "localization/es/client-session/README.md",
    "content": "---\ntitle: Client Session\nshortTitle: Client Session\ncategory: Behavioral\nlanguage: es\ntags:\n    - Session management\n    - Web development\n---\n\n## También conocido como\n\n* User session\n\n## Propósito\n\nEl patrón de diseño Client Session tiene como objetivo mantener el estado y los datos de un usuario a través de múltiples peticiones dentro de una aplicación web, asegurando una experiencia de usuario continua y personalizada.\n\n## Explicación\n\nEjemplo real\n\n> Quieres crear una aplicación de gestión de datos que permita a los usuarios enviar peticiones al servidor para modificar y realizar cambios en los datos almacenados en sus dispositivos. Estas peticiones son pequeñas y los datos son individuales para cada usuario, negando la necesidad de una implementación de base de datos a gran escala. Utilizando el patrón de sesión de cliente, se pueden gestionar múltiples peticiones simultáneas, equilibrando la carga de clientes entre diferentes servidores con facilidad debido a que los servidores permanecen sin estado. También se elimina la necesidad de almacenar identificadores de sesión en el lado del servidor debido a que los clientes proporcionan toda la información que un servidor necesita para realizar su proceso.\n\nEn pocas palabras\n\n> En lugar de almacenar información sobre el cliente actual y la información a la que se está accediendo en el servidor, se mantiene sólo en el lado del cliente. El cliente tiene que enviar datos de sesión con cada solicitud al servidor y tiene que enviar un estado actualizado de vuelta al cliente, que se almacena en la máquina del cliente. El servidor no tiene que almacenar la información del cliente. ([ref](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-client))\n\n**Ejemplo programático**\n\nAquí está el código de ejemplo para describir el patrón cliente-sesión. En el siguiente código estamos creando primero una instancia del Servidor. Esta instancia del servidor se utilizará entonces para obtener objetos Session para dos clientes. Como puedes ver en el siguiente código, el objeto Session puede ser utilizado para almacenar cualquier información relevante que sea requerida por el servidor para procesar la petición del cliente. Estos objetos Session serán pasados con cada Request al servidor. La solicitud tendrá el objeto Session que almacena los detalles relevantes del cliente junto con los datos requeridos para procesar la solicitud. La información de sesión en cada solicitud ayuda al servidor a identificar al cliente y procesar la solicitud en consecuencia.\n\n```java\npublic class App {\n\n    public static void main(String[] args) {\n        var server = new Server(\"localhost\", 8080);\n        var session1 = server.getSession(\"Session1\");\n        var session2 = server.getSession(\"Session2\");\n        var request1 = new Request(\"Data1\", session1);\n        var request2 = new Request(\"Data2\", session2);\n        server.process(request1);\n        server.process(request2);\n    }\n}\n\n@Data\n@AllArgsConstructor\npublic class Session {\n\n    /**\n     * Session id.\n     */\n    private String id;\n\n    /**\n     * Client name.\n     */\n    private String clientName;\n\n}\n\n@Data\n@AllArgsConstructor\npublic class Request {\n\n    private String data;\n\n    private Session session;\n\n}\n```\n\n## Diagrama de arquitectura\n\n![alt text](./etc/session_state_pattern.png \"Session State Pattern\")\n\n## Aplicabilidad\n\nUtilice el patrón de estado del cliente cuando:\n\n* Aplicaciones web que requieran autenticación y autorización del usuario.\n* Aplicaciones que necesiten realizar un seguimiento de las actividades y preferencias del usuario a lo largo de múltiples peticiones o visitas.\n* Sistemas donde los recursos del servidor necesitan ser optimizados descargando la gestión del estado al lado del cliente.\n\n## Usos conocidos\n\n* Sitios web de comercio electrónico para rastrear el contenido de la cesta de la compra a lo largo de las sesiones.\n* Plataformas en línea que ofrecen contenidos personalizados basados en las preferencias y el historial del usuario.\n* Aplicaciones web que requieren el inicio de sesión del usuario para acceder a contenidos personalizados o seguros.\n\n## Consecuencias\n\nBeneficios:\n\n* Mejora del rendimiento del servidor al reducir la necesidad de almacenar el estado del usuario en el servidor.\n* Mejora de la experiencia del usuario a través de contenidos personalizados y navegación fluida a través de las diferentes partes de la aplicación.\n* Flexibilidad en la gestión de sesiones a través de varios mecanismos de almacenamiento del lado del cliente (por ejemplo, cookies, Web Storage API).\n\nDesventajas:\n\n* Riesgos potenciales de seguridad si se almacena información sensible en las sesiones del cliente sin el cifrado y la validación adecuados.\n* Dependencia de las capacidades y ajustes del cliente, como las políticas de cookies, que pueden variar según el navegador y la configuración del usuario.\n* Mayor complejidad en la lógica de gestión de sesiones, especialmente en la gestión de la caducidad, renovación y sincronización de sesiones en varios dispositivos o pestañas.\n\n## Patrones relacionados\n\n* Sesión Servidor: A menudo se utiliza junto con el patrón Client Session para proporcionar un equilibrio entre la eficiencia del lado del cliente y el control del lado del servidor.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Asegurar una única instancia de la sesión de un usuario en toda la aplicación.\n* [Estado](https://java-design-patterns.com/patterns/state/): Gestionar las transiciones de estado en una sesión, como los estados autenticado, invitado o caducado.\n\n## Créditos\n\n* [DZone - Practical PHP patterns](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-client)\n* [Client Session State Design Pattern - Ram N Java](https://www.youtube.com/watch?v=ycOSj9g41pc)\n* [Professional Java for Web Applications](https://amzn.to/4aazY59)\n* [Securing Web Applications with Spring Security](https://amzn.to/3PCCEA1)\n"
  },
  {
    "path": "localization/es/collecting-parameter/README.md",
    "content": "---\ntitle: Collecting Parameter\nshortTitle: Collecting Parameter\ncategory: Behavioral\nlanguage: es\ntag:\n    - Accumulation\n    - Generic\n---\n\n## También conocido como\n\n* Collector\n* Accumulator\n\n## Propósito\n\nSu objetivo es simplificar los métodos que recopilan información pasando un único objeto de colección a través de varias llamadas a métodos, permitiéndoles añadir resultados a esta colección en lugar de que cada método cree su propia colección.\n\n## Explicación\n\n### Ejemplo del mundo real\n\nDentro de un gran edificio corporativo, existe una cola de impresión global que es una colección de todos los trabajos de impresión que están actualmente pendientes. Las diferentes plantas contienen diferentes modelos de impresoras, cada una con una política de impresión diferente. Debemos construir un programa que pueda añadir continuamente trabajos de impresión apropiados a una colección, que se llama el *parámetro de recogida*.\n\n### En palabras sencillas\n\nEn lugar de tener un método gigante que contenga numerosas políticas para recoger información en una variable, podemos crear numerosas funciones más pequeñas que tomen cada parámetro, y añadan nueva información. Podemos pasar el parámetro a todas estas funciones más pequeñas y al final, tendremos lo que queríamos originalmente. Esta vez, el código es más limpio y fácil de entender. Debido a que la función más grande se ha dividido, el código también es más fácil de modificar ya que los cambios se localizan en las funciones más pequeñas.\n\n### Wikipedia dice\n\nEn el modismo de Parámetros de Recolección una colección (lista, mapa, etc.) se pasa repetidamente como parámetro a un método que añade elementos a la colección.\n\n### Ejemplo programático\n\nCodificando nuestro ejemplo anterior, podemos utilizar la colección `resultado` como parámetro recolector. Se implementan las siguientes restricciones:\n\n- Si un papel A4 es de color, también debe ser de una sola cara. Se aceptan todos los demás papeles no coloreados.\n- El papel A3 no debe ser de color y debe ser de una sola cara.\n- El papel A2 debe ser de una sola página, a una cara y sin colorear.\n\n```java\npackage com.iluwatar.collectingparameter;\n\nimport java.util.LinkedList;\nimport java.util.Queue;\n\npublic class App {\n    static PrinterQueue printerQueue = PrinterQueue.getInstance();\n\n    /**\n     * Program entry point.\n     *\n     * @param args command line args\n     */\n    public static void main(String[] args) {\n    /*\n      Initialising the printer queue with jobs\n    */\n        printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A4, 5, false, false));\n        printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A3, 2, false, false));\n        printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A2, 5, false, false));\n\n    /*\n      This variable is the collecting parameter.\n    */\n        var result = new LinkedList<PrinterItem>();\n\n        /*\n         * Using numerous sub-methods to collaboratively add information to the result collecting parameter\n         */\n        addA4Papers(result);\n        addA3Papers(result);\n        addA2Papers(result);\n    }\n}\n```\n\nUtilizamos los métodos `addA4Paper`, `addA3Paper` y `addA2Paper` para rellenar el parámetro de recogida `result` con los trabajos de impresión adecuados según la política descrita anteriormente. Las tres políticas se codifican a continuación,\n\n```java\npublic class App {\n    static PrinterQueue printerQueue = PrinterQueue.getInstance();\n\n    /**\n     * Adds A4 document jobs to the collecting parameter according to some policy that can be whatever the client\n     * (the print center) wants.\n     *\n     * @param printerItemsCollection the collecting parameter\n     */\n    public static void addA4Papers(Queue<PrinterItem> printerItemsCollection) {\n    /*\n      Iterate through the printer queue, and add A4 papers according to the correct policy to the collecting parameter,\n      which is 'printerItemsCollection' in this case.\n     */\n        for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n            if (nextItem.paperSize.equals(PaperSizes.A4)) {\n                var isColouredAndSingleSided =\n                        nextItem.isColour && !nextItem.isDoubleSided;\n                if (isColouredAndSingleSided) {\n                    printerItemsCollection.add(nextItem);\n                } else if (!nextItem.isColour) {\n                    printerItemsCollection.add(nextItem);\n                }\n            }\n        }\n    }\n\n    /**\n     * Adds A3 document jobs to the collecting parameter according to some policy that can be whatever the client\n     * (the print center) wants. The code is similar to the 'addA4Papers' method. The code can be changed to accommodate\n     * the wants of the client.\n     *\n     * @param printerItemsCollection the collecting parameter\n     */\n    public static void addA3Papers(Queue<PrinterItem> printerItemsCollection) {\n        for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n            if (nextItem.paperSize.equals(PaperSizes.A3)) {\n\n                // Encoding the policy into a Boolean: the A3 paper cannot be coloured and double-sided at the same time\n                var isNotColouredAndSingleSided =\n                        !nextItem.isColour && !nextItem.isDoubleSided;\n                if (isNotColouredAndSingleSided) {\n                    printerItemsCollection.add(nextItem);\n                }\n            }\n        }\n    }\n\n    /**\n     * Adds A2 document jobs to the collecting parameter according to some policy that can be whatever the client\n     * (the print center) wants. The code is similar to the 'addA4Papers' method. The code can be changed to accommodate\n     * the wants of the client.\n     *\n     * @param printerItemsCollection the collecting parameter\n     */\n    public static void addA2Papers(Queue<PrinterItem> printerItemsCollection) {\n        for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n            if (nextItem.paperSize.equals(PaperSizes.A2)) {\n\n                // Encoding the policy into a Boolean: the A2 paper must be single page, single-sided, and non-coloured.\n                var isNotColouredSingleSidedAndOnePage =\n                        nextItem.pageCount == 1 &&\n                                !nextItem.isDoubleSided\n                                && !nextItem.isColour;\n                if (isNotColouredSingleSidedAndOnePage) {\n                    printerItemsCollection.add(nextItem);\n                }\n            }\n        }\n    }\n}\n```\n\nCada método toma como argumento un parámetro de recogida. A continuación, añade elementos, tomados de una variable global, a este parámetro de recogida si cada elemento satisface un criterio determinado. Estos métodos pueden tener la política que desee el cliente.\n\nEn este ejemplo de programación, se añaden tres trabajos de impresión a la cola. Sólo los dos primeros trabajos de impresión deben añadirse al parámetro de recogida según la política. Los elementos de la variable `result` después de la ejecución son,\n\n| paperSize | pageCount | isDoubleSided | isColour |\n|-----------|-----------|---------------|----------|\n| A4        | 5         | false         | false    |\n| A3        | 2         | false         | false    |\n\nque es lo que esperábamos.\n\n## Diagrama de clases\n\n![alt text](./etc/collecting-parameter.urm.png \"Collecting Parameter\")\n\n## Aplicabilidad\n\nUtilice el patrón de diseño Recopilación de parámetros cuando\n\n- Cuando múltiples métodos producen una colección de resultados y quieres agregar estos resultados de una manera unificada.\n- En escenarios donde reducir el número de colecciones creadas por métodos puede mejorar la eficiencia de memoria y el rendimiento.\n- Al refactorizar métodos grandes que realizan varias tareas, incluida la recopilación de resultados de varias operaciones.\n\n## Tutoriales\n\nLos tutoriales para este método se encuentran en:\n\n- [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf) por Joshua Kerivsky\n- [Smalltalk Best Practice Patterns](https://ptgmedia.pearsoncmg.com/images/9780134769042/samplepages/013476904X.pdf) por Kent Beck\n\n## Usos conocidos\n\nJoshua Kerivsky da un ejemplo real en su libro 'Refactoring to Patterns'. Da un ejemplo de uso del patrón de diseño \"Collecting Parameter\" para crear un método `toString()` para un árbol XML. Sin utilizar este patrón de diseño, esto requeriría una función voluminosa con condicionales y concatenación que empeoraría la legibilidad del código. Un método de este tipo puede dividirse en métodos más pequeños, cada uno de los cuales añade su propio conjunto de información al parámetro de recogida. Véase esto en [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf).\n\nOtros ejemplos son:\n\n- Agregar mensajes de error o fallos de validación en un proceso de validación complejo.\n- Recopilar elementos o información mientras se recorre una estructura de datos compleja.\n- Refactorización de funcionalidades de informes complejas en las que varias partes de un informe se generan mediante métodos diferentes.\n\n## Consecuencias\n\nVentajas:\n\n- Reduce la duplicación de código centralizando el manejo de las colecciones en un único lugar.\n- Mejora la claridad y la capacidad de mantenimiento al hacer explícito dónde y cómo se recogen los resultados.\n- Mejora el rendimiento al minimizar la creación y gestión de múltiples objetos de recopilación.\n\nDesventajas:\n\n- Aumenta el acoplamiento entre el invocador y los métodos invocados, ya que deben ponerse de acuerdo sobre la colección a utilizar.\n- Puede introducir efectos secundarios en los métodos si no se gestionan con cuidado, ya que los métodos ya no son autónomos en su gestión de resultados.\n\n## Patrones relacionados\n\n- [Composite](https://java-design-patterns.com/patterns/composite/): Puede utilizarse junto con Collecting Parameter cuando se trabaja con estructuras jerárquicas, permitiendo que los resultados se recojan a través de una estructura compuesta.\n- [Visitante](https://java-design-patterns.com/patterns/visitor/): A menudo se utiliza conjuntamente, donde Visitor se encarga de recorrer y realizar operaciones en una estructura, y Collecting Parameter acumula los resultados.\n- [Comando](https://java-design-patterns.com/patterns/command/): Los comandos pueden utilizar el parámetro de recopilación para agregar resultados de varias operaciones ejecutadas por los objetos de comando.\n\n## Créditos\n\n- [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf) by Joshua Kerivsky\n- [Smalltalk Best Practice Patterns](https://ptgmedia.pearsoncmg.com/images/9780134769042/samplepages/013476904X.pdf) by Kent Beck\n- [Wiki](https://wiki.c2.com/?CollectingParameter)\n- [Refactoring: Improving the Design of Existing Code](https://amzn.to/3TVEgaB)\n- [Clean Code: A Handbook of Agile Software Craftsmanship](https://amzn.to/4aApLP0)\n"
  },
  {
    "path": "localization/es/command/README.md",
    "content": "---\ntitle: Command\nshortTitle: Command\ncategory: Behavioral\nlanguage: es\ntag:\n    - Gang of Four\n---\n\n## También conocido como\n\n* Action\n* Transaction\n\n## Propósito\n\nEl patrón de diseño Command encapsula una petición como un objeto, permitiendo así la parametrización de clientes con colas, peticiones y operaciones. También permite soportar operaciones deshechas.\n\n## Explicación\n\nEjemplo real\n\n> Hay un mago lanzando hechizos sobre un goblin. Los hechizos se ejecutan sobre el duende uno a uno. El primer hechizo encoge al duende y el segundo lo hace invisible. A continuación, el mago invierte los hechizos uno a uno. Cada hechizo es un objeto de comando que se puede deshacer.\n\nEn palabras simples:\n\n> Almacenar peticiones como objetos de comando permite realizar una acción o deshacerla en un momento posterior.\n\nWikipedia dice:\n\n> En programación orientada a objetos, el patrón de comandos es un patrón de diseño de comportamiento en el que un objeto se utiliza para encapsular toda la información necesaria para realizar una acción o desencadenar un evento en un momento posterior.\n\n**Ejemplo programático**\n\nAquí está el código de ejemplo con mago `Wizard` y duende `Goblin`. Empecemos por la clase Mago `Wizard`.\n\n```java\n\n@Slf4j\npublic class Wizard {\n\n    private final Deque<Runnable> undoStack = new LinkedList<>();\n    private final Deque<Runnable> redoStack = new LinkedList<>();\n\n    public Wizard() {\n    }\n\n    public void castSpell(Runnable runnable) {\n        runnable.run();\n        undoStack.offerLast(runnable);\n    }\n\n    public void undoLastSpell() {\n        if (!undoStack.isEmpty()) {\n            var previousSpell = undoStack.pollLast();\n            redoStack.offerLast(previousSpell);\n            previousSpell.run();\n        }\n    }\n\n    public void redoLastSpell() {\n        if (!redoStack.isEmpty()) {\n            var previousSpell = redoStack.pollLast();\n            undoStack.offerLast(previousSpell);\n            previousSpell.run();\n        }\n    }\n\n    @Override\n    public String toString() {\n        return \"Wizard\";\n    }\n}\n```\n\nA continuación, tenemos al duende `Goblin` que es el objetivo `Target` de los hechizos.\n\n```java\n\n@Slf4j\npublic abstract class Target {\n\n    private Size size;\n\n    private Visibility visibility;\n\n    public Size getSize() {\n        return size;\n    }\n\n    public void setSize(Size size) {\n        this.size = size;\n    }\n\n    public Visibility getVisibility() {\n        return visibility;\n    }\n\n    public void setVisibility(Visibility visibility) {\n        this.visibility = visibility;\n    }\n\n    @Override\n    public abstract String toString();\n\n    public void printStatus() {\n        LOGGER.info(\"{}, [size={}] [visibility={}]\", this, getSize(), getVisibility());\n    }\n}\n\npublic class Goblin extends Target {\n\n    public Goblin() {\n        setSize(Size.NORMAL);\n        setVisibility(Visibility.VISIBLE);\n    }\n\n    @Override\n    public String toString() {\n        return \"Goblin\";\n    }\n\n    public void changeSize() {\n        var oldSize = getSize() == Size.NORMAL ? Size.SMALL : Size.NORMAL;\n        setSize(oldSize);\n    }\n\n    public void changeVisibility() {\n        var visible = getVisibility() == Visibility.INVISIBLE\n                ? Visibility.VISIBLE : Visibility.INVISIBLE;\n        setVisibility(visible);\n    }\n}\n```\n\nPor último, tenemos al mago en la función principal lanzando hechizos.\n\n```java\npublic static void main(String[]args){\n        var wizard=new Wizard();\n        var goblin=new Goblin();\n\n        // casts shrink/unshrink spell\n        wizard.castSpell(goblin::changeSize);\n\n        // casts visible/invisible spell\n        wizard.castSpell(goblin::changeVisibility);\n\n        // undo and redo casts\n        wizard.undoLastSpell();\n        wizard.redoLastSpell();\n```\n\nEste es el ejemplo en acción.\n\n```java\nvar wizard=new Wizard();\n        var goblin=new Goblin();\n\n        goblin.printStatus();\n        wizard.castSpell(goblin::changeSize);\n        goblin.printStatus();\n\n        wizard.castSpell(goblin::changeVisibility);\n        goblin.printStatus();\n\n        wizard.undoLastSpell();\n        goblin.printStatus();\n\n        wizard.undoLastSpell();\n        goblin.printStatus();\n\n        wizard.redoLastSpell();\n        goblin.printStatus();\n\n        wizard.redoLastSpell();\n        goblin.printStatus();\n```\n\nAquí está la salida del programa:\n\n```java\nGoblin,[size=normal][visibility=visible]\n        Goblin,[size=small][visibility=visible]\n        Goblin,[size=small][visibility=invisible]\n        Goblin,[size=small][visibility=visible]\n        Goblin,[size=normal][visibility=visible]\n        Goblin,[size=small][visibility=visible]\n        Goblin,[size=small][visibility=invisible]\n```\n\n## Diagrama de clases\n\n![alt text](./etc/command.png \"Command\")\n\n## Aplicabilidad\n\nUtilice el patrón Comando (Command) para:\n\n* Parametrizar objetos mediante una acción a realizar. Puedes expresar dicha parametrización en un lenguaje procedimental con una función callback, es decir, una función que se registra en algún lugar para ser llamada en un momento posterior. Los comandos son un sustituto orientado a objetos de las retrollamadas.\n* Especifican, ponen en cola y ejecutan peticiones en diferentes momentos. Un objeto Command puede tener una vida independiente de la petición original. Si el receptor de una petición puede ser representado de una manera independiente del espacio de direcciones, entonces puedes transferir un objeto comando para la petición a un proceso diferente y cumplir la petición allí.\n* Soporta deshacer. La operación de ejecución del comando puede almacenar el estado para revertir sus efectos en el propio comando. La interfaz del Comando debe tener una operación añadida de des-ejecutar que revierta los efectos de una llamada previa a ejecutar. Los comandos ejecutados se almacenan en una lista de historial. La funcionalidad de deshacer y rehacer a nivel ilimitado se consigue recorriendo esta lista hacia atrás y hacia delante llamando a un-ejecutar y ejecutar, respectivamente.\n* Soporta el registro de cambios para que puedan volver a aplicarse en caso de caída del sistema. Al aumentar la interfaz de comandos con operaciones de carga y almacenamiento, puede mantener un registro persistente de los cambios. La recuperación de un fallo implica volver a cargar los comandos registrados desde el disco y volver a ejecutarlos con la operación de ejecución.\n* Estructurar un sistema en torno a operaciones de alto nivel construidas sobre operaciones primitivas. Esta estructura es común en los sistemas de información que admiten transacciones. Una transacción encapsula un conjunto de cambios de datos. El patrón Command ofrece una forma de modelar las transacciones. Los comandos tienen una interfaz común que permite invocar todas las transacciones de la misma manera. El patrón también facilita la ampliación del sistema con nuevas transacciones.\n* Mantener un historial de peticiones.\n* Implementar la funcionalidad de callback.\n* Implementar la funcionalidad de deshacer.\n\n## Usos conocidos\n\n* Botones GUI y elementos de menú en aplicaciones de escritorio.\n* Operaciones en sistemas de bases de datos y sistemas transaccionales que soportan rollback.\n* Grabación de macros en aplicaciones como editores de texto y hojas de cálculo.\n* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)\n* [org.junit.runners.model.Statement](https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/runners/model/Statement.java)\n* [Netflix Hystrix](https://github.com/Netflix/Hystrix/wiki)\n* [javax.swing.Action](http://docs.oracle.com/javase/8/docs/api/javax/swing/Action.html)\n\n## Consecuencias\n\nVentajas:\n\n* Desacopla el objeto que invoca la operación del que sabe cómo realizarla.\n* Es fácil añadir nuevos Comandos, porque no tienes que cambiar las clases existentes.\n* Puedes ensamblar un conjunto de comandos en un comando compuesto.\n\nDesventajas:\n\n* Aumenta el número de clases para cada comando individual.\n* Puede complicar el diseño al añadir múltiples capas entre emisores y receptores.\n\n## Patrones Relacionados\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): Los comandos pueden ser compuestos usando el patrón Composite para crear macro comandos.\n* [Memento](https://java-design-patterns.com/patterns/memento/): Puede usarse para implementar mecanismos de deshacer.\n* [Observador](https://java-design-patterns.com/patterns/observer/): El patrón puede ser observado para cambios que activan comandos.\n\n## Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n* [Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/3PFUqSY)\n"
  },
  {
    "path": "localization/es/commander/README.md",
    "content": "---\ntitle: Commander\nshortTitle: Commander\ncategory: Behavioral\nlanguage: es\ntag:\n    - Cloud distributed\n    - Microservices\n    - Transactions\n---\n\n## También conocido como\n\n* Distributed Transaction Commander\n* Transaction Coordinator\n\n## Propósito\n\nLa intención del patrón Commander en el contexto de las transacciones distribuidas es gestionar y coordinar transacciones complejas a través de múltiples componentes o servicios distribuidos, asegurando la consistencia e integridad de la transacción global. Encapsula comandos de transacciones y lógica de coordinación, facilitando la implementación de protocolos de transacciones distribuidas como commit de dos fases o Saga.\n\n## Explicación\n\nEjemplo real\n\n> Imagine que organiza un gran festival internacional de música en el que están programadas actuaciones de varios grupos de todo el mundo. La llegada, la prueba de sonido y la actuación de cada grupo son como transacciones individuales en un sistema distribuido. El organizador del festival actúa como el \"Comandante\", coordinando estas transacciones para garantizar que si el vuelo de una banda se retrasa (similar a un fallo de transacción), hay un plan de respaldo, como reprogramar o intercambiar franjas horarias con otra banda (acciones compensatorias), para mantener intacto el programa general. Esta configuración refleja el patrón del Comandante en las transacciones distribuidas, en las que varios componentes deben coordinarse para lograr un resultado satisfactorio a pesar de los fallos individuales.\n\nEn palabras sencillas\n\n> El patrón Commander convierte una petición en un objeto independiente, permitiendo la parametrización de comandos, la puesta en cola de acciones y la implementación de operaciones de deshacer.\n\n**Ejemplo programático**\n\nLa gestión de transacciones a través de diferentes servicios en un sistema distribuido, como una plataforma de comercio electrónico con microservicios separados de Pago y Envío, requiere una cuidadosa coordinación para evitar problemas. Cuando un usuario realiza un pedido pero un servicio (por ejemplo, Pago) no está disponible mientras que el otro (por ejemplo, Envío) está listo, necesitamos una solución robusta para manejar esta discrepancia.\n\nUna estrategia para resolver este problema consiste en utilizar un componente Commander que orqueste el proceso. Inicialmente, el pedido es procesado por el servicio disponible (Envío en este caso). A continuación, el comandante intenta sincronizar el pedido con el servicio no disponible en ese momento (Pago) almacenando los detalles del pedido en una base de datos o poniéndolo en cola para su procesamiento futuro. Este sistema de colas también debe tener en cuenta posibles fallos al añadir solicitudes a la cola.\n\nEl comandante intenta repetidamente procesar los pedidos en cola para garantizar que ambos servicios reflejen finalmente los mismos datos de transacción. Este proceso implica garantizar la idempotencia, lo que significa que incluso si la misma solicitud de sincronización de pedidos se realiza varias veces, sólo se ejecutará una vez, evitando transacciones duplicadas. El objetivo es lograr una coherencia final entre los servicios, en la que todos los sistemas se sincronicen a lo largo del tiempo a pesar de los fallos o retrasos iniciales.\n\nEn el código proporcionado, el patrón Commander se utiliza para manejar transacciones distribuidas a través de múltiples servicios (PaymentService, ShippingService, MessagingService, EmployeeHandle). Cada servicio tiene su propia base de datos y puede lanzar excepciones para simular fallos.\n\nLa clase Commander es la parte central de este patrón. Toma instancias de todos los servicios y sus bases de datos, junto con algunos parámetros de configuración. El método placeOrder de la clase Commander se utiliza para realizar un pedido, lo que implica interactuar con todos los servicios.\n\n```java\npublic class Commander {\n    // ... constructor and other methods ...\n\n    public void placeOrder(Order order) {\n        // ... implementation ...\n    }\n}\n```\n\nLas clases Usuario y Pedido representan un usuario y un pedido respectivamente. Un pedido lo realiza un usuario.\n\n```java\npublic class User {\n    // ... constructor and other methods ...\n}\n\npublic class Order {\n    // ... constructor and other methods ...\n}\n```\n\nCada servicio (por ejemplo, PaymentService, ShippingService, MessagingService, EmployeeHandle) tiene su propia base de datos y puede lanzar excepciones para simular fallos. Por ejemplo, el PaymentService puede lanzar una DatabaseUnavailableException si su base de datos no está disponible.\n\n```java\npublic class PaymentService {\n    // ... constructor and other methods ...\n}\n```\n\nLas clases DatabaseUnavailableException, ItemUnavailableException y ShippingNotPossibleException representan diferentes tipos de excepciones que pueden ocurrir.\n\n```java\npublic class DatabaseUnavailableException extends Exception {\n    // ... constructor and other methods ...\n}\n\npublic class ItemUnavailableException extends Exception {\n    // ... constructor and other methods ...\n}\n\npublic class ShippingNotPossibleException extends Exception {\n    // ... constructor and other methods ...\n}\n```\n\nEn el método principal de cada clase (AppQueueFailCases, AppShippingFailCases), se simulan diferentes escenarios creando instancias de la clase Commander con diferentes configuraciones y llamando al método placeOrder.\n\n## Diagrama de clases\n\n![alt text](./etc/commander.urm.png \"Commander class diagram\")\n\n## Aplicabilidad\n\nUtilice el patrón Commander para transacciones distribuidas cuando:\n\n* Necesites asegurar la consistencia de los datos entre servicios distribuidos en caso de fallos parciales del sistema.\n* Las transacciones abarcan múltiples microservicios o componentes distribuidos que requieren un commit o rollback coordinado.\n* Está implementando transacciones de larga duración que requieren acciones compensatorias para la reversión.\n\n## Usos conocidos\n\n* Protocolos Two-Phase Commit (2PC): Coordinación de commit o rollback a través de bases de datos o servicios distribuidos.\n* Implementaciones del patrón Saga: Gestión de procesos de negocio de larga duración que abarcan múltiples microservicios, con cada paso teniendo una acción compensatoria para la reversión.\n* Transacciones distribuidas en arquitectura de microservicios: Coordinación de operaciones complejas entre microservicios manteniendo la integridad y consistencia de los datos.\n\n## Consecuencias\n\nBeneficios:\n\n* Proporciona un mecanismo claro para gestionar transacciones distribuidas complejas, mejorando la fiabilidad del sistema.\n* Permite la implementación de transacciones compensatorias, que son cruciales para mantener la coherencia en transacciones de larga duración.\n* Facilita la integración de sistemas heterogéneos en un contexto transaccional.\n\nContrapartidas:\n\n* Aumenta la complejidad, especialmente en situaciones de fallo, debido a la necesidad de mecanismos de reversión coordinados.\n* Potencialmente afecta al rendimiento debido a la sobrecarga de la coordinación y las comprobaciones de coherencia.\n* Las implementaciones basadas en Saga pueden llevar a una mayor complejidad en la comprensión del flujo global del proceso de negocio.\n\n## Patrones relacionados\n\n[Saga Pattern](https://java-design-patterns.com/patterns/saga/): A menudo se discute junto con el patrón Commander para transacciones distribuidas, centrándose en transacciones de larga duración con acciones compensatorias.\n\n## Créditos\n\n* [Distributed Transactions: The Icebergs of Microservices](https://www.grahamlea.com/2016/08/distributed-transactions-microservices-icebergs/)\n* [Microservices Patterns: With examples in Java](https://amzn.to/4axjnYW)\n* [Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems](https://amzn.to/4axHwOV)\n* [Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions](https://amzn.to/4aATcRe)\n"
  },
  {
    "path": "localization/es/composite/README.md",
    "content": "---\ntitle: Composite\nshortTitle: Composite\ncategory: Structural\nlanguage: es\ntag:\n  - Gang of Four\n  - Object composition\n  - Recursion\n---\n\n## También conocido como\n\n* Object Tree\n* Composite Structure\n\n## Propósito\n\nComponga objetos en estructuras de árbol para representar jerarquías parte-todo. Composite permite a los clientes tratar\nobjetos individuales y composiciones de objetos de manera uniforme.\n\n## Explanation\n\nReal-world example\n\n> Cada frase se compone de palabras que a su vez se componen de caracteres. Cada uno de estos objetos es imprimible y\n> puede tener algo impreso antes o después de ellos, como la frase siempre termina con punto final y la palabra siempre\n> tiene espacio antes de ella.\n\nEn pocas palabras\n\n> El patrón compuesto permite a los clientes tratar uniformemente los objetos individuales.\n\nWikipedia dice\n\n> En ingeniería de software, el patrón compuesto es un patrón de diseño de partición. El patrón compuesto describe que\n> un grupo de objetos debe ser tratado de la misma manera que una única instancia de un objeto. La intención de un\n> compuesto es \"componer\" objetos en estructuras de árbol para representar jerarquías parte-todo. La implementación del\n> patrón de composición permite a los clientes tratar los objetos individuales y las composiciones de manera uniforme.\n\n**Ejemplo programático**\n\nTomando nuestro ejemplo anterior. Aquí tenemos la clase base `LetterComposite` y los diferentes tipos\nimprimibles `Letter`, `Word` y `Sentence`.\n\n```java\npublic abstract class LetterComposite {\n\n    private final List<LetterComposite> children = new ArrayList<>();\n\n    public void add(LetterComposite letter) {\n        children.add(letter);\n    }\n\n    public int count() {\n        return children.size();\n    }\n\n    protected void printThisBefore() {\n    }\n\n    protected void printThisAfter() {\n    }\n\n    public void print() {\n        printThisBefore();\n        children.forEach(LetterComposite::print);\n        printThisAfter();\n    }\n}\n\npublic class Letter extends LetterComposite {\n\n    private final char character;\n\n    public Letter(char c) {\n        this.character = c;\n    }\n\n    @Override\n    protected void printThisBefore() {\n        System.out.print(character);\n    }\n}\n\npublic class Word extends LetterComposite {\n\n    public Word(List<Letter> letters) {\n        letters.forEach(this::add);\n    }\n\n    public Word(char... letters) {\n        for (char letter : letters) {\n            this.add(new Letter(letter));\n        }\n    }\n\n    @Override\n    protected void printThisBefore() {\n        System.out.print(\" \");\n    }\n}\n\npublic class Sentence extends LetterComposite {\n\n    public Sentence(List<Word> words) {\n        words.forEach(this::add);\n    }\n\n    @Override\n    protected void printThisAfter() {\n        System.out.print(\".\");\n    }\n}\n```\n\nEntonces tenemos un mensajero para llevar mensajes:\n\n```java\npublic class Messenger {\n\n    LetterComposite messageFromOrcs() {\n\n        var words = List.of(\n                new Word('W', 'h', 'e', 'r', 'e'),\n                new Word('t', 'h', 'e', 'r', 'e'),\n                new Word('i', 's'),\n                new Word('a'),\n                new Word('w', 'h', 'i', 'p'),\n                new Word('t', 'h', 'e', 'r', 'e'),\n                new Word('i', 's'),\n                new Word('a'),\n                new Word('w', 'a', 'y')\n        );\n\n        return new Sentence(words);\n\n    }\n\n    LetterComposite messageFromElves() {\n\n        var words = List.of(\n                new Word('M', 'u', 'c', 'h'),\n                new Word('w', 'i', 'n', 'd'),\n                new Word('p', 'o', 'u', 'r', 's'),\n                new Word('f', 'r', 'o', 'm'),\n                new Word('y', 'o', 'u', 'r'),\n                new Word('m', 'o', 'u', 't', 'h')\n        );\n\n        return new Sentence(words);\n\n    }\n\n}\n```\n\nY entonces se puede utilizar como:\n\n```java\nvar messenger=new Messenger();\n\n        LOGGER.info(\"Message from the orcs: \");\n        messenger.messageFromOrcs().print();\n\n        LOGGER.info(\"Message from the elves: \");\n        messenger.messageFromElves().print();\n```\n\nLa salida de la consola:\n\n```\nMessage from the orcs: \n Where there is a whip there is a way.\nMessage from the elves: \n Much wind pours from your mouth.\n```\n\n## Diagrama de clases\n\n![alt text](./etc/composite.urm.png \"Diagrama de clases compuestas\")\n\n## Aplicabilidad\n\nUtilice el patrón Composite cuando\n\n* Desea representar jerarquías parciales de objetos.\n* Desea que los clientes puedan ignorar la diferencia entre composiciones de objetos y objetos individuales. Los\n  clientes tratarán todos los objetos de la estructura compuesta de manera uniforme.\n\n## Usos conocidos\n\n* Interfaces gráficas de usuario donde los componentes pueden contener otros componentes (por ejemplo, paneles que\n  contienen botones, etiquetas, otros paneles).\n* Representaciones de sistemas de archivos donde los directorios pueden contener archivos y otros directorios.\n* Estructuras organizativas en las que un departamento puede contener subdepartamentos y empleados.\n* [java.awt.Container](http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html)\n  y [java.awt.Component](http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html)\n* Árbol de componentes [Apache Wicket](https://github.com/apache/wicket),\n  ver [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java)\n  y [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)\n\n## Consecuencias\n\nVentajas:\n\n* Simplifica el código cliente, ya que puede tratar estructuras compuestas y objetos individuales de manera uniforme.\n* Facilita la adición de nuevos tipos de componentes, ya que no es necesario modificar el código existente.\n\nContrapartidas:\n\n* Puede hacer que el diseño sea demasiado general. Puede ser difícil restringir los componentes de un compuesto.\n* Puede dificultar la restricción de los tipos de componentes de un compuesto.\n\n## Patrones relacionados\n\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Composite puede usar Flyweight para compartir\n  instancias de componentes entre varios composites.\n* [Iterador](https://java-design-patterns.com/patterns/iterator/): Puede ser utilizado para atravesar estructuras\n  Composite.\n* [Visitante](https://java-design-patterns.com/patterns/visitor/): Puede aplicar una operación sobre una estructura\n  Composite.\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n* [Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/3xoLAmi)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3vBKXWb)\n"
  },
  {
    "path": "localization/es/composite-entity/README.md",
    "content": "---\ntitle: Composite Entity\nshortTitle: Composite Entity\ncategory: Structural\nlanguage: es\ntag:\n  - Client-server\n  - Data access\n  - Enterprise patterns\n---\n\n## También conocido como\n\n* Coarse-Grained Entity\n\n## Propósito\n\nEl patrón de diseño Entidad Compuesta tiene como objetivo gestionar un conjunto de objetos persistentes\ninterrelacionados como si fueran una única entidad. Se utiliza comúnmente en el contexto de Enterprise JavaBeans (EJB) y\nmarcos empresariales similares para representar estructuras de datos basadas en gráficos dentro de modelos de negocio,\npermitiendo a los clientes tratarlos como una sola unidad.\n\n## Explicación\n\nEjemplo real\n\n> En una consola, puede haber muchas interfaces que necesiten ser gestionadas y controladas. Usando el patrón de entidad\n> compuesta, objetos dependientes como mensajes y señales pueden ser combinados y controlados usando un único objeto.\n\nEn palabras sencillas\n\n> El patrón de entidad compuesta permite representar y gestionar un conjunto de objetos relacionados mediante un objeto\n> unificado.\n\n**Ejemplo programático**\n\nNecesitamos una solución genérica para el problema. Para ello, vamos a introducir un patrón genérico de entidad\ncompuesta.\n\n```java\npublic abstract class DependentObject<T> {\n\n    T data;\n\n    public void setData(T message) {\n        this.data = message;\n    }\n\n    public T getData() {\n        return data;\n    }\n}\n\npublic abstract class CoarseGrainedObject<T> {\n\n    DependentObject<T>[] dependentObjects;\n\n    public void setData(T... data) {\n        IntStream.range(0, data.length).forEach(i -> dependentObjects[i].setData(data[i]));\n    }\n\n    public T[] getData() {\n        return (T[]) Arrays.stream(dependentObjects).map(DependentObject::getData).toArray();\n    }\n}\n\n```\n\nLa entidad compuesta especializada `consola` hereda de esta clase base de la siguiente manera.\n\n```java\npublic class MessageDependentObject extends DependentObject<String> {\n\n}\n\npublic class SignalDependentObject extends DependentObject<String> {\n\n}\n\npublic class ConsoleCoarseGrainedObject extends CoarseGrainedObject<String> {\n\n    @Override\n    public String[] getData() {\n        super.getData();\n        return new String[] {\n                dependentObjects[0].getData(), dependentObjects[1].getData()\n        };\n    }\n\n    public void init() {\n        dependentObjects = new DependentObject[] {\n                new MessageDependentObject(), new SignalDependentObject()};\n    }\n}\n\npublic class CompositeEntity {\n\n    private final ConsoleCoarseGrainedObject console = new ConsoleCoarseGrainedObject();\n\n    public void setData(String message, String signal) {\n        console.setData(message, signal);\n    }\n\n    public String[] getData() {\n        return console.getData();\n    }\n}\n```\n\nGestionando ahora la asignación de objetos mensaje y señal con la entidad compuesta `consola`.\n\n```java\nvar console=new CompositeEntity();\n        console.init();\n        console.setData(\"No Danger\",\"Green Light\");\n        Arrays.stream(console.getData()).forEach(LOGGER::info);\n        console.setData(\"Danger\",\"Red Light\");\n        Arrays.stream(console.getData()).forEach(LOGGER::info);\n```\n\n## Diagrama de clases\n\n![alt text](./etc/composite_entity.urm.png \"Patrón de entidad compuesta\")\n\n## Aplicabilidad\n\n* Útil en aplicaciones empresariales donde los objetos de negocio son complejos e involucran varios objetos\n  interdependientes.\n* Ideal para escenarios donde los clientes necesitan trabajar con una interfaz unificada para un conjunto de objetos en\n  lugar de entidades individuales.\n* Aplicable en sistemas que requieren una vista simplificada de un modelo de datos complejo para clientes o servicios\n  externos.\n\n## Usos conocidos\n\n* Aplicaciones empresariales con modelos de negocio complejos, particularmente aquellas que utilizan EJB o marcos\n  empresariales similares.\n* Sistemas que requieren abstracción sobre esquemas de bases de datos complejos para simplificar las interacciones con\n  los clientes.\n* Aplicaciones que necesitan reforzar la consistencia o las transacciones a través de múltiples objetos en una entidad\n  de negocio.\n\n## Consecuencias\n\nVentajas:\n\n* Simplifica las interacciones del cliente con modelos de entidad complejos proporcionando una interfaz unificada.\n* Mejora la reutilización y el mantenimiento de la capa de negocio al desacoplar el código del cliente de los complejos\n  componentes internos de las entidades de negocio.\n* Facilita la gestión de transacciones y la aplicación de la coherencia en un conjunto de objetos relacionados.\n\nContrapartidas:\n\n* Puede introducir un nivel de indirección que podría afectar al rendimiento.\n* Puede dar lugar a interfaces de grano demasiado grueso que podrían no ser tan flexibles para todas las necesidades de\n  los clientes.\n* Requiere un diseño cuidadoso para evitar entidades compuestas hinchadas que sean difíciles de gestionar.\n\n## Patrones relacionados\n\n* [Decorador](https://java-design-patterns.com/patterns/decorator/): Para añadir dinámicamente comportamiento a objetos\n  individuales dentro de la entidad compuesta sin afectar a la estructura.\n* [Fachada](https://java-design-patterns.com/patterns/facade/): Proporciona una interfaz simplificada a un subsistema\n  complejo, de forma similar a como una entidad compuesta simplifica el acceso a un conjunto de objetos.\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Útil para gestionar objetos compartidos dentro de\n  una entidad compuesta para reducir la huella de memoria.\n\n## Créditos\n\n* [Composite Entity Pattern in wikipedia](https://en.wikipedia.org/wiki/Composite_entity_pattern)\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap)\n* [Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML](https://amzn.to/49mslqS)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3xjKdpe)\n"
  },
  {
    "path": "localization/es/composite-view/README.md",
    "content": "---\ntitle: Composite View\nshortTitle: Composite View\ncategory: Structural\nlanguage: es\ntag:\n  - Enterprise patterns\n  - Presentation\n---\n\n## Propósito\n\nEl objetivo principal del patrón de diseño Composite View es componer objetos en estructuras de árbol para representar\njerarquías parte-todo. Esto permite a los clientes tratar objetos individuales y composiciones de objetos de manera\nuniforme, simplificando la gestión de estructuras complejas.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Un sitio de noticias quiere mostrar la fecha actual y las noticias a diferentes usuarios basándose en las preferencias\n> de ese usuario. El sitio de noticias sustituirá en diferentes componentes de alimentación de noticias en función de\n> los intereses del usuario, por defecto a las noticias locales.\n\nEn pocas palabras\n\n> El patrón de vista compuesta consiste en tener una vista principal compuesta por subvistas más pequeñas. El diseño de\n> esta vista compuesta se basa en una plantilla. Un View-manager decide entonces qué subvistas incluir en esta\n> plantilla.\n\nWikipedia dice\n\n> Vistas compuestas que están formadas por múltiples subvistas atómicas. Cada componente de la plantilla puede incluirse\n> dinámicamente en el conjunto y el diseño de la página puede gestionarse independientemente del contenido. Esta\n> solución permite crear una vista compuesta basada en la inclusión y sustitución de fragmentos modulares de plantillas\n> dinámicas y estáticas. Promueve la reutilización de porciones atómicas de la vista fomentando el diseño modular.\n\n**Ejemplo programático**\n\nDado que se trata de un patrón de desarrollo web, se requiere un servidor para demostrarlo. Este ejemplo utiliza Tomcat\n10.0.13 para ejecutar el servlet, y este ejemplo programático sólo funcionará con Tomcat 10+.\n\nEn primer lugar, existe `AppServlet` que es un `HttpServlet` que se ejecuta en Tomcat 10+.\n\n```java\npublic class AppServlet extends HttpServlet {\n    private String msgPartOne = \"<h1>This Server Doesn't Support\";\n    private String msgPartTwo = \"Requests</h1>\\n\"\n            + \"<h2>Use a GET request with boolean values for the following parameters<h2>\\n\"\n            + \"<h3>'name'</h3>\\n<h3>'bus'</h3>\\n<h3>'sports'</h3>\\n<h3>'sci'</h3>\\n<h3>'world'</h3>\";\n\n    private String destination = \"newsDisplay.jsp\";\n\n    public AppServlet() {\n\n    }\n\n    @Override\n    public void doGet(HttpServletRequest req, HttpServletResponse resp)\n            throws ServletException, IOException {\n        RequestDispatcher requestDispatcher = req.getRequestDispatcher(destination);\n        ClientPropertiesBean reqParams = new ClientPropertiesBean(req);\n        req.setAttribute(\"properties\", reqParams);\n        requestDispatcher.forward(req, resp);\n    }\n\n    @Override\n    public void doPost(HttpServletRequest req, HttpServletResponse resp)\n            throws ServletException, IOException {\n        resp.setContentType(\"text/html\");\n        PrintWriter out = resp.getWriter();\n        out.println(msgPartOne + \" Post \" + msgPartTwo);\n\n    }\n\n    @Override\n    public void doDelete(HttpServletRequest req, HttpServletResponse resp)\n            throws ServletException, IOException {\n        resp.setContentType(\"text/html\");\n        PrintWriter out = resp.getWriter();\n        out.println(msgPartOne + \" Delete \" + msgPartTwo);\n\n    }\n\n    @Override\n    public void doPut(HttpServletRequest req, HttpServletResponse resp)\n            throws ServletException, IOException {\n        resp.setContentType(\"text/html\");\n        PrintWriter out = resp.getWriter();\n        out.println(msgPartOne + \" Put \" + msgPartTwo);\n\n    }\n}\n\n```\n\nEste servlet no forma parte del patrón, y simplemente reenvía las peticiones GET a la JSP correcta. Las peticiones PUT,\nPOST y DELETE no están soportadas y simplemente mostrarán un mensaje de error.\n\nLa gestión de la vista en este ejemplo se realiza a través de una clase javabean: `ClientPropertiesBean`, que almacena\nlas preferencias del usuario.\n\n```java\npublic class ClientPropertiesBean implements Serializable {\n\n    private static final String WORLD_PARAM = \"world\";\n    private static final String SCIENCE_PARAM = \"sci\";\n    private static final String SPORTS_PARAM = \"sport\";\n    private static final String BUSINESS_PARAM = \"bus\";\n    private static final String NAME_PARAM = \"name\";\n\n    private static final String DEFAULT_NAME = \"DEFAULT_NAME\";\n    private boolean worldNewsInterest;\n    private boolean sportsInterest;\n    private boolean businessInterest;\n    private boolean scienceNewsInterest;\n    private String name;\n\n    public ClientPropertiesBean() {\n        worldNewsInterest = true;\n        sportsInterest = true;\n        businessInterest = true;\n        scienceNewsInterest = true;\n        name = DEFAULT_NAME;\n\n    }\n\n    public ClientPropertiesBean(HttpServletRequest req) {\n        worldNewsInterest = Boolean.parseBoolean(req.getParameter(WORLD_PARAM));\n        sportsInterest = Boolean.parseBoolean(req.getParameter(SPORTS_PARAM));\n        businessInterest = Boolean.parseBoolean(req.getParameter(BUSINESS_PARAM));\n        scienceNewsInterest = Boolean.parseBoolean(req.getParameter(SCIENCE_PARAM));\n        String tempName = req.getParameter(NAME_PARAM);\n        if (tempName == null || tempName == \"\") {\n            tempName = DEFAULT_NAME;\n        }\n        name = tempName;\n    }\n    // getters and setters generated by Lombok \n}\n```\n\nEste javabean tiene un constructor por defecto, y otro que toma un `HttpServletRequest`.\n\nEste segundo constructor toma el objeto de solicitud, analiza los parámetros de la solicitud que contienen las\npreferencias del usuario para los diferentes tipos de noticias.\n\nLa plantilla para la página de noticias está en `newsDisplay.jsp`.\n\n```html\n\n<html>\n<head>\n    <style>\n        h1 {\n            text-align: center;\n        }\n\n        h2 {\n            text-align: center;\n        }\n\n        h3 {\n            text-align: center;\n        }\n\n        .centerTable {\n            margin-left: auto;\n            margin-right: auto;\n        }\n\n        table {\n            border: 1px solid black;\n        }\n\n        tr {\n            text-align: center;\n        }\n\n        td {\n            text-align: center;\n        }\n    </style>\n</head>\n<body>\n<%ClientPropertiesBean propertiesBean = (ClientPropertiesBean) request.getAttribute(\"properties\");%>\n<h1>Welcome <%= propertiesBean.getName()%></h1>\n<jsp:include page=\"header.jsp\"></jsp:include>\n<table class=\"centerTable\">\n\n    <tr>\n        <td></td>\n        <% if(propertiesBean.isWorldNewsInterest()) { %>\n        <td><%@include file=\"worldNews.jsp\"%></td>\n        <% } else { %>\n        <td><%@include file=\"localNews.jsp\"%></td>\n        <% } %>\n        <td></td>\n    </tr>\n    <tr>\n        <% if(propertiesBean.isBusinessInterest()) { %>\n        <td><%@include file=\"businessNews.jsp\"%></td>\n        <% } else { %>\n        <td><%@include file=\"localNews.jsp\"%></td>\n        <% } %>\n        <td></td>\n        <% if(propertiesBean.isSportsInterest()) { %>\n        <td><%@include file=\"sportsNews.jsp\"%></td>\n        <% } else { %>\n        <td><%@include file=\"localNews.jsp\"%></td>\n        <% } %>\n    </tr>\n    <tr>\n        <td></td>\n        <% if(propertiesBean.isScienceNewsInterest()) { %>\n        <td><%@include file=\"scienceNews.jsp\"%></td>\n        <% } else { %>\n        <td><%@include file=\"localNews.jsp\"%></td>\n        <% } %>\n        <td></td>\n    </tr>\n</table>\n</body>\n</html>\n```\n\nEsta página JSP es la plantilla. Declara una tabla con tres filas, con un componente en la primera fila, dos componentes\nen la segunda fila y un componente en la tercera fila.\n\nLos scriplets en el archivo son parte de la estrategia de gestión de vistas que incluyen diferentes subvistas atómicas\nbasadas en las preferencias del usuario en el Javabean.\n\nA continuación se muestran dos ejemplos de las subvistas atómicas simuladas utilizadas en el\ncompuesto: `businessNews.jsp`\n\n```html\n\n<html>\n<head>\n    <style>\n        h2 {\n            text-align: center;\n        }\n\n        table {\n            border: 1px solid black;\n        }\n\n        tr {\n            text-align: center;\n        }\n\n        td {\n            text-align: center;\n        }\n    </style>\n</head>\n<body>\n<h2>\n    Generic Business News\n</h2>\n<table style=\"margin-right: auto; margin-left: auto\">\n    <tr>\n        <td>Stock prices up across the world</td>\n        <td>New tech companies to invest in</td>\n    </tr>\n    <tr>\n        <td>Industry leaders unveil new project</td>\n        <td>Price fluctuations and what they mean</td>\n    </tr>\n</table>\n</body>\n</html>\n```\n\n`localNews.jsp`\n\n```html\n\n<html>\n<body>\n<div style=\"text-align: center\">\n    <h3>\n        Generic Local News\n    </h3>\n    <ul style=\"list-style-type: none\">\n        <li>\n            Mayoral elections coming up in 2 weeks\n        </li>\n        <li>\n            New parking meter rates downtown coming tomorrow\n        </li>\n        <li>\n            Park renovations to finish by the next year\n        </li>\n        <li>\n            Annual marathon sign ups available online\n        </li>\n    </ul>\n</div>\n</body>\n</html>\n```\n\nLos resultados son los siguientes:\n\n1) El usuario ha puesto su nombre como `Tammy` en los parámetros de la petición y ninguna\n   preferencia: ![alt text](./etc/images/noparam.png)\n2) El usuario ha puesto su nombre como `Johnny` en los parámetros de la petición y tiene preferencia por noticias del\n   mundo, negocios y ciencia: ![alt text](./etc/images/threeparams.png)\n\nLas distintas subvistas como `worldNews.jsp`, `businessNews.jsp`, etc. se incluyen condicionalmente en función de los\nparámetros de la solicitud.\n\n**Cómo utilizarlo**\n\nPara probar este ejemplo, asegúrese de tener Tomcat 10+ instalado. Configure su IDE para construir un archivo WAR a\npartir del módulo y despliegue ese archivo en el servidor\n\nIntelliJ:\n\nEn `Run` y `edit configurations` Asegúrate de que el servidor Tomcat es una de las configuraciones de ejecución. Vaya a\nla pestaña de despliegue y asegúrese de que se está construyendo un artefacto llamado `composite-view:war exploded`. Si\nno está presente, añada uno.\n\nAsegúrate de que el artefacto se está construyendo a partir del contenido del directorio `web` y de los resultados de la\ncompilación del módulo. Apunta la salida del artefacto a un lugar conveniente. Ejecute la configuración y vea la página\nde destino, siga las instrucciones de esa página para continuar.\n\n## Diagrama de clases\n\n![alt text](./etc/composite_view.png)\n\nEl diagrama de clases aquí muestra el Javabean que es el gestor de vistas. Las vistas son JSP's dentro del directorio\nweb.\n\n## Aplicabilidad:\n\nUtiliza el patrón de diseño Composite View cuando:\n\n## Desea representar jerarquías parciales de objetos.\n\n* Esperas que las estructuras compuestas puedan incluir nuevos componentes en el futuro.\n* Desea que los clientes puedan ignorar la diferencia entre composiciones de objetos y objetos individuales. Los\n  clientes tratarán todos los objetos de la estructura compuesta de manera uniforme.\n\n## Usos conocidos\n\n* Interfaces gráficas de usuario (GUI) en las que los widgets pueden contener otros widgets (por ejemplo, una ventana\n  con paneles, botones y campos de texto).\n* Estructuras de documentos, como la representación de tablas que contienen filas, que a su vez contienen celdas, todas\n  las cuales pueden tratarse como elementos de una jerarquía unificada.\n\n## Consecuencias\n\nVentajas:\n\n* Gran flexibilidad a la hora de añadir nuevos componentes: Como los compuestos y los nodos hoja se tratan de manera\n  uniforme, es más fácil añadir nuevos tipos de componentes.\n* Código cliente simplificado: Los clientes pueden tratar las estructuras compuestas y los elementos individuales de\n  manera uniforme, lo que reduce la complejidad del código cliente.\n\nContrapartidas:\n\n* Generalización excesiva: El diseño del sistema puede volverse más complejo si haces que todo sea compuesto,\n  especialmente si tu aplicación no lo requiere.\n* Dificultad en la aplicación de restricciones: Puede ser más difícil restringir los componentes de un compuesto a sólo\n  ciertos tipos.\n\n## Patrones Relacionados\n\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Mientras que Decorator se utiliza para añadir\n  responsabilidades a los objetos, Composite está pensado para construir estructuras de objetos.\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Composite puede combinarse a menudo con Flyweight\n  para implementar nodos hoja compartidos en una estructura compuesta, reduciendo la huella de memoria.\n* [Cadena de responsabilidad](https://java-design-patterns.com/patterns/chain-of-responsibility/): Puede usarse con\n  Composite para permitir a los componentes pasar peticiones a través de la jerarquía.\n* [Composite](https://java-design-patterns.com/patterns/composite/)\n* [Ayudante de vista](https://www.oracle.com/java/technologies/viewhelper.html)\n\n## Créditos\n\n* [Core J2EE Patterns - Composite View](https://www.oracle.com/java/technologies/composite-view.html)\n* [Composite View Design Pattern – Core J2EE Patterns](https://www.dineshonjava.com/composite-view-design-pattern/)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/49jpQG3)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/3xfntGJ)\n"
  },
  {
    "path": "localization/es/context-object/README.md",
    "content": "---\ntitle: Context object\nshortTitle: Context object\ncategory: Creational\nlanguage: es\ntags:\n  - Data access\n---\n\n## Nombre / Clasificación\n\nContext Object\n\n## También conocido como\n\nContext, Encapsulate Context\n\n## Propósito\n\nDesacoplar los datos de las clases específicas del protocolo y almacenar los datos del ámbito en un objeto independiente\nde la tecnología del protocolo subyacente.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Esta aplicación tiene diferentes capas etiquetadas como A, B y C, cada una extrayendo información específica de un\n> contexto similar para su uso posterior en el software. Pasar cada pieza de información individualmente sería\n> ineficiente, se necesita un método para almacenar y pasar información de manera eficiente.\n> En palabras sencillas\n\n> Crea un objeto y almacena los datos allí y pasa este objeto a donde se necesita.\n\n[Core J2EE Patterns](http://corej2eepatterns.com/ContextObject.htm) dice\n\n> Utilice un objeto de contexto (Context Object) para encapsular el estado de una manera independiente del protocolo para ser compartido\n> en toda tu aplicación.\n\n**Ejemplo programático**\n\nDefinimos qué datos contiene un objeto de contexto (Context Object) de servicio `ServiceContext`.\n\n```Java\npublic class ServiceContext {\n\n    String ACCOUNT_SERVICE, SESSION_SERVICE, SEARCH_SERVICE;\n\n    public void setACCOUNT_SERVICE(String ACCOUNT_SERVICE) {\n        this.ACCOUNT_SERVICE = ACCOUNT_SERVICE;\n    }\n\n    public void setSESSION_SERVICE(String SESSION_SERVICE) {\n        this.SESSION_SERVICE = SESSION_SERVICE;\n    }\n\n    public void setSEARCH_SERVICE(String SEARCH_SERVICE) {\n        this.SEARCH_SERVICE = SEARCH_SERVICE;\n    }\n\n    public String getACCOUNT_SERVICE() {\n        return ACCOUNT_SERVICE;\n    }\n\n    public String getSESSION_SERVICE() {\n        return SESSION_SERVICE;\n    }\n\n    public String getSEARCH_SERVICE() {\n        return SEARCH_SERVICE;\n    }\n    \n    public String toString() { return ACCOUNT_SERVICE + \" \" + SESSION_SERVICE + \" \" + SEARCH_SERVICE;}\n}\n```\n\nSe crea una interfaz `ServiceContextFactory` utilizada en partes de la aplicación para crear objetos de contexto.\n\n```Java\npublic class ServiceContextFactory {\n\n    public static ServiceContext createContext() {\n        return new ServiceContext();\n    }\n}\n```\n\nInstanciar el objeto de contexto en la primera capa `LayerA` y la capa contigua `LayerB` hasta llamar al contexto en la capa actual `LayerC`,\nque estructura el objeto.\n\n```Java\npublic class LayerA {\n\n    private static ServiceContext context;\n\n    public LayerA() {\n        context = ServiceContextFactory.createContext();\n    }\n\n    public static ServiceContext getContext() {\n        return context;\n    }\n\n    public void addAccountInfo(String accountService) {\n        context.setACCOUNT_SERVICE(accountService);\n    }\n}\n\npublic class LayerB {\n\n    private static ServiceContext context;\n\n    public LayerB(LayerA layerA) {\n        this.context = layerA.getContext();\n    }\n\n    public static ServiceContext getContext() {\n        return context;\n    }\n\n    public void addSessionInfo(String sessionService) {\n        context.setSESSION_SERVICE(sessionService);\n    }\n}\n\npublic class LayerC {\n\n    public static ServiceContext context;\n\n    public LayerC(LayerB layerB) {\n        this.context = layerB.getContext();\n    }\n\n    public static ServiceContext getContext() {\n        return context;\n    }\n\n    public void addSearchInfo(String searchService) {\n        context.setSEARCH_SERVICE(searchService);\n    }\n}\n```\n\nHe aquí el objeto de contexto y las capas en acción.\n\n```Java\nvar layerA = new LayerA();\nlayerA.addAccountInfo(SERVICE);\nLOGGER.info(\"Context = {}\",layerA.getContext());\nvar layerB = new LayerB(layerA);\nlayerB.addSessionInfo(SERVICE);\nLOGGER.info(\"Context = {}\",layerB.getContext());\nvar layerC = new LayerC(layerB);\nlayerC.addSearchInfo(SERVICE);\nLOGGER.info(\"Context = {}\",layerC.getContext());\n```\n\nSalida del programa:\n\n```Java\nContext = SERVICE null null\nContext = SERVICE SERVICE null\nContext = SERVICE SERVICE SERVICE\n```\n\n## Diagrama de clases\n\n![alt text](./etc/context-object.png \"Context object\")\n\n## Aplicabilidad\n\nUtilizar el patrón Objeto Contexto (Context Object) para:\n\n* Compartir información entre diferentes capas del sistema.\n* Desacoplar datos de software de contextos específicos de protocolo.\n* Exponer solo las API relevantes dentro del contexto.\n\n## Usos conocidos\n\n* [Spring: ApplicationContext](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html)\n* [Oracle: SecurityContext](https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/SecurityContext.html)\n* [Oracle: ServletContext](https://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html)\n\n## Créditos\n\n* [Core J2EE Design Patterns](https://amzn.to/3IhcY9w)\n* [Core J2EE Design Patterns website - Context Object](http://corej2eepatterns.com/ContextObject.htm)\n* [Allan Kelly - The Encapsulate Context Pattern](https://accu.org/journals/overload/12/63/kelly_246/)\n* [Arvid S. Krishna et al. - Context Object](https://www.dre.vanderbilt.edu/~schmidt/PDF/Context-Object-Pattern.pdf)\n"
  },
  {
    "path": "localization/es/converter/README.md",
    "content": "---\ntitle: Converter\nshortTitle: Converter\ncategory: Creational\nlanguage: es\ntag:\n  - Decoupling\n---\n\n## Propósito\n\nEl propósito del patrón Conversor (Converter) es proporcionar una forma genérica y común de conversión bidireccional\nentre tipos correspondientes, permitiendo una implementación limpia en la que los tipos no\ntienen que conocerse entre sí. Además, el patrón Converter introduce la asignación bidireccional de colecciones\nbidireccional, reduciendo al mínimo el código repetitivo.\n\n## Explicación\n\nEjemplo del mundo real\n\n> En las aplicaciones del mundo real, a menudo se da el caso de que la capa de base de datos consta de entidades que\n> necesitan ser mapeadas en DTO para su uso en la capa de lógica de negocio. Un mapeo similar se realiza para\n> potencialmente enorme cantidad de clases y necesitamos una forma genérica de lograrlo.\n\nEn palabras sencillas\n\n> El patrón de conversión (Converter) facilita la asignación de instancias de una clase a instancias de otra clase.\n\n**Ejemplo programático**\n\nNecesitamos una solución genérica para el problema del mapeo. Para ello, introduzcamos un convertidor genérico.\n\n```java\npublic class Converter<T, U> {\n\n  private final Function<T, U> fromDto;\n  private final Function<U, T> fromEntity;\n\n  public Converter(final Function<T, U> fromDto, final Function<U, T> fromEntity) {\n    this.fromDto = fromDto;\n    this.fromEntity = fromEntity;\n  }\n\n  public final U convertFromDto(final T dto) {\n    return fromDto.apply(dto);\n  }\n\n  public final T convertFromEntity(final U entity) {\n    return fromEntity.apply(entity);\n  }\n\n  public final List<U> createFromDtos(final Collection<T> dtos) {\n    return dtos.stream().map(this::convertFromDto).collect(Collectors.toList());\n  }\n\n  public final List<T> createFromEntities(final Collection<U> entities) {\n    return entities.stream().map(this::convertFromEntity).collect(Collectors.toList());\n  }\n}\n```\n\nLos convertidores especializados heredan de esta clase base de la siguiente manera.\n\n```java\npublic class UserConverter extends Converter<UserDto, User> {\n\n  public UserConverter() {\n    super(UserConverter::convertToEntity, UserConverter::convertToDto);\n  }\n\n  private static UserDto convertToDto(User user) {\n    return new UserDto(user.getFirstName(), user.getLastName(), user.isActive(), user.getUserId());\n  }\n\n  private static User convertToEntity(UserDto dto) {\n    return new User(dto.getFirstName(), dto.getLastName(), dto.isActive(), dto.getEmail());\n  }\n\n}\n```\n\nAhora el mapeo entre `User` y `UserDto` se vuelve trivial.\n\n```java\nvar userConverter = new UserConverter();\nvar dtoUser = new UserDto(\"John\", \"Doe\", true, \"whatever[at]wherever.com\");\nvar user = userConverter.convertFromDto(dtoUser);\n```\n\n## Diagrama de Clases\n\n![alt text](./etc/converter.png \"Converter Pattern\")\n\n## Aplicabilidad\n\nUtilice el patrón de conversión en las siguientes situaciones:\n\n* Cuando tiene tipos que lógicamente se corresponden entre sí y necesita convertir entidades\n  entre ellos.\n* Cuando quieras proporcionar diferentes formas de conversión de tipos dependiendo del contexto.\n* Siempre que introduzca un DTO (Data transfer object), probablemente necesitará convertirlo en la\n  equivalencia de dominio.\n\n## Créditos\n\n* [Converter Pattern in Java 8](http://www.xsolve.pl/blog/converter-pattern-in-java-8/)\n"
  },
  {
    "path": "localization/es/crtp/README.md",
    "content": "---\ntitle: Curiously Recurring Template Pattern\nlanguage: es\ncategory: Structural\ntag:\n- Extensibility\n- Instantiation\n---\n\n## Nombre / clasificación\n\nCuriously Recurring Template Pattern\n\n## También conocido como\n\nRecursive Type Bound, Recursive Generic\n\n## Propósito\n\nPermitir que los componentes derivados hereden ciertas funcionalidades de un componente base que sean compatibles con el tipo derivado.\n\n## Explicación\n\nUn ejemplo real\n\n> Para una promoción de artes marciales mixtas que esté planificando un evento, es crucial asegurarse de que los combates se organicen entre atletas de la misma categoría de peso. Así se evitan los enfrentamientos entre luchadores de tallas muy diferentes, como un peso pesado contra un peso gallo.\n\nEn pocas palabras\n\n> Hacer que ciertos métodos dentro de un tipo acepten argumentos específicos de sus subtipos.\n\nWikipedia dice\n\n> El patrón de plantilla curiosamente recurrente (CRTP) es un modismo, originalmente en C++, en el que una clase X deriva de una instanciación de plantilla de clase usando la propia X como argumento de plantilla.\n\n**Ejemplo programático**\n\nDefinamos la interfaz genérica Fighter\n\n```java\npublic interface Fighter<T> {\n\n  void fight(T t);\n\n}\n```\n\nLa clase `MMAFighter` se utiliza para crear luchadores que se distinguen por su categoría de peso.\n\n```java\npublic class MmaFighter<T extends MmaFighter<T>> implements Fighter<T> {\n\n  private final String name;\n  private final String surname;\n  private final String nickName;\n  private final String speciality;\n\n  public MmaFighter(String name, String surname, String nickName, String speciality) {\n    this.name = name;\n    this.surname = surname;\n    this.nickName = nickName;\n    this.speciality = speciality;\n  }\n\n  @Override\n  public void fight(T opponent) {\n    LOGGER.info(\"{} is going to fight against {}\", this, opponent);\n  }\n\n  @Override\n  public String toString() {\n    return name + \" \\\"\" + nickName + \"\\\" \" + surname;\n  }\n```\n\nLos siguientes son algunos subtipos de `MmaFighter`\n\n```java\nclass MmaBantamweightFighter extends MmaFighter<MmaBantamweightFighter> {\n\n  public MmaBantamweightFighter(String name, String surname, String nickName, String speciality) {\n    super(name, surname, nickName, speciality);\n  }\n\n}\n\npublic class MmaHeavyweightFighter extends MmaFighter<MmaHeavyweightFighter> {\n\n  public MmaHeavyweightFighter(String name, String surname, String nickName, String speciality) {\n    super(name, surname, nickName, speciality);\n  }\n\n}\n```\n\nUn luchador puede enfrentarse a un oponente de la misma categoría de peso, si el oponente es de una categoría de peso diferente\nse produce un error.\n\n```java\nMmaBantamweightFighter fighter1 = new MmaBantamweightFighter(\"Joe\", \"Johnson\", \"The Geek\", \"Muay Thai\");\nMmaBantamweightFighter fighter2 = new MmaBantamweightFighter(\"Ed\", \"Edwards\", \"The Problem Solver\", \"Judo\");\nfighter1.fight(fighter2); // This is fine\n\nMmaHeavyweightFighter fighter3 = new MmaHeavyweightFighter(\"Dave\", \"Davidson\", \"The Bug Smasher\", \"Kickboxing\");\nMmaHeavyweightFighter fighter4 = new MmaHeavyweightFighter(\"Jack\", \"Jackson\", \"The Pragmatic\", \"Brazilian Jiu-Jitsu\");\nfighter3.fight(fighter4); // This is fine too\n\nfighter1.fight(fighter3); // This will raise a compilation error\n```\n\n## Diagrama de clases\n\n![alt text](./etc/crtp.png \"Diagrama de clases CRTP\")\n\n## Aplicabilidad\n\nUtilice el Patrón de Plantilla Curiosamente Recurrente cuando\n\n* Tienes conflictos de tipos al encadenar métodos en una jerarquía de objetos\n* Desea utilizar un método de clase parametrizado que pueda aceptar subclases de la clase como argumentos, permitiendo que se aplique a objetos que heredan de la clase\n* Desea que ciertos métodos funcionen sólo con instancias del mismo tipo, por ejemplo, para lograr la comparabilidad mutua.\n\n## Tutoriales\n\n* [El blog de NuaH](https://nuah.livejournal.com/328187.html)\n* Respuesta de Yogesh Umesh Vaity a [¿Qué significa \"Recursive type bound\" en Generics?](https://stackoverflow.com/questions/7385949/what-does-recursive-type-bound-in-generics-mean)\n\n## Usos conocidos\n\n* [java.lang.Enum](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Enum.html)\n\n## Créditos\n\n* [How do I decrypt \"Enum<E extends Enum\\<E>>\"?](http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ106)\n* Chapter 5 Generics, Item 30 in [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n"
  },
  {
    "path": "localization/es/data-locality/README.md",
    "content": "---\ntitle: Data Locality\nshortTitle: Data Locality\ncategory: Behavioral\nlanguage: es\ntag:\n - Game programming\n - Performance\n---\n\n## Propósito\nAcelera el acceso a la memoria organizando los datos para aprovechar la caché de la CPU.\n\nLas CPU modernas disponen de cachés para acelerar el acceso a la memoria. Éstas pueden acceder mucho más rápido a la memoria adyacente a la memoria a la que se ha accedido recientemente. Aprovéchate de ello para mejorar el rendimiento aumentando la localidad de los datos, manteniéndolos en memoria contigua en el orden en que los procesas.\n\n## Diagrama de clases\n![alt text](./etc/data-locality.urm.png \"Data Locality pattern class diagram\")\n\n## Aplicabilidad\n\n* Como la mayoría de las optimizaciones, la primera pauta para usar el patrón Data Locality es cuando se tiene un problema de rendimiento.\n* Con este patrón específicamente, también querrás estar seguro de que tus problemas de rendimiento son causados por pérdidas de caché.\n\n## Ejemplo del mundo real\n\n* El motor de juego [Artemis](http://gamadu.com/artemis/) es uno de los primeros y más conocidos frameworks que utiliza IDs simples para las entidades del juego.\n\n## Créditos\n\n* [Game Programming Patterns Optimization Patterns: Data Locality](http://gameprogrammingpatterns.com/data-locality.html)"
  },
  {
    "path": "localization/es/decorator/README.md",
    "content": "---\ntitle: Decorator\nshortTitle: Decorator\ncategory: Structural\nlanguage: es\ntag:\n  - Gang of Four\n  - Extensibility\n---\n\n## También conocido como\n\nWrapper\n\n## Propósito\n\nAdjunte responsabilidades adicionales a un objeto de forma dinámica. Los decoradores proporcionan una alternativa\nflexible a la subclase para ampliar la funcionalidad.\n\n## Explicación\n\nEjemplo real\n\n> En las colinas cercanas vive un trol furioso. Normalmente va con las manos desnudas, pero a veces lleva un arma. Para\n> armar al troll no es necesario crear un nuevo troll sino decorarlo dinámicamente con un arma adecuada.\n\nEn pocas palabras\n\n> El patrón decorador permite cambiar dinámicamente el comportamiento de un objeto en tiempo de ejecución envolviéndolo\n> en un objeto de una clase decoradora.\n\nWikipedia says\n\n> En programación orientada a objetos, el patrón decorador es un patrón de diseño que permite añadir comportamiento a un\n> objeto individual, ya sea de forma estática o dinámica, sin afectar al comportamiento de otros objetos de la misma\n> clase. El patrón decorador suele ser útil para adherirse al Principio de Responsabilidad Única, ya que permite dividir\n> la funcionalidad entre clases con áreas de interés únicas, así como al Principio Abierto-Cerrado, al permitir extender\n> la funcionalidad de una clase sin modificarla.\n\n**Ejemplo programático**\n\nTomemos el ejemplo del troll. En primer lugar tenemos un `SimpleTroll` que implementa la interfaz `Troll`:\n\n```java\npublic interface Troll {\n  void atacar();\n  int getPoderAtaque();\n  void huirBatalla();\n}\n\n@Slf4j\npublic class SimpleTroll implements Troll {\n\n  @Override\n  public void atacar() {\n    LOGGER.info(\"¡El troll intenta atraparte!\");\n  }\n\n  @Override\n  public int getPoderAtaque() {\n    return 10;\n  }\n\n  @Override\n  public void huirBatalla() {\n    LOGGER.info(\"¡El troll chilla de horror y huye!\");\n  }\n}\n```\n\nA continuación, queremos añadir un palo para el troll. Podemos hacerlo de forma dinámica mediante el uso de un\ndecorador:\n\n```java\n@Slf4j\npublic class TrollConGarrote implements Troll {\n\n  private final Troll decorado;\n\n  public TrollConGarrote(Troll decorado) {\n    this.decorado = decorado;\n  }\n\n  @Override\n  public void atacar() {\n    decorado.atacar();\n    LOGGER.info(\"¡El troll te golpea con un garrote!\");\n  }\n\n  @Override\n  public int getPoderAtaque() {\n    return decorado.getPoderAtaque() + 10;\n  }\n\n  @Override\n  public void huirBatalla() {\n    decorado.huirBatalla();\n  }\n}\n```\n\nAquí está el troll en acción:\n\n```java\n// troll simple\nLOGGER.info(\"Un troll de aspecto simple se acerca.\");\nvar troll = new SimpleTroll();\ntroll.atacar();\ntroll.huirBatalla();\nLOGGER.info(\"Poder del troll simple: {}.\\n\", troll.getPoderAtaque());\n\n// cambia el comportamiento del troll simple agregando un decorador\nLOGGER.info(\"Un troll con un enorme garrote te sorprende.\");\nvar trollConGarrote = new TrollConGarrote(troll);\ntrollConGarrote.atacar();\ntrollConGarrote.huirBatalla();\nLOGGER.info(\"Poder del troll con garrote: {}.\\n\", trollConGarrote.getPoderAtaque());\n```\n\nSalida del programa:\n\n```java\nUn troll de aspecto simple se acerca. \n¡El troll intenta atraparte!\n¡El troll chilla de horror y huye!\nPoder del troll simple: 10.\n\nUn troll con un enorme garrote te sorprende.\n¡El troll intenta atraparte!\n¡El troll te golpea con un garrote!\n¡El troll chilla de horror y huye!\nPoder del troll con garrote: 20.\n```\n\n## Diagrama de clases\n\n![alt text](./etc/decorator.urm.png \"Decorator pattern class diagram\")\n\n## Aplicabilidad\n\nDecorator se utiliza para:\n\n* Añadir responsabilidades a objetos individuales de forma dinámica y transparente, es decir, sin\n  afectar a otros objetos.\n* Para responsabilidades que pueden ser retiradas.\n* Cuando la extensión por subclase es poco práctica. A veces es posible un gran número de extensiones independientes\n  son posibles y producirían una explosión de subclases para soportar cada combinación. O la definición de una clase\n  puede estar oculta o no estar disponible para subclases.\n\n## Tutoriales\n\n* [Decorator Pattern Tutorial](https://www.journaldev.com/1540/decorator-design-pattern-in-java-example)\n\n## Usos conocidos\n\n* [java.io.InputStream](http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html), [java.io.OutputStream](http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html),\n  [java.io.Reader](http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html)\n  y [java.io.Writer](http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html)\n* [java.util.Collections#synchronizedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedCollection-java.util.Collection-)\n* [java.util.Collections#unmodifiableXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableCollection-java.util.Collection-)\n* [java.util.Collections#checkedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedCollection-java.util.Collection-java.lang.Class-)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n"
  },
  {
    "path": "localization/es/delegation/README.md",
    "content": "---\ntitle: Delegation\nshortTitle: Delegation\ncategory: Structural\nlanguage: es\ntag:\n  - Decoupling\n---\n\n## También conocido como\n\nProxy Pattern\n\n## Propósito\n\nEs una técnica en la que un objeto expresa cierto comportamiento al exterior pero en realidad delega la responsabilidad\nde implementar ese comportamiento en un objeto asociado.\n\n## Explanation\n\nReal-world example\n\n> Imaginemos que tenemos aventureros que luchan contra monstruos con diferentes armas dependiendo de sus habilidades y\n> destrezas. Debemos ser capaces de equiparles con diferentes sin tener que modificar su código fuente para cada una de\n> ellas. El patrón de delegación lo hace posible delegando el trabajo dinámico a un objeto específico que implementa una\n> interfaz con métodos relevantes.\n\nWikipedia dice\n\n> En programación orientada a objetos, la delegación se refiere a la evaluación de un miembro (propiedad o método) de un\n> objeto (el receptor) en el contexto de otro objeto original (el emisor). La delegación puede hacerse explícitamente,\n> pasando el objeto emisor al objeto receptor, lo que puede hacerse en cualquier lenguaje orientado a objetos; o\n> implícitamente, mediante las reglas de búsqueda de miembros del lenguaje, lo que requiere soporte del lenguaje para la\n> función.\n\n**Ejemplo programático**\n\nTenemos una interfaz `Printer` y tres implementaciones `CanonPrinter`, `EpsonPrinter` y `HpPrinter`.\n\n```java\npublic interface Printer {\n  void print(final String message);\n}\n\n@Slf4j\npublic class CanonPrinter implements Printer {\n  @Override\n  public void print(String message) {\n    LOGGER.info(\"Canon Printer : {}\", message);\n  }\n}\n\n@Slf4j\npublic class EpsonPrinter implements Printer {\n  @Override\n  public void print(String message) {\n    LOGGER.info(\"Epson Printer : {}\", message);\n  }\n}\n\n@Slf4j\npublic class HpPrinter implements Printer {\n  @Override\n  public void print(String message) {\n    LOGGER.info(\"HP Printer : {}\", message);\n  }\n}\n```\n\nEl `PrinterController` puede ser utilizado como un `Printer` delegando cualquier trabajo manejado por este\na un objeto que la implemente.\n\n```java\npublic class PrinterController implements Printer {\n  \n  private final Printer printer;\n  \n  public PrinterController(Printer printer) {\n    this.printer = printer;\n  }\n  \n  @Override\n  public void print(String message) {\n    printer.print(message);\n  }\n}\n```\n\nNow on the client code printer controllers can print messages differently depending on the\nobject they're delegating that work to.\n\n```java\nprivate static final String MESSAGE_TO_PRINT = \"hello world\";\n\nvar hpPrinterController = new PrinterController(new HpPrinter());\nvar canonPrinterController = new PrinterController(new CanonPrinter());\nvar epsonPrinterController = new PrinterController(new EpsonPrinter());\n\nhpPrinterController.print(MESSAGE_TO_PRINT);\ncanonPrinterController.print(MESSAGE_TO_PRINT);\nepsonPrinterController.print(MESSAGE_TO_PRINT)\n```\n\nSalida del programa:\n\n```java\nHP Printer : hello world\nCanon Printer : hello world\nEpson Printer : hello world\n```\n\n## Diagrama de clases\n\n![alt text](./etc/delegation.png \"Delegate\")\n\n## Aplicabilidad\n\nUtilice el patrón Delegate para conseguir lo siguiente\n\n* Reducir el acoplamiento de los métodos a su clase\n* Componentes que se comportan de forma idéntica, pero teniendo en cuenta que esta situación puede cambiar en el futuro.\n\n## Créditos\n\n* [Delegate Pattern: Wikipedia ](https://en.wikipedia.org/wiki/Delegation_pattern)\n* [Proxy Pattern: Wikipedia ](https://en.wikipedia.org/wiki/Proxy_pattern)\n"
  },
  {
    "path": "localization/es/dependency-injection/README.md",
    "content": "---\ntitle: Dependency Injection\nshortTitle: Dependency Injection\ncategory: Creational\nlanguage: es\ntag:\n  - Decoupling\n---\n\n## Propósito\n\nLa inyección de dependencias es un patrón de diseño de software en el que una o más dependencias (o servicios)\nse inyectan, o se pasan por referencia, a un objeto dependiente (o cliente) y pasan a formar parte del estado del\ncliente. El patrón separa la creación de las dependencias de un cliente de su propio comportamiento,\nlo que permite que los diseños de los programas estén poco acoplados y sigan los principios de inversión de control y\nresponsabilidad única.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Al viejo mago le gusta llenar su pipa y fumar tabaco de vez en cuando. Sin embargo, no quiere depender de una sola\n> marca de tabaco, sino que le gusta poder disfrutar de todas ellas de manera intercambiable.\n\nEn palabras sencillas\n\n> La Inyección de Dependencias separa la creación de las dependencias del cliente de su propio comportamiento.\n\nWikipedia dice\n\n> En ingeniería de software, la inyección de dependencias es una técnica en la que un objeto recibe otros objetos de los\n> que depende. Estos otros objetos se llaman dependencias.\n\n**Ejemplo programático**\n\nPresentemos primero la interfaz tabaco `Tobacco` y las marcas concretas.\n\n```java\n@Slf4j\npublic abstract class Tobacco {\n\n  public void smoke(Wizard wizard) {\n    LOGGER.info(\"{} smoking {}\", wizard.getClass().getSimpleName(),\n        this.getClass().getSimpleName());\n  }\n}\n\npublic class SecondBreakfastTobacco extends Tobacco {\n}\n\npublic class RivendellTobacco extends Tobacco {\n}\n\npublic class OldTobyTobacco extends Tobacco {\n}\n```\n\nA continuación se muestra la interfaz `Wizard` y su implementación.\n\n```java\npublic interface Wizard {\n\n  void smoke();\n}\n\npublic class AdvancedWizard implements Wizard {\n\n  private final Tobacco tobacco;\n\n  public AdvancedWizard(Tobacco tobacco) {\n    this.tobacco = tobacco;\n  }\n\n  @Override\n  public void smoke() {\n    tobacco.smoke(this);\n  }\n}\n```\n\nY por último podemos demostrar lo fácil que es darle al viejo mago cualquier marca de tabaco `Tobacco`.\n\n```java\n    var advancedWizard = new AdvancedWizard(new SecondBreakfastTobacco());\n    advancedWizard.smoke();\n```\n\n## Diagrama de Clases\n\n![alt text](./etc/dependency-injection.png \"Dependency Injection\")\n\n## Aplicabilidad\n\nUtilice el patrón de Inyección de Dependencia cuando:\n\n* Cuando necesites eliminar el conocimiento de la implementación concreta del objeto.\n* Para permitir pruebas unitarias de clases de forma aislada utilizando objetos simulados o stubs.\n\n## Créditos\n\n* [Dependency Injection Principles, Practices, and Patterns](https://www.amazon.com/gp/product/161729473X/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=161729473X&linkId=57079257a5c7d33755493802f3b884bd)\n* [Clean Code: A Handbook of Agile Software Craftsmanship](https://www.amazon.com/gp/product/0132350882/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0132350882&linkCode=as2&tag=javadesignpat-20&linkId=2c390d89cc9e61c01b9e7005c7842871)\n* [Java 9 Dependency Injection: Write loosely coupled code with Spring 5 and Guice](https://www.amazon.com/gp/product/1788296257/ref=as_li_tl?ie=UTF8&tag=javadesignpat-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=1788296257&linkId=4e9137a3bf722a8b5b156cce1eec0fc1)\n* [Google Guice: Agile Lightweight Dependency Injection Framework](https://www.amazon.com/gp/product/1590599977/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1590599977&linkId=3b10c90b7ba480a1b7777ff38000f956)\n"
  },
  {
    "path": "localization/es/dirty-flag/README.md",
    "content": "---\ntitle: Dirty Flag\nshortTitle: Dirty Flag\ncategory: Behavioral\nlanguage: es\ntag:\n - Game programming\n - Performance\n---\n\n## También conocido como\n* IsDirty pattern\n\n## Propósito\nEvitar la costosa readquisición de recursos. Los recursos conservan su identidad, se guardan en algún almacenamiento de acceso rápido y se reutilizan para evitar tener que adquirirlos de nuevo.\n\n## Diagrama de clases\n![alt text](./etc/dirty-flag.png \"Dirty Flag\")\n\n## Aplicabilidad\nUtilice el patrón Dirty Flag cuando\n\n* La adquisición, inicialización y liberación repetitiva del mismo recurso causa una sobrecarga de rendimiento innecesaria.\n\n## Créditos\n\n* [Design Patterns: Dirty Flag](https://www.takeupcode.com/podcast/89-design-patterns-dirty-flag/)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n"
  },
  {
    "path": "localization/es/double-buffer/README.md",
    "content": "---\ntitle: Double Buffer\nshortTitle: Double Buffer\ncategory: Behavioral\nlanguage: es\ntag:\n    - Performance\n    - Game programming  \n---\n\n## Propósito\n\nDoble búfer es un término utilizado para describir un dispositivo que tiene dos búferes. El uso de varios búferes aumenta el rendimiento global de un dispositivo y ayuda a evitar cuellos de botella. Este ejemplo muestra el uso de doble búfer en gráficos. Se utiliza para mostrar una imagen o un fotograma mientras se almacena en el búfer otro fotograma que se mostrará a continuación. Este método hace que las animaciones y los juegos parezcan más realistas que los realizados en modo de búfer único.\n\n## Explicación\n\nEjemplo del mundo real\n> Un ejemplo típico, y que todo motor de juego debe abordar, es el renderizado. Cuando el juego dibuja el mundo que ven los usuarios, lo hace pieza a pieza: las montañas a lo lejos, las colinas ondulantes, los árboles, cada uno a su vez. Si el usuario viera cómo se dibuja la vista de forma incremental, se rompería la ilusión de un mundo coherente. La escena debe actualizarse con fluidez y rapidez, mostrando una serie de fotogramas completos, cada uno de los cuales aparece al instante. La doble memoria intermedia resuelve el problema.\n\nEn pocas palabras\n> Garantiza un estado que se renderiza correctamente mientras ese estado se modifica de forma incremental. Se utiliza mucho en gráficos por ordenador.\n\nWikipedia dice\n> En informática, el almacenamiento en búfer múltiple es el uso de más de un búfer para contener un bloque de datos, de modo que un \"lector\" vea una versión completa (aunque quizás antigua) de los datos, en lugar de una versión parcialmente actualizada de los datos que está creando un \"escritor\". Se utiliza mucho en las imágenes de ordenador.\n\n**Ejemplo programático**\n\nInterfaz `Buffer` que asegura las funcionalidades básicas de un buffer.\n\n```java\n/**\n * Buffer interface.\n */\npublic interface Buffer {\n\n    /**\n     * Clear the pixel in (x, y).\n     *\n     * @param x X coordinate\n     * @param y Y coordinate\n     */\n    void clear(int x, int y);\n\n    /**\n     * Draw the pixel in (x, y).\n     *\n     * @param x X coordinate\n     * @param y Y coordinate\n     */\n    void draw(int x, int y);\n\n    /**\n     * Clear all the pixels.\n     */\n    void clearAll();\n\n    /**\n     * Get all the pixels.\n     *\n     * @return pixel list\n     */\n    Pixel[] getPixels();\n\n}\n```\n\nUna de las implementaciones de la interfaz `Buffer`.\n\n```java\n/**\n * FrameBuffer implementation class.\n */\npublic class FrameBuffer implements Buffer {\n\n    public static final int WIDTH = 10;\n    public static final int HEIGHT = 8;\n\n    private final Pixel[] pixels = new Pixel[WIDTH * HEIGHT];\n\n    public FrameBuffer() {\n        clearAll();\n    }\n\n    @Override\n    public void clear(int x, int y) {\n        pixels[getIndex(x, y)] = Pixel.WHITE;\n    }\n\n    @Override\n    public void draw(int x, int y) {\n        pixels[getIndex(x, y)] = Pixel.BLACK;\n    }\n\n    @Override\n    public void clearAll() {\n        Arrays.fill(pixels, Pixel.WHITE);\n    }\n\n    @Override\n    public Pixel[] getPixels() {\n        return pixels;\n    }\n\n    private int getIndex(int x, int y) {\n        return x + WIDTH * y;\n    }\n}\n```\n\n```java\n/**\n * Pixel enum. Each pixel can be white (not drawn) or black (drawn).\n */\npublic enum Pixel {\n\n    WHITE, BLACK;\n}\n```\n\n`Scene` representa la escena del juego en la que ya se ha renderizado el búfer actual.\n\n```java\n/**\n * Scene class. Render the output frame.\n */\n@Slf4j\npublic class Scene {\n\n    private final Buffer[] frameBuffers;\n\n    private int current;\n\n    private int next;\n\n    /**\n     * Constructor of Scene.\n     */\n    public Scene() {\n        frameBuffers = new FrameBuffer[2];\n        frameBuffers[0] = new FrameBuffer();\n        frameBuffers[1] = new FrameBuffer();\n        current = 0;\n        next = 1;\n    }\n\n    /**\n     * Draw the next frame.\n     *\n     * @param coordinateList list of pixels of which the color should be black\n     */\n    public void draw(List<? extends Pair<Integer, Integer>> coordinateList) {\n        LOGGER.info(\"Start drawing next frame\");\n        LOGGER.info(\"Current buffer: \" + current + \" Next buffer: \" + next);\n        frameBuffers[next].clearAll();\n        coordinateList.forEach(coordinate -> {\n            var x = coordinate.getKey();\n            var y = coordinate.getValue();\n            frameBuffers[next].draw(x, y);\n        });\n        LOGGER.info(\"Swap current and next buffer\");\n        swap();\n        LOGGER.info(\"Finish swapping\");\n        LOGGER.info(\"Current buffer: \" + current + \" Next buffer: \" + next);\n    }\n\n    public Buffer getBuffer() {\n        LOGGER.info(\"Get current buffer: \" + current);\n        return frameBuffers[current];\n    }\n\n    private void swap() {\n        current = current ^ next;\n        next = current ^ next;\n        current = current ^ next;\n    }\n\n}\n```\n\n```java\npublic static void main(String[] args) {\n    final var scene = new Scene();\n    var drawPixels1 = List.of(new MutablePair<>(1, 1), new MutablePair<>(5, 6), new MutablePair<>(3, 2));\n    scene.draw(drawPixels1);\n    var buffer1 = scene.getBuffer();\n    printBlackPixelCoordinate(buffer1);\n\n    var drawPixels2 = List.of(new MutablePair<>(3, 7), new MutablePair<>(6, 1));\n    scene.draw(drawPixels2);\n    var buffer2 = scene.getBuffer();\n    printBlackPixelCoordinate(buffer2);\n}\n\nprivate static void printBlackPixelCoordinate(Buffer buffer) {\n    StringBuilder log = new StringBuilder(\"Black Pixels: \");\n    var pixels = buffer.getPixels();\n    for (var i = 0; i < pixels.length; ++i) {\n        if (pixels[i] == Pixel.BLACK) {\n            var y = i / FrameBuffer.WIDTH;\n            var x = i % FrameBuffer.WIDTH;\n            log.append(\" (\").append(x).append(\", \").append(y).append(\")\");\n        }\n    }\n    LOGGER.info(log.toString());\n}\n```\n\nLa salida de la consola\n\n```text\n[main] INFO com.iluwatar.doublebuffer.Scene - Start drawing next frame\n[main] INFO com.iluwatar.doublebuffer.Scene - Current buffer: 0 Next buffer: 1\n[main] INFO com.iluwatar.doublebuffer.Scene - Swap current and next buffer\n[main] INFO com.iluwatar.doublebuffer.Scene - Finish swapping\n[main] INFO com.iluwatar.doublebuffer.Scene - Current buffer: 1 Next buffer: 0\n[main] INFO com.iluwatar.doublebuffer.Scene - Get current buffer: 1\n[main] INFO com.iluwatar.doublebuffer.App - Black Pixels:  (1, 1) (3, 2) (5, 6)\n[main] INFO com.iluwatar.doublebuffer.Scene - Start drawing next frame\n[main] INFO com.iluwatar.doublebuffer.Scene - Current buffer: 1 Next buffer: 0\n[main] INFO com.iluwatar.doublebuffer.Scene - Swap current and next buffer\n[main] INFO com.iluwatar.doublebuffer.Scene - Finish swapping\n[main] INFO com.iluwatar.doublebuffer.Scene - Current buffer: 0 Next buffer: 1\n[main] INFO com.iluwatar.doublebuffer.Scene - Get current buffer: 0\n[main] INFO com.iluwatar.doublebuffer.App - Black Pixels:  (6, 1) (3, 7)\n```\n\n## Diagrama de clases\n\n![alt text](./etc/double-buffer.urm.png \"Double Buffer pattern class diagram\")\n\n## Aplicabilidad\n\nEste patrón es uno de esos que sabrás cuándo lo necesitas. Si tienes un sistema que carece de doble búfer, probablemente tendrá un aspecto visiblemente incorrecto (tearing, etc.) o se comportará de forma incorrecta. Pero decir \"lo sabrás cuando lo necesites\" no da mucho de sí. Más concretamente, este patrón es apropiado cuando todo esto es cierto:\n\n- Tenemos algún estado que está siendo modificado incrementalmente.\n- Ese mismo estado puede ser accedido en medio de la modificación.\n- Queremos evitar que el código que está accediendo al estado vea el trabajo en curso.\n- Queremos poder leer el estado y no queremos tener que esperar mientras se escribe.\n\n## Créditos\n\n* [Game Programming Patterns - Double Buffer](http://gameprogrammingpatterns.com/double-buffer.html)\n"
  },
  {
    "path": "localization/es/embedded-value/README.md",
    "content": "---\ntitle: Embedded Value\nshortTitle: Embedded Value\ncategory: Structural\nlanguage: es\ntag:\n  - Data Access\n  - Enterprise Application Pattern\n---\n\n## También conocido como\n\nAsignación agregada, Compositor\n\n## Propósito\n\nMuchos objetos pequeños tienen sentido en un sistema OO que no tienen sentido como tablas en una base de datos. Un valor\nincrustado asigna los valores de un objeto a campos del registro del propietario del objeto.\n\n## Explicación\n\nEjemplo real\n\n> Algunos ejemplos son los objetos monetarios y los intervalos de fechas. Aunque el pensamiento por defecto es guardar\n> un objeto como una tabla, ninguna persona en su sano juicio querría una tabla de valores monetarios.\n> Otro ejemplo serían los pedidos online que tienen una dirección de envío como calle, ciudad, estado. Asignamos estos\n> valores del objeto Dirección de envío a los campos del registro del objeto Pedido.\n\nEn pocas palabras\n\n> El patrón de valores incrustados permite asignar un objeto a varios campos de la tabla de otro objeto.\n\n**Ejemplo programático**\n\nConsideremos el ejemplo de un pedido online donde tenemos detalles del artículo pedido y la dirección de envío. Tenemos\nla dirección de envío incrustada en el objeto Pedido. Pero en la base de datos asignamos los valores de la dirección de\nenvío en el registro del pedido en lugar de crear una tabla separada para la dirección de envío y utilizar una clave\nexterna para hacer referencia al objeto del pedido.\n\nPrimero, tenemos POJOs `Order` y `ShippingAddress`.\n\n```java\npublic class Order {\n\n    private int id;\n    private String item;\n    private String orderedBy;\n    private ShippingAddress ShippingAddress;\n\n    public Order(String item, String orderedBy, ShippingAddress           ShippingAddress) {\n        this.item = item;\n        this.orderedBy = orderedBy;\n        this.ShippingAddress = ShippingAddress;\n    }\n```\n\n```java\npublic class ShippingAddress {\n\n    private String city;\n    private String state;\n    private String pincode;\n\n    public ShippingAddress(String city, String state, String pincode) {\n        this.city = city;\n        this.state = state;\n        this.pincode = pincode;\n    }\n}\n```\n\nAhora, tenemos que crear sólo una tabla para el Pedido junto con los campos para los atributos de la dirección de envío.\n\n```Sql\nCREATE TABLE Orders (Id INT AUTO_INCREMENT, item VARCHAR(50) NOT NULL, orderedBy VARCHAR(50) city VARCHAR(50), state VARCHAR(50), pincode CHAR(6) NOT NULL, PRIMARY KEY(Id))\n```\n\nMientras realizamos las consultas e inserciones en la base de datos, encasillamos y desencasillamos los detalles de las\ndirecciones de envío.\n\n```java\nfinal String INSERT_ORDER = \"INSERT INTO Orders (item, orderedBy, city, state, pincode) VALUES (?, ?, ?, ?, ?)\";\n\npublic boolean insertOrder(Order order) throws Exception {\n  var insertOrder = new PreparedStatement(INSERT_ORDER);\n  var address = order.getShippingAddress();\n  conn.setAutoCommit(false);\n  insertIntoOrders.setString(1, order.getItem());\n  insertIntoOrders.setString(2, order.getOrderedBy());\n  insertIntoOrders.setString(3, address.getCity());\n  insertIntoOrders.setString(4, address.getState());\n  insertIntoOrders.setString(5, address.getPincode());\n  \n  var affectedRows = insertIntoOrders.executeUpdate();\n  if(affectedRows == 1){\n    Logger.info(\"Inserted successfully\");\n  }else{\n    Logger.info(\"Couldn't insert \" + order);\n  }\n}\n```\n\n## Diagrama de clases\n\n![alt text](./etc/embedded-value.urm.png \"Embedded value class diagram\")\n\n## Aplicabilidad\n\nUtilice el patrón Valor incrustado cuando\n\n* Muchos objetos pequeños tienen sentido en un sistema OO que no tienen sentido como tablas en una base de datos.\n* Los casos más simples para Embedded Value son los claros y simples Value Objects como dinero y rango de fechas.\n* Si está mapeando a un esquema existente, puede utilizar este patrón cuando una tabla contiene datos que desea dividir\n  en más de un objeto en memoria. Esto puede ocurrir cuando se desea factorizar algún comportamiento en el modelo de\n  objetos.\n* En la mayoría de los casos, sólo utilizará el valor incrustado en un objeto de referencia cuando la asociación entre\n  ellos tenga un único valor en ambos extremos (una asociación uno a uno).\n\n## Tutoriales\n\n* [Dzone](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-3)\n* [Ram N Java](https://ramj2ee.blogspot.com/2013/08/embedded-value-design-pattern.html)\n* [Five's Weblog](https://powerdream5.wordpress.com/2007/10/09/embedded-value/)\n\n## Consecuencias\n\n* La gran ventaja del valor incrustado es que permite realizar consultas SQL contra los valores del objeto dependiente.\n* El objeto valor incrustado no tiene ningún comportamiento de persistencia.\n* Al usar esto, tienes que tener cuidado de que cualquier cambio en el dependiente marque al propietario como sucio-lo\n  cual no es un problema con los Objetos de Valor que son reemplazados en el propietario.\n* Otro problema es la carga y el guardado. Si sólo carga la memoria del objeto incrustado cuando carga el propietario,\n  eso es un argumento para guardar ambos en la misma tabla.\n* Otra cuestión es si querrás acceder a los datos de los objetos incrustados por separado a través de SQL. Esto puede\n  ser importante si estás haciendo informes a través de SQL y no tienes una base de datos separada para los informes.\n\n## Créditos\n\n* [Fowler, Martin - Patterns of enterprise application architecture-Addison-Wesley](https://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420)\n* [Ram N Java](https://ramj2ee.blogspot.com/2013/08/embedded-value-design-pattern.html)"
  },
  {
    "path": "localization/es/event-aggregator/README.md",
    "content": "---\ntitle: Event Aggregator\nshortTitle: Event Aggregator\ncategory: Structural\nlanguage: es\ntag:\n  - Reactive\n---\n\n## Nombre\n\nAgregador de eventos\n\n## Intención\n\nUn sistema con muchos objetos puede resultar complejo cuando un cliente quiere suscribirse a eventos. El cliente tiene\nque encontrar y registrarse para\ncada objeto individualmente, si cada objeto tiene múltiples eventos entonces cada evento requiere una suscripción\nseparada. Un Agregador de Eventos actúa como una única fuente\nde eventos para muchos objetos. Se registra para todos los eventos de los muchos objetos permitiendo a los clientes\nregistrarse sólo con el agregador.\n\n## Explicación\n\nUn ejemplo real\n\n> El rey Joffrey se sienta en el trono de hierro y gobierna los siete reinos de Poniente. Recibe la mayor parte de su\n> información crítica de Mano del Rey, el segundo al mando. La Mano del Rey tiene muchos consejeros cercanos que le\n> proporcionan información relevante sobre los acontecimientos que ocurren en el reino.\n\nEn pocas palabras\n\n> El Agregador de Eventos es un mediador de eventos que recoge eventos de múltiples fuentes y los entrega a los\n> observadores registrados.\n\n**Ejemplo programático**\n\nEn nuestro ejemplo programático, demostramos la implementación de un patrón agregador de eventos. Algunos de los objetos\nson escuchadores de eventos, otros son emisores de eventos, y el agregador de eventos hace ambas cosas.\n\n```java\npublic interface EventObserver {\n  void onEvent(Event e);\n}\n\npublic abstract class EventEmitter {\n\n  private final Map<Event, List<EventObserver>> observerLists;\n\n  public EventEmitter() {\n    observerLists = new HashMap<>();\n  }\n\n  public final void registerObserver(EventObserver obs, Event e) {\n    ...\n  }\n\n  protected void notifyObservers(Event e) {\n    ...\n  }\n}\n```\n\n`KingJoffrey` está escuchando eventos de `KingsHand`.\n\n```java\n@Slf4j\npublic class KingJoffrey implements EventObserver {\n  @Override\n  public void onEvent(Event e) {\n    LOGGER.info(\"Received event from the King's Hand: {}\", e.toString());\n  }\n}\n```\n\nEl `ReyMano` está escuchando los acontecimientos de sus subordinados `LordBaelish`, `LordVarys` y `Scout`.\nLo que escuche de ellos, se lo entrega al \"Rey Joffrey\".\n\n```java\npublic class KingsHand extends EventEmitter implements EventObserver {\n\n  public KingsHand() {\n  }\n\n  public KingsHand(EventObserver obs, Event e) {\n    super(obs, e);\n  }\n\n  @Override\n  public void onEvent(Event e) {\n    notifyObservers(e);\n  }\n}\n```\n\nPor ejemplo, `LordVarys` encuentra un traidor cada domingo y lo notifica al `KingsHand`.\n\n```java\n@Slf4j\npublic class LordVarys extends EventEmitter implements EventObserver {\n  @Override\n  public void timePasses(Weekday day) {\n    if (day == Weekday.SATURDAY) {\n      notifyObservers(Event.TRAITOR_DETECTED);\n    }\n  }\n}\n```\n\nEl siguiente fragmento muestra cómo se construyen y conectan los objetos.\n\n```java\n    var kingJoffrey = new KingJoffrey();\n\n    var kingsHand = new KingsHand();\n    kingsHand.registerObserver(kingJoffrey, Event.TRAITOR_DETECTED);\n    kingsHand.registerObserver(kingJoffrey, Event.STARK_SIGHTED);\n    kingsHand.registerObserver(kingJoffrey, Event.WARSHIPS_APPROACHING);\n    kingsHand.registerObserver(kingJoffrey, Event.WHITE_WALKERS_SIGHTED);\n\n    var varys = new LordVarys();\n    varys.registerObserver(kingsHand, Event.TRAITOR_DETECTED);\n    varys.registerObserver(kingsHand, Event.WHITE_WALKERS_SIGHTED);\n\n    var scout = new Scout();\n    scout.registerObserver(kingsHand, Event.WARSHIPS_APPROACHING);\n    scout.registerObserver(varys, Event.WHITE_WALKERS_SIGHTED);\n\n    var baelish = new LordBaelish(kingsHand, Event.STARK_SIGHTED);\n\n    var emitters = List.of(\n        kingsHand,\n        baelish,\n        varys,\n        scout\n    );\n\n    Arrays.stream(Weekday.values())\n        .<Consumer<? super EventEmitter>>map(day -> emitter -> emitter.timePasses(day))\n        .forEachOrdered(emitters::forEach);\n```\n\nLa salida de la consola después de ejecutar el ejemplo.\n\n```\n18:21:52.955 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: Warships approaching\n18:21:52.960 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: White walkers sighted\n18:21:52.960 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: Stark sighted\n18:21:52.960 [main] INFO com.iluwatar.event.aggregator.KingJoffrey - Received event from the King's Hand: Traitor detected\n```\n\n## Diagrama de clases\n\n![alt text](etc/classes.png \"Event Aggregator\")\n\n## Aplicabilidad\n\nUtilice el patrón Agregador de eventos cuando\n\n* El Agregador de Eventos es una buena opción cuando tienes muchos objetos que son fuentes potenciales de eventos. En\n  lugar de hacer que el observador se ocupe de registrarse con todos ellos, puedes centralizar la lógica de registro en\n  el Agregador de Eventos. Además de simplificar el registro, un Agregador de Eventos también simplifica los problemas\n  de gestión de memoria en el uso de observadores.\n\n## Patrones relacionados\n\n* [Observer](https://java-design-patterns.com/patterns/observer/)\n\n## Créditos\n\n* [Martin Fowler - Event Aggregator](http://martinfowler.com/eaaDev/EventAggregator.html)\n"
  },
  {
    "path": "localization/es/extension-objects/README.md",
    "content": "---\ntitle: Extension objects\nshortTitle: Extension objects\ncategory: Behavioral\nlanguage: es\ntag:\n - Extensibility\n---\n\n# Extention Objects Pattern\n\n## Propósito\nAnticipar que la interfaz de un objeto debe ampliarse en el futuro. Las interfaces adicionales se definen mediante objetos de extensión (Extension objects).\n\n## Explicación\nEjemplo real\n\n> Suponga que está desarrollando un juego basado en Java para un cliente y, en mitad del proceso de desarrollo, le sugieren nuevas funcionalidades. El patrón Extension Objects permite a su programa adaptarse a cambios imprevistos con una refactorización mínima, especialmente al integrar funcionalidades adicionales en su proyecto.\n\nEn palabras sencillas\n\n> El patrón Extension Objects se utiliza para añadir dinámicamente funcionalidad a los objetos sin modificar sus clases principales. Es un patrón de diseño de comportamiento utilizado para añadir nuevas funcionalidades a clases y objetos existentes dentro de un programa. Este patrón proporciona a los programadores la capacidad de extender/modificar la funcionalidad de las clases sin tener que refactorizar el código fuente existente.\n\nWikipedia dice\n\n> En la programación informática orientada a objetos, un patrón de objetos de extensión es un patrón de diseño añadido a un objeto después de que el objeto original fue compilado. El objeto modificado es a menudo una clase, un prototipo o un tipo. Los patrones de objetos de extensión son características de algunos lenguajes de programación orientados a objetos. No hay diferencia sintáctica entre llamar a un método de extensión y llamar a un método declarado en la definición del tipo.\n\n**Ejemplo programático**\n\nEl objetivo de utilizar el patrón de objetos de extensión (Extension objects) es implementar nuevas características/funcionalidades sin tener que refactorizar cada clase.\nLos siguientes ejemplos muestran la utilización de este patrón para una clase Enemigo que extiende Entidad dentro de un juego:\n\nClase App primaria desde la que ejecutar nuestro programa.\n\n```java\npublic class App {\n    public static void main(String[] args) {\n        Entity enemy = new Enemy(\"Enemy\");\n        checkExtensionsForEntity(enemy);\n    }\n\n    private static void checkExtensionsForEntity(Entity entity) {\n        Logger logger = Logger.getLogger(App.class.getName());\n        String name = entity.getName();\n        Function<String, Runnable> func = (e) -> () -> logger.info(name + \" without \" + e);\n\n        String extension = \"EnemyExtension\";\n        Optional.ofNullable(entity.getEntityExtension(extension))\n                .map(e -> (EnemyExtension) e)\n                .ifPresentOrElse(EnemyExtension::extendedAction, func.apply(extension));\n    }\n}\n```\nClase de enemigo con acciones iniciales y extensiones.\n\n```java\nclass Enemy extends Entity {\n    public Enemy(String name) {\n        super(name);\n    }\n\n    @Override\n    protected void performInitialAction() {\n        super.performInitialAction();\n        System.out.println(\"Enemy wants to attack you.\");\n    }\n\n    @Override\n    public EntityExtension getEntityExtension(String extensionName) {\n        if (extensionName.equals(\"EnemyExtension\")) {\n            return Optional.ofNullable(entityExtension).orElseGet(EnemyExtension::new);\n        }\n        return super.getEntityExtension(extensionName);\n    }\n}\n```\n\nClase EnemyExtension con sobreescritura del método extendAction().\n\n```java\nclass EnemyExtension implements EntityExtension {\n    @Override\n    public void extendedAction() {\n        System.out.println(\"Enemy has advanced towards you!\");\n    }\n}\n```\n\nClase de entidad que será extendida por Enemy.\n\n```java\nclass Entity {\n    private String name;\n    protected EntityExtension entityExtension;\n\n    public Entity(String name) {\n        this.name = name;\n        performInitialAction();\n    }\n\n    protected void performInitialAction() {\n        System.out.println(name + \" performs the initial action.\");\n    }\n\n    public EntityExtension getEntityExtension(String extensionName) {\n        return null;\n    }\n\n    public String getName() {\n        return name;\n    }\n}\n```\nInterfaz EntityExtension que utilizará EnemyExtension.\n\n```java\ninterface EntityExtension {\n    void extendedAction();\n}\n```\nSalida del programa:\n\n```markdown\nEnemy performs the initial action.\nEnemy wants to attack you.\nEnemy has advanced towards you!\n```\nEn este ejemplo, el patrón de Objetos de Extensión permite a la entidad enemiga realizar acciones iniciales únicas y acciones avanzadas cuando se aplican extensiones específicas. Este patrón proporciona flexibilidad y extensibilidad a la base de código a la vez que minimiza la necesidad de realizar cambios importantes en el código.\n\n## Diagrama de clases\n![Extension_objects](./etc/extension_obj.png \"Extension objects\")\n\n## Aplicabilidad\nUtilice el patrón de Objetos de Extensión (Extension objects) cuando:\n\n* Necesita soportar la adición de interfaces nuevas o imprevistas a clases existentes y no quieres impactar a clientes que no necesitan esta nueva interfaz. Los objetos de extensión te permiten mantener juntas operaciones relacionadas definiéndolas en una clase separada\n* Una clase que representa una abstracción clave desempeña diferentes funciones para diferentes clientes. El número de funciones que puede desempeñar la clase debe ser ilimitado. Es necesario preservar la propia abstracción clave. Por ejemplo, un objeto cliente sigue siendo un objeto cliente aunque distintos subsistemas lo vean de forma diferente.\n* Una clase debe ser extensible con nuevos comportamientos sin necesidad de subclasificar a partir de ella.\n\n## Ejemplos del mundo real\n\n* [OpenDoc](https://en.wikipedia.org/wiki/OpenDoc)\n* [Object Linking and Embedding](https://en.wikipedia.org/wiki/Object_Linking_and_Embedding)\n"
  },
  {
    "path": "localization/es/facade/README.md",
    "content": "---\ntitle: Facade\nshortTitle: Facade\ncategory: Structural\nlanguage: es\ntag:\n  - Gang Of Four\n  - Decoupling\n---\n\n## Propósito\n\nProporcionar una interfaz unificada a un conjunto de interfaces de un subsistema. La fachada define una interfaz que\nfacilita el uso del subsistema.\n\n## Explicación\n\nUn ejemplo real\n\n> ¿Cómo funciona una mina de oro? \"¡Bueno, los mineros bajan y sacan oro!\" dices. Eso es lo que crees porque estás\n> usando una interfaz simple que la mina de oro proporciona en el exterior, internamente tiene que hacer un montón de\n> cosas para que suceda. Esta interfaz simple al subsistema complejo es una fachada.\n\nEn pocas palabras\n\n> El patrón Facade proporciona una interfaz simplificada a un subsistema complejo.\n\nWikipedia dice\n\n> Una fachada es un objeto que proporciona una interfaz simplificada a un cuerpo de código mayor, como una biblioteca de\n> clases.\n\n**Ejemplo programático**\n\nTomemos el ejemplo de la mina de oro. Aquí tenemos la jerarquía de los trabajadores enanos de la mina. Primero hay una\nclase base `DwarvenMineWorker`:\n\n```java\n\n@Slf4j\npublic abstract class DwarvenMineWorker {\n\n    public void goToSleep() {\n        LOGGER.info(\"{} goes to sleep.\", name());\n    }\n\n    public void wakeUp() {\n        LOGGER.info(\"{} wakes up.\", name());\n    }\n\n    public void goHome() {\n        LOGGER.info(\"{} goes home.\", name());\n    }\n\n    public void goToMine() {\n        LOGGER.info(\"{} goes to the mine.\", name());\n    }\n\n    private void action(Action action) {\n        switch (action) {\n            case GO_TO_SLEEP -> goToSleep();\n            case WAKE_UP -> wakeUp();\n            case GO_HOME -> goHome();\n            case GO_TO_MINE -> goToMine();\n            case WORK -> work();\n            default -> LOGGER.info(\"Undefined action\");\n        }\n    }\n\n    public void action(Action... actions) {\n        Arrays.stream(actions).forEach(this::action);\n    }\n\n    public abstract void work();\n\n    public abstract String name();\n\n    enum Action {\n        GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK\n    }\n}\n```\n\nLuego tenemos las clases concretas enanas `DwarvenTunnelDigger`, `DwarvenGoldDigger` y `DwarvenCartOperator`:\n\n```java\n@Slf4j\npublic class DwarvenTunnelDigger extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} creates another promising tunnel.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarven tunnel digger\";\n  }\n}\n\n@Slf4j\npublic class DwarvenGoldDigger extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} digs for gold.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarf gold digger\";\n  }\n}\n\n@Slf4j\npublic class DwarvenCartOperator extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} moves gold chunks out of the mine.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarf cart operator\";\n  }\n}\n\n```\n\nPara manejar a todos estos trabajadores de la mina de oro tenemos la `FachadaDwarvenGoldmine`:\n\n```java\npublic class DwarvenGoldmineFacade {\n\n  private final List<DwarvenMineWorker> workers;\n\n  public DwarvenGoldmineFacade() {\n      workers = List.of(\n            new DwarvenGoldDigger(),\n            new DwarvenCartOperator(),\n            new DwarvenTunnelDigger());\n  }\n\n  public void startNewDay() {\n    makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE);\n  }\n\n  public void digOutGold() {\n    makeActions(workers, DwarvenMineWorker.Action.WORK);\n  }\n\n  public void endDay() {\n    makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);\n  }\n\n  private static void makeActions(Collection<DwarvenMineWorker> workers,\n      DwarvenMineWorker.Action... actions) {\n    workers.forEach(worker -> worker.action(actions));\n  }\n}\n```\n\nAhora vamos a utilizar la fachada:\n\n```java\nvar facade = new DwarvenGoldmineFacade();\nfacade.startNewDay();\nfacade.digOutGold();\nfacade.endDay();\n```\n\nSalida del programa:\n\n```java\n// Dwarf gold digger wakes up.\n// Dwarf gold digger goes to the mine.\n// Dwarf cart operator wakes up.\n// Dwarf cart operator goes to the mine.\n// Dwarven tunnel digger wakes up.\n// Dwarven tunnel digger goes to the mine.\n// Dwarf gold digger digs for gold.\n// Dwarf cart operator moves gold chunks out of the mine.\n// Dwarven tunnel digger creates another promising tunnel.\n// Dwarf gold digger goes home.\n// Dwarf gold digger goes to sleep.\n// Dwarf cart operator goes home.\n// Dwarf cart operator goes to sleep.\n// Dwarven tunnel digger goes home.\n// Dwarven tunnel digger goes to sleep.\n```\n\n## Diagrama de clases\n\n![alt text](./etc/facade.urm.png \"Facade pattern class diagram\")\n\n## Aplicabilidad\n\nUtilice el patrón Fachada cuando\n\n* Quieres proporcionar una interfaz sencilla a un subsistema complejo. Los subsistemas a menudo se vuelven más complejos\n  a medida que evolucionan. La mayoría de los patrones, cuando se aplican, dan como resultado más clases y más pequeñas.\n  Esto hace que el subsistema sea más reutilizable y más fácil de personalizar, pero también se vuelve más difícil de\n  usar para los clientes que no necesitan personalizarlo. Una fachada puede proporcionar una simple vista por defecto\n  del subsistema que es lo suficiente para la mayoría de los clientes. Sólo los clientes que necesiten más\n  personalización tendrán que mirar más allá de la fachada.\n* Hay muchas dependencias entre los clientes y las clases de implementación de una abstracción.\n  Introducir una fachada para desacoplar el subsistema de los clientes y otros subsistemas, promoviendo así\n  independencia y portabilidad del subsistema.\n* Quieres estratificar tus subsistemas. Utiliza una fachada para definir un punto de entrada a cada nivel de subsistema.\n  Si los subsistemas son dependientes, puedes simplificar las dependencias entre ellos haciéndolos que se comuniquen\n  entre sí únicamente a través de sus fachadas.\n\n## Tutoriales\n\n*[DigitalOcean](https://www.digitalocean.com/community/tutorials/facade-design-pattern-in-java)\n\n* [Refactoring Guru](https://refactoring.guru/design-patterns/facade)\n* [GeekforGeeks](https://www.geeksforgeeks.org/facade-design-pattern-introduction/)\n* [Tutorialspoint](https://www.tutorialspoint.com/design_pattern/facade_pattern.htm)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/es/factory/README.md",
    "content": "---\ntitle: Factory\nshortTitle: Factory\ncategory: Creational\nlanguage: es\ntag:\n  - Gang of Four\n---\n\n## También conocido como\n\n* Simple Factory\n* Static Factory Method\n\n## Propósito\n\nProporcionar un método estático encapsulado en una clase llamada fábrica (Factory), para ocultar la lógica de\nimplementación y\nhacer que el código del cliente se centre en el uso en lugar de inicializar nuevos objetos.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Imagina un alquimista que está a punto de fabricar monedas. El alquimista debe ser capaz de crear tanto monedas de oro\n> como de cobre y cambiar entre ellas debe ser posible sin modificar el código fuente existente. El patrón de fábrica lo\n> hace posible proporcionando un método de construcción estático que puede ser llamado con los parámetros relevantes.\n\nWikipedia dice\n\n> La fábrica (Factory) es un objeto para crear otros objetos: formalmente, una fábrica es una función o método que\n> devuelve objetos de un prototipo o clase variable.\n\n**Ejemplo programático**\n\nTenemos una interfaz moneda `Coin` y dos implementaciones moneda de oro `GoldCoin` y moneda de cobre `CopperCoin`.\n\n```java\npublic interface Coin {\n  String getDescription();\n}\n\npublic class GoldCoin implements Coin {\n\n  static final String DESCRIPTION = \"This is a gold coin.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\npublic class CopperCoin implements Coin {\n   \n  static final String DESCRIPTION = \"This is a copper coin.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n```\n\nLa siguiente enumeración representa los tipos de monedas que admitimos (`GoldCoin` y `CopperCoin`).\n\n```java\n@RequiredArgsConstructor\n@Getter\npublic enum CoinType {\n\n  COPPER(CopperCoin::new),\n  GOLD(GoldCoin::new);\n\n  private final Supplier<Coin> constructor;\n}\n```\n\nLuego tenemos el método estático obtener moneda `getCoin` para crear objetos moneda encapsulados en la clase fábrica\n`CoinFactory`.\n\n```java\npublic class CoinFactory {\n\n  public static Coin getCoin(CoinType type) {\n    return type.getConstructor().get();\n  }\n}\n```\n\nAhora en el código cliente podemos crear diferentes tipos de monedas utilizando la clase fábrica.\n\n```java\nLOGGER.info(\"The alchemist begins his work.\");\nvar coin1 = CoinFactory.getCoin(CoinType.COPPER);\nvar coin2 = CoinFactory.getCoin(CoinType.GOLD);\nLOGGER.info(coin1.getDescription());\nLOGGER.info(coin2.getDescription());\n```\n\nSalida del programa:\n\n```java\nThe alchemist begins his work.\nThis is a copper coin.\nThis is a gold coin.\n```\n\n## Diagrama de clases\n\n![alt text](./etc/factory.urm.png \"Factory pattern diagrama de clases\")\n\n## Aplicabilidad\n\nUtilice el patrón de fábrica cuando solo se preocupe por la creación de un objeto, no de cómo crearlo\ny gestionarlo.\n\nVentajas\n\n* Permite mantener toda la creación de objetos en un solo lugar y evitar la propagación de la palabra clave 'new' a\n  través de la base de código.\n* Permite escribir código poco acoplado. Algunas de sus principales ventajas incluyen mejor testabilidad, código fácil\n  de entender, componentes intercambiables, escalabilidad y características aisladas.\n\nContras\n\n* El código se vuelve más complicado de lo que debería.\n\n## Usos conocidos\n\n* [java.util.Calendar#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)\n* [java.util.ResourceBundle#getBundle()](https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)\n* [java.text.NumberFormat#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)\n* [java.nio.charset.Charset#forName()](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)\n* [java.net.URLStreamHandlerFactory#createURLStreamHandler(String)](https://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html) (\n  devuelve diferentes objetos singleton, en función de un protocolo)\n* [java.util.EnumSet#of()](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of(E))\n* [javax.xml.bind.JAXBContext#createMarshaller()](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--)\n  y otros métodos similares.\n\n## Patrones relacionados\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/)\n"
  },
  {
    "path": "localization/es/factory-kit/README.md",
    "content": "---\ntitle: Factory Kit\nshortTitle: Factory Kit\ncategory: Creational\nlanguage: es\ntag:\n  - Extensibility\n---\n\n## También conocido como\n\nAbstract-Factory\n\n## Propósito\n\nDefine una fábrica de contenido inmutable con interfaces de constructor y fábrica separadas.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Imagina una fábrica de armas mágicas que puede crear cualquier tipo de arma que se desee. Cuando la fábrica se\n> desempaqueta, el maestro recita los tipos de armas necesarios para prepararla. Después de eso, cualquiera de esos\n> tipos\n> de armas pueden ser invocados en un instante.\n\nEn palabras sencillas\n\n> El kit de fábrica (Kit Factory) es un constructor de objetos configurable, una fábrica para crear fábricas.\n\n**Ejemplo programático**\n\nDefinamos primero la interfaz simple arma `Weapon`.\n\n```java\npublic interface Weapon {\n}\n\npublic enum WeaponType {\n    SWORD,\n    AXE,\n    BOW,\n    SPEAR\n}\n\npublic class Sword implements Weapon {\n    @Override\n    public String toString() {\n        return \"Sword\";\n    }\n}\n\n// Hacha `Axe`, Arco `Bow` y Lanza `Spear` se definen de forma similar\n```\n\nA continuación, definimos una interfaz funcional que permite añadir un constructor con un nombre a la fábrica.\n\n```java\npublic interface Builder {\n  void add(WeaponType name, Supplier<Weapon> supplier);\n}\n```\n\nEl núcleo del ejemplo es la interfaz `WeaponFactory` que implementa el patrón de fábrica. El método `#factory` se\nutiliza para configurar la fábrica con las clases que necesita para ser capaz de construir. El método `#create` se\nutiliza para crear instancias del objeto.\n\n```java\npublic interface WeaponFactory {\n\n  static WeaponFactory factory(Consumer<Builder> consumer) {\n      var map = new HashMap<WeaponType, Supplier<Weapon>>();\n      consumer.accept(map::put);\n      return name -> map.get(name).get();\n  }\n    \n  Weapon create(WeaponType name);\n}\n```\n\nAhora, podemos mostrar cómo se puede utilizar `WeaponFactory`.\n\n```java\nvar factory = WeaponFactory.factory(builder -> {\n  builder.add(WeaponType.SWORD, Sword::new);\n  builder.add(WeaponType.AXE, Axe::new);\n  builder.add(WeaponType.SPEAR, Spear::new);\n  builder.add(WeaponType.BOW, Bow::new);\n});\nvar list = new ArrayList<Weapon>();\nlist.add(factory.create(WeaponType.AXE));\nlist.add(factory.create(WeaponType.SPEAR));\nlist.add(factory.create(WeaponType.SWORD));\nlist.add(factory.create(WeaponType.BOW));\nlist.stream().forEach(weapon -> LOGGER.info(\"{}\", weapon.toString()));\n```\n\nEsta es la salida de la consola cuando se ejecuta el ejemplo.\n\n```\n21:15:49.709 [main] INFO com.iluwatar.factorykit.App - Axe\n21:15:49.713 [main] INFO com.iluwatar.factorykit.App - Spear\n21:15:49.713 [main] INFO com.iluwatar.factorykit.App - Sword\n21:15:49.713 [main] INFO com.iluwatar.factorykit.App - Bow\n```\n\n## Diagrama de clases\n\n![alt text](./etc/factory-kit.png \"Factory Kit\")\n\n## Aplicabilidad\n\nUtilice el patrón Factory Kit cuando\n\n* La clase de fábrica no puede anticipar los tipos de objetos que debe crear.\n* Se necesita una nueva instancia de un constructor personalizado en lugar de uno global.\n* Los tipos de objetos que la fábrica puede construir necesitan ser definidos fuera de la clase.\n* Es necesario separar las interfaces del constructor y del creador.\n* Desarrollos de juegos y otras aplicaciones que tienen personalización del usuario\n\n## Patrones relacionados\n\n* [Builder](https://java-design-patterns.com/patterns/builder/)\n* [Factory](https://java-design-patterns.com/patterns/factory/)\n* [Abstract-Factory](https://java-design-patterns.com/patterns/abstract-factory/)\n\n## Tutoriales\n\n* [Factory kit implementation tutorial](https://diego-pacheco.medium.com/factory-kit-pattern-66d5ccb0c405)\n\n## Créditos\n\n* [Design Pattern Reloaded by Remi Forax](https://www.youtube.com/watch?v=-k2X7guaArU)\n"
  },
  {
    "path": "localization/es/factory-method/README.md",
    "content": "---\ntitle: Factory Method\nshortTitle: Factory Method\ncategory: Creational\nlanguage: es\ntag:\n  - Extensibility\n  - Gang of Four\n---\n\n## También conocido como\n\nVirtual Constructor\n\n## Propósito\n\nDefinir una interfaz para crear un objeto, pero dejar que las subclases decidan qué clase instanciar. El método de\nfábrica permite que una clase difiera la instanciación a las subclases.\n\n## Explicación\n\nEjemplo del mundo real\n\n> El herrero fabrica armas. Los elfos requieren armas élficas y los orcos requieren armas orcas. Dependiendo del cliente\n> en cuestión, se convoca al tipo correcto de herrero.\n\nEn palabras sencillas\n\n> Proporciona una forma de delegar la lógica de instanciación a las clases hijas.\n\nWikipedia dice\n\n> En la programación basada en clases, el patrón de método de fábrica es un patrón de creación que utiliza métodos de\n> fábrica para lidiar con el problema de crear objetos sin tener que especificar la clase exacta del objeto que se\n> creará.\n> Esto se hace creando objetos llamando a un método de fábrica — ya sea especificado en una interfaz e implementado por\n> clases hijas, o implementado en una clase base y opcionalmente sobrescrito por clases derivadas — en lugar de llamar a\n> un constructor.\n\n**Ejemplo programático**\n\nTomando nuestro ejemplo del herrero. En primer lugar, tenemos una interfaz `Blacksmith` y algunas implementaciones para\nello:\n\n```java\npublic interface Blacksmith {\n  Weapon manufactureWeapon(WeaponType weaponType);\n}\n\npublic class ElfBlacksmith implements Blacksmith {\n  public Weapon manufactureWeapon(WeaponType weaponType) {\n    return ELFARSENAL.get(weaponType);\n  }\n}\n\npublic class OrcBlacksmith implements Blacksmith {\n  public Weapon manufactureWeapon(WeaponType weaponType) {\n    return ORCARSENAL.get(weaponType);\n  }\n}\n```\n\nCuando llegan los clientes, se llama al herrero adecuado y se fabrican las armas solicitadas:\n\n```java\nBlacksmith blacksmith = new OrcBlacksmith();\nWeapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);\nLOGGER.info(\"{} manufactured {}\", blacksmith, weapon);\nweapon = blacksmith.manufactureWeapon(WeaponType.AXE);\nLOGGER.info(\"{} manufactured {}\", blacksmith, weapon);\n\nblacksmith = new ElfBlacksmith();\nweapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);\nLOGGER.info(\"{} manufactured {}\", blacksmith, weapon);\nweapon = blacksmith.manufactureWeapon(WeaponType.AXE);\nLOGGER.info(\"{} manufactured {}\", blacksmith, weapon);\n```\n\nSalida del programa:\n\n```\nThe orc blacksmith manufactured an orcish spear\nThe orc blacksmith manufactured an orcish axe\nThe elf blacksmith manufactured an elven spear\nThe elf blacksmith manufactured an elven axe\n```\n\n## Diagrama de clases\n\n![alt text](./etc/factory-method.urm.png \"Factory Method pattern diagrama de clases\")\n\n## Aplicabilidad\n\nUtilice el patrón Método de Fábrica cuando:\n\n* La clase no puede anticipar la clase de objetos que debe crear.\n* La clase quiere que sus subclases especifiquen los objetos que crea.\n* Las clases delegan la responsabilidad a una de varias subclases ayudantes, y desea localizar el conocimiento de qué\n  subclase ayudante es el delegado. conocimiento de qué subclase ayudante es el delegado.\n\n## Usos conocidos\n\n* [java.util.Calendar](http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)\n* [java.util.ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)\n* [java.text.NumberFormat](http://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)\n* [java.nio.charset.Charset](http://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)\n* [java.net.URLStreamHandlerFactory](http://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html#createURLStreamHandler-java.lang.String-)\n* [java.util.EnumSet](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of-E-)\n* [javax.xml.bind.JAXBContext](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/es/feature-toggle/README.md",
    "content": "---\ntitle: Feature Toggle\nshortTitle: Feature Toggle\ncategory: Behavioral\nlanguage: es\ntag:\n - Extensibility\n---\n\n## También conocido como\nFeature Flag\n\n## Propósito\nTécnica utilizada en el desarrollo de software para controlar y gestionar el despliegue de características o funcionalidades específicas en un programa sin cambiar el código. Puede actuar como un interruptor de encendido/apagado de funciones en función del estado o las propiedades de otros valores del programa. Esto es similar a las pruebas A/B, en las que las funciones se despliegan en función de propiedades como la ubicación o el dispositivo. La implementación de este patrón de diseño puede aumentar la complejidad del código, y es importante recordar eliminar el código redundante si este patrón de diseño se utiliza para eliminar gradualmente un sistema o característica.\n\n## Explicación\nEjemplo del mundo real\n> Este patrón de diseño funciona realmente bien en cualquier tipo de desarrollo, en particular en el desarrollo móvil. Digamos que quieres introducir una característica como el modo oscuro, pero quieres asegurarte de que la característica funciona correctamente y no quieres desplegar la característica a todo el mundo inmediatamente. Escribes el código y lo desactivas por defecto. A partir de aquí, es fácil activar el código para usuarios específicos basándose en criterios de selección, o aleatoriamente. Esto también permitirá que la función se desactive fácilmente sin ningún cambio drástico en el código, o cualquier necesidad de redistribución o actualizaciones.\n\nEn pocas palabras\n> Feature Toggle es una forma de introducir nuevas funciones gradualmente en lugar de desplegarlas todas a la vez.\n\nWikipedia dice\n> Una función de conmutación en el desarrollo de software proporciona una alternativa al mantenimiento de múltiples ramas de características en el código fuente. Una condición dentro del código activa o desactiva una característica durante el tiempo de ejecución. En un entorno ágil, el conmutador se utiliza en producción, para activar la función bajo demanda, para algunos o todos los usuarios.\n\n**Ejemplo programático**\nEste ejemplo muestra código Java que permite mostrar una funcionalidad cuando es activada por el desarrollador, y cuando un usuario es miembro Premium de la aplicación. Esto es útil para características bloqueadas por suscripción.\n\n```java\npublic class FeatureToggleExample {\n    // Bool for feature enabled or disabled\n    private static boolean isNewFeatureEnabled = false;\n\n    public static void main(String[] args) {\n        boolean userIsPremium = true; // Example: Check if the user is a premium user\n\n        // Check if the new feature should be enabled for the user\n        if (userIsPremium && isNewFeatureEnabled) {\n            // User is premium and the new feature is enabled\n            showNewFeature();\n        }\n    }\n\n    private static void showNewFeature() {\n        // If user is allowed to see locked feature, this is where the code would go\n    }\n}\n```\nEl código muestra lo sencillo que es aplicar este patrón de diseño, y los criterios pueden refinarse o ampliarse aún más si los desarrolladores así lo deciden.\n\n## Diagrama de clases\n![alt text](./etc/feature-toggle.png \"Feature Toggle\")\n\n## Aplicabilidad\nUtilice el patrón de alternancia de funciones cuando\n\n* Dar diferentes características a diferentes usuarios.\n* Desplegar una nueva característica de forma incremental.\n* Cambiar entre entornos de desarrollo y producción.\n* Desactivar rápidamente funciones problemáticas.\n* Gestión externa del despliegue de características.\n* Capacidad de mantener múltiples versiones de una característica.\n* Despliegue \"oculto\", liberando una característica en código para pruebas designadas, pero sin ponerla a disposición del público.\n\n## Consecuencias\nConsecuencias del uso del patrón de alternancia de funciones\n\n* Aumenta la complejidad del código\n* Probar múltiples estados es más difícil y consume más tiempo\n* Confusión entre amigos sobre por qué faltan características\n* Mantener la documentación actualizada con todas las características puede ser difícil.\n\n## Créditos\n\n* [Martin Fowler 29 October 2010 (2010-10-29).](http://martinfowler.com/bliki/FeatureToggle.html)\n* [Feature Toggle - Java Design Patterns](https://java-design-patterns.com/patterns/feature-toggle/)\n"
  },
  {
    "path": "localization/es/flux/README.md",
    "content": "---\ntitle: Flux\nshortTitle: Flux\ncategory: Structural\nlanguage: es\ntag:\n - Decoupling\n---\n\n## Propósito\nFlux evita MVC en favor de un flujo de datos unidireccional. Cuando un usuario\nusuario interactúa con una vista, ésta propaga una acción a través de un\ncentral, a los distintos almacenes que contienen los datos de la aplicación y la\nque actualiza todas las vistas afectadas.\n\n## Diagrama de clases\n![alt text](./etc/flux.png \"Flux\")\n\n## Aplicabilidad\nUtilice el patrón Flux cuando\n\n* Debes centrarte en crear rutas de actualización explícitas y comprensibles para los datos de tu aplicación, lo que simplifica el seguimiento de los cambios durante el desarrollo y facilita la localización y corrección de errores.\n\n## Créditos\n\n* [Flux - Application architecture for building user interfaces](http://facebook.github.io/flux/)\n"
  },
  {
    "path": "localization/es/flyweight/README.md",
    "content": "---\ntitle: Flyweight\nshortTitle: Flyweight\ncategory: Structural\nlanguage: es\ntag:\n  - Gang of Four\n  - Performance\n---\n\n## Propósito\n\nUtilice la compartición para dar soporte a un gran número de objetos finos de forma eficiente.\n\n## Explicación\n\nUn ejemplo real\n\n> La tienda del alquimista tiene estanterías llenas de pociones mágicas. Muchas de las pociones son las mismas, por lo\n> que no es necesario crear un nuevo objeto para cada una de ellas. En su lugar, una instancia de objeto puede\n> representar\n> múltiples elementos de la estantería para que la huella de memoria siga siendo pequeña.\n\nEn pocas palabras\n\n> Se utiliza para minimizar el uso de memoria o los gastos computacionales compartiendo todo lo posible con objetos\n> similares.\n\nWikipedia dice\n\n> En programación informática, flyweight es un patrón de diseño de software. Un flyweight es un objeto que minimiza el\n> uso de memoria compartiendo tantos datos como sea posible con otros objetos similares; es una forma de utilizar\n> objetos\n> en grandes cantidades cuando una simple representación repetida utilizaría una cantidad inaceptable de memoria.\n\n**Ejemplo programático**\n\nTraduciendo nuestro ejemplo de la tienda de alquimia de arriba. En primer lugar, tenemos diferentes tipos de\npociones `Potion`: `HealingPotion`, `HolyWaterPotion` e `InvisibilityPotion`:\n\n```java\npublic interface Potion {\n  void drink();\n}\n\n@Slf4j\npublic class HealingPotion implements Potion {\n  @Override\n  public void drink() {\n    LOGGER.info(\"You feel healed. (Potion={})\", System.identityHashCode(this));\n  }\n}\n\n@Slf4j\npublic class HolyWaterPotion implements Potion {\n  @Override\n  public void drink() {\n    LOGGER.info(\"You feel blessed. (Potion={})\", System.identityHashCode(this));\n  }\n}\n\n@Slf4j\npublic class InvisibilityPotion implements Potion {\n  @Override\n  public void drink() {\n    LOGGER.info(\"You become invisible. (Potion={})\", System.identityHashCode(this));\n  }\n}\n```\n\nLuego la clase Flyweight `PotionFactory`, que es la fábrica para crear pociones.\n\n```java\npublic class PotionFactory {\n\n  private final Map<PotionType, Potion> potions;\n\n  public PotionFactory() {\n    potions = new EnumMap<>(PotionType.class);\n  }\n\n  Potion createPotion(PotionType type) {\n    var potion = potions.get(type);\n    if (potion == null) {\n      switch (type) {\n        case HEALING -> {\n          potion = new HealingPotion();\n          potions.put(type, potion);\n        }\n        case HOLY_WATER -> {\n          potion = new HolyWaterPotion();\n          potions.put(type, potion);\n        }\n        case INVISIBILITY -> {\n          potion = new InvisibilityPotion();\n          potions.put(type, potion);\n        }\n        default -> {\n        }\n      }\n    }\n    return potion;\n  }\n}\n```\n\n`AlchemistShop` contiene dos estantes de pociones mágicas. Las pociones se crean utilizando la antes\nmencionada `PotionFactory`.\n\n```java\n@Slf4j\npublic class AlchemistShop {\n\n  private final List<Potion> topShelf;\n  private final List<Potion> bottomShelf;\n\n  public AlchemistShop() {\n    var factory = new PotionFactory();\n    topShelf = List.of(\n        factory.createPotion(PotionType.INVISIBILITY),\n        factory.createPotion(PotionType.INVISIBILITY),\n        factory.createPotion(PotionType.STRENGTH),\n        factory.createPotion(PotionType.HEALING),\n        factory.createPotion(PotionType.INVISIBILITY),\n        factory.createPotion(PotionType.STRENGTH),\n        factory.createPotion(PotionType.HEALING),\n        factory.createPotion(PotionType.HEALING)\n    );\n    bottomShelf = List.of(\n        factory.createPotion(PotionType.POISON),\n        factory.createPotion(PotionType.POISON),\n        factory.createPotion(PotionType.POISON),\n        factory.createPotion(PotionType.HOLY_WATER),\n        factory.createPotion(PotionType.HOLY_WATER)\n    );\n  }\n\n  public final List<Potion> getTopShelf() {\n    return List.copyOf(this.topShelf);\n  }\n\n  public final List<Potion> getBottomShelf() {\n    return List.copyOf(this.bottomShelf);\n  }\n\n  public void drinkPotions() {\n    LOGGER.info(\"Drinking top shelf potions\\n\");\n    topShelf.forEach(Potion::drink);\n    LOGGER.info(\"Drinking bottom shelf potions\\n\");\n    bottomShelf.forEach(Potion::drink);\n  }\n}\n```\n\nEn nuestro escenario, un valiente visitante entra en la tienda del alquimista y se bebe todas las pociones.\n\n```java\n// create the alchemist shop with the potions\nvar alchemistShop = new AlchemistShop();\n// a brave visitor enters the alchemist shop and drinks all the potions\nalchemistShop.drinkPotions();\n```\n\nSalida del programa:\n\n```java\nDrinking top shelf potions \nYou become invisible. (Potion=1509514333)\nYou become invisible. (Potion=1509514333)\nYou feel strong. (Potion=739498517)\nYou feel healed. (Potion=125130493)\nYou become invisible. (Potion=1509514333)\nYou feel strong. (Potion=739498517)\nYou feel healed. (Potion=125130493)\nYou feel healed. (Potion=125130493)\nDrinking bottom shelf potions\nUrgh! This is poisonous. (Potion=166239592)\nUrgh! This is poisonous. (Potion=166239592)\nUrgh! This is poisonous. (Potion=166239592)\nYou feel blessed. (Potion=991505714)\nYou feel blessed. (Potion=991505714)\n```\n\n## Diagrama de clases\n\n![alt text](./etc/flyweight.urm.png \"Flyweight pattern class diagram\")\n\n## Aplicabilidad\n\nLa eficacia del patrón Flyweight depende en gran medida de cómo y dónde se utilice. Aplique el patrón\nFlyweight cuando se cumplan todas las condiciones siguientes:\n\n* Una aplicación utiliza un gran número de objetos.\n* Los costes de almacenamiento son altos debido a la gran cantidad de objetos.\n* La mayor parte del estado de los objetos puede hacerse extrínseco.\n* Muchos grupos de objetos pueden ser reemplazados por relativamente pocos objetos compartidos una vez que el estado extrínseco\n  extrínseco.\n* La aplicación no depende de la identidad de los objetos. Dado que los objetos flyweight pueden ser compartidos, las pruebas de identidad\n  devolverán verdadero para objetos conceptualmente distintos.\n\n## Usos conocidos\n\n* [java.lang.Integer#valueOf(int)](http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#valueOf%28int%29) y\n  de forma similar para Byte, Carácter y otros tipos envueltos (Wrappers).\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/es/front-controller/README.md",
    "content": "---\ntitle: Front Controller\nshortTitle: Front Controller\ncategory: Structural\nlanguage: es\ntag:\n - Decoupling\n---\n\n## Propósito\nIntroducir un gestor común para todas las solicitudes de un sitio web. De esta\nmanera podemos encapsular funcionalidad común como la seguridad,\ninternacionalización, enrutamiento y registro en un solo lugar.\n\n## Diagrama de clases\n![alt text](./etc/front-controller.png \"Front Controller\")\n\n## Aplicabilidad\nUtilice el patrón del controlador frontal cuando\n\n* Desea encapsular la funcionalidad común de gestión de peticiones en un único lugar.\n* Desea implementar la gestión dinámica de peticiones, es decir, cambiar el enrutamiento sin modificar el código.\n* hacer portable la configuración del servidor web, sólo necesitas registrar el manejador de forma específica para el servidor web\n\n## Ejemplos del mundo real\n\n* [Apache Struts](https://struts.apache.org/)\n\n## Créditos\n\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Presentation Tier Patterns](http://www.javagyan.com/tutorials/corej2eepatterns/presentation-tier-patterns)\n* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321127420&linkCode=as2&tag=javadesignpat-20&linkId=d9f7d37b032ca6e96253562d075fcc4a)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n"
  },
  {
    "path": "localization/es/game-loop/README.md",
    "content": "---  \ntitle: Game Loop \nshortTitle: Game Loop \ncategory: Behavioral\nlanguage: es\ntag:  \n - Game programming\n---  \n  \n## Propósito\n\nUn bucle de juego se ejecuta continuamente durante la partida. En cada vuelta del bucle, procesa las entradas del usuario sin bloquearse, actualiza el estado del juego y lo renderiza. Realiza un seguimiento del paso del tiempo para controlar el ritmo de juego.\n\nEste patrón desvincula la progresión del tiempo de juego de la entrada del usuario y de la velocidad del procesador.\n\n## Aplicabilidad\n\nEste patrón se utiliza en todos los motores de juego.\n\n## Explicación\n\nEjemplo del mundo real\n\n> El bucle de juego es el proceso principal de todos los hilos de renderizado del juego. Está presente en todos los juegos modernos. Controla el proceso de entrada, la actualización del estado interno, el renderizado, la IA y todos los demás procesos.\n\nEn pocas palabras\n\n> El patrón de bucle de juego garantiza que el tiempo de juego progrese a la misma velocidad en todas las configuraciones de hardware diferentes.\n\nWikipedia dice\n\n> El componente central de cualquier juego, desde el punto de vista de la programación, es el bucle de juego. El bucle de juego permite que el juego se ejecute sin problemas, independientemente de la entrada de un usuario, o la falta de ella.\n\n**Ejemplo programático**\n\nEmpecemos con algo sencillo. Aquí está la clase `Bullet`. Las balas se moverán en nuestro juego. Para propósitos de demostración es suficiente que tenga una posición unidimensional.\n\n```java\npublic class Bullet {\n\n  private float position;\n\n  public Bullet() {\n    position = 0.0f;\n  }\n\n  public float getPosition() {\n    return position;\n  }\n\n  public void setPosition(float position) {\n    this.position = position;\n  }\n}\n```\n\nEl `GameController` es el responsable de mover los objetos del juego, incluida la mencionada bala.\n\n```java\npublic class GameController {\n\n  protected final Bullet bullet;\n\n  public GameController() {\n    bullet = new Bullet();\n  }\n\n  public void moveBullet(float offset) {\n    var currentPosition = bullet.getPosition();\n    bullet.setPosition(currentPosition + offset);\n  }\n\n  public float getBulletPosition() {\n    return bullet.getPosition();\n  }\n}\n```\n\nAhora introducimos el bucle de juego. O en realidad en esta demo tenemos 3 bucles de juego diferentes. Veamos primero la clase base `GameLoop`.\n\n```java\npublic enum GameStatus {\n\n  RUNNING, STOPPED\n}\n\npublic abstract class GameLoop {\n\n  protected final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n  protected volatile GameStatus status;\n\n  protected GameController controller;\n\n  private Thread gameThread;\n\n  public GameLoop() {\n    controller = new GameController();\n    status = GameStatus.STOPPED;\n  }\n\n  public void run() {\n    status = GameStatus.RUNNING;\n    gameThread = new Thread(this::processGameLoop);\n    gameThread.start();\n  }\n\n  public void stop() {\n    status = GameStatus.STOPPED;\n  }\n\n  public boolean isGameRunning() {\n    return status == GameStatus.RUNNING;\n  }\n\n  protected void processInput() {\n    try {\n      var lag = new Random().nextInt(200) + 50;\n      Thread.sleep(lag);\n    } catch (InterruptedException e) {\n      logger.error(e.getMessage());\n    }\n  }\n\n  protected void render() {\n    var position = controller.getBulletPosition();\n    logger.info(\"Current bullet position: \" + position);\n  }\n\n  protected abstract void processGameLoop();\n}\n```\n\nAquí está la primera implementación del bucle de juego, `FrameBasedGameLoop`:\n\n```java\npublic class FrameBasedGameLoop extends GameLoop {\n\n  @Override\n  protected void processGameLoop() {\n    while (isGameRunning()) {\n      processInput();\n      update();\n      render();\n    }\n  }\n\n  protected void update() {\n    controller.moveBullet(0.5f);\n  }\n}\n```\n\nPor último, mostramos todos los bucles del juego en acción.\n\n```java\n    try {\n      LOGGER.info(\"Start frame-based game loop:\");\n      var frameBasedGameLoop = new FrameBasedGameLoop();\n      frameBasedGameLoop.run();\n      Thread.sleep(GAME_LOOP_DURATION_TIME);\n      frameBasedGameLoop.stop();\n      LOGGER.info(\"Stop frame-based game loop.\");\n\n      LOGGER.info(\"Start variable-step game loop:\");\n      var variableStepGameLoop = new VariableStepGameLoop();\n      variableStepGameLoop.run();\n      Thread.sleep(GAME_LOOP_DURATION_TIME);\n      variableStepGameLoop.stop();\n      LOGGER.info(\"Stop variable-step game loop.\");\n\n      LOGGER.info(\"Start fixed-step game loop:\");\n      var fixedStepGameLoop = new FixedStepGameLoop();\n      fixedStepGameLoop.run();\n      Thread.sleep(GAME_LOOP_DURATION_TIME);\n      fixedStepGameLoop.stop();\n      LOGGER.info(\"Stop variable-step game loop.\");\n      \n    } catch (InterruptedException e) {\n      LOGGER.error(e.getMessage());\n    }\n```\n\nSalida del programa:\n\n```java\nStart frame-based game loop:\nCurrent bullet position: 0.5\nCurrent bullet position: 1.0\nCurrent bullet position: 1.5\nCurrent bullet position: 2.0\nCurrent bullet position: 2.5\nCurrent bullet position: 3.0\nCurrent bullet position: 3.5\nCurrent bullet position: 4.0\nCurrent bullet position: 4.5\nCurrent bullet position: 5.0\nCurrent bullet position: 5.5\nCurrent bullet position: 6.0\nStop frame-based game loop.\nStart variable-step game loop:\nCurrent bullet position: 6.5\nCurrent bullet position: 0.038\nCurrent bullet position: 0.084\nCurrent bullet position: 0.145\nCurrent bullet position: 0.1805\nCurrent bullet position: 0.28\nCurrent bullet position: 0.32\nCurrent bullet position: 0.42549998\nCurrent bullet position: 0.52849996\nCurrent bullet position: 0.57799995\nCurrent bullet position: 0.63199997\nCurrent bullet position: 0.672\nCurrent bullet position: 0.778\nCurrent bullet position: 0.848\nCurrent bullet position: 0.8955\nCurrent bullet position: 0.9635\nStop variable-step game loop.\nStart fixed-step game loop:\nCurrent bullet position: 0.0\nCurrent bullet position: 1.086\nCurrent bullet position: 0.059999995\nCurrent bullet position: 0.12999998\nCurrent bullet position: 0.24000004\nCurrent bullet position: 0.33999994\nCurrent bullet position: 0.36999992\nCurrent bullet position: 0.43999985\nCurrent bullet position: 0.5399998\nCurrent bullet position: 0.65999967\nCurrent bullet position: 0.68999964\nCurrent bullet position: 0.7299996\nCurrent bullet position: 0.79999954\nCurrent bullet position: 0.89999944\nCurrent bullet position: 0.98999935\nStop variable-step game loop.\n```\n\n## Diagrama de clases\n\n![alt text](./etc/game-loop.urm.png \"Game Loop pattern class diagram\")\n\n## Créditos\n  \n* [Game Programming Patterns - Game Loop](http://gameprogrammingpatterns.com/game-loop.html)\n* [Game Programming Patterns](https://www.amazon.com/gp/product/0990582906/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0990582906&linkId=1289749a703b3fe0e24cd8d604d7c40b)\n* [Game Engine Architecture, Third Edition](https://www.amazon.com/gp/product/1138035459/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1138035459&linkId=94502746617211bc40e0ef49d29333ac)\n"
  },
  {
    "path": "localization/es/gateway/README.md",
    "content": "---\ntitle: Gateway\nshortTitle: Gateway\ncategory: Structural\nlanguage: es\ntag:\n- Decoupling\n\n---\n\n## Propósito\n\nProporcionar una interfaz de acceso a un conjunto de sistemas o funcionalidades externas. Gateway proporciona una vista simple y uniforme de\nrecursos externos a los internos de una aplicación.\n\n## Explicación\n\nUn ejemplo real\n\n> Gateway actúa como una verdadera puerta de entrada de una ciudad determinada. Las personas dentro de la ciudad se llaman sistema interno, y las diferentes ciudades externas se llaman servicios externos. La puerta de enlace está aquí para proporcionar acceso al sistema interno a diferentes servicios externos.\n\nEn pocas palabras\n\n> La pasarela puede proporcionar una interfaz que permita al sistema interno utilizar un servicio externo.\n\nWikipedia dice\n\n> Un servidor que actúa como front-end de la API, recibe solicitudes de la API, aplica políticas de estrangulamiento y seguridad, pasa las solicitudes al servicio back-end y, a continuación, devuelve la respuesta al solicitante.\n\n**Ejemplo programático**\n\nLa clase principal de nuestro ejemplo es el `ExternalService` que contiene elementos.\n\n```java\nclass ExternalServiceA implements Gateway {\n    @Override\n    public void execute() throws Exception {\n        LOGGER.info(\"Executing Service A\");\n        // Simulate a time-consuming task\n        Thread.sleep(1000);\n    }\n}\n\n/**\n * ExternalServiceB is one of external services.\n */\nclass ExternalServiceB implements Gateway {\n    @Override\n    public void execute() throws Exception {\n        LOGGER.info(\"Executing Service B\");\n        // Simulate a time-consuming task\n        Thread.sleep(1000);\n    }\n}\n\n/**\n * ExternalServiceC is one of external services.\n */\nclass ExternalServiceC implements Gateway {\n    @Override\n    public void execute() throws Exception {\n        LOGGER.info(\"Executing Service C\");\n        // Simulate a time-consuming task\n        Thread.sleep(1000);\n    }\n\n    public void error() throws Exception {\n        // Simulate an exception\n        throw new RuntimeException(\"Service C encountered an error\");\n    }\n}\n```\n\nPara operar estos servicios externos, aquí está la clase `App`:\n\n```java\npublic class App {\n    /**\n     * Simulate an application calling external services.\n     */\n    public static void main(String[] args) throws Exception {\n        GatewayFactory gatewayFactory = new GatewayFactory();\n\n        // Register different gateways\n        gatewayFactory.registerGateway(\"ServiceA\", new ExternalServiceA());\n        gatewayFactory.registerGateway(\"ServiceB\", new ExternalServiceB());\n        gatewayFactory.registerGateway(\"ServiceC\", new ExternalServiceC());\n\n        // Use an executor service for asynchronous execution\n        Gateway serviceA = gatewayFactory.getGateway(\"ServiceA\");\n        Gateway serviceB = gatewayFactory.getGateway(\"ServiceB\");\n        Gateway serviceC = gatewayFactory.getGateway(\"ServiceC\");\n\n        // Execute external services\n        try {\n            serviceA.execute();\n            serviceB.execute();\n            serviceC.execute();\n        } catch (ThreadDeath e) {\n            LOGGER.info(\"Interrupted!\" + e);\n            throw e;\n        }\n    }\n}\n```\n\nLa interfaz `Gateway` es extremadamente sencilla.\n\n```java\ninterface Gateway {\n    void execute() throws Exception;\n}\n```\n\nSalida del programa:\n\n```java\n        Executing Service A\n        Executing Service B\n        Executing Service C\n```\n\n## Diagrama de clases\n\n![alt text](./etc/gateway.urm.png \"gateway\")\n\n## Aplicabilidad\n\nUtilizar el patrón Gateway\n\n* Para acceder al contenido de un objeto agregado sin exponer su representación interna.\n* Para la integración con múltiples servicios externos o APIs.\n* Para proporcionar una interfaz uniforme para recorrer diferentes estructuras de agregados.\n\n## Tutoriales\n\n* [Pattern: API Gateway / Backends for Frontends](https://microservices.io/patterns/apigateway.html)\n\n## Usos conocidos\n\n* [API Gateway](https://java-design-patterns.com/patterns/microservices-api-gateway/)\n* [10 most common use cases of an API Gateway](https://apisix.apache.org/blog/2022/10/27/ten-use-cases-api-gateway/)\n\n## Créditos\n\n* [Gateway](https://martinfowler.com/articles/gateway-pattern.html)\n* [What is the difference between Facade and Gateway design patterns?](https://stackoverflow.com/questions/4422211/what-is-the-difference-between-facade-and-gateway-design-patterns)\n"
  },
  {
    "path": "localization/es/health-check/README.md",
    "content": "---\ntitle: Health Check Pattern\nshortTitle: Health Check Pattern\ncategory: Behavioral\nlanguage: es\ntag:\n  - Performance\n  - Microservices\n  - Resilience\n  - Observability\n---\n\n# Health Check Pattern\n\n## También conocido como\nHealth Monitoring, Service Health Check\n\n## Propósito\nGarantizar la estabilidad y resistencia de los servicios en una arquitectura de microservicios proporcionando una forma de supervisar y diagnosticar su estado.\n\n## Explicación\nEn la arquitectura de microservicios, es crítico comprobar continuamente la salud de los servicios individuales. El Health Check Pattern es un mecanismo para que los microservicios expongan su estado de salud. Este patrón se implementa incluyendo un punto final de comprobación de salud en los microservicios que devuelve el estado actual del servicio. Esto es vital para mantener la resistencia del sistema y la disponibilidad operativa.\n\nPara obtener más información, consulte el patrón API Health Check en [Microservices.io](https://microservices.io/patterns/observability/health-check-api.html).\n\n\n## Ejemplo del mundo real\nEn un entorno nativo en la nube, como Kubernetes o AWS ECS, las comprobaciones de estado se utilizan para garantizar que los contenedores se ejecutan correctamente. Si un servicio falla su chequeo de salud, puede ser reiniciado o reemplazado automáticamente, asegurando alta disponibilidad y resiliencia.\n\n## En pocas palabras\nEl patrón de comprobación de la salud es como una visita periódica al médico para los servicios en una arquitectura de microservicios. Ayuda en la detección temprana de problemas y asegura que los servicios estén sanos y disponibles.\n\n\n## Ejemplo Programático\nAquí, se proporcionan ejemplos detallados de implementaciones de chequeo de salud en un entorno de microservicios.\n\n### AsynchronousHealthChecker\nUn componente de comprobación de salud asíncrono que ejecuta comprobaciones de salud en un hilo separado.\n\n```java\n  /**\n   * Performs a health check asynchronously using the provided health check logic with a specified\n   * timeout.\n   *\n   * @param healthCheck the health check logic supplied as a {@code Supplier<Health>}\n   * @param timeoutInSeconds the maximum time to wait for the health check to complete, in seconds\n   * @return a {@code CompletableFuture<Health>} object that represents the result of the health\n   *     check\n   */\n  public CompletableFuture<Health> performCheck(\n      Supplier<Health> healthCheck, long timeoutInSeconds) {\n    CompletableFuture<Health> future =\n        CompletableFuture.supplyAsync(healthCheck, healthCheckExecutor);\n\n    // Schedule a task to enforce the timeout\n    healthCheckExecutor.schedule(\n        () -> {\n          if (!future.isDone()) {\n            LOGGER.error(HEALTH_CHECK_TIMEOUT_MESSAGE);\n            future.completeExceptionally(new TimeoutException(HEALTH_CHECK_TIMEOUT_MESSAGE));\n          }\n        },\n        timeoutInSeconds,\n        TimeUnit.SECONDS);\n\n    return future.handle(\n        (result, throwable) -> {\n          if (throwable != null) {\n            LOGGER.error(HEALTH_CHECK_FAILED_MESSAGE, throwable);\n            // Check if the throwable is a TimeoutException or caused by a TimeoutException\n            Throwable rootCause =\n                throwable instanceof CompletionException ? throwable.getCause() : throwable;\n            if (!(rootCause instanceof TimeoutException)) {\n              LOGGER.error(HEALTH_CHECK_FAILED_MESSAGE, rootCause);\n              return Health.down().withException(rootCause).build();\n            } else {\n              LOGGER.error(HEALTH_CHECK_TIMEOUT_MESSAGE, rootCause);\n              // If it is a TimeoutException, rethrow it wrapped in a CompletionException\n              throw new CompletionException(rootCause);\n            }\n          } else {\n            return result;\n          }\n        });\n  }\n```\n\n### CpuHealthIndicator\nUn indicador de salud que comprueba la salud de la CPU del sistema.\n\n```java\n  /**\n   * Checks the health of the system's CPU and returns a health indicator object.\n   *\n   * @return a health indicator object\n   */\n  @Override\n  public Health health() {\n    if (!(osBean instanceof com.sun.management.OperatingSystemMXBean sunOsBean)) {\n      LOGGER.error(\"Unsupported operating system MXBean: {}\", osBean.getClass().getName());\n      return Health.unknown()\n          .withDetail(ERROR_MESSAGE, \"Unsupported operating system MXBean\")\n          .build();\n    }\n\n    double systemCpuLoad = sunOsBean.getCpuLoad() * 100;\n    double processCpuLoad = sunOsBean.getProcessCpuLoad() * 100;\n    int availableProcessors = sunOsBean.getAvailableProcessors();\n    double loadAverage = sunOsBean.getSystemLoadAverage();\n\n    Map<String, Object> details = new HashMap<>();\n    details.put(\"timestamp\", Instant.now());\n    details.put(\"systemCpuLoad\", String.format(\"%.2f%%\", systemCpuLoad));\n    details.put(\"processCpuLoad\", String.format(\"%.2f%%\", processCpuLoad));\n    details.put(\"availableProcessors\", availableProcessors);\n    details.put(\"loadAverage\", loadAverage);\n\n    if (systemCpuLoad > systemCpuLoadThreshold) {\n      LOGGER.error(HIGH_SYSTEM_CPU_LOAD_MESSAGE, systemCpuLoad);\n      return Health.down()\n          .withDetails(details)\n          .withDetail(ERROR_MESSAGE, HIGH_SYSTEM_CPU_LOAD_MESSAGE_WITHOUT_PARAM)\n          .build();\n    } else if (processCpuLoad > processCpuLoadThreshold) {\n      LOGGER.error(HIGH_PROCESS_CPU_LOAD_MESSAGE, processCpuLoad);\n      return Health.down()\n          .withDetails(details)\n          .withDetail(ERROR_MESSAGE, HIGH_PROCESS_CPU_LOAD_MESSAGE_WITHOUT_PARAM)\n          .build();\n    } else if (loadAverage > (availableProcessors * loadAverageThreshold)) {\n      LOGGER.error(HIGH_LOAD_AVERAGE_MESSAGE, loadAverage);\n      return Health.up()\n          .withDetails(details)\n          .withDetail(ERROR_MESSAGE, HIGH_LOAD_AVERAGE_MESSAGE_WITHOUT_PARAM)\n          .build();\n    } else {\n      return Health.up().withDetails(details).build();\n    }\n  }\n\n```\n\n\n\n### CustomHealthIndicator\nUn indicador de estado personalizado que comprueba periódicamente el estado de una base de datos y almacena en caché el resultado. Aprovecha un comprobador de estado asíncrono para realizar las comprobaciones de estado.\n\n- `AsynchronousHealthChecker`: Un componente para realizar comprobaciones de estado de forma asíncrona.\n- `CacheManager`: Gestiona el almacenamiento en caché de los resultados de los controles de salud.\n- `HealthCheckRepository`: Un repositorio para consultar datos relacionados con la salud desde la base de datos.\n\n```java\n/**\n * Perform a health check and cache the result.\n *\n * @return the health status of the application\n * @throws HealthCheckInterruptedException if the health check is interrupted\n */\n@Override\n@Cacheable(value = \"health-check\", unless = \"#result.status == 'DOWN'\")\npublic Health health() {\n    LOGGER.info(\"Performing health check\");\n    CompletableFuture<Health> healthFuture =\n        healthChecker.performCheck(this::check, timeoutInSeconds);\n    try {\n        return healthFuture.get(timeoutInSeconds, TimeUnit.SECONDS);\n    } catch (InterruptedException e) {\n        Thread.currentThread().interrupt();\n        LOGGER.error(\"Health check interrupted\", e);\n        throw new HealthCheckInterruptedException(e);\n    } catch (Exception e) {\n        LOGGER.error(\"Health check failed\", e);\n        return Health.down(e).build();\n    }\n}\n\n/**\n * Checks the health of the database by querying for a simple constant value expected from the\n * database.\n *\n * @return Health indicating UP if the database returns the constant correctly, otherwise DOWN.\n */\nprivate Health check() {\n    Integer result = healthCheckRepository.checkHealth();\n    boolean databaseIsUp = result != null && result == 1;\n    LOGGER.info(\"Health check result: {}\", databaseIsUp);\n    return databaseIsUp\n        ? Health.up().withDetail(\"database\", \"reachable\").build()\n        : Health.down().withDetail(\"database\", \"unreachable\").build();\n}\n\n/**\n * Evicts all entries from the health check cache. This is scheduled to run at a fixed rate\n * defined in the application properties.\n */\n@Scheduled(fixedRateString = \"${health.check.cache.evict.interval:60000}\")\npublic void evictHealthCache() {\n    LOGGER.info(\"Evicting health check cache\");\n    try {\n        Cache healthCheckCache = cacheManager.getCache(\"health-check\");\n        LOGGER.info(\"Health check cache: {}\", healthCheckCache);\n        if (healthCheckCache != null) {\n            healthCheckCache.clear();\n        }\n    } catch (Exception e) {\n        LOGGER.error(\"Failed to evict health check cache\", e);\n    }\n}\n\n```\n\n### DatabaseTransactionHealthIndicator\nUn indicador de salud que comprueba la salud de las transacciones de la base de datos intentando realizar una transacción de prueba utilizando un mecanismo de reintento.\n\n- Repositorio de comprobaciones de estado**: Un repositorio para realizar comprobaciones de salud en la base de datos.\n- AsynchronousHealthChecker**: Un comprobador de salud asíncrono utilizado para ejecutar comprobaciones de salud en un hilo independiente.\n- Plantilla de reintento**: Una plantilla de reintento utilizada para reintentar la transacción de prueba si falla debido a un error transitorio.\n\n```java\n/**\n * Performs a health check by attempting to perform a test transaction with retry support.\n *\n * @return the health status of the database transactions\n */\n@Override\npublic Health health() {\n    LOGGER.info(\"Calling performCheck with timeout {}\", timeoutInSeconds);\n    Supplier<Health> dbTransactionCheck =\n        () -> {\n            try {\n                healthCheckRepository.performTestTransaction();\n                return Health.up().build();\n            } catch (Exception e) {\n                LOGGER.error(\"Database transaction health check failed\", e);\n                return Health.down(e).build();\n            }\n        };\n    try {\n        return asynchronousHealthChecker.performCheck(dbTransactionCheck, timeoutInSeconds).get();\n    } catch (InterruptedException | ExecutionException e) {\n        LOGGER.error(\"Database transaction health check timed out or was interrupted\", e);\n        Thread.currentThread().interrupt();\n        return Health.down(e).build();\n    }\n}\n```\n\n\n### GarbageCollectionHealthIndicator\nUn indicador de salud personalizado que comprueba el estado de recogida de basura de la aplicación e informa del estado de salud en consecuencia.\n\n```java\n  /**\n   * Performs a health check by gathering garbage collection metrics and evaluating the overall\n   * health of the garbage collection system.\n   *\n   * @return a {@link Health} object representing the health status of the garbage collection system\n   */\n  @Override\n  public Health health() {\n    List<GarbageCollectorMXBean> gcBeans = getGarbageCollectorMxBeans();\n    List<MemoryPoolMXBean> memoryPoolMxBeans = getMemoryPoolMxBeans();\n    Map<String, Map<String, String>> gcDetails = new HashMap<>();\n\n    for (GarbageCollectorMXBean gcBean : gcBeans) {\n      Map<String, String> collectorDetails = createCollectorDetails(gcBean, memoryPoolMxBeans);\n      gcDetails.put(gcBean.getName(), collectorDetails);\n    }\n    return Health.up().withDetails(gcDetails).build();\n  }\n\n```\n\n### MemoryHealthIndicator\nUn indicador de salud personalizado que comprueba el uso de memoria de la aplicación e informa del estado de salud en consecuencia.\n\n```java\n  /**\n   * Performs a health check by checking the memory usage of the application.\n   *\n   * @return the health status of the application\n   */\n  public Health checkMemory() {\n    Supplier<Health> memoryCheck =\n        () -> {\n          MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean();\n          MemoryUsage heapMemoryUsage = memoryMxBean.getHeapMemoryUsage();\n          long maxMemory = heapMemoryUsage.getMax();\n          long usedMemory = heapMemoryUsage.getUsed();\n\n          double memoryUsage = (double) usedMemory / maxMemory;\n          String format = String.format(\"%.2f%% of %d max\", memoryUsage * 100, maxMemory);\n\n          if (memoryUsage < memoryThreshold) {\n            LOGGER.info(\"Memory usage is below threshold: {}\", format);\n            return Health.up().withDetail(\"memory usage\", format).build();\n          } else {\n            return Health.down().withDetail(\"memory usage\", format).build();\n          }\n        };\n\n    try {\n      CompletableFuture<Health> future =\n          asynchronousHealthChecker.performCheck(memoryCheck, timeoutInSeconds);\n      return future.get();\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Health check interrupted\", e);\n      Thread.currentThread().interrupt();\n      return Health.down().withDetail(\"error\", \"Health check interrupted\").build();\n    } catch (ExecutionException e) {\n      LOGGER.error(\"Health check failed\", e);\n      Throwable cause = e.getCause() == null ? e : e.getCause();\n      return Health.down().withDetail(\"error\", cause.toString()).build();\n    }\n  }\n\n  /**\n   * Retrieves the health status of the application by checking the memory usage.\n   *\n   * @return the health status of the application\n   */\n  @Override\n  public Health health() {\n    return checkMemory();\n  }\n}\n```\n\n\n\n## Usando Spring Boot Actuator para Comprobaciones de Salud\nSpring Boot Actuator proporciona una funcionalidad de comprobación de salud incorporada que puede integrarse fácilmente en su aplicación. Añadiendo la dependencia Spring Boot Actuator, puede exponer la información de comprobación de estado a través de un punto final predefinido, normalmente `/actuator/health`.\n\n## Salida\nEsto muestra la salida del patrón de comprobación de salud utilizando una petición GET al punto final de salud de Actuator.\n\n### HTTP GET Request\n```\ncurl -X GET \"http://localhost:6161/actuator/health\"\n```\n\n### Output\n```json\n{\n    \"status\": \"UP\",\n    \"components\": {\n        \"cpu\": {\n            \"status\": \"UP\",\n            \"details\": {\n                \"processCpuLoad\": \"0.03%\",\n                \"availableProcessors\": 10,\n                \"systemCpuLoad\": \"21.40%\",\n                \"loadAverage\": 3.3916015625,\n                \"timestamp\": \"2023-12-03T08:44:19.488422Z\"\n            }\n        },\n        \"custom\": {\n            \"status\": \"UP\",\n            \"details\": {\n                \"database\": \"reachable\"\n            }\n        },\n        \"databaseTransaction\": {\n            \"status\": \"UP\"\n        },\n        \"db\": {\n            \"status\": \"UP\",\n            \"details\": {\n                \"database\": \"H2\",\n                \"validationQuery\": \"isValid()\"\n            }\n        },\n        \"diskSpace\": {\n            \"status\": \"UP\",\n            \"details\": {\n                \"total\": 994662584320,\n                \"free\": 377635827712,\n                \"threshold\": 10485760,\n                \"exists\": true\n            }\n        },\n        \"garbageCollection\": {\n            \"status\": \"UP\",\n            \"details\": {\n                \"G1 Young Generation\": {\n                    \"count\": \"11\",\n                    \"time\": \"30ms\",\n                    \"memoryPools\": \"G1 Old Gen: 0.005056262016296387%\"\n                },\n                \"G1 Old Generation\": {\n                    \"count\": \"0\",\n                    \"time\": \"0ms\",\n                    \"memoryPools\": \"G1 Old Gen: 0.005056262016296387%\"\n                }\n            }\n        },\n        \"livenessState\": {\n            \"status\": \"UP\"\n        },\n        \"memory\": {\n            \"status\": \"UP\",\n            \"details\": {\n                \"memory usage\": \"1.36% of 4294967296 max\"\n            }\n        },\n        \"ping\": {\n            \"status\": \"UP\"\n        },\n        \"readinessState\": {\n            \"status\": \"UP\"\n        }\n    },\n    \"groups\": [\n        \"liveness\",\n        \"readiness\"\n    ]\n}\n```\n\n## Diagrama de clases\n![Health Check Pattern](./etc/health-check.png)\n\n## Aplicabilidad\nUtilice el Patrón de Comprobación de Salud cuando:\n- Tienes una aplicación compuesta por múltiples servicios y necesitas monitorizar la salud de cada servicio individualmente.\n- Desea implementar la recuperación o sustitución automática de servicios basándose en el estado de salud.\n- Está empleando herramientas de orquestación o automatización que se basan en comprobaciones de estado para gestionar instancias de servicio.\n\n## Tutoriales\n- Implementación de Health Checks en Java usando Spring Boot Actuator.\n\n## Usos conocidos\n- Kubernetes Liveness y Readiness Probes\n- Comprobaciones de estado de AWS Elastic Load Balancing\n- Actuador Spring Boot\n\n## Consecuencias\n**Pros:**\n- Mejora la tolerancia a fallos del sistema detectando fallos y permitiendo una rápida recuperación.\n- Mejora la visibilidad del estado del sistema para la supervisión operativa y las alertas.\n\n**Contras:**\n- Añade complejidad a la implementación del servicio.\n- Requiere una estrategia para gestionar los fallos en cascada cuando los servicios dependientes no están en buen estado.\n\n## Patrones relacionados\n- Circuit Breaker\n- Retry Pattern\n- Timeout Pattern\n\n## Créditos\nInspirado en el patrón Health Check API de [microservices.io](https://microservices.io/patterns/observability/health-check-api.html), y el tema [#2695](https://github.com/iluwatar/java-design-patterns/issues/2695) en el repositorio de patrones de diseño Java de iluwatar."
  },
  {
    "path": "localization/es/identity-map/README.md",
    "content": "---\ntitle: Identity Map\nshortTitle: Identity Map\ncategory: Behavioral\nlanguage: es\ntag:\n- Performance\n- Data access\n---\n\n## Propósito\n\nGarantiza que cada objeto se cargue una sola vez guardando cada objeto cargado en un mapa.\nBusca objetos utilizando el mapa cuando se refiere a ellos.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Estamos escribiendo un programa que el usuario puede utilizar para encontrar los registros de una persona determinada en una base de datos.\n\nEn palabras simples\n\n> Construir un mapa de identidades que almacene los registros de los elementos buscados recientemente en la base de datos. Cuando busquemos el mismo registro la próxima vez lo cargaremos desde el mapa no iremos a la base de datos.\n\nWikipedia dice\n\n> En el diseño de DBMS, el patrón de mapa de identidad es un patrón de diseño de acceso a base de datos utilizado para mejorar el rendimiento, proporcionando un contexto específico, en la memoria caché para evitar la recuperación duplicada de los mismos datos de objetos de la base de datos\n\n**Ejemplo programático**\n\n* Para el propósito de esta demostración supongamos que ya hemos creado una instancia de base de datos **db**.\n* Veamos primero la implementación de una entidad persona y sus campos:\n\n```java\n@EqualsAndHashCode(onlyExplicitlyIncluded = true)\n@Getter\n@Setter\n@AllArgsConstructor\npublic final class Person implements Serializable {\n\n  private static final long serialVersionUID = 1L;\n\n  @EqualsAndHashCode.Include\n  private int personNationalId;\n  private String name;\n  private long phoneNum;\n\n  @Override\n  public String toString() {\n\n    return \"Person ID is : \" + personNationalId + \" ; Person Name is : \" + name + \" ; Phone Number is :\" + phoneNum;\n\n  }\n\n}\n\n```\n\n* La siguiente es la implementación del personFinder que es la entidad que el usuario utilizará para buscar un registro en nuestra base de datos. Tiene adjunta la BD correspondiente. También mantiene un IdentityMap para almacenar los registros leídos recientemente.\n\n```java\n@Slf4j\n@Getter\n@Setter\npublic class PersonFinder {\n  private static final long serialVersionUID = 1L;\n  //  Access to the Identity Map\n  private IdentityMap identityMap = new IdentityMap();\n  private PersonDbSimulatorImplementation db = new PersonDbSimulatorImplementation();\n  /**\n   * get person corresponding to input ID.\n   *\n   * @param key : personNationalId to look for.\n   */\n  public Person getPerson(int key) {\n    // Try to find person in the identity map\n    Person person = this.identityMap.getPerson(key);\n    if (person != null) {\n      LOGGER.info(\"Person found in the Map\");\n      return person;\n    } else {\n      // Try to find person in the database\n      person = this.db.find(key);\n      if (person != null) {\n        this.identityMap.addPerson(person);\n        LOGGER.info(\"Person found in DB.\");\n        return person;\n      }\n      LOGGER.info(\"Person with this ID does not exist.\");\n      return null;\n    }\n  }\n}\n\n```\n\n* El campo de mapa de identidad en la clase anterior es simplemente una abstracción de un hashMap con **personNationalId** como claves y el objeto persona correspondiente como valor. Aquí está su implementación:\n\n```java\n@Slf4j\n@Getter\npublic class IdentityMap {\n  private Map<Integer, Person> personMap = new HashMap<>();\n  /**\n   * Add person to the map.\n   */\n  public void addPerson(Person person) {\n    if (!personMap.containsKey(person.getPersonNationalId())) {\n      personMap.put(person.getPersonNationalId(), person);\n    } else { // Ensure that addPerson does not update a record. This situation will never arise in our implementation. Added only for testing purposes.\n      LOGGER.info(\"Key already in Map\");\n    }\n  }\n\n  /**\n   * Get Person with given id.\n   *\n   * @param id : personNationalId as requested by user.\n   */\n  public Person getPerson(int id) {\n    Person person = personMap.get(id);\n    if (person == null) {\n      LOGGER.info(\"ID not in Map.\");\n    }\n    return person;\n  }\n\n  /**\n   * Get the size of the map.\n   */\n  public int size() {\n    if (personMap == null) {\n      return 0;\n    }\n    return personMap.size();\n  }\n\n}\n\n```\n\n* Ahora debemos construir una persona ficticia para fines de demostración y poner a esa persona en nuestra base de datos.\n\n```java\n  Person person1 = new Person(1, \"John\", 27304159);\n  db.insert(person1);\n```\n\n* Ahora vamos a crear un objeto person finder y buscar a la persona con personNationalId = 1(supongamos que el objeto personFinder ya tiene la db y un IdentityMap adjunto):  \n\n```java\n  PersonFinder finder = new PersonFinder();\n  finder.getPerson(1);\n```\n\n* En esta etapa este registro se cargará desde la base de datos y la salida sería:\n\n```java\n  ID not in Map.\n  Person ID is:1;Person Name is:John;Phone Number is:27304159\n  Person found in DB.\n```\n\n* Sin embargo, la próxima vez que busquemos de nuevo este registro lo encontraremos en el mapa, por lo que no necesitaremos ir a la base de datos.\n\n```java\n  Person ID is:1;Person Name is:John;Phone Number is:27304159\n  Person found in Map.\n```\n\n* Si el registro correspondiente no está en la base de datos, se lanza una excepción. Esta es su implementación.\n\n```java\npublic class IdNotFoundException extends RuntimeException {\n  public IdNotFoundException(final String message) {\n    super(message);\n  }\n}\n```\n## Diagrama de clases\n\n![alt text](./etc/IdentityMap.png \"Identity Map Pattern\")\n\n## Aplicabilidad\n\n* La idea detrás del patrón Identity Map es que cada vez que leemos un registro de la base de datos, primero comprobamos el Identity Map para ver si el registro ya ha sido recuperado. Esto nos permite simplemente devolver una nueva referencia al registro en memoria en lugar de crear un nuevo objeto, manteniendo la integridad referencial.\n* Una ventaja secundaria del Mapa de Identidad es que, al actuar como caché, reduce el número de llamadas a la base de datos necesarias para recuperar objetos, lo que supone una mejora del rendimiento.\n\n## Créditos\n\n* [Identity Map](https://www.sourcecodeexamples.net/2018/04/identity-map-pattern.html)\n"
  },
  {
    "path": "localization/es/intercepting-filter/README.md",
    "content": "---\ntitle: Intercepting Filter\nshortTitle: Intercepting Filter\ncategory: Behavioral\nlanguage: es\ntag:\n - Decoupling\n---\n\n## Propósito\nUn filtro de intercepción es un útil patrón de diseño Java que se utiliza cuando se desea preprocesar o postprocesar una petición en una aplicación. Estos filtros se crean y se aplican a la solicitud antes de que se le da a la aplicación de destino. Algunos ejemplos de uso incluyen la autenticación, que es necesario procesar antes de que la solicitud se entregue a la aplicación.\n\n## Explicación\nEjemplo del mundo real\n> Un ejemplo de uso del patrón de diseño Filtro Interceptor es relevante a la hora de realizar una plataforma de comercio electrónico. Es importante implementar varios filtros para la autenticación de la cuenta, la autenticación del pago, el registro y el almacenamiento en caché. Los tipos de filtros importantes en este ejemplo son los filtros de autenticación, registro, seguridad y almacenamiento en caché.\n\nEn palabras sencillas\n> Un filtro de intercepción en Java es como una serie de puntos de control de seguridad para peticiones y respuestas en una aplicación de software. Comprueba y procesa los datos a medida que entran y salen, ayudando con tareas como la autenticación, el registro y la seguridad, mientras mantiene el núcleo de la aplicación seguro y limpio.\n\nWikipedia dice\n> El filtro de intercepción es un patrón de Java que crea filtros conectables para procesar servicios comunes de una manera estándar sin necesidad de realizar cambios en el código de procesamiento de solicitudes.\n\n## Ejemplo Programático\nComo ejemplo, podemos crear una clase Filtro básica y definir un Filtro de Autenticación. Al filtro le falta lógica, pero\n\n```java\n// 1. Define a Filter interface\ninterface Filter {\n    void runFilter(String request);\n}\n// 2. Create a Authentication filter\nclass AuthenticationFilter implements Filter {\n    public void runFilter(String request) {\n        // Authentication logic would be passed in here\n        if (request.contains(\"authenticated=true\")) {\n            System.out.println(\"Authentication successful for request: \" + request);\n        } else {\n            System.out.println(\"Authentication failed for request: \" + request);\n        }\n    }\n}\n// 3. Create a Client to send requests and activate the filter\nclass Client {\n    // create an instance of the filter in the Client class\n    private Filter filter;\n\n    // create constructor\n    public Client(Filter filter) {\n        this.filter = filter;\n    }\n\n    // send the String request to the filter, the request does not have to be a string\n    // it can be anything\n    public void sendRequest(String request) {\n        filter.runFilter(request);\n    }\n}\n// 4. Demonstrate the Authentication Filter\npublic class AuthenticationFilterExample {\n    public static void main(String[] args) {\n        Filter authenticationFilter = new AuthenticationFilter();\n        Client client = new Client(authenticationFilter);\n\n        // Simulate requests for false\n        client.sendRequest(\"GET /public-page\");\n        // this request would come back as true as the link includes an argument\n        // for successful authentication\n        client.sendRequest(\"GET /private-page?authenticated=true\");\n    }\n}\n```\nEste es un ejemplo básico de cómo implementar el esqueleto de un filtro. Falta la lógica de autenticación en AuthenticationFilterExample, pero se puede rellenar en los huecos.\n\nAdemás, el cliente puede ser configurado para ejecutar múltiples filtros en su solicitud utilizando un bucle For poblado con filtros como se puede ver a continuación:\n\n```java\n// 1. Define a Filter interface\ninterface Filter {\n    void runFilter(String request);\n}\n\n// 2. Create an Authentication filter\nclass AuthenticationFilter implements Filter {\n    public void runFilter(String request) {\n        // Authentication logic would be placed here\n        if (request.contains(\"authenticated=true\")) {\n            System.out.println(\"Authentication successful for request: \" + request);\n        } else {\n            System.out.println(\"Authentication failed for request: \" + request);\n        }\n    }\n}\n\n// 3. Create a Client to send requests and activate multiple filters\nclass Client {\n    // create a list of filters in the Client class\n    private List<Filter> filters = new ArrayList<>();\n\n    // add filters to the list\n    public void addFilter(Filter filter) {\n        filters.add(filter);\n    }\n\n    // send the request through all the filters\n    public void sendRequest(String request) {\n        for (Filter filter : filters) {\n            filter.runFilter(request);\n        }\n    }\n}\n\n// 4. Demonstrate multiple filters\npublic class MultipleFiltersExample {\n    public static void main(String[] args) {\n        // Create a client\n        Client client = new Client();\n\n        // Add filters to the client\n        Filter authenticationFilter = new AuthenticationFilter();\n        client.addFilter(authenticationFilter);\n\n        // Add more filters as needed\n        // Filter anotherFilter = new AnotherFilter();\n        // client.addFilter(anotherFilter);\n\n        // Simulate requests\n        client.sendRequest(\"GET /public-page\");\n        client.sendRequest(\"GET /private-page?authenticated=true\");\n    }\n}\n```\nEste método permite manipular y comprobar los datos de forma rápida y sencilla antes de autenticar un inicio de sesión o finalizar otro tipo de acción.\n\n## Diagrama de clases\n![alt text](./etc/intercepting-filter.png \"Intercepting Filter\")\n\n## Aplicabilidad\nUtilice el patrón Filtro interceptor cuando\n\n* Un programa necesita preprocesar o postprocesar datos\n* Un sistema necesita servicios de autorización/autenticación para acceder a datos sensibles\n* Desea registrar/auditar peticiones o respuestas con fines de depuración o almacenamiento, como marcas de tiempo y acciones del usuario\n* Desea transformar datos de un tipo a otro antes de entregarlos al proceso final.\n* Desea implementar un manejo específico de excepciones\n\n## Consecuencias\nConsecuencias de la aplicación del filtro de interceptación\n\n* Aumento de la complejidad del código, disminuyendo la facilidad de lectura\n* Puede haber problemas en el orden en que se aplican los filtros si el orden es importante\n* Aplicar múltiples filtros a una petición puede crear un retraso en el tiempo de respuesta\n* Probar los efectos de múltiples filtros en una petición puede ser difícil.\n* La compatibilidad y la gestión de versiones pueden ser difíciles si se tienen muchos filtros.\n\n## Tutoriales\n\n* [Introduction to Intercepting Filter Pattern in Java](https://www.baeldung.com/intercepting-filter-pattern-in-java)\n\n## Ejemplos del mundo real\n\n* [javax.servlet.FilterChain](https://tomcat.apache.org/tomcat-8.0-doc/servletapi/javax/servlet/FilterChain.html) and [javax.servlet.Filter](https://tomcat.apache.org/tomcat-8.0-doc/servletapi/javax/servlet/Filter.html)\n* [Struts 2 - Interceptors](https://struts.apache.org/core-developers/interceptors.html)\n\n## Créditos\n\n* [TutorialsPoint - Intercepting Filter](http://www.tutorialspoint.com/design_pattern/intercepting_filter_pattern.htm)\n"
  },
  {
    "path": "localization/es/interpreter/README.md",
    "content": "---\ntitle: Interpreter\nshortTitle: Interpreter\ncategory: Behavioral\nlanguage: es\ntag:\n - Gang of Four\n---\n\n## Propósito\n\nDado un lenguaje, defina una representación para su gramática junto con un intérprete que utilice la\nrepresentación para interpretar las frases del lenguaje.\n\n## Explicación\n\nEjemplo real\n\n> Los niños enanos están aprendiendo matemáticas básicas en la escuela. Empiezan por lo más básico: \"1 + 1\", \"4 - 2\", \"5 + 5\", etcétera.\n\nEn palabras simples\n\n> El patrón intérprete interpreta las frases en el idioma deseado.\n\nWikipedia dice\n\n> En programación informática, el patrón intérprete es un patrón de diseño que especifica cómo evaluar sentencias en un lenguaje. La idea básica es tener una clase para cada símbolo (terminal o no terminal) en un lenguaje informático especializado. El árbol sintáctico de una sentencia en el lenguaje es una instancia del patrón compuesto y se utiliza para evaluar (interpretar) la sentencia para un cliente.\n\n**Ejemplo programático**\n\nPara poder interpretar matemáticas básicas, necesitamos una jerarquía de expresiones. La abstracción básica para ello es la clase `Expression`.\n\n```java\npublic abstract class Expression {\n\n  public abstract int interpret();\n\n  @Override\n  public abstract String toString();\n}\n```\n\nLa más sencilla de las expresiones es la `NumberExpression` que contiene un único número entero.\n\n```java\npublic class NumberExpression extends Expression {\n\n  private final int number;\n\n  public NumberExpression(int number) {\n    this.number = number;\n  }\n\n  public NumberExpression(String s) {\n    this.number = Integer.parseInt(s);\n  }\n\n  @Override\n  public int interpret() {\n    return number;\n  }\n\n  @Override\n  public String toString() {\n    return \"number\";\n  }\n}\n```\n\nLas expresiones más complejas son operaciones como `PlusExpression`, `MinusExpression` y\n`MultiplicarExpresión`. Aquí está la primera de ellas, las otras son similares.\n\n```java\npublic class PlusExpression extends Expression {\n\n  private final Expression leftExpression;\n  private final Expression rightExpression;\n\n  public PlusExpression(Expression leftExpression, Expression rightExpression) {\n    this.leftExpression = leftExpression;\n    this.rightExpression = rightExpression;\n  }\n\n  @Override\n  public int interpret() {\n    return leftExpression.interpret() + rightExpression.interpret();\n  }\n\n  @Override\n  public String toString() {\n    return \"+\";\n  }\n}\n```\n\nAhora podemos mostrar el patrón del intérprete en acción analizando algunas matemáticas sencillas.\n\n```java\n    // the halfling kids are learning some basic math at school\n    // define the math string we want to parse\n    final var tokenString = \"4 3 2 - 1 + *\";\n\n    // the stack holds the parsed expressions\n    var stack = new Stack<Expression>();\n\n    // tokenize the string and go through them one by one\n    var tokenList = tokenString.split(\" \");\n    for (var s : tokenList) {\n        if (isOperator(s)) {\n            // when an operator is encountered we expect that the numbers can be popped from the top of\n            // the stack\n            var rightExpression = stack.pop();\n            var leftExpression = stack.pop();\n            LOGGER.info(\"popped from stack left: {} right: {}\",\n            leftExpression.interpret(), rightExpression.interpret());\n            var operator = getOperatorInstance(s, leftExpression, rightExpression);\n            LOGGER.info(\"operator: {}\", operator);\n            var result = operator.interpret();\n            // the operation result is pushed on top of the stack\n            var resultExpression = new NumberExpression(result);\n            stack.push(resultExpression);\n            LOGGER.info(\"push result to stack: {}\", resultExpression.interpret());\n        } else {\n            // numbers are pushed on top of the stack\n            var i = new NumberExpression(s);\n            stack.push(i);\n            LOGGER.info(\"push to stack: {}\", i.interpret());\n        }\n    }\n    // in the end, the final result lies on top of the stack\n    LOGGER.info(\"result: {}\", stack.pop().interpret());\n```\n\nLa ejecución del programa produce la siguiente salida de consola.\n\n```\npopped from stack left: 1 right: 1\noperator: +\npush result to stack: 2\npopped from stack left: 4 right: 2\noperator: *\npush result to stack: 8\nresult: 8\n```\n\n## Diagrama de clases\n\n![alt text](./etc/interpreter_1.png \"Interpreter\")\n\n## Aplicabilidad\n\nUtilice el patrón Intérprete cuando exista un lenguaje que interpretar, y pueda representar las sentencias\ndel lenguaje como árboles sintácticos abstractos. El patrón Intérprete funciona mejor cuando\n\n* La gramática es simple. Para gramáticas complejas, la jerarquía de clases para la gramática se hace grande e inmanejable. Herramientas como los generadores de analizadores sintácticos son una mejor alternativa en estos casos. Pueden interpretar expresiones sin construir árboles sintácticos abstractos, lo que puede ahorrar espacio y posiblemente tiempo.\n* La eficiencia no es una preocupación crítica. Por lo general, los intérpretes más eficientes no se implementan interpretando directamente los árboles de análisis sintáctico, sino traduciéndolos primero a otra forma. Por ejemplo, las expresiones regulares suelen transformarse en máquinas de estados. Pero incluso entonces, el traductor puede ser implementado por el patrón Intérprete, por lo que el patrón sigue siendo aplicable.\n\n## Usos conocidos\n\n* [java.util.Pattern](http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html)\n* [java.text.Normalizer](http://docs.oracle.com/javase/8/docs/api/java/text/Normalizer.html)\n* Todas las subclases de [java.text.Format](http://docs.oracle.com/javase/8/docs/api/java/text/Format.html)\n* [javax.el.ELResolver](http://docs.oracle.com/javaee/7/api/javax/el/ELResolver.html)\n\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/es/iterator/README.md",
    "content": "---\ntitle: Iterator\nshortTitle: Iterator\ncategory: Behavioral\nlanguage: es\ntag:\n - Gang of Four\n---\n\n## También conocido como\n\nCursor\n\n## Propósito\nProporcionar una forma de acceder a los elementos de un objeto agregado secuencialmente sin exponer su\nrepresentación subyacente.\n\n## Explicación\n\nEjemplo del mundo real\n\n> El cofre del tesoro contiene un conjunto de objetos mágicos. Hay múltiples tipos de artículos tales como anillos, \n> Los objetos pueden buscarse por tipo utilizando un iterador que proporciona \n> el cofre del tesoro.\n\nEn palabras sencillas\n\n> Los contenedores pueden proporcionar una interfaz de iterador agnóstica de representación \n> para proporcionar acceso a los elementos.\n\nWikipedia dice\n\n> En programación orientada a objetos, el patrón iterador es un patrón de diseño en el que \n> se utiliza un iterador para recorrer un contenedor y acceder a sus elementos.\n\n**Ejemplo programático**\n\nLa clase principal de nuestro ejemplo es `TreasureChest` que contiene ítems.\n\n```java\npublic class TreasureChest {\n\n  private final List<Item> items;\n\n  public TreasureChest() {\n    items = List.of(\n        new Item(ItemType.POTION, \"Potion of courage\"),\n        new Item(ItemType.RING, \"Ring of shadows\"),\n        new Item(ItemType.POTION, \"Potion of wisdom\"),\n        new Item(ItemType.POTION, \"Potion of blood\"),\n        new Item(ItemType.WEAPON, \"Sword of silver +1\"),\n        new Item(ItemType.POTION, \"Potion of rust\"),\n        new Item(ItemType.POTION, \"Potion of healing\"),\n        new Item(ItemType.RING, \"Ring of armor\"),\n        new Item(ItemType.WEAPON, \"Steel halberd\"),\n        new Item(ItemType.WEAPON, \"Dagger of poison\"));\n  }\n\n  public Iterator<Item> iterator(ItemType itemType) {\n    return new TreasureChestItemIterator(this, itemType);\n  }\n\n  public List<Item> getItems() {\n    return new ArrayList<>(items);\n  }\n}\n```\n\nEsta es la clase `Item`:\n\n```java\npublic class Item {\n\n  private ItemType type;\n  private final String name;\n\n  public Item(ItemType type, String name) {\n    this.setType(type);\n    this.name = name;\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n\n  public ItemType getType() {\n    return type;\n  }\n\n  public final void setType(ItemType type) {\n    this.type = type;\n  }\n}\n\npublic enum ItemType {\n\n  ANY, WEAPON, RING, POTION\n\n}\n```\n\nLa interfaz `Iterator` es extremadamente sencilla.\n\n```java\npublic interface Iterator<T> {\n\n  boolean hasNext();\n\n  T next();\n}\n```\n\nEn el siguiente ejemplo, iteramos a través de los objetos de tipo anillo encontrados en el cofre. \n\n```java\nvar itemIterator = TREASURE_CHEST.iterator(ItemType.RING);\nwhile (itemIterator.hasNext()) {\n  LOGGER.info(itemIterator.next().toString());\n}\n```\n\nSalida del programa:\n\n```java\nRing of shadows\nRing of armor\n```\n\n## Diagrama de clases\n\n![alt text](./etc/iterator_1.png \"Iterator\")\n\n## Aplicabilidad\n\nUtilizar el patrón Iterator\n\n* Para acceder al contenido de un objeto agregado sin exponer su representación interna.\n* Para soportar múltiples recorridos de objetos agregados.\n* Proporcionar una interfaz uniforme para recorrer diferentes estructuras de agregados.\n\n## Tutoriales\n\n* [How to Use Iterator?](http://www.tutorialspoint.com/java/java_using_iterator.htm)\n\n## Usos conocidos\n\n* [java.util.Iterator](http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html)\n* [java.util.Enumeration](http://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/es/layers/README.md",
    "content": "---\ntitle: Layers\nshortTitle: Layers\ncategory: Architectural\nlanguage: es\ntag:\n- Decoupling\n---\n\n## Propósito\n\nCapas (*Layers* en inglés) es un patrón arquitectónico donde las responsabilidades del software se dividen entre diferentes\ncapas de la aplicación.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Considere un sitio web que muestra pasteles decorados para bodas y similares. En lugar de que la página web\n> acceda directamente a la base de datos, depende de un servicio para entregar esta información. Luego, el\n> servicio consulta la capa de datos para recopilar la información necesaria.\n\nEn otras palabras\n\n> Con el patrón arquitectónico de Capas, diferentes responsabilidades residen en capas separadas. La capa de vista solo\n> está interesada en la renderización, la capa de servicio ensambla los datos solicitados de varias fuentes, y\n> la capa de datos obtiene la información del almacenamiento de datos.\n\nWikipedia dice\n\n> En ingeniería de software, la arquitectura de varios niveles _multitier_ (a menudo referida como arquitectura n-tier) o\n> arquitectura multicapa es una arquitectura cliente-servidor en la que las funciones de presentación, procesamiento de aplicaciones\n> y gestión de datos están físicamente separadas.\n\n**Ejemplo programático**\n\nEn la capa de datos, guardamos nuestros elementos básicos. `Cake` consta de capas (*layers*) y cobertura (*topping*).\n\n```java\n@Entity\npublic class Cake {\n  @Id\n  @GeneratedValue\n  private Long id;\n  @OneToOne(cascade = CascadeType.REMOVE)\n  private CakeTopping topping;\n  @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER)\n  private Set<CakeLayer> layers;\n}\n```\n\nLa capa de servicio ofrece `CakeBakingService` para un fácil acceso a diferentes aspectos de los pasteles.\n\n```java\npublic interface CakeBakingService {\n  void bakeNewCake(CakeInfo cakeInfo) throws CakeBakingException;\n  List<CakeInfo> getAllCakes();\n  void saveNewTopping(CakeToppingInfo toppingInfo);\n  List<CakeToppingInfo> getAvailableToppings();\n  void saveNewLayer(CakeLayerInfo layerInfo);\n  List<CakeLayerInfo> getAvailableLayers();\n}\n```\n\nEn la parte superior tenemos nuestra `View`, responsable de renderizar los pasteles.\n\n```java\npublic interface View {\n  void render();\n}\n@Slf4j\npublic class CakeViewImpl implements View {\n  private final CakeBakingService cakeBakingService;\n  public CakeViewImpl(CakeBakingService cakeBakingService) {\n    this.cakeBakingService = cakeBakingService;\n  }\n  public void render() {\n    cakeBakingService.getAllCakes().forEach(cake -> LOGGER.info(cake.toString()));\n  }\n}\n```\n\n## Diagrama de clases\n\n![alt text](./etc/layers.png \"Layers\")\n\n## Aplicabilidad\n\nUtilice la arquitectura de Capas cuando:\n\n* Quiera dividir claramente las responsabilidades del software en diferentes partes del programa.\n* Quiera evitar que un cambio se propague a lo largo de la aplicación.\n* Quiera hacer su aplicación más mantenible y testeable.\n\n## Créditos\n\n* [Pattern Oriented Software Architecture Volume 1: A System of Patterns](https://www.amazon.com/gp/product/0471958697/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0471958697&linkCode=as2&tag=javadesignpat-20&linkId=e3f42d7a2a4cc8c619bbc0136b20dadb)\n"
  },
  {
    "path": "localization/es/lazy-loading/README.md",
    "content": "---\ntitle: Lazy Loading\nshortTitle: Lazy Loading\ncategory: Idiom\nlanguage: es\ntag:\n - Performance\n---\n\n## Propósito\nLa carga diferida (*Lazy loading* en inglés) es un patrón de diseño comúnmente usado para diferir\nla inicialización de un objeto hasta el punto en que se necesita. Puede\ncontribuir a la eficiencia en la operación del programa si se usa de manera adecuada.\n\n## Diagrama de clases\n![alt text](./etc/lazy-loading.png \"Lazy Loading\")\n\n## Aplicabilidad\nUtilice el modelo de Carga Diferida cuando:\n\n* La carga anticipada es costosa o el objeto a cargar podría no ser necesario en absoluto\n\n## Ejemplos del mundo real\n\n* Anotaciones JPA `@OneToOne`, `@OneToMany`, `@ManyToOne`, `@ManyToMany` y `fetch = FetchType.LAZY`\n\n## Créditos\n\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321127420&linkCode=as2&tag=javadesignpat-20&linkId=d9f7d37b032ca6e96253562d075fcc4a)\n"
  },
  {
    "path": "localization/es/leader-election/README.md",
    "content": "---\ntitle: Leader Election\nshortTitle: Leader Election\ncategory: Behavioral\nlanguage: es\ntag:\n - Cloud distributed\n---\n\n## Propósito\nEl patrón de elección (Leader pattern) del líder se utiliza habitualmente en el diseño de sistemas en la nube. Puede ayudar a garantizar que las instancias de tarea seleccionen la instancia líder correctamente y no entren en conflicto entre sí, causen contención por recursos compartidos o interfieran inadvertidamente con el trabajo que otras instancias de tarea están realizando.\n\n## Explicación\n\nEjemplo del mundo real\n> En un sistema basado en la nube de escalado horizontal, múltiples instancias de la misma tarea podrían estar ejecutándose al mismo tiempo con cada instancia sirviendo a un usuario diferente. Si estas instancias escriben en un recurso compartido, es necesario coordinar sus acciones para evitar que cada instancia sobrescriba los cambios realizados por las demás. En otro escenario, si las tareas están realizando elementos individuales de un cálculo complejo en paralelo, los resultados necesitan ser agregados cuando todos ellos se completan.\n\nEn palabras sencillas\n> este patrón se utiliza en sistemas distribuidos basados en la nube en los que el líder debe actuar como coordinador/agregador entre instancias de escalado horizontal para evitar conflictos en los recursos compartidos.\n\nWikipedia dice\n> En computación distribuida, la elección del líder es el proceso de designar un único proceso como organizador de alguna tarea distribuida entre varios ordenadores (nodos).\n\n**Ejemplo programático**\n\nEl algoritmo Ring y el algoritmo Bully implementan el patrón de elección de líder.\nCada algoritmo requiere que cada instancia participante tenga un ID único.\n\n```java\npublic interface Instance {\n\n  /**\n   * Comprueba si la instancia está viva o no.\n   *\n   * @return {@code true} si la instancia está viva.\n   */\n  boolean isAlive();\n\n  /**\n   * Establece el estado de salud de la instancia en cuestión.\n   *\n   * @param alive {@code true} por vivo.\n   */\n  void setAlive(boolean alive);\n\n  /**\n   * Consumir mensajes de otras instancias.\n   *\n   * @param message Mensaje enviado por otras instancias\n   */\n  void onMessage(Message message);\n\n}\n```\n\nClase abstracta que implementa las interfaces Instance y Runnable.\n\n```java\npublic abstract class AbstractInstance implements Instance, Runnable {\n\n  protected static final int HEARTBEAT_INTERVAL = 5000;\n  private static final String INSTANCE = \"Instance \";\n\n  protected MessageManager messageManager;\n  protected Queue<Message> messageQueue;\n  protected final int localId;\n  protected int leaderId;\n  protected boolean alive;\n\n  /**\n   * Constructor de BullyInstance.\n   */\n  public AbstractInstance(MessageManager messageManager, int localId, int leaderId) {\n    this.messageManager = messageManager;\n    this.messageQueue = new ConcurrentLinkedQueue<>();\n    this.localId = localId;\n    this.leaderId = leaderId;\n    this.alive = true;\n  }\n\n  /**\n   * La instancia ejecutará el mensaje en su cola de mensajes periódicamente una vez que esté viva.\n   */\n  @Override\n  @SuppressWarnings(\"squid:S2189\")\n  public void run() {\n    while (true) {\n      if (!this.messageQueue.isEmpty()) {\n        this.processMessage(this.messageQueue.remove());\n      }\n    }\n  }\n\n  /**\n   * Una vez que los mensajes son enviados a una instancia determinada, se añaden a la cola y esperan a ser ejecutados.\n   *\n   * @param message Mensaje enviado por otras instancias\n   */\n  @Override\n  public void onMessage(Message message) {\n    messageQueue.offer(message);\n  }\n\n  /**\n   * Comprueba si la instancia está viva o no.\n   *\n   * @return {@code true} si la instancia está viva.\n   */\n  @Override\n  public boolean isAlive() {\n    return alive;\n  }\n\n  /**\n   * Establece el estado de salud de la instancia en cuestión.\n   *\n   * @param alive {@code true} por vivo.\n   */\n  @Override\n  public void setAlive(boolean alive) {\n    this.alive = alive;\n  }\n\n  /**\n   * Procesa el mensaje según su tipo.\n   *\n   * @param message Mensaje sondeado desde la cola.\n   */\n  private void processMessage(Message message) {\n    switch (message.getType()) {\n      case ELECTION -> {\n        LOGGER.info(INSTANCE + localId + \" - Election Message handling...\");\n        handleElectionMessage(message);\n      }\n      case LEADER -> {\n        LOGGER.info(INSTANCE + localId + \" - Leader Message handling...\");\n        handleLeaderMessage(message);\n      }\n      case HEARTBEAT -> {\n        LOGGER.info(INSTANCE + localId + \" - Heartbeat Message handling...\");\n        handleHeartbeatMessage(message);\n      }\n      case ELECTION_INVOKE -> {\n        LOGGER.info(INSTANCE + localId + \" - Election Invoke Message handling...\");\n        handleElectionInvokeMessage();\n      }\n      case LEADER_INVOKE -> {\n        LOGGER.info(INSTANCE + localId + \" - Leader Invoke Message handling...\");\n        handleLeaderInvokeMessage();\n      }\n      case HEARTBEAT_INVOKE -> {\n        LOGGER.info(INSTANCE + localId + \" - Heartbeat Invoke Message handling...\");\n        handleHeartbeatInvokeMessage();\n      }\n      default -> {\n      }\n    }\n  }\n\n  /**\n   * Métodos abstractos para manejar diferentes tipos de mensajes. \n   * Estos métodos deben implementarse en la clase de instancia concreta para implementar el patrón de selección de líder correspondiente.\n   */\n  protected abstract void handleElectionMessage(Message message);\n\n  protected abstract void handleElectionInvokeMessage();\n\n  protected abstract void handleLeaderMessage(Message message);\n\n  protected abstract void handleLeaderInvokeMessage();\n\n  protected abstract void handleHeartbeatMessage(Message message);\n\n  protected abstract void handleHeartbeatInvokeMessage();\n\n}\n```\n\n```java\n/**\n * Mensaje utilizado para transportar datos entre instancias.\n */\n@Setter\n@Getter\n@EqualsAndHashCode\n@AllArgsConstructor\n@NoArgsConstructor\npublic class Message {\n\n  private MessageType type;\n  private String content;\n\n}\n```\n\n```java\npublic interface MessageManager {\n\n  /**\n   * Envía un mensaje heartbeat a la instancia líder para comprobar si la instancia líder está viva.\n   *\n   * @param leaderId ID de instancia de la instancia líder.\n   * @return {@code true} si la instancia líder está viva, o {@code false} si no.\n   */\n  boolean sendHeartbeatMessage(int leaderId);\n\n  /**\n   * Enviar mensaje electoral a otras instancias.\n   *\n   * @param currentId ID de la instancia que envía este mensaje.\n   * @param content Contenido del mensaje electoral.\n   * @return {@code true} si el mensaje es aceptado por las instancias de destino.\n   */\n  boolean sendElectionMessage(int currentId, String content);\n\n  /**\n   * Enviar mensaje de notificación de nuevo líder a otras instancias.\n   *\n   * @param currentId ID de la instancia que envía este mensaje.\n   * @param leaderId  Contenido del mensaje del líder.\n   * @return {@code true} si el mensaje es aceptado por las instancias de destino.\n   */\n  boolean sendLeaderMessage(int currentId, int leaderId);\n\n  /**\n   * Enviar mensaje de invocación de heartbeat. Esto invocará la tarea heartbeat en la instancia de destino.\n   *\n   * @param currentId ID de la instancia que envía este mensaje.\n   */\n  void sendHeartbeatInvokeMessage(int currentId);\n\n}\n```\nThese type of messages are used to pass among instances.\n```java\n/**\n * Enum de tipo de mensaje.\n */\npublic enum MessageType {\n\n  /**\n   * Comienza la elección. El contenido del mensaje almacena ID(s) de la(s) instancia(s) candidata(s).\n   */\n  ELECTION,\n\n  /**\n   * Nodifica al nuevo líder. El contenido del mensaje debe ser el ID del líder.\n   */\n  LEADER,\n\n  /**\n   * Comprueba la salud de la instancia de líder actual.\n   */\n  HEARTBEAT,\n\n  /**\n   * Informar a la instancia de destino para iniciar la elección.\n   */\n  ELECTION_INVOKE,\n\n  /**\n   * Informar a la instancia de destino para que notifique a todas las demás instancias que es el nuevo líder.\n   */\n  LEADER_INVOKE,\n\n  /**\n   * Informar a la instancia de destino para que inicie el heartbeat.\n   */\n  HEARTBEAT_INVOKE\n\n}\n```\n\nClase abstracta que implementa la interfaz MessageManager. Ayuda a gestionar mensajes entre instancias.\n\n```java\n/**\n * Clase abstracta de todas las clases de gestores de mensajes.\n */\npublic abstract class AbstractMessageManager implements MessageManager {\n\n  /**\n   * Contiene todas las instancias del sistema. La clave es su ID y el valor es la propia instancia.   \n   */\n  \n  protected Map<Integer, Instance> instanceMap;\n\n  /**\n   * Constructor de AbstractMessageManager.\n   */\n  public AbstractMessageManager(Map<Integer, Instance> instanceMap) {\n    this.instanceMap = instanceMap;\n  }\n\n  /**\n   * Encuentra la siguiente instancia con el ID más pequeño.\n   *\n   * @return La siguiente instancia.\n   */\n  protected Instance findNextInstance(int currentId) {\n    Instance result = null;\n    var candidateList = instanceMap.keySet()\n        .stream()\n        .filter((i) -> i > currentId && instanceMap.get(i).isAlive())\n        .sorted()\n        .toList();\n    if (candidateList.isEmpty()) {\n      var index = instanceMap.keySet()\n          .stream()\n          .filter((i) -> instanceMap.get(i).isAlive())\n          .sorted()\n          .toList()\n          .get(0);\n      result = instanceMap.get(index);\n    } else {\n      var index = candidateList.get(0);\n      result = instanceMap.get(index);\n    }\n    return result;\n  }\n\n}\n```\n\nHere the implementation of Ring Algorithm\n```java\n/**\n * Implementación con algoritmo token ring. Las instancias en el sistema se organizan como un anillo.\n * Cada instancia debe tener un id secuencial y la instancia con el id más pequeño (o más grande) debe\n * ser el líder inicial. Todas las demás instancias envían un mensaje heartbeat al líder periódicamente para\n * comprobar su salud. Si una instancia determinada encuentra que el servidor ha terminado, enviará un mensaje de elección\n * a la siguiente instancia viva en el anillo, que contiene su propio ID. Entonces la siguiente instancia añade su\n * ID en el mensaje y se lo pasa a la siguiente. Después de que todos los ID de las instancias vivas se añaden al * mensaje, el mensaje se devuelve.\n * mensaje, el mensaje es enviado de vuelta a la primera instancia y ésta elegirá la instancia con\n * menor ID para ser el nuevo líder, y entonces enviará un mensaje de líder a otras instancias para informar del\n * resultado.\n */\n@Slf4j\npublic class RingInstance extends AbstractInstance {\n  private static final String INSTANCE = \"Instance \";\n\n  /**\n   * Constructor de RingInstance.\n   */\n  public RingInstance(MessageManager messageManager, int localId, int leaderId) {\n    super(messageManager, localId, leaderId);\n  }\n\n  /**\n   * Procesar el mensaje de invocación heartbeat. Después de recibir el mensaje, la instancia enviará un\n   * heartbeat (latido) al líder para comprobar su salud. Si está vivo, informará a la siguiente instancia para hacer el\n   * heartbeat. Si no, iniciará el proceso de elección.\n   */\n  @Override\n  protected void handleHeartbeatInvokeMessage() {\n    try {\n      var isLeaderAlive = messageManager.sendHeartbeatMessage(this.leaderId);\n      if (isLeaderAlive) {\n        LOGGER.info(INSTANCE + localId + \"- Leader is alive. Start next heartbeat in 5 second.\");\n        Thread.sleep(HEARTBEAT_INTERVAL);\n        messageManager.sendHeartbeatInvokeMessage(this.localId);\n      } else {\n        LOGGER.info(INSTANCE + localId + \"- Leader is not alive. Start election.\");\n        messageManager.sendElectionMessage(this.localId, String.valueOf(this.localId));\n      }\n    } catch (InterruptedException e) {\n      LOGGER.info(INSTANCE + localId + \"- Interrupted.\");\n    }\n  }\n\n  /**\n   * Procesar mensaje de elección. Si el ID local está contenido en la lista de ID, la instancia seleccionará\n   * la instancia viva con menor ID para ser el nuevo líder, y enviará el mensaje de información al líder.\n   * Si no, añadirá su ID local a la lista y enviará el mensaje a la siguiente instancia en el anillo.\n   * anillo.\n   */\n  @Override\n  protected void handleElectionMessage(Message message) {\n    var content = message.getContent();\n    LOGGER.info(INSTANCE + localId + \" - Election Message: \" + content);\n    var candidateList = Arrays.stream(content.trim().split(\",\"))\n        .map(Integer::valueOf)\n        .sorted()\n        .toList();\n    if (candidateList.contains(localId)) {\n      var newLeaderId = candidateList.get(0);\n      LOGGER.info(INSTANCE + localId + \" - New leader should be \" + newLeaderId + \".\");\n      messageManager.sendLeaderMessage(localId, newLeaderId);\n    } else {\n      content += \",\" + localId;\n      messageManager.sendElectionMessage(localId, content);\n    }\n  }\n\n  /**\n   * Procesar mensaje de líder. La instancia establecerá el ID de líder para que sea el nuevo y enviará el\n   * mensaje a la siguiente instancia hasta que todas las instancias vivas del anillo estén informadas.\n   */\n  @Override\n  protected void handleLeaderMessage(Message message) {\n    var newLeaderId = Integer.valueOf(message.getContent());\n    if (this.leaderId != newLeaderId) {\n      LOGGER.info(INSTANCE + localId + \" - Update leaderID\");\n      this.leaderId = newLeaderId;\n      messageManager.sendLeaderMessage(localId, newLeaderId);\n    } else {\n      LOGGER.info(INSTANCE + localId + \" - Leader update done. Start heartbeat.\");\n      messageManager.sendHeartbeatInvokeMessage(localId);\n    }\n  }\n\n  /**\n   * No se utiliza en la instancia Ring.\n   */\n  @Override\n  protected void handleLeaderInvokeMessage() {\n      // No se utiliza en la instancia Ring.\n  }\n\n  @Override\n  protected void handleHeartbeatMessage(Message message) {\n      // No se utiliza en la instancia Ring.\n  }\n\n  @Override\n  protected void handleElectionInvokeMessage() {\n      // No se utiliza en la instancia Ring.\n  }\n\n}\n```\n\n```java\n/**\n * Implementación de RingMessageManager.\n */\npublic class RingMessageManager extends AbstractMessageManager {\n\n  /**\n   * Constructor de RingMessageManager.\n   */\n  public RingMessageManager(Map<Integer, Instance> instanceMap) {\n    super(instanceMap);\n  }\n\n  /**\n   * Envía un mensaje de heartbeat a la instancia líder actual para comprobar su estado.\n   *\n   * @param leaderId leaderID\n   * @return {@code true} si el líder está vivo.\n   */\n  @Override\n  public boolean sendHeartbeatMessage(int leaderId) {\n    var leaderInstance = instanceMap.get(leaderId);\n    var alive = leaderInstance.isAlive();\n    return alive;\n  }\n\n  /**\n   * Enviar mensaje de elección a la siguiente instancia.\n   *\n   * @param currentId currentID\n   * @param content   contiene todos los ID de las instancias que han recibido este mensaje de elección\n   *                  mensaje.\n   * @return {@code true} si el mensaje de elección es aceptado por la instancia de destino.\n   */\n  @Override\n  public boolean sendElectionMessage(int currentId, String content) {\n    var nextInstance = this.findNextInstance(currentId);\n    var electionMessage = new Message(MessageType.ELECTION, content);\n    nextInstance.onMessage(electionMessage);\n    return true;\n  }\n\n  /**\n   * Enviar mensaje de líder a la siguiente instancia.\n   *\n   * @param currentId ID de la instancia que envía este mensaje.\n   * @param leaderId Contenido del mensaje del líder.\n   * @return {@code true} si el mensaje de líder es aceptado por la instancia de destino.\n   */\n  @Override\n  public boolean sendLeaderMessage(int currentId, int leaderId) {\n    var nextInstance = this.findNextInstance(currentId);\n    var leaderMessage = new Message(MessageType.LEADER, String.valueOf(leaderId));\n    nextInstance.onMessage(leaderMessage);\n    return true;\n  }\n\n  /**\n   * Enviar mensaje de invocación de heartbeat a la siguiente instancia.\n   *\n   * @param currentId ID de la instancia que envía este mensaje.\n   */\n  @Override\n  public void sendHeartbeatInvokeMessage(int currentId) {\n    var nextInstance = this.findNextInstance(currentId);\n    var heartbeatInvokeMessage = new Message(MessageType.HEARTBEAT_INVOKE, \"\");\n    nextInstance.onMessage(heartbeatInvokeMessage);\n  }\n\n}\n```\n```java\npublic static void main(String[] args) {\n\n    Map<Integer, Instance> instanceMap = new HashMap<>();\n    var messageManager = new RingMessageManager(instanceMap);\n\n    var instance1 = new RingInstance(messageManager, 1, 1);\n    var instance2 = new RingInstance(messageManager, 2, 1);\n    var instance3 = new RingInstance(messageManager, 3, 1);\n    var instance4 = new RingInstance(messageManager, 4, 1);\n    var instance5 = new RingInstance(messageManager, 5, 1);\n\n    instanceMap.put(1, instance1);\n    instanceMap.put(2, instance2);\n    instanceMap.put(3, instance3);\n    instanceMap.put(4, instance4);\n    instanceMap.put(5, instance5);\n\n    instance2.onMessage(new Message(MessageType.HEARTBEAT_INVOKE, \"\"));\n\n    final var thread1 = new Thread(instance1);\n    final var thread2 = new Thread(instance2);\n    final var thread3 = new Thread(instance3);\n    final var thread4 = new Thread(instance4);\n    final var thread5 = new Thread(instance5);\n\n    thread1.start();\n    thread2.start();\n    thread3.start();\n    thread4.start();\n    thread5.start();\n\n    instance1.setAlive(false);\n  }\n```\n\nThe console output\n```\n[Thread-1] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 2 - Heartbeat Invoke Message handling...\n[Thread-1] INFO com.iluwatar.leaderelection.ring.RingInstance - Instance 2- Leader is not alive. Start election.\n[Thread-2] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 3 - Election Message handling...\n[Thread-2] INFO com.iluwatar.leaderelection.ring.RingInstance - Instance 3 - Election Message: 2\n[Thread-3] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 4 - Election Message handling...\n[Thread-3] INFO com.iluwatar.leaderelection.ring.RingInstance - Instance 4 - Election Message: 2,3\n[Thread-4] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 5 - Election Message handling...\n[Thread-4] INFO com.iluwatar.leaderelection.ring.RingInstance - Instance 5 - Election Message: 2,3,4\n[Thread-1] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 2 - Election Message handling...\n[Thread-1] INFO com.iluwatar.leaderelection.ring.RingInstance - Instance 2 - Election Message: 2,3,4,5\n[Thread-1] INFO com.iluwatar.leaderelection.ring.RingInstance - Instance 2 - New leader should be 2.\n[Thread-2] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 3 - Leader Message handling...\n[Thread-2] INFO com.iluwatar.leaderelection.ring.RingInstance - Instance 3 - Update leaderID\n[Thread-3] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 4 - Leader Message handling...\n[Thread-3] INFO com.iluwatar.leaderelection.ring.RingInstance - Instance 4 - Update leaderID\n[Thread-4] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 5 - Leader Message handling...\n[Thread-4] INFO com.iluwatar.leaderelection.ring.RingInstance - Instance 5 - Update leaderID\n[Thread-1] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 2 - Leader Message handling...\n[Thread-1] INFO com.iluwatar.leaderelection.ring.RingInstance - Instance 2 - Update leaderID\n[Thread-2] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 3 - Leader Message handling...\n[Thread-2] INFO com.iluwatar.leaderelection.ring.RingInstance - Instance 3 - Leader update done. Start heartbeat.\n[Thread-3] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 4 - Heartbeat Invoke Message handling...\n[Thread-3] INFO com.iluwatar.leaderelection.ring.RingInstance - Instance 4- Leader is alive. Start next heartbeat in 5 second.\n```\nHere the implementation of Bully algorithm\n```java\n/**\n * Impelemetación con algoritmo bully. Cada instancia debe tener un id secuencial y es capaz de\n * comunicarse con otras instancias del sistema. Inicialmente la instancia con menor (o mayor)\n * ID más pequeño (o más grande) es seleccionado para ser el líder. Todas las demás instancias envían un mensaje heartbeat al líder\n * periódicamente para comprobar su salud. Si una instancia determinada considera que el servidor ha terminado, enviará un mensaje de elección a todas las instancias del sistema.\n * mensaje de elección a todas las instancias cuyo ID sea mayor. Si la instancia objetivo está viva,\n * devolverá un mensaje alive (en este ejemplo devolverá true) y entonces enviará un mensaje de elección con\n * su ID. Si no, la instancia original enviará un mensaje de líder a todas las demás instancias.\n */\n@Slf4j\npublic class BullyInstance extends AbstractInstance {\n  private static final String INSTANCE = \"Instance \";\n\n  /**\n   * Constructor de BullyInstance.\n   */\n  public BullyInstance(MessageManager messageManager, int localId, int leaderId) {\n    super(messageManager, localId, leaderId);\n  }\n\n  /**\n   * Procesar el mensaje de invocación heartbeat. Después de recibir el mensaje, la instancia enviará un\n   * heartbeat al líder para comprobar su salud. Si está vivo, informará a la siguiente instancia para hacer el\n   * heartbeat. Si no, iniciará el proceso de elección.\n   */\n  @Override\n  protected void handleHeartbeatInvokeMessage() {\n    try {\n      boolean isLeaderAlive = messageManager.sendHeartbeatMessage(leaderId);\n      if (isLeaderAlive) {\n        LOGGER.info(INSTANCE + localId + \"- Leader is alive.\");\n        Thread.sleep(HEARTBEAT_INTERVAL);\n        messageManager.sendHeartbeatInvokeMessage(localId);\n      } else {\n        LOGGER.info(INSTANCE + localId + \"- Leader is not alive. Start election.\");\n        boolean electionResult =\n            messageManager.sendElectionMessage(localId, String.valueOf(localId));\n        if (electionResult) {\n          LOGGER.info(INSTANCE + localId + \"- Succeed in election. Start leader notification.\");\n          messageManager.sendLeaderMessage(localId, localId);\n        }\n      }\n    } catch (InterruptedException e) {\n      LOGGER.info(INSTANCE + localId + \"- Interrupted.\");\n    }\n  }\n\n  /**\n   * Procesar mensaje de invocación de elección. Enviar mensaje de elección a todas las instancias con menor ID. Si\n   * alguna de ellas está viva, no hacer nada. Si ninguna instancia está viva, enviar mensaje de líder a todas las instancias vivas y reiniciar el heartbeat.\n   * instancia viva y reiniciar heartbeat.\n   */\n  @Override\n  protected void handleElectionInvokeMessage() {\n    if (!isLeader()) {\n      LOGGER.info(INSTANCE + localId + \"- Start election.\");\n      boolean electionResult = messageManager.sendElectionMessage(localId, String.valueOf(localId));\n      if (electionResult) {\n        LOGGER.info(INSTANCE + localId + \"- Succeed in election. Start leader notification.\");\n        leaderId = localId;\n        messageManager.sendLeaderMessage(localId, localId);\n        messageManager.sendHeartbeatInvokeMessage(localId);\n      }\n    }\n  }\n\n  /**\n   * Procesar mensaje de líder. Actualizar la información del líder local.\n   */\n  @Override\n  protected void handleLeaderMessage(Message message) {\n    leaderId = Integer.valueOf(message.getContent());\n    LOGGER.info(INSTANCE + localId + \" - Leader update done.\");\n  }\n\n  private boolean isLeader() {\n    return localId == leaderId;\n  }\n\n  @Override\n  protected void handleLeaderInvokeMessage() {\n    // Not used in Bully Instance\n  }\n\n  @Override\n  protected void handleHeartbeatMessage(Message message) {\n    // Not used in Bully Instance\n  }\n\n  @Override\n  protected void handleElectionMessage(Message message) {\n    // Not used in Bully Instance\n  }\n}\n```\n\n```java\n/**\n * Implementación de BullyMessageManager.\n */\npublic class BullyMessageManager extends AbstractMessageManager {\n\n  /**\n   *  Constructor de BullyMessageManager.\n   */\n  public BullyMessageManager(Map<Integer, Instance> instanceMap) {\n    super(instanceMap);\n  }\n\n  /**\n   * Envía un mensaje de heartbeat a la instancia líder actual para comprobar su estado.\n   *\n   * @param leaderId leaderID\n   * @return {@code true} si el líder está vivo.\n   */\n  @Override\n  public boolean sendHeartbeatMessage(int leaderId) {\n    var leaderInstance = instanceMap.get(leaderId);\n    var alive = leaderInstance.isAlive();\n    return alive;\n  }\n\n  /**\n   * Enviar mensaje electoral a todas las instancias con menor ID.\n   *\n   * @param currentId ID de la instancia que envía este mensaje.\n   * @param content Contenido del mensaje electoral.\n   * @return {@code true} si ninguna instancia viva tiene menor ID, para que se acepte la elección.\n   */\n  @Override\n  public boolean sendElectionMessage(int currentId, String content) {\n    var candidateList = findElectionCandidateInstanceList(currentId);\n    if (candidateList.isEmpty()) {\n      return true;\n    } else {\n      var electionMessage = new Message(MessageType.ELECTION_INVOKE, \"\");\n      candidateList.stream().forEach((i) -> instanceMap.get(i).onMessage(electionMessage));\n      return false;\n    }\n  }\n\n  /**\n   * Enviar mensaje de líder a todas las instancias para notificar el nuevo líder.\n   *\n   * @param currentId ID de la instancia que envía este mensaje.\n   * @param leaderId Contenido del mensaje del líder.\n   * @return {@code true} si se acepta el mensaje.\n   */\n  @Override\n  public boolean sendLeaderMessage(int currentId, int leaderId) {\n    var leaderMessage = new Message(MessageType.LEADER, String.valueOf(leaderId));\n    instanceMap.keySet()\n        .stream()\n        .filter((i) -> i != currentId)\n        .forEach((i) -> instanceMap.get(i).onMessage(leaderMessage));\n    return false;\n  }\n\n  /**\n   * Enviar mensaje de invocación de heartbeat a la siguiente instancia.\n   *\n   * @param currentId ID de la instancia que envía este mensaje.\n   */\n  @Override\n  public void sendHeartbeatInvokeMessage(int currentId) {\n    var nextInstance = this.findNextInstance(currentId);\n    var heartbeatInvokeMessage = new Message(MessageType.HEARTBEAT_INVOKE, \"\");\n    nextInstance.onMessage(heartbeatInvokeMessage);\n  }\n\n  /**\n   * Encuentra todas las instancias vivas con un ID menor que la instancia actual.\n   *\n   * @param currentId ID de la instancia actual.\n   * @return Lista de ID de todas las instancias candidatas.\n   */\n  private List<Integer> findElectionCandidateInstanceList(int currentId) {\n    return instanceMap.keySet()\n        .stream()\n        .filter((i) -> i < currentId && instanceMap.get(i).isAlive())\n        .toList();\n  }\n\n}\n```\n\n```java\npublic static void main(String[] args) {\n\n    Map<Integer, Instance> instanceMap = new HashMap<>();\n    var messageManager = new BullyMessageManager(instanceMap);\n\n    var instance1 = new BullyInstance(messageManager, 1, 1);\n    var instance2 = new BullyInstance(messageManager, 2, 1);\n    var instance3 = new BullyInstance(messageManager, 3, 1);\n    var instance4 = new BullyInstance(messageManager, 4, 1);\n    var instance5 = new BullyInstance(messageManager, 5, 1);\n\n    instanceMap.put(1, instance1);\n    instanceMap.put(2, instance2);\n    instanceMap.put(3, instance3);\n    instanceMap.put(4, instance4);\n    instanceMap.put(5, instance5);\n\n    instance4.onMessage(new Message(MessageType.HEARTBEAT_INVOKE, \"\"));\n\n    final var thread1 = new Thread(instance1);\n    final var thread2 = new Thread(instance2);\n    final var thread3 = new Thread(instance3);\n    final var thread4 = new Thread(instance4);\n    final var thread5 = new Thread(instance5);\n\n    thread1.start();\n    thread2.start();\n    thread3.start();\n    thread4.start();\n    thread5.start();\n\n    instance1.setAlive(false);\n  }\n```\n\nLa salida de la consola\n```\n[Thread-3] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 4 - Heartbeat Invoke Message handling...\n[Thread-3] INFO com.iluwatar.leaderelection.bully.BullyInstance - Instance 4- Leader is alive.\n[Thread-4] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 5 - Heartbeat Invoke Message handling...\n[Thread-4] INFO com.iluwatar.leaderelection.bully.BullyInstance - Instance 5- Leader is not alive. Start election.\n[Thread-3] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 4 - Election Invoke Message handling...\n[Thread-2] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 3 - Election Invoke Message handling...\n[Thread-3] INFO com.iluwatar.leaderelection.bully.BullyInstance - Instance 4- Start election.\n[Thread-2] INFO com.iluwatar.leaderelection.bully.BullyInstance - Instance 3- Start election.\n[Thread-2] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 3 - Election Invoke Message handling...\n[Thread-2] INFO com.iluwatar.leaderelection.bully.BullyInstance - Instance 3- Start election.\n[Thread-1] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 2 - Election Invoke Message handling...\n[Thread-1] INFO com.iluwatar.leaderelection.bully.BullyInstance - Instance 2- Start election.\n[Thread-1] INFO com.iluwatar.leaderelection.bully.BullyInstance - Instance 2- Succeed in election. Start leader notification.\n[Thread-1] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 2 - Election Invoke Message handling...\n[Thread-3] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 4 - Leader Message handling...\n[Thread-2] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 3 - Leader Message handling...\n[Thread-1] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 2 - Election Invoke Message handling...\n[Thread-4] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 5 - Leader Message handling...\n[Thread-0] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 1 - Leader Message handling...\n[Thread-1] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 2 - Election Invoke Message handling...\n[Thread-3] INFO com.iluwatar.leaderelection.bully.BullyInstance - Instance 4 - Leader update done.\n[Thread-2] INFO com.iluwatar.leaderelection.bully.BullyInstance - Instance 3 - Leader update done.\n[Thread-0] INFO com.iluwatar.leaderelection.bully.BullyInstance - Instance 1 - Leader update done.\n[Thread-4] INFO com.iluwatar.leaderelection.bully.BullyInstance - Instance 5 - Leader update done.\n[Thread-2] INFO com.iluwatar.leaderelection.AbstractInstance - Instance 3 - Heartbeat Invoke Message handling...\n[Thread-2] INFO com.iluwatar.leaderelection.bully.BullyInstance - Instance 3- Leader is alive.\n```\n\n## Diagrama de clases\n![alt text](./etc/leader-election.urm.png \"Leader Election pattern class diagram\")\n\n## Aplicabilidad\nUtilice este patrón cuando\n\n* las tareas en una aplicación distribuida, como una solución alojada en la nube, requieren una coordinación cuidadosa y no hay un líder natural.\n\nNo utilice este patrón cuando\n\n* exista un líder natural o un proceso dedicado que pueda actuar siempre como líder. Por ejemplo, puede ser posible implementar un proceso singleton que coordine las instancias de tareas. Si este proceso falla o se vuelve insalubre, el sistema puede apagarlo y reiniciarlo.\n* la coordinación entre tareas puede lograrse fácilmente utilizando un mecanismo más ligero. Por ejemplo, si varias instancias de tareas simplemente requieren un acceso coordinado a un recurso compartido, una solución preferible podría ser utilizar un bloqueo optimista o pesimista para controlar el acceso a ese recurso.\n\n## Créditos\n\n* [Leader Election pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/leader-election)\n* [Raft Leader Election](https://github.com/ronenhamias/raft-leader-election)\n"
  },
  {
    "path": "localization/es/map-reduce/README.md",
    "content": "---\ntitle: \"Patrón de Diseño MapReduce en Java\"\nshortTitle: MapReduce\ndescription: \"Aprende el patrón de diseño MapReduce en Java con ejemplos de la vida real, diagramas de clases y tutoriales. Entiende su intención, aplicación, beneficios y usos conocidos para mejorar tu conocimiento sobre patrones de diseño.\"\ncategory: Optimización de Rendimiento\nlanguage: es\ntag:\n    - Data processing\n    - Code simplification\n    - Delegation\n    - Performance\n    - Procesamiento de datos\n    - Simplificación de coódigo\n    - Delegación\n    - Rendimiento\n---\n\n## También conocido como:\n\n-   Estrategia Separa-Aplica-Combina (Split-Apply-Combine Strategy)\n-   Patrón Dispersa-Recolecta (Scatter-Gather Pattern)\n\n## Intención del Patrón de Diseño Map Reduce\n\nMapReduce pretende procesar y generar grandes conjuntos de datos con un algoritmo en paralelo y distribuido en un grupo. Divide la carga de trabajo en dos fases principales: Mapear (Map) y Reducir (Reduce), permitiendo así una mayor eficiencia en procesamiento de datos en paralelo.\n\n## Explicación Detallada del Patrón de Diseño Map Reduce con Ejemplos del Mundo Real\n\nEjemplo Práctico\n\n> Imagina una compañía de comercio en línea (e-commerce) que quiere analizar sus datos de ventas a lo largo de múltplies regiones. Tienen terabytes de datos de transacciones almacenados en cientos de servidores. Usando MapReduce, pueden procesar estos datos eficientemente para calcular las ventas totales por categoría de producto. La función Map procesaría registros de ventas individuales, regresando pares clave-valor de (categoría, cantidad de venta). La función Reduce entonces sumaría todas las cantidades de ventas por cada categoría, produciendo el resultado final.\n\nEn palabras sencillas\n\n> MapReduce divide un gran problema en partes más pequeñas, las procesa en paralelo y después combina los resultados.\n\nEn Wikipedia dice:\n\n> \"MapReduce es un modelo de programación e implementación asociada para procesar y generar grandes conjuntos de información con un algoritmo en paralelo y distribuido en un grupo\".\n> MapReduce consiste de dos funciones principales:\n> El nodo principal toma la entrada de información, la divide en problemas más pequeños (sub-problemas) y los distribuye a los nodos restantes (de trabajo). Un nodo de trabajo puede repetir este proceso llevando a una estructura de árbol multinivel. El nodo de trabajo procesa el sub-problema y le regresa la respuesta al nodo principal.\n> El nodo principal recolecta todas las respuestas de todos los sub-problemas y las combina de cierta manera para regresar la salida de información - la respuesta del principal problema que estaba resolviendo.\n> Este acercamiento permite un procesamiento eficiente de grandes cantidades de datos através de múltiples máquinas, convirtiéndola en una técnica fundamental en análisis de cantidades enormes de datos y computo distribuido.\n\n## Ejemplo Programático de Map Reduce en Java\n\n### 1. Fase de Map (Mapeador; División & Procesamiento de Datos)\n\n-   El Mapper toma una entrada de texto (string), lo divide en palabras y cuenta las ocurrencias.\n-   Salida: Un mapa {palabra → conteo} por cada línea de entrada.\n\n#### `Mapper.java`\n\n```java\npublic class Mapper {\n    public static Map<String, Integer> map(String input) {\n        Map<String, Integer> wordCount = new HashMap<>();\n        String[] words = input.split(\"\\\\s+\");\n        for (String word : words) {\n            word = word.toLowerCase().replaceAll(\"[^a-z]\", \"\");\n            if (!word.isEmpty()) {\n                wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);\n            }\n        }\n        return wordCount;\n    }\n}\n```\n\nEjemplo de Entrada: `\"Hello world hello\"`\nSalida: `{hello=2, world=1}`\n\n### 2. Fase de Shuffle (Combinación; Agrupar Datos por Clave)\n\n-   La Combinación recolecta pares clave-valor de múltiples mapeadores (mappers) y valores de grupo por clave.\n\n#### `Shuffler.java`\n\n```java\npublic class Shuffler {\n    public static Map<String, List<Integer>> shuffleAndSort(List<Map<String, Integer>> mapped) {\n        Map<String, List<Integer>> grouped = new HashMap<>();\n        for (Map<String, Integer> map : mapped) {\n            for (Map.Entry<String, Integer> entry : map.entrySet()) {\n                grouped.putIfAbsent(entry.getKey(), new ArrayList<>());\n                grouped.get(entry.getKey()).add(entry.getValue());\n            }\n        }\n        return grouped;\n    }\n}\n```\n\nEjemplo de Entrada:\n\n```\n[\n    {\"hello\": 2, \"world\": 1},\n    {\"hello\": 1, \"java\": 1}\n]\n```\n\nSalida:\n\n```\n{\n    \"hello\": [2, 1],\n    \"world\": [1],\n    \"java\": [1]\n}\n```\n\n### 3. Fase de Reduce (Reductor; Agregar Resultados)\n\n-   El Reductor suma todas las ocurrencias de cada palabra.\n\n#### `Reducer.java`\n\n```java\npublic class Reducer {\n    public static List<Map.Entry<String, Integer>> reduce(Map<String, List<Integer>> grouped) {\n        Map<String, Integer> reduced = new HashMap<>();\n        for (Map.Entry<String, List<Integer>> entry : grouped.entrySet()) {\n            reduced.put(entry.getKey(), entry.getValue().stream().mapToInt(Integer::intValue).sum());\n        }\n\n        List<Map.Entry<String, Integer>> result = new ArrayList<>(reduced.entrySet());\n        result.sort(Map.Entry.comparingByValue(Comparator.reverseOrder()));\n        return result;\n    }\n}\n```\n\nEjemplo de Entrada:\n\n```\n{\n    \"hello\": [2, 1],\n    \"world\": [1],\n    \"java\": [1]\n}\n```\n\nSalida:\n\n```\n[\n    {\"hello\": 3},\n    {\"world\": 1},\n    {\"java\": 1}\n]\n```\n\n### 4. Ejecutar el Proceso Completo de MapReduce\n\n-   La clase MapReduce coordina los tres pasos.\n\n#### `MapReduce.java`\n\n```java\npublic class MapReduce {\n    public static List<Map.Entry<String, Integer>> mapReduce(List<String> inputs) {\n        List<Map<String, Integer>> mapped = new ArrayList<>();\n        for (String input : inputs) {\n            mapped.add(Mapper.map(input));\n        }\n\n        Map<String, List<Integer>> grouped = Shuffler.shuffleAndSort(mapped);\n\n        return Reducer.reduce(grouped);\n    }\n}\n```\n\n### 5. Ejecución Principal (Llamar a MapReduce)\n\n-   La clase Main ejecuta el \"pipeline\" de MapReduce y regresa el conteo final de palabras.\n\n#### `Main.java`\n\n```java\n  public static void main(String[] args) {\n    List<String> inputs = Arrays.asList(\n            \"Hello world hello\",\n            \"MapReduce is fun\",\n            \"Hello from the other side\",\n            \"Hello world\"\n    );\n    List<Map.Entry<String, Integer>> result = MapReduce.mapReduce(inputs);\n    for (Map.Entry<String, Integer> entry : result) {\n        System.out.println(entry.getKey() + \": \" + entry.getValue());\n    }\n}\n```\n\nSalida:\n\n```\nhello: 4\nworld: 2\nthe: 1\nother: 1\nside: 1\nmapreduce: 1\nis: 1\nfrom: 1\nfun: 1\n```\n\n## Cuándo Usar el Patrón de Diseño MapReduce en Java\n\nUsa MapReduce cuando se están:\n\n-   Procesando grandes conjuntos de información que no quepa en la memoria de una sola máquina.\n-   Realizando cálculos que se puedan desarrollar en paralelo.\n-   Trabajando en escenarios tolerante a fallos y computación distribuida.\n-   Analizando archivos de registro, datos de rastreo web o datos científicos.\n\n## Tutoriales del Patrón de Diseño MapReduce en Java\n\n-   [Tutorial MapReduce (Apache Hadoop)](https://hadoop.apache.org/docs/stable/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html)\n-   [Ejemplo MapReduce (Simplilearn)](https://www.youtube.com/watch?v=l2clwKnrtO8)\n\n## Ventajas y Desventajas del Patrón de Diseño MapReduce\n\nVentajas:\n\n-   Escalabilidad: Puede procesar grandes cantidades de datos através de múltiples máquinas\n-   Tolerancia a Fallos: Maneja los fallos elegantemente\n-   Simplicidad: Resume detalles complejos de distribución computacional\n\nDesventajas:\n\n-   Costo-Beneficio: Ineficiente para conjuntos de datos chicos por la preparación y coordinación necesaria\n-   Flexibilidad Limitada: Inadecuado para todos los tipos de computación o algoritmos\n-   Latencia: En relación a lotes de información podría ser inadecaudo para necesidades de procesamiento en tiempo real\n\n## Aplicaciones Reales para el Patrón de Diseño MapReduce en Java\n\n-   Implementación original de Google para indexar páginas web\n-   Hadoop MapReduce para procesamiento de información extensa\n-   Sistemas de análisis de registros a gran escala\n-   Secuencia genómica en análisis de bio-informática\n\n## Patrones de Diseño relacionados a Java\n\n-   Patrón de Encadenamiento (Chaining Pattern)\n-   Patrón de Maestro-Trabajador (Master-Worker Pattern)\n-   Patrón de Tubería (Pipeline Pattern)\n\n## Referencias y Creditos\n\n-   [¿Qué es MapReduce?](https://www.ibm.com/think/topics/mapreduce)\n-   [¿Por qué MapReduce no ha muerto?](https://www.codemotion.com/magazine/ai-ml/big-data/mapreduce-not-dead-heres-why-its-still-ruling-in-the-cloud/)\n-   [Soluciones Escalables de Procesamiento de Datos Distribuidos](https://tcpp.cs.gsu.edu/curriculum/?q=system%2Ffiles%2Fch07.pdf)\n-   [Patrones de Diseño en Java: Experiencia Práctica con Ejemplos del Mundo Real](https://amzn.to/3HWNf4U)\n"
  },
  {
    "path": "localization/es/marker/README.md",
    "content": "---\ntitle: Marker Interface\nshortTitle: Marker Interface\ncategory: Structural\nlanguage: es\ntag:\n - Decoupling\n---\n\n## Propósito\nUtilización de interfaces vacías como marcadores para distinguir objetos con un tratamiento especial.\n\n## Diagrama de clases\n![alt text](./etc/MarkerDiagram.png \"Marker Interface\")\n\n## Aplicabilidad\nUtilice el patrón de interfaz de marcador cuando\n\n* Desea identificar los objetos especiales de los objetos normales (para tratarlos de forma diferente)\n* Desea indicar que un objeto está disponible para cierto tipo de operaciones.\n\n## Ejemplos del mundo real\n\n* [javase.8.docs.api.java.io.Serializable](https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html)\n* [javase.8.docs.api.java.lang.Cloneable](https://docs.oracle.com/javase/8/docs/api/java/lang/Cloneable.html)\n\n## Créditos\n\n* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n"
  },
  {
    "path": "localization/es/mediator/README.md",
    "content": "---\ntitle: Mediator\nshortTitle: Mediator\ncategory: Behavioral\nlanguage: es\ntag:\n - Gang Of Four\n - Decoupling\n---\n\n## Propósito\n\nDefine un objeto que encapsula cómo interactúa un conjunto de objetos. Mediator fomenta el acoplamiento flexible al evitar que los objetos se refieran entre sí de forma explícita, y te permite variar su interacción de forma independiente.\n\n## Explicación\n\nUn ejemplo real\n\n> Pícaro, mago, hobbit y cazador han decidido unir sus fuerzas y viajar en la misma party. Para evitar acoplar a cada miembro entre sí, utilizan la interfaz de la party para comunicarse entre ellos.\n\nEn pocas palabras\n\n> Mediator desacopla un conjunto de clases forzando su flujo de comunicaciones a través de un objeto mediador.\n\nWikipedia dice\n\n> En ingeniería de software, el patrón mediador define un objeto que encapsula cómo interactúa un conjunto de objetos. Este patrón se considera un patrón de comportamiento debido a la forma en que puede alterar el comportamiento de ejecución del programa. En la programación orientada a objetos, los programas suelen constar de muchas clases. La lógica de negocio y la computación se distribuyen entre estas clases. Sin embargo, a medida que se añaden más clases a un programa, especialmente durante el mantenimiento y/o la refactorización, el problema de la comunicación entre estas clases puede volverse más complejo. Esto hace que el programa sea más difícil de leer y mantener. Además, puede resultar difícil modificar el programa, ya que cualquier cambio puede afectar al código de otras clases. Con el patrón mediador, la comunicación entre objetos se encapsula en un objeto mediador. Los objetos ya no se comunican directamente entre sí, sino a través del mediador. Esto reduce las dependencias entre los objetos que se comunican, reduciendo así el acoplamiento.\n\n**Ejemplo programático**\n\nEn este ejemplo, el mediador encapsula cómo interactúan un conjunto de objetos. En lugar de referirse unos a otros directamente, utilizan la interfaz del mediador.\n\nLos miembros de la party `Rogue`, `Wizard`, `Hobbit`, y `Hunter` heredan del `PartyMemberBase` implementando la interfaz `PartyMember`.\n\n```java\npublic interface PartyMember {\n\n  void joinedParty(Party party);\n\n  void partyAction(Action action);\n\n  void act(Action action);\n}\n\n@Slf4j\npublic abstract class PartyMemberBase implements PartyMember {\n\n  protected Party party;\n\n  @Override\n  public void joinedParty(Party party) {\n    LOGGER.info(\"{} joins the party\", this);\n    this.party = party;\n  }\n\n  @Override\n  public void partyAction(Action action) {\n    LOGGER.info(\"{} {}\", this, action.getDescription());\n  }\n\n  @Override\n  public void act(Action action) {\n    if (party != null) {\n      LOGGER.info(\"{} {}\", this, action);\n      party.act(this, action);\n    }\n  }\n\n  @Override\n  public abstract String toString();\n}\n\npublic class Rogue extends PartyMemberBase {\n\n  @Override\n  public String toString() {\n    return \"Rogue\";\n  }\n}\n\n// Wizard, Hobbit, and Hunter are implemented similarly\n```\n\nNuestro sistema mediador consta de la interfaz `Party` y su implementación.\n\n```java\npublic interface Party {\n\n  void addMember(PartyMember member);\n\n  void act(PartyMember actor, Action action);\n}\n\npublic class PartyImpl implements Party {\n\n  private final List<PartyMember> members;\n\n  public PartyImpl() {\n    members = new ArrayList<>();\n  }\n\n  @Override\n  public void act(PartyMember actor, Action action) {\n    for (var member : members) {\n      if (!member.equals(actor)) {\n        member.partyAction(action);\n      }\n    }\n  }\n\n  @Override\n  public void addMember(PartyMember member) {\n    members.add(member);\n    member.joinedParty(this);\n  }\n}\n```\n\nAquí tienes una demo que muestra el patrón mediador (Mediator) en acción.\n\n```java\n    // create party and members\n    Party party = new PartyImpl();\n    var hobbit = new Hobbit();\n    var wizard = new Wizard();\n    var rogue = new Rogue();\n    var hunter = new Hunter();\n\n    // add party members\n    party.addMember(hobbit);\n    party.addMember(wizard);\n    party.addMember(rogue);\n    party.addMember(hunter);\n\n    // perform actions -> the other party members\n    // are notified by the party\n    hobbit.act(Action.ENEMY);\n    wizard.act(Action.TALE);\n    rogue.act(Action.GOLD);\n    hunter.act(Action.HUNT);\n```\n\nEsta es la salida de la consola al ejecutar el ejemplo.\n\n```\nHobbit joins the party\nWizard joins the party\nRogue joins the party\nHunter joins the party\nHobbit spotted enemies\nWizard runs for cover\nRogue runs for cover\nHunter runs for cover\nWizard tells a tale\nHobbit comes to listen\nRogue comes to listen\nHunter comes to listen\nRogue found gold\nHobbit takes his share of the gold\nWizard takes his share of the gold\nHunter takes his share of the gold\nHunter hunted a rabbit\nHobbit arrives for dinner\nWizard arrives for dinner\nRogue arrives for dinner\n```\n\n## Diagrama de clases\n\n![alt text](./etc/mediator_1.png \"Mediator\")\n\n## Aplicabilidad\n\nUtilice el patrón Mediator cuando:\n\n* Un conjunto de objetos se comunican de formas bien definidas pero complejas. Las interdependencias resultantes no están estructuradas y son difíciles de entender\n* La reutilización de un objeto es difícil porque hace referencia y se comunica con muchos otros objetos.\n* Un comportamiento que se distribuye entre varias clases debe ser personalizable sin muchas subclases.\n\n## Usos conocidos\n\n* Todos los métodos scheduleXXX() de [java.util.Timer](http://docs.oracle.com/javase/8/docs/api/java/util/Timer.html)\n* [java.util.concurrent.Executor#execute()](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-)\n* Métodos submit() e invokeXXX() de [java.util.concurrent.ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html)\n* Método scheduleXXX() de [java.util.concurrent.ScheduledExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html)\n* [java.lang.reflect.Method#invoke()](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#invoke-java.lang.Object-java.lang.Object...-)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/es/memento/README.md",
    "content": "---\ntitle: Memento\nshortTitle: Memento\ncategory: Behavioral\nlanguage: es\ntag:\n - Gang of Four\n---\n\n## También conocido como\n\nToken\n\n## Propósito\n\nSin violar la encapsulación, capturar y externalizar el estado interno de un objeto para que el objeto pueda ser restaurado a este estado más tarde.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Estamos trabajando en una aplicación de astrología en la que necesitamos analizar las propiedades de las estrellas a lo largo del tiempo. Estamos creando instantáneas de los estados de las estrellas utilizando el patrón Memento.\n\nEn palabras sencillas\n\n> El patrón Memento captura el estado interno de los objetos facilitando su almacenamiento y restauración en cualquier punto del tiempo.\n\nWikipedia dice\n\n> El patrón memento es un patrón de diseño de software que proporciona la capacidad de restaurar un objeto a su estado anterior (deshacer vía rollback).\n\n**Ejemplo programático**\n\nDefinamos primero los tipos de estrellas que somos capaces de manejar.\n\n```java\npublic enum StarType {\n  SUN(\"sun\"),\n  RED_GIANT(\"red giant\"),\n  WHITE_DWARF(\"white dwarf\"),\n  SUPERNOVA(\"supernova\"),\n  DEAD(\"dead star\");\n  ...\n}\n```\n\nA continuación, vayamos directamente a lo esencial. Aquí está la clase `Star` junto con los mementos que necesitamos manipular. Presta especial atención a los métodos `getMemento` y `setMemento`.\n\n```java\npublic interface StarMemento {\n}\n\npublic class Star {\n\n    private StarType type;\n    private int ageYears;\n    private int massTons;\n\n    public Star(StarType startType, int startAge, int startMass) {\n        this.type = startType;\n        this.ageYears = startAge;\n        this.massTons = startMass;\n    }\n\n    public void timePasses() {\n        ageYears *= 2;\n        massTons *= 8;\n        switch (type) {\n            case RED_GIANT -> type = StarType.WHITE_DWARF;\n            case SUN -> type = StarType.RED_GIANT;\n            case SUPERNOVA -> type = StarType.DEAD;\n            case WHITE_DWARF -> type = StarType.SUPERNOVA;\n            case DEAD -> {\n                ageYears *= 2;\n                massTons = 0;\n            }\n            default -> {\n            }\n        }\n    }\n\n    StarMemento getMemento() {\n        var state = new StarMementoInternal();\n        state.setAgeYears(ageYears);\n        state.setMassTons(massTons);\n        state.setType(type);\n        return state;\n    }\n\n    void setMemento(StarMemento memento) {\n        var state = (StarMementoInternal) memento;\n        this.type = state.getType();\n        this.ageYears = state.getAgeYears();\n        this.massTons = state.getMassTons();\n    }\n\n    @Override\n    public String toString() {\n        return String.format(\"%s age: %d years mass: %d tons\", type.toString(), ageYears, massTons);\n    }\n\n    private static class StarMementoInternal implements StarMemento {\n\n        private StarType type;\n        private int ageYears;\n        private int massTons;\n\n        // setters and getters ->\n    ...\n    }\n}\n```\n\nY, por último, así es como utilizamos los recuerdos para almacenar y restaurar estados estelares.\n\n```java\n    var states = new Stack<>();\n    var star = new Star(StarType.SUN, 10000000, 500000);\n    LOGGER.info(star.toString());\n    states.add(star.getMemento());\n    star.timePasses();\n    LOGGER.info(star.toString());\n    states.add(star.getMemento());\n    star.timePasses();\n    LOGGER.info(star.toString());\n    states.add(star.getMemento());\n    star.timePasses();\n    LOGGER.info(star.toString());\n    states.add(star.getMemento());\n    star.timePasses();\n    LOGGER.info(star.toString());\n    while (states.size() > 0) {\n      star.setMemento(states.pop());\n      LOGGER.info(star.toString());\n    }\n```\n\nSalida del programa:\n\n```\nsun age: 10000000 years mass: 500000 tons\nred giant age: 20000000 years mass: 4000000 tons\nwhite dwarf age: 40000000 years mass: 32000000 tons\nsupernova age: 80000000 years mass: 256000000 tons\ndead star age: 160000000 years mass: 2048000000 tons\nsupernova age: 80000000 years mass: 256000000 tons\nwhite dwarf age: 40000000 years mass: 32000000 tons\nred giant age: 20000000 years mass: 4000000 tons\nsun age: 10000000 years mass: 500000 tons\n```\n\n## Diagrama de clases\n\n![alt text](./etc/memento.png \"Memento\")\n\n## Aplicabilidad\n\nUtilice el patrón Memento cuando:\n\n* Es necesario guardar una instantánea del estado de un objeto para poder restaurarlo más tarde, y\n* Una interfaz directa para obtener el estado expondría detalles de implementación y rompería la encapsulación del objeto.\n\n## Usos conocidos\n\n* [java.util.Date](http://docs.oracle.com/javase/8/docs/api/java/util/Date.html)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/es/module/README.md",
    "content": "---\ntitle: Module\nshortTitle: Module\ncategory: Structural\nlanguage: es\ntag:\n - Decoupling\n---\n\n## Propósito\nEl patrón de módulos se utiliza para implementar el concepto de módulos de software, definido por la programación modular, en un lenguaje de programación con soporte directo incompleto para el concepto.\n\n## Explicación\n\nEjemplo real\n\n> En una bulliciosa ciudad del software, distintos componentes de software, como la base de datos, la interfaz de usuario y la API, a menudo necesitan colaborar. En lugar de que cada componente hable directamente con los demás, confían en el gestor de módulos. Este gestor de módulos actúa como un mercado central, donde cada componente registra sus servicios y solicitudes para los demás. Esto garantiza que los componentes permanezcan desacoplados y que los cambios en uno de ellos no afecten a todo el sistema.\n\n\n> Imagina un smartphone moderno. Tiene distintas aplicaciones, como mensajería, cámara y reproductor de música. Aunque cada una funciona de forma independiente, a veces necesitan compartir recursos como el acceso a los contactos o el almacenamiento. En lugar de que cada aplicación tenga su propia forma de acceder a estos recursos, utilizan los módulos integrados del teléfono, como el módulo de contactos o el de almacenamiento. Esto garantiza una experiencia coherente para el usuario y evita posibles conflictos entre aplicaciones.\n\nEn pocas palabras\n\n> El patrón Módulo encapsula funciones y datos relacionados en una sola unidad, lo que permite tener componentes de software organizados y manejables.\n\nWikipedia dice\n\n> En ingeniería de software, el patrón módulo es un patrón de diseño utilizado para implementar el concepto de módulos de software, definido por la programación modular, en un lenguaje de programación con soporte directo incompleto para el concepto.\n\n> Este patrón se puede implementar de varias maneras dependiendo del lenguaje de programación anfitrión, como el patrón de diseño singleton, miembros estáticos orientados a objetos en una clase y funciones globales de procedimiento. En Python, el patrón está integrado en el lenguaje, y cada archivo .py es automáticamente un módulo. Lo mismo ocurre en Ada, donde el paquete puede considerarse un módulo (similar a una clase estática).\n\n**Ejemplo programático**\n\n```java\n//Define Logger abstract class\nabstract class Logger {\n    protected String output;\n    protected String error;\n\n    public abstract void prepare();\n    public abstract void unprepare();\n    public abstract void printString(String message);\n    public abstract void printErrorString(String errorMessage);\n}\n\n//File log module\nclass FileLoggerModule extends Logger {\n    private static final String OUTPUT_FILE = \"output.log\";\n    private static final String ERROR_FILE = \"error.log\";\n\n    private static FileLoggerModule instance;\n\n    private FileLoggerModule() {\n        this.output = OUTPUT_FILE;\n        this.error = ERROR_FILE;\n    }\n\n    public static FileLoggerModule getSingleton() {\n        if (instance == null) {\n            instance = new FileLoggerModule();\n        }\n        return instance;\n    }\n\n    @Override\n    public void prepare() {\n        // For example, open file operation\n        // add the action you want\n    }\n\n    @Override\n    public void unprepare() {\n        // For example, close file operation\n        // add the action you want\n    }\n\n    @Override\n    public void printString(String message) {\n        System.out.println(\"Writing to \" + output + \": \" + message);\n    }\n\n    @Override\n    public void printErrorString(String errorMessage) {\n        System.out.println(\"Writing to \" + error + \": \" + errorMessage);\n    }\n}\n\n//Console log module\nclass ConsoleLoggerModule extends Logger {\n    private static ConsoleLoggerModule instance;\n\n    private ConsoleLoggerModule() {}\n\n    public static ConsoleLoggerModule getSingleton() {\n        if (instance == null) {\n            instance = new ConsoleLoggerModule();\n        }\n        return instance;\n    }\n\n    @Override\n    public void prepare() {\n        //Initialize console operation\n    }\n\n    @Override\n    public void unprepare() {\n        //End console operation\n    }\n\n    @Override\n    public void printString(String message) {\n        System.out.println(\"Console Output: \" + message);\n    }\n\n    @Override\n    public void printErrorString(String errorMessage) {\n        System.err.println(\"Console Error: \" + errorMessage);\n    }\n}\n\n\npublic class App {\n    public void prepare() {\n        FileLoggerModule.getSingleton().prepare();\n        ConsoleLoggerModule.getSingleton().prepare();\n    }\n\n    public void unprepare() {\n        FileLoggerModule.getSingleton().unprepare();\n        ConsoleLoggerModule.getSingleton().unprepare();\n    }\n\n    public void execute(String message) {\n        FileLoggerModule.getSingleton().printString(message);\n        ConsoleLoggerModule.getSingleton().printString(message);\n    }\n\n    public static void main(String[] args) {\n        App app = new App();\n        app.prepare();\n        app.execute(\"Hello, Module Pattern!\");\n        app.unprepare();\n    }\n}\n```\n\nResultados del programa:\n\n```\nWriting to output.log: Hello, Module Pattern!\nConsole Output: Hello, Module Pattern!\n```\n\n## Diagrama de clases\n![alt text](./etc/module.png \"Module\")\n\n## Aplicabilidad\nEl patrón Módulo puede considerarse un patrón de creación y un patrón estructural. Gestiona la creación y organización de otros elementos, y los agrupa como lo hace el patrón estructural.\n\nUn objeto que aplica este patrón puede proporcionar el equivalente de un espacio de nombres, proporcionando el proceso de inicialización y finalización de una clase estática o de una clase con miembros estáticos con una sintaxis y una semántica más limpias y concisas.\n\n## Créditos\n\n* [Module](https://en.wikipedia.org/wiki/Module_pattern)\n"
  },
  {
    "path": "localization/es/monostate/README.md",
    "content": "---\ntitle: MonoState\nshortTitle: MonoState\ncategory: Creational\nlanguage: es\ntag:\n - Instantiation\n---\n\n## También conocido como\nBorg\n\n## Propósito\nImpone un comportamiento como compartir el mismo estado entre todas las instancias.\n\n## Diagrama de Clases\n![alt text](./etc/monostate.png \"MonoState\")\n\n## Applicability\nUtilice el patrón Monostate cuando\n\n* El mismo estado debe ser compartido por todas las instancias de una clase.\n* Típicamente, este patrón puede ser usado en cualquier lugar donde un Singleton pueda ser usado. Sin embargo, el uso de Singleton no es transparente, el uso de Monostate sí lo es.\n* Monostate tiene una gran ventaja sobre Singleton. Las subclases pueden decorar el estado compartido como deseen y, por lo tanto, pueden proporcionar dinámicamente un comportamiento diferente de la clase base.\n\n## Casos de uso típicos\n\n* La clase de registro\n* Gestión de una conexión a una base de datos\n* Gestor de archivos\n\n## Ejemplos del mundo real\n\nAún no lo he visto.\n"
  },
  {
    "path": "localization/es/multiton/README.md",
    "content": "---\ntitle: Multiton\nshortTitle: Multiton\ncategory: Creational\nlanguage: es\ntag:\n  - Instantiation\n---\n\n## También conocido como\n\nRegistry\n\n## Propósito\n\nAsegúrese de que una clase solo tiene un número limitado de instancias y proporcione un punto de acceso global a las\nmismas.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Los Nazgûl, también llamados espectros del anillo o los Nueve Jinetes, son los sirvientes más terribles de Sauron. Por\n> definición, siempre hay nueve de ellos.\n\nEn palabras simples\n\n> El patrón Multiton asegura que hay una cantidad predefinida de instancias disponibles globalmente.\n\nWikipedia dice\n\n> En ingeniería de software, el patrón multiton es un patrón de diseño que generaliza el patrón singleton. Mientras que\n> el singleton permite que solo se cree una instancia de una clase, el patrón multiton permite la creación controlada de\n> múltiples instancias, las cuales gestiona mediante el uso de un mapa.\n\n**Ejemplo Programático**\n\n`Nazgul` es la clase multiton.\n\n```java\npublic enum NazgulName {\n\n  KHAMUL, MURAZOR, DWAR, JI_INDUR, AKHORAHIL, HOARMURATH, ADUNAPHEL, REN, UVATHA\n}\n\npublic final class Nazgul {\n\n  private static final Map<NazgulName, Nazgul> nazguls;\n\n  private final NazgulName name;\n\n  static {\n    nazguls = new ConcurrentHashMap<>();\n    nazguls.put(NazgulName.KHAMUL, new Nazgul(NazgulName.KHAMUL));\n    nazguls.put(NazgulName.MURAZOR, new Nazgul(NazgulName.MURAZOR));\n    nazguls.put(NazgulName.DWAR, new Nazgul(NazgulName.DWAR));\n    nazguls.put(NazgulName.JI_INDUR, new Nazgul(NazgulName.JI_INDUR));\n    nazguls.put(NazgulName.AKHORAHIL, new Nazgul(NazgulName.AKHORAHIL));\n    nazguls.put(NazgulName.HOARMURATH, new Nazgul(NazgulName.HOARMURATH));\n    nazguls.put(NazgulName.ADUNAPHEL, new Nazgul(NazgulName.ADUNAPHEL));\n    nazguls.put(NazgulName.REN, new Nazgul(NazgulName.REN));\n    nazguls.put(NazgulName.UVATHA, new Nazgul(NazgulName.UVATHA));\n  }\n\n  private Nazgul(NazgulName name) {\n    this.name = name;\n  }\n\n  public static Nazgul getInstance(NazgulName name) {\n    return nazguls.get(name);\n  }\n\n  public NazgulName getName() {\n    return name;\n  }\n}\n```\n\nY así es como accedemos a las instancias `Nazgul`.\n\n```java\n// eagerly initialized multiton\nLOGGER.info(\"Printing out eagerly initialized multiton contents\");\nLOGGER.info(\"KHAMUL={}\", Nazgul.getInstance(NazgulName.KHAMUL));\nLOGGER.info(\"MURAZOR={}\", Nazgul.getInstance(NazgulName.MURAZOR));\nLOGGER.info(\"DWAR={}\", Nazgul.getInstance(NazgulName.DWAR));\nLOGGER.info(\"JI_INDUR={}\", Nazgul.getInstance(NazgulName.JI_INDUR));\nLOGGER.info(\"AKHORAHIL={}\", Nazgul.getInstance(NazgulName.AKHORAHIL));\nLOGGER.info(\"HOARMURATH={}\", Nazgul.getInstance(NazgulName.HOARMURATH));\nLOGGER.info(\"ADUNAPHEL={}\", Nazgul.getInstance(NazgulName.ADUNAPHEL));\nLOGGER.info(\"REN={}\", Nazgul.getInstance(NazgulName.REN));\nLOGGER.info(\"UVATHA={}\", Nazgul.getInstance(NazgulName.UVATHA));\n\n// enum multiton\nLOGGER.info(\"Printing out enum-based multiton contents\");\nLOGGER.info(\"KHAMUL={}\", NazgulEnum.KHAMUL);\nLOGGER.info(\"MURAZOR={}\", NazgulEnum.MURAZOR);\nLOGGER.info(\"DWAR={}\", NazgulEnum.DWAR);\nLOGGER.info(\"JI_INDUR={}\", NazgulEnum.JI_INDUR);\nLOGGER.info(\"AKHORAHIL={}\", NazgulEnum.AKHORAHIL);\nLOGGER.info(\"HOARMURATH={}\", NazgulEnum.HOARMURATH);\nLOGGER.info(\"ADUNAPHEL={}\", NazgulEnum.ADUNAPHEL);\nLOGGER.info(\"REN={}\", NazgulEnum.REN);\nLOGGER.info(\"UVATHA={}\", NazgulEnum.UVATHA);\n```\n\nSalida del programa:\n\n```\n20:35:07.413 [main] INFO com.iluwatar.multiton.App - Printing out eagerly initialized multiton contents\n20:35:07.417 [main] INFO com.iluwatar.multiton.App - KHAMUL=com.iluwatar.multiton.Nazgul@48cf768c\n20:35:07.419 [main] INFO com.iluwatar.multiton.App - MURAZOR=com.iluwatar.multiton.Nazgul@7960847b\n20:35:07.419 [main] INFO com.iluwatar.multiton.App - DWAR=com.iluwatar.multiton.Nazgul@6a6824be\n20:35:07.419 [main] INFO com.iluwatar.multiton.App - JI_INDUR=com.iluwatar.multiton.Nazgul@5c8da962\n20:35:07.419 [main] INFO com.iluwatar.multiton.App - AKHORAHIL=com.iluwatar.multiton.Nazgul@512ddf17\n20:35:07.419 [main] INFO com.iluwatar.multiton.App - HOARMURATH=com.iluwatar.multiton.Nazgul@2c13da15\n20:35:07.419 [main] INFO com.iluwatar.multiton.App - ADUNAPHEL=com.iluwatar.multiton.Nazgul@77556fd\n20:35:07.419 [main] INFO com.iluwatar.multiton.App - REN=com.iluwatar.multiton.Nazgul@368239c8\n20:35:07.420 [main] INFO com.iluwatar.multiton.App - UVATHA=com.iluwatar.multiton.Nazgul@9e89d68\n20:35:07.420 [main] INFO com.iluwatar.multiton.App - Printing out enum-based multiton contents\n20:35:07.420 [main] INFO com.iluwatar.multiton.App - KHAMUL=KHAMUL\n20:35:07.420 [main] INFO com.iluwatar.multiton.App - MURAZOR=MURAZOR\n20:35:07.420 [main] INFO com.iluwatar.multiton.App - DWAR=DWAR\n20:35:07.420 [main] INFO com.iluwatar.multiton.App - JI_INDUR=JI_INDUR\n20:35:07.421 [main] INFO com.iluwatar.multiton.App - AKHORAHIL=AKHORAHIL\n20:35:07.421 [main] INFO com.iluwatar.multiton.App - HOARMURATH=HOARMURATH\n20:35:07.421 [main] INFO com.iluwatar.multiton.App - ADUNAPHEL=ADUNAPHEL\n20:35:07.421 [main] INFO com.iluwatar.multiton.App - REN=REN\n20:35:07.421 [main] INFO com.iluwatar.multiton.App - UVATHA=UVATHA\n```\n\n## Diagrama de Clases\n\n![alt text](./etc/multiton.png \"Multiton\")\n\n## Aplicabilidad\n\nUtilice el patrón Multiton cuando\n\n* Debe haber un número determinado de instancias de una clase, y deben ser accesibles a los clientes desde un punto de\n  acceso conocido.\n"
  },
  {
    "path": "localization/es/null-object/README.md",
    "content": "---\ntitle: Null Object\nshortTitle: Null Object\ncategory: Behavioral\nlanguage: es\ntag:\n - Extensibility\n---\n\n## Propósito\n\nEn la mayoría de los lenguajes orientados a objetos, como Java o C#, las referencias pueden ser nulas. Estas referencias deben comprobarse para asegurarse de que no son nulas antes de invocar cualquier método, porque normalmente los métodos no pueden invocarse sobre referencias nulas. En lugar de utilizar una referencia nula para indicar la ausencia de un objeto (por ejemplo, un cliente inexistente), se utiliza un objeto que implementa la interfaz esperada, pero cuyo cuerpo de método está vacío. La ventaja de este enfoque sobre una implementación por defecto es que un objeto nulo es muy predecible y no tiene efectos secundarios: no hace nada.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Estamos construyendo un árbol binario a partir de nodos. Hay nodos normales y nodos \"vacíos\". Recorrer el árbol normalmente no debería causar errores, por lo que utilizamos el patrón de objetos nulos cuando es necesario.\n\nEn palabras sencillas\n\n> El patrón de objetos nulos maneja los objetos \"vacíos\" con elegancia.\n\nWikipedia dice\n\n> En programación informática orientada a objetos, un objeto nulo es un objeto sin valor referenciado o con un comportamiento neutro (\"nulo\") definido. El patrón de diseño de objetos nulos describe los usos de tales objetos y su comportamiento (o la falta del mismo).\n\n**Ejemplo programático**\n\nEsta es la definición de la interfaz `Node`.\n\n```java\npublic interface Node {\n\n  String getName();\n\n  int getTreeSize();\n\n  Node getLeft();\n\n  Node getRight();\n\n  void walk();\n}\n```\n\nTenemos dos implementaciones de `Node`. La implementación normal `NodeImpl` y `NullNode` para nodos vacíos.\n\n```java\n@Slf4j\npublic class NodeImpl implements Node {\n\n  private final String name;\n  private final Node left;\n  private final Node right;\n\n  /**\n   * Constructor.\n   */\n  public NodeImpl(String name, Node left, Node right) {\n    this.name = name;\n    this.left = left;\n    this.right = right;\n  }\n\n  @Override\n  public int getTreeSize() {\n    return 1 + left.getTreeSize() + right.getTreeSize();\n  }\n\n  @Override\n  public Node getLeft() {\n    return left;\n  }\n\n  @Override\n  public Node getRight() {\n    return right;\n  }\n\n  @Override\n  public String getName() {\n    return name;\n  }\n\n  @Override\n  public void walk() {\n    LOGGER.info(name);\n    if (left.getTreeSize() > 0) {\n      left.walk();\n    }\n    if (right.getTreeSize() > 0) {\n      right.walk();\n    }\n  }\n}\n\npublic final class NullNode implements Node {\n\n  private static final NullNode instance = new NullNode();\n\n  private NullNode() {\n  }\n\n  public static NullNode getInstance() {\n    return instance;\n  }\n\n  @Override\n  public int getTreeSize() {\n    return 0;\n  }\n\n  @Override\n  public Node getLeft() {\n    return null;\n  }\n\n  @Override\n  public Node getRight() {\n    return null;\n  }\n\n  @Override\n  public String getName() {\n    return null;\n  }\n\n  @Override\n  public void walk() {\n    // Do nothing\n  }\n}\n```\n\nEntonces podemos construir y recorrer el árbol binario sin errores de la siguiente manera.\n\n```java\n    var root = new NodeImpl(\"1\",\n            new NodeImpl(\"11\",\n                new NodeImpl(\"111\", NullNode.getInstance(), NullNode.getInstance()),\n                NullNode.getInstance()\n            ),\n            new NodeImpl(\"12\",\n                NullNode.getInstance(),\n                new NodeImpl(\"122\", NullNode.getInstance(), NullNode.getInstance())\n            )\n        );\n    root.walk();\n```\n\nSalida del programa:\n\n```\n1\n11\n111\n12\n122\n```\n\n## Diagrama de clases\n\n![alt text](./etc/null-object.png \"Null Object\")\n\n## Aplicabilidad\n\nUtilice el patrón Objeto nulo cuando\n\n* Desea evitar la comprobación explícita de nulos y mantener el algoritmo elegante y fácil de leer.\n\n## Créditos\n\n* [Pattern Languages of Program Design 3](https://www.amazon.com/gp/product/0201310112/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201310112&linkCode=as2&tag=javadesignpat-20&linkId=7372ffb8a4e39a3bb10f199b89aef921)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/es/object-mother/README.md",
    "content": "---\ntitle: Object Mother\nshortTitle: Object Mother\ncategory: Creational\nlanguage: es\ntag:\n  - Instantiation\n---\n\n## Propósito\n\nSe utiliza para definir una fábrica de contenido inmutable con interfaces de constructor y fábrica separadas.\n\n## Diagrama de Clases\n\n![alt text](./etc/object-mother.png \"Object Mother\")\n\n## Aplicabilidad\n\nUtilice el patrón Object Mother cuando\n\n* Quieres objetos consistentes a lo largo de varias pruebas\n* Desea reducir el código para la creación de objetos en las pruebas.\n* Cada prueba debe ejecutarse con datos nuevos\n\n## Comprender el patrón madre objeto (Object Mother)\n\n### Escenario real\n\nImagine que está desarrollando una aplicación Java para una agencia de viajes. En su sistema, hay diferentes tipos de\nviajeros, como turistas, viajeros de negocios y agentes de viajes, cada uno con atributos y comportamientos específicos.\nPara realizar pruebas exhaustivas, necesita crear y manipular estos objetos viajeros en varios contextos. El patrón\nObject Mother puede ayudarle a generar objetos viajeros coherentes y predefinidos para las pruebas, garantizando que\nestas se basen en datos conocidos y fiables.\n\n### En palabras simples\n\nEl Patrón Objeto Madre (Object Mother) es un patrón de diseño utilizado en Java para simplificar la creación de objetos\ncon configuraciones específicas, especialmente para pruebas. En lugar de construir manualmente objetos con propiedades\nvariables para cada caso de prueba, se crea una clase o método \"Objeto Madre\" dedicado que produce estos objetos con\nconfiguraciones predefinidas. De este modo se garantiza la coherencia y previsibilidad de los datos de las pruebas, lo\nque las hace más fiables y fáciles de gestionar.\n\n### Visión general desde el punto de vista de las pruebas\n\nEl patrón Objeto Madre (Object Mother) es un patrón de diseño relacionado con las pruebas que ayuda a mantener un\nentorno de pruebas coherente y fiable. Permite definir y crear objetos con atributos específicos, lo que ayuda a\ngarantizar que las pruebas produzcan resultados coherentes y predecibles, lo que facilita la detección de problemas y el\nmantenimiento del conjunto de pruebas.\n\n### Uso práctico en pruebas\n\nEn las pruebas de software, sobre todo en las unitarias, el Patrón Objeto Madre tiene un valor incalculable. Ayuda a\nasegurar que sus pruebas no están influenciadas por datos impredecibles, haciendo así sus pruebas más robustas y\nrepetibles. Al centralizar la creación de objetos de prueba en un Objeto Madre, puede adaptar fácilmente sus datos de\nprueba a diferentes escenarios.\n\n### Ejemplo en Java\n\nHe aquí un ejemplo ilustrativo en Java del Patrón Objeto Madre (Object Mother) en el contexto de una aplicación de\nagencia de viajes:\n\n```java\nclass Traveler {\n    private String name;\n    private int age;\n    private boolean isBusinessTraveler;\n\n    // Constructor and methods for the traveler\n    // ...\n\n    // Getter and setter methods\n    // ...\n}\n\nclass TravelerMother {\n    public static Traveler createTourist(String name, int age) {\n        Traveler traveler = new Traveler();\n        traveler.setName(name);\n        traveler.setAge(age);\n        traveler.setBusinessTraveler(false);\n        return traveler;\n    }\n\n    public static Traveler createBusinessTraveler(String name, int age) {\n        Traveler traveler = new Traveler();\n        traveler.setName(name);\n        traveler.setAge(age);\n        traveler.setBusinessTraveler(true);\n        return traveler;\n    }\n}\n\npublic class TravelAgency {\n    public static void main(String[] args) {\n        // Using the Object Mother to create traveler objects for testing\n        Traveler tourist = TravelerMother.createTourist(\"Alice\", 28);\n        Traveler businessTraveler = TravelerMother.createBusinessTraveler(\"Bob\", 35);\n\n        // Now you have consistent traveler objects for testing.\n    }\n}\n\n```\n\nEn este ejemplo, TravelerMother es la clase Object Mother responsable de generar objetos Traveler predefinidos con\nconfiguraciones específicas. Este enfoque garantiza que disponga de datos de prueba coherentes para diversos escenarios\nen una aplicación de agencia de viajes, lo que mejora la fiabilidad y la eficacia de sus esfuerzos de prueba.\n\n## Credits\n\n* [Answer by David Brown](http://stackoverflow.com/questions/923319/what-is-an-objectmother) a la pregunta de\n  stackoverflow: [What is an ObjectMother?](http://stackoverflow.com/questions/923319/what-is-an-objectmother)\n* [c2wiki - Object Mother](http://c2.com/cgi/wiki?ObjectMother)\n* [Nat Pryce - Test Data Builders: an alternative to the Object Mother pattern](http://www.natpryce.com/articles/000714.html)\n"
  },
  {
    "path": "localization/es/object-pool/README.md",
    "content": "---\ntitle: Object Pool\nshortTitle: Object Pool\ncategory: Creational\nlanguage: es\ntag:\n  - Game programming\n  - Performance\n---\n\n## También conocido como\n\nResource Pool\n\n## Propósito\n\nCuando los objetos son costosos de crear y solo se necesitan durante cortos períodos de tiempo, es ventajoso utilizar el\npatrón de Object Pool. El Object Pool proporciona una caché para objetos instanciados, rastreando cuáles están en uso y\ncuáles están disponibles.\n\n## Explicación\n\nEjemplo del mundo real\n\n> En nuestro juego de guerra necesitamos usar olifantes, bestias masivas y míticas, pero el problema es que son\n> extremadamente costosos de crear. La solución es crear un grupo de ellos, rastrear cuáles están en uso y, en lugar de\n> desecharlos, reutilizar las instancias.\n\nEn palabras simples\n\n> Object Pool gestiona un conjunto de instancias en lugar de crearlas y destruirlas bajo demanda.\n\nWikipedia dice\n\n> El patrón de object pool es un patrón de diseño de creación de software que utiliza un conjunto de objetos\n> inicializados listos para usar, un \"pool\", en lugar de asignar y destruirlos a demanda.\n\n**Ejemplo Programático**\n\nAquí está la clase básica olifante `Oliphaunt`. Estos gigantes son muy caros de crear.\n\n```java\npublic class Oliphaunt {\n\n  private static final AtomicInteger counter = new AtomicInteger(0);\n\n  private final int id;\n\n  public Oliphaunt() {\n    id = counter.incrementAndGet();\n    try {\n      Thread.sleep(1000);\n    } catch (InterruptedException e) {\n      e.printStackTrace();\n    }\n  }\n\n  public int getId() {\n    return id;\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\"Oliphaunt id=%d\", id);\n  }\n}\n```\n\nA continuación se muestra el `ObjectPool` y más concretamente el `OliphauntPool`.\n\n```java\npublic abstract class ObjectPool<T> {\n\n  private final Set<T> available = new HashSet<>();\n  private final Set<T> inUse = new HashSet<>();\n\n  protected abstract T create();\n\n  public synchronized T checkOut() {\n    if (available.isEmpty()) {\n      available.add(create());\n    }\n    var instance = available.iterator().next();\n    available.remove(instance);\n    inUse.add(instance);\n    return instance;\n  }\n\n  public synchronized void checkIn(T instance) {\n    inUse.remove(instance);\n    available.add(instance);\n  }\n\n  @Override\n  public synchronized String toString() {\n    return String.format(\"Pool available=%d inUse=%d\", available.size(), inUse.size());\n  }\n}\n\npublic class OliphauntPool extends ObjectPool<Oliphaunt> {\n\n  @Override\n  protected Oliphaunt create() {\n    return new Oliphaunt();\n  }\n}\n```\n\nPor último, así es como utilizamos la piscina.\n\n```java\n    var pool = new OliphauntPool();\n    var oliphaunt1 = pool.checkOut();\n    var oliphaunt2 = pool.checkOut();\n    var oliphaunt3 = pool.checkOut();\n    pool.checkIn(oliphaunt1);\n    pool.checkIn(oliphaunt2);\n    var oliphaunt4 = pool.checkOut();\n    var oliphaunt5 = pool.checkOut();\n```\n\nSalida del programa:\n\n```\nPool available=0 inUse=0\nChecked out Oliphaunt id=1\nPool available=0 inUse=1\nChecked out Oliphaunt id=2\nChecked out Oliphaunt id=3\nPool available=0 inUse=3\nChecking in Oliphaunt id=1\nChecking in Oliphaunt id=2\nPool available=2 inUse=1\nChecked out Oliphaunt id=2\nChecked out Oliphaunt id=1\nPool available=0 inUse=3\n```\n\n## Diagrama de Clases\n\n![alt text](./etc/object-pool.png \"Object Pool\")\n\n## Aplicabilidad\n\nUtilice el patrón Object Pool cuando\n\n* Los objetos son caros de crear (coste de asignación).\n* Necesitas un gran número de objetos de vida corta (fragmentación de memoria).\n"
  },
  {
    "path": "localization/es/observer/README.md",
    "content": "---\ntitle: Observer\nshortTitle: Observer\ncategory: Behavioral\nlanguage: en\ntag:\n - Gang Of Four\n - Reactive\n---\n\n## También conocido como\n\nDependents, Publish-Subscribe\n\n## Propósito\n\nDefina una dependencia de uno a muchos entre objetos para que cuando un objeto cambie de estado, todos sus dependientes sean notificados y actualizados automáticamente.\n\n## Explicación\n\nEjemplo real\n\n> En una tierra muy lejana viven las razas de los hobbits y los orcos. Ambos viven principalmente al aire libre, por lo que siguen de cerca los cambios meteorológicos. Se podría decir que observan constantemente el tiempo.\n\nEn palabras simples\n\n> Se registran como observadores para recibir los cambios de estado del objeto.\n\nWikipedia dice\n\n> El patrón observador es un patrón de diseño de software en el que un objeto, llamado sujeto, mantiene una lista de sus dependientes, llamados observadores, y les notifica automáticamente cualquier cambio de estado, normalmente llamando a uno de sus métodos.\n\n**Ejemplo programático**\n\nPresentemos primero la interfaz `WeatherObserver` y nuestras razas, `Orcs` y `Hobbits`.\n\n```java\npublic interface WeatherObserver {\n\n  void update(WeatherType currentWeather);\n}\n\n@Slf4j\npublic class Orcs implements WeatherObserver {\n\n  @Override\n  public void update(WeatherType currentWeather) {\n    LOGGER.info(\"The orcs are facing \" + currentWeather.getDescription() + \" weather now\");\n  }\n}\n\n@Slf4j\npublic class Hobbits implements WeatherObserver {\n\n  @Override\n  public void update(WeatherType currentWeather) {\n    switch (currentWeather) {\n      LOGGER.info(\"The hobbits are facing \" + currentWeather.getDescription() + \" weather now\");\n    }\n  }\n}\n```\n\nLuego está el clima `Weather`, que cambia constantemente.\n\n```java\n@Slf4j\npublic class Weather {\n\n  private WeatherType currentWeather;\n  private final List<WeatherObserver> observers;\n\n  public Weather() {\n    observers = new ArrayList<>();\n    currentWeather = WeatherType.SUNNY;\n  }\n\n  public void addObserver(WeatherObserver obs) {\n    observers.add(obs);\n  }\n\n  public void removeObserver(WeatherObserver obs) {\n    observers.remove(obs);\n  }\n\n  /**\n   * Makes time pass for weather.\n   */\n  public void timePasses() {\n    var enumValues = WeatherType.values();\n    currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length];\n    LOGGER.info(\"The weather changed to {}.\", currentWeather);\n    notifyObservers();\n  }\n\n  private void notifyObservers() {\n    for (var obs : observers) {\n      obs.update(currentWeather);\n    }\n  }\n}\n```\nAquí está el ejemplo completo en acción.\n\n```java\n    var weather = new Weather();\n    weather.addObserver(new Orcs());\n    weather.addObserver(new Hobbits());\n    weather.timePasses();\n    weather.timePasses();\n    weather.timePasses();\n    weather.timePasses();\n```\n\nSalida del programa:\n\n```\nThe weather changed to rainy.\nThe orcs are facing rainy weather now\nThe hobbits are facing rainy weather now\nThe weather changed to windy.\nThe orcs are facing windy weather now\nThe hobbits are facing windy weather now\nThe weather changed to cold.\nThe orcs are facing cold weather now\nThe hobbits are facing cold weather now\nThe weather changed to sunny.\nThe orcs are facing sunny weather now\nThe hobbits are facing sunny weather now\n```\n\n## Diagrama de clases\n\n![alt text](./etc/observer.png \"Observer\")\n\n## Aplicabilidad\n\nUtilice el patrón Observador en cualquiera de las siguientes situaciones:\n\n* Cuando una abstracción tiene dos aspectos, uno dependiente del otro. Encapsular estos aspectos en objetos separados te permite variarlos y reutilizarlos independientemente.\n* Cuando un cambio en un objeto requiere cambiar otros, y no sabes cuántos objetos necesitan ser cambiados.\n* Cuando un objeto debe ser capaz de notificar a otros objetos sin hacer suposiciones sobre quiénes son estos objetos. En otras palabras, no quieres que estos objetos estén estrechamente acoplados.\n\n## Usos conocidos\n\n* [java.util.Observer](http://docs.oracle.com/javase/8/docs/api/java/util/Observer.html)\n* [java.util.EventListener](http://docs.oracle.com/javase/8/docs/api/java/util/EventListener.html)\n* [javax.servlet.http.HttpSessionBindingListener](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionBindingListener.html)\n* [RxJava](https://github.com/ReactiveX/RxJava)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Java Generics and Collections](https://www.amazon.com/gp/product/0596527756/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596527756&linkCode=as2&tag=javadesignpat-20&linkId=246e5e2c26fe1c3ada6a70b15afcb195)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/es/page-controller/README.md",
    "content": "---\ntitle: Page Controller\nshortTitle: Page Controller\ncategory: Structural\nlanguage: es\ntags:\n- Decoupling\n---\n\n## Nombre / clasificación\n\nPage Controller\n\n## Propósito\n\nSe trata de un enfoque de una página que conduce a un archivo lógico que gestiona acciones o peticiones en un sitio web.\n\n## Explicación\n\nUn ejemplo real\n\n> En un sitio web de compras, hay una página de registro para dar de alta un perfil de usuario. Una vez finalizado el registro, la página de registro se redirigirá a una página de usuario para mostrar la información registrada del usuario.\n\nEn pocas palabras\n\n> El controlador de página gestiona las peticiones HTTP y los datos en una página específica usando la idea MVC.\n> La idea es que una página contiene un controlador que maneja el modelo y la vista.\n\n**Ejemplo programático**\n\nAquí está el controlador Signup cuando un usuario registra su información para un sitio web.\n\n```java\n@Slf4j\n@Controller\n@Component\npublic class SignupController {\n  SignupView view = new SignupView();\n  /**\n   * Signup Controller can handle http request and decide which model and view use.\n   */\n  SignupController() {\n  }\n\n  /**\n   * Handle http GET request.\n   */\n  @GetMapping(\"/signup\")\n  public String getSignup() {\n    return view.display();\n  }\n\n  /**\n   * Handle http POST request and access model and view.\n   */\n  @PostMapping(\"/signup\")\n  public String create(SignupModel form, RedirectAttributes redirectAttributes) {\n    LOGGER.info(form.getName());\n    LOGGER.info(form.getEmail());\n    redirectAttributes.addAttribute(\"name\", form.getName());\n    redirectAttributes.addAttribute(\"email\", form.getEmail());\n    redirectAttributes.addFlashAttribute(\"userInfo\", form);\n    return view.redirect(form);\n  }\n}\n```\nAquí está el modelo y la vista de Signup que son manejados por el controlador de Signup.\n\n```java\n@Component\n@Getter\n@Setter\npublic class SignupModel {\n  private String name;\n  private String email;\n  private String password;\n  \n  public SignupModel() {\n  }\n}\n```\n\n```java\n@Slf4j\npublic class SignupView {\n  public SignupView() {\n  }\n\n  public String display() {\n    LOGGER.info(\"display signup front page\");\n    return \"/signup\";\n  }\n\n  /**\n   * redirect to user page.\n   */\n  public String redirect(SignupModel form) {\n    LOGGER.info(\"Redirect to user page with \" + \"name \" + form.getName() + \" email \" + form.getEmail());\n    return \"redirect:/user\";\n  }\n}\n```\n\nEste es el Controlador de Usuario para manejar la petición Get en una página de usuario.\n\n```java\n@Slf4j\n@Controller\npublic class UserController {\n  UserView view = new UserView();\n\n  public UserController() {}\n\n  /**\n   * Handle http GET request and access view and model.\n   */\n  @GetMapping(\"/user\")\n  public String getUserPath(SignupModel form, Model model) {\n    model.addAttribute(\"name\", form.getName());\n    model.addAttribute(\"email\", form.getEmail());\n    return view.display(form);\n  }\n}\n```\n\nAquí están el Modelo de Usuario y la Vista que son manejados por el controlador de Usuario.\n\n```java\n@Getter\n@Setter\npublic class UserModel {\n  private String name;\n  private String email;\n\n  public UserModel() {}\n}\n```\n\n```java\n@Slf4j\npublic class UserView {\n  /**\n   * displaying command to generate html.\n   * @param user model content.\n   */\n  public String display(SignupModel user) {\n    LOGGER.info(\"display user html\" + \" name \" + user.getName() + \" email \" + user.getEmail());\n    return \"/user\";\n  }\n}\n```\n\n## Diagrama de clases\n![alt text](./etc/page-controller.urm.png)\n\n## Aplicabilidad\nUtilice el patrón Page Controller cuando\n- implementas un sitio donde la mayor parte de la lógica del controlador es simple\n- implementa un sitio en el que determinadas acciones se gestionan con una página de servidor concreta\n\n## Créditos\n- [Page Controller](https://www.martinfowler.com/eaaCatalog/pageController.html)\n- [Pattern of Enterprise Application Architecture](https://www.martinfowler.com/books/eaa.html)"
  },
  {
    "path": "localization/es/page-object/README.md",
    "content": "---\ntitle: Page Object\nshortTitle: Page Object\ncategory: Structural\nlanguage: es\ntag:\n- Decoupling\n---\n\n# Patrón de objetos de página en Java\n\n## Ejemplo del mundo real\n\nConsidera un escenario de automatización web donde necesitas interactuar con una página web usando un framework de pruebas como Selenium. El patrón Page Object puede aplicarse para modelar cada página web como una clase Java. Cada clase encapsula la estructura y el comportamiento de la página web correspondiente, facilitando la gestión y actualización del código de automatización.\n\n## Intención\n\nPage Object encapsula la interfaz de usuario, ocultando el widget de interfaz de usuario subyacente de una aplicación (normalmente una aplicación web) y proporcionando una API específica de la aplicación para permitir la manipulación de los componentes de interfaz de usuario necesarios para las pruebas. De este modo, permite a la clase de prueba centrarse en la lógica de la prueba.\n\n## En pocas palabras\n\nEl patrón Page Object en Java es un patrón de diseño utilizado en la automatización de pruebas para representar páginas web como clases Java. Cada clase corresponde a una página web específica y contiene métodos para interactuar con los elementos de esa página. Este patrón mejora el mantenimiento y la legibilidad del código en las pruebas automatizadas.\n\n## Wikipedia dice\n\nAunque no hay una entrada específica en Wikipedia para el patrón Page Object, se utiliza ampliamente en las pruebas de software, en particular en el contexto de la automatización de la interfaz de usuario. El patrón Page Object ayuda a abstraer los detalles de una página web, proporcionando una forma más limpia y fácil de mantener para interactuar con elementos web en pruebas automatizadas.\n\n## Ejemplo programático\n\nVamos a crear un ejemplo programático simple del patrón Page Object para una página de login utilizando Selenium en Java:\n\n```java\nimport org.openqa.selenium.By;\nimport org.openqa.selenium.WebDriver;\nimport org.openqa.selenium.WebElement;\n\npublic class LoginPage {\n    private final WebDriver driver;\n\n    // Web elements on the login page\n    private final By usernameInput = By.id(\"username\");\n    private final By passwordInput = By.id(\"password\");\n    private final By loginButton = By.id(\"login-button\");\n\n    public LoginPage(WebDriver driver) {\n        this.driver = driver;\n    }\n\n    // Methods to interact with the login page\n\n    public void enterUsername(String username) {\n        WebElement usernameElement = driver.findElement(usernameInput);\n        usernameElement.sendKeys(username);\n    }\n\n    public void enterPassword(String password) {\n        WebElement passwordElement = driver.findElement(passwordInput);\n        passwordElement.sendKeys(password);\n    }\n\n    public void clickLoginButton() {\n        WebElement loginButtonElement = driver.findElement(loginButton);\n        loginButtonElement.click();\n    }\n\n    // Other methods specific to the login page if needed\n}\n```\n\nEn este ejemplo, la clase `LoginPage` representa la página de login de una aplicación web. Encapsula los elementos web de la página y proporciona métodos para interactuar con esos elementos. La instancia real de Selenium WebDriver se pasa al constructor, permitiendo a los métodos realizar acciones en la página web.\n\nEste objeto de página se puede utilizar en scripts de prueba para interactuar con la página de inicio de sesión sin exponer los detalles de la estructura de la página en el código de prueba, lo que favorece el mantenimiento y la reutilización.\n\n## Aplicabilidad\n\nUtilice el patrón Page Object cuando\n\n* Estás escribiendo pruebas automatizadas para tu aplicación web y quieres separar la manipulación de la interfaz de usuario necesaria para las pruebas de la lógica de prueba real.\n* Haga sus pruebas menos frágiles, y más legibles y robustas.\n\n## Otro ejemplo con diagrama de clases\n![alt text](./etc/page-object.png \"Page Object\")\n\n## Créditos\n\n* [Martin Fowler - PageObject](http://martinfowler.com/bliki/PageObject.html)\n* [Selenium - Page Objects](https://github.com/SeleniumHQ/selenium/wiki/PageObjects)\n"
  },
  {
    "path": "localization/es/parameter-object/README.md",
    "content": "---\ntitle: Parameter Object\nshortTitle: Parameter Object\ncategory: Behavioral\nlanguage: es\ntag:\n - Extensibility\n---\n\n## Propósito\n\nLa sintaxis del lenguaje Java no permite declarar un método con un valor predefinido para un parámetro. Probablemente la mejor opción para conseguir parámetros de método predefinidos en Java es utilizar la sobrecarga de métodos. La sobrecarga de métodos permite declarar varios métodos con el mismo nombre pero con un número diferente de parámetros. Pero el principal problema con la sobrecarga de métodos como solución para los valores de los parámetros por defecto se revela cuando un método acepta múltiples parámetros. Crear un método sobrecargado para cada posible combinación de parámetros puede resultar engorroso. Para solucionar este problema, se utiliza el patrón Objeto Parámetro.\n\n## Explicación\n\nEl Objeto Parámetro (Parameter Object) es simplemente un objeto envoltorio para todos los parámetros de un método. No es más que un POJO normal. La ventaja del Objeto Parámetro sobre una lista regular de parámetros de método es el hecho de que los campos de clase pueden tener valores por defecto. Una vez creada la clase envoltorio para la lista de parámetros del método, se crea también una clase constructora correspondiente. Normalmente es una clase estática interna. El paso final es utilizar el constructor para construir un nuevo objeto parámetro. Para aquellos parámetros que se omitan, se utilizarán sus valores por defecto.\n\n\n**Ejemplo programático**\n\nAquí está la simple clase `SearchService` donde se utiliza la sobrecarga de métodos para los valores por defecto aquí. Para utilizar la sobrecarga de métodos, el número de argumentos o el tipo de argumento tiene que ser diferente.\n\n```java\npublic class SearchService {\n  //Method Overloading example. SortOrder is defaulted in this method\n  public String search(String type, String sortBy) {\n    return getQuerySummary(type, sortBy, SortOrder.DESC);\n  }\n\n  /* Method Overloading example. SortBy is defaulted in this method. Note that the type has to be \n  different here to overload the method */\n  public String search(String type, SortOrder sortOrder) {\n    return getQuerySummary(type, \"price\", sortOrder);\n  }\n\n  private String getQuerySummary(String type, String sortBy, SortOrder sortOrder) {\n    return \"Requesting shoes of type \\\"\" + type + \"\\\" sorted by \\\"\" + sortBy + \"\\\" in \\\"\"\n        + sortOrder.getValue() + \"ending\\\" order...\";\n  }\n}\n\n```\n\nA continuación presentamos el `SearchService` con `ParameterObject` creado con el patrón Builder.\n\n```java\npublic class SearchService {\n\n  /* Parameter Object example. Default values are abstracted into the Parameter Object \n  at the time of Object creation */\n  public String search(ParameterObject parameterObject) {\n    return getQuerySummary(parameterObject.getType(), parameterObject.getSortBy(),\n        parameterObject.getSortOrder());\n  }\n  \n  private String getQuerySummary(String type, String sortBy, SortOrder sortOrder) {\n    return \"Requesting shoes of type \\\"\" + type + \"\\\" sorted by \\\"\" + sortBy + \"\\\" in \\\"\"\n        + sortOrder.getValue() + \"ending\\\" order...\";\n  }\n}\n\npublic class ParameterObject {\n  public static final String DEFAULT_SORT_BY = \"price\";\n  public static final SortOrder DEFAULT_SORT_ORDER = SortOrder.ASC;\n\n  private String type;\n  private String sortBy = DEFAULT_SORT_BY;\n  private SortOrder sortOrder = DEFAULT_SORT_ORDER;\n\n  private ParameterObject(Builder builder) {\n    type = builder.type;\n    sortBy = builder.sortBy != null && !builder.sortBy.isBlank() ? builder.sortBy : sortBy;\n    sortOrder = builder.sortOrder != null ? builder.sortOrder : sortOrder;\n  }\n\n  public static Builder newBuilder() {\n    return new Builder();\n  }\n\n  //Getters and Setters...\n\n  public static final class Builder {\n\n    private String type;\n    private String sortBy;\n    private SortOrder sortOrder;\n\n    private Builder() {\n    }\n\n    public Builder withType(String type) {\n      this.type = type;\n      return this;\n    }\n\n    public Builder sortBy(String sortBy) {\n      this.sortBy = sortBy;\n      return this;\n    }\n\n    public Builder sortOrder(SortOrder sortOrder) {\n      this.sortOrder = sortOrder;\n      return this;\n    }\n\n    public ParameterObject build() {\n      return new ParameterObject(this);\n    }\n  }\n}\n\n\n```\n\n## Diagrama de clases\n\n![alt text](./etc/parameter-object.png \"Parameter Object\")\n\n## Aplicabilidad\n\nEste patrón nos muestra la forma de tener parámetros por defecto para un método en Java ya que el lenguaje no tiene la característica de parámetros por defecto fuera de la caja.\n\n## Créditos\n\n- [Does Java have default parameters?](http://dolszewski.com/java/java-default-parameters)\n"
  },
  {
    "path": "localization/es/partial-response/README.md",
    "content": "---\ntitle: Partial Response\nshortTitle: Partial Response\ncategory: Behavioral\nlanguage: es\ntag:\n - Decoupling\n---\n\n## Propósito\nEnviar una respuesta parcial del servidor al cliente en función de sus necesidades. El cliente especificará los campos que necesita al servidor, en lugar de servir todos los detalles del recurso.\n\n## Diagrama de clases\n![alt text](./etc/partial-response.urm.png \"Partial Response\")\n\n## Aplicabilidad\nUtilice el patrón de respuesta parcial cuando\n\n* El cliente sólo necesita un subconjunto de datos del recurso.\n* Para evitar demasiada transferencia de datos por cable\n\n## Créditos\n\n* [Common Design Patterns](https://cloud.google.com/apis/design/design_patterns)\n"
  },
  {
    "path": "localization/es/pipeline/README.md",
    "content": "---\ntitle: Pipeline\nshortTitle: Pipeline\ncategory: Behavioral\nlanguage: es\ntag:\n - Decoupling\n---\n\n## Propósito\n\nPermite procesar los datos en una serie de etapas, introduciendo una entrada inicial y pasando la salida procesada para que la utilicen las etapas siguientes.\n\n## Explicación\n\nEl patrón Pipeline utiliza etapas ordenadas para procesar una secuencia de valores de entrada. Cada tarea implementada está representada por una etapa de la tubería. Puede pensar en las canalizaciones como algo similar a las líneas de ensamblaje de una fábrica, donde cada elemento de la línea de ensamblaje se construye por etapas. El artículo parcialmente ensamblado pasa de una etapa de ensamblaje a otra. Las salidas de la cadena de montaje se producen en el mismo orden que las entradas.\n\nEjemplo del mundo real\n\n> Supongamos que queremos pasar una cadena a una serie de etapas de filtrado y convertirla como una matriz char en la última etapa.\n\nEn palabras sencillas\n\n> El patrón pipeline es una cadena de montaje donde los resultados parciales pasan de una etapa a otra.\n\nWikipedia dice\n\n> En ingeniería de software, un pipeline consiste en una cadena de elementos de procesamiento (procesos, hilos, coroutines, funciones, etc.), dispuestos de forma que la salida de cada elemento es la entrada del siguiente; el nombre es por analogía a un pipeline físico.\n\n**Ejemplo programático**\n\nLas etapas de nuestro pipeline se llaman `Handler`s.\n```java\ninterface Handler<I, O> {\n  O process(I input);\n}\n```\n\nEn nuestro ejemplo de procesamiento de cadenas tenemos 3 `Handler`s concretos diferentes.\n\n```java\nclass RemoveAlphabetsHandler implements Handler<String, String> {\n  ...\n}\n\nclass RemoveDigitsHandler implements Handler<String, String> {\n  ...\n}\n\nclass ConvertToCharArrayHandler implements Handler<String, char[]> {\n  ...\n}\n```\n\nAquí está el `Pipeline` que recogerá y ejecutará los handlers uno a uno.\n\n```java\nclass Pipeline<I, O> {\n\n  private final Handler<I, O> currentHandler;\n\n  Pipeline(Handler<I, O> currentHandler) {\n    this.currentHandler = currentHandler;\n  }\n\n  <K> Pipeline<I, K> addHandler(Handler<O, K> newHandler) {\n    return new Pipeline<>(input -> newHandler.process(currentHandler.process(input)));\n  }\n\n  O execute(I input) {\n    return currentHandler.process(input);\n  }\n}\n```\n\nY aquí está la `Pipeline` en acción procesando la cadena.\n\n```java\n    var filters = new Pipeline<>(new RemoveAlphabetsHandler())\n        .addHandler(new RemoveDigitsHandler())\n        .addHandler(new ConvertToCharArrayHandler());\n    filters.execute(\"GoYankees123!\");\n```\n\n## Diagrama de clases\n\n![alt text](./etc/pipeline.urm.png \"Diagrama de clases del patrón Pipeline \")\n\n## Aplicabilidad\n\nUtilice el patrón Pipeline cuando desee\n\n* Ejecutar etapas individuales que produzcan un valor final.\n* Añadir legibilidad a secuencias complejas de operaciones proporcionando un constructor fluido como interfaz.\n* Mejorar la comprobabilidad del código, ya que las etapas probablemente harán una sola cosa, cumpliendo con el [Principio de Responsabilidad Única (SRP)](https://java-design-patterns.com/principles/#single-responsibility-principle)\n\n## Usos conocidos\n\n* [java.util.Stream](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html)\n* [Maven Build Lifecycle](http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html)\n* [Functional Java](https://github.com/functionaljava/functionaljava)\n\n## Patrones relacionados\n\n* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/)\n\n## Créditos\n\n* [The Pipeline Pattern — for fun and profit](https://medium.com/@aaronweatherall/the-pipeline-pattern-for-fun-and-profit-9b5f43a98130)\n* [The Pipeline design pattern (in Java)](https://medium.com/@deepakbapat/the-pipeline-design-pattern-in-java-831d9ce2fe21)\n* [Pipelines | Microsoft Docs](https://docs.microsoft.com/en-us/previous-versions/msp-n-p/ff963548(v=pandp.10))\n"
  },
  {
    "path": "localization/es/poison-pill/README.md",
    "content": "---\ntitle: Poison Pill\nshortTitle: Poison Pill\ncategory: Behavioral\nlanguage: es\ntag:\n - Cloud distributed\n - Reactive\n---\n\n## Propósito\n\nLa píldora venenosa es un elemento de datos predefinido conocido que permite proporcionar un cierre graceful para un proceso de consumo distribuido independiente.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Pensemos en una cola de mensajes con un productor y un consumidor. El productor sigue introduciendo nuevos mensajes en la cola y el consumidor sigue leyéndolos. Finalmente, cuando llega el momento de cerrar la cola, el productor envía el mensaje de píldora venenosa.\n\nEn pocas palabras\n\n> Poison Pill es una estructura de mensaje conocida que pone fin al intercambio de mensajes.\n\n**Ejemplo programático**\n\nDefinamos primero la estructura del mensaje. Hay una interfaz `Message` y una implementación `SimpleMessage`.\n\n```java\npublic interface Message {\n\n  ...\n\n  enum Headers {\n    DATE, SENDER\n  }\n\n  void addHeader(Headers header, String value);\n\n  String getHeader(Headers header);\n\n  Map<Headers, String> getHeaders();\n\n  void setBody(String body);\n\n  String getBody();\n}\n\npublic class SimpleMessage implements Message {\n\n  private final Map<Headers, String> headers = new HashMap<>();\n  private String body;\n\n  @Override\n  public void addHeader(Headers header, String value) {\n    headers.put(header, value);\n  }\n\n  @Override\n  public String getHeader(Headers header) {\n    return headers.get(header);\n  }\n\n  @Override\n  public Map<Headers, String> getHeaders() {\n    return Collections.unmodifiableMap(headers);\n  }\n\n  @Override\n  public void setBody(String body) {\n    this.body = body;\n  }\n\n  @Override\n  public String getBody() {\n    return body;\n  }\n}\n```\n\nPara pasar mensajes utilizamos colas de mensajes. Aquí definimos los tipos relacionados con la cola de mensajes: `MqPublishPoint`, `MqSubscribePoint` y `MessageQueue`. `SimpleMessageQueue` implementa todas estas interfaces.\n\n```java\npublic interface MqPublishPoint {\n\n  void put(Message msg) throws InterruptedException;\n}\n\npublic interface MqSubscribePoint {\n\n  Message take() throws InterruptedException;\n}\n\npublic interface MessageQueue extends MqPublishPoint, MqSubscribePoint {\n}\n\npublic class SimpleMessageQueue implements MessageQueue {\n\n  private final BlockingQueue<Message> queue;\n\n  public SimpleMessageQueue(int bound) {\n    queue = new ArrayBlockingQueue<>(bound);\n  }\n\n  @Override\n  public void put(Message msg) throws InterruptedException {\n    queue.put(msg);\n  }\n\n  @Override\n  public Message take() throws InterruptedException {\n    return queue.take();\n  }\n}\n```\n\nA continuación necesitamos los mensajes `Producer` y `Consumer`. Internamente utilizan las colas de mensajes de arriba. Es importante notar que cuando `Producer` se detiene, envía la píldora venenosa para informar a `Consumer` que la mensajería ha terminado.\n\n```java\npublic class Producer {\n  \n  ... \n\n  public void send(String body) {\n    if (isStopped) {\n      throw new IllegalStateException(String.format(\n          \"Producer %s was stopped and fail to deliver requested message [%s].\", body, name));\n    }\n    var msg = new SimpleMessage();\n    msg.addHeader(Headers.DATE, new Date().toString());\n    msg.addHeader(Headers.SENDER, name);\n    msg.setBody(body);\n\n    try {\n      queue.put(msg);\n    } catch (InterruptedException e) {\n      // allow thread to exit\n      LOGGER.error(\"Exception caught.\", e);\n    }\n  }\n\n  public void stop() {\n    isStopped = true;\n    try {\n      queue.put(Message.POISON_PILL);\n    } catch (InterruptedException e) {\n      // allow thread to exit\n      LOGGER.error(\"Exception caught.\", e);\n    }\n  }\n}\n\npublic class Consumer {\n\n  ...\n\n  public void consume() {\n    while (true) {\n      try {\n        var msg = queue.take();\n        if (Message.POISON_PILL.equals(msg)) {\n          LOGGER.info(\"Consumer {} receive request to terminate.\", name);\n          break;\n        }\n        var sender = msg.getHeader(Headers.SENDER);\n        var body = msg.getBody();\n        LOGGER.info(\"Message [{}] from [{}] received by [{}]\", body, sender, name);\n      } catch (InterruptedException e) {\n        // allow thread to exit\n        LOGGER.error(\"Exception caught.\", e);\n        return;\n      }\n    }\n  }\n}\n```\n\nPor último, estamos listos para presentar todo el ejemplo en acción.\n\n```java\n    var queue = new SimpleMessageQueue(10000);\n\n    final var producer = new Producer(\"PRODUCER_1\", queue);\n    final var consumer = new Consumer(\"CONSUMER_1\", queue);\n\n    new Thread(consumer::consume).start();\n\n    new Thread(() -> {\n      producer.send(\"hand shake\");\n      producer.send(\"some very important information\");\n      producer.send(\"bye!\");\n      producer.stop();\n    }).start();\n```\n\nSalida del programa:\n\n```\nMessage [hand shake] from [PRODUCER_1] received by [CONSUMER_1]\nMessage [some very important information] from [PRODUCER_1] received by [CONSUMER_1]\nMessage [bye!] from [PRODUCER_1] received by [CONSUMER_1]\nConsumer CONSUMER_1 receive request to terminate.\n```\n\n## Diagrama de clases\n\n![alt text](./etc/poison-pill.png \"Poison Pill\")\n\n## Aplicabilidad\n\nUtiliza la expresión \"píldora envenenada\" (Poison pill) cuando:\n\n* Hay una necesidad de enviar una señal de un hilo/proceso a otro para terminar.\n\n## Ejemplos del mundo real\n\n* [akka.actor.PoisonPill](http://doc.akka.io/docs/akka/2.1.4/java/untyped-actors.html)\n"
  },
  {
    "path": "localization/es/presentation-model/README.md",
    "content": "---\ntitle: Presentation Model\nshortTitle: Presentation Model\ncategory: Behavioral\nlanguage: es\ntag:\n - Decoupling\n---\n\n## También conocido como\nApplication Model\n\n## Propósito\nEl modelo de presentación extrae el estado y el comportamiento de la vista a una clase modelo que forma parte de la presentación.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Cuando necesitamos escribir un programa con GUI, no es necesario que pongamos todo el comportamiento de la presentación en la clase view. Porque será más difícil de probar. Así que podemos utilizar Presentation Model Pattern para separar el comportamiento y la vista. La vista solo necesita cargar los datos y estados de otra clase y mostrar estos datos en la pantalla de acuerdo a los estados.\n\nEn palabras simples\n\n> un patrón que divide la presentación y el control.\n\nEjemplo de código\n\nLa clase `view` es la GUI de los álbumes. Los métodos `saveToPMod` y `loadFromPMod` se utilizan para lograr la sincronización.\n\n```java\npublic class View {\n  /**\n   * the model that controls this view.\n   */\n  private final PresentationModel model;\n\n  private TextField txtTitle;\n  private TextField txtArtist;\n  private JCheckBox chkClassical;\n  private TextField txtComposer;\n  private JList<String> albumList;\n  private JButton apply;\n  private JButton cancel;\n\n  public View() {\n    model = new PresentationModel(PresentationModel.albumDataSet());\n  }\n\n  /**\n   * save the data to PresentationModel.\n   */\n  public void saveToPMod() {\n    LOGGER.info(\"Save data to PresentationModel\");\n    model.setArtist(txtArtist.getText());\n    model.setTitle(txtTitle.getText());\n    model.setIsClassical(chkClassical.isSelected());\n    model.setComposer(txtComposer.getText());\n  }\n\n  /**\n   * load the data from PresentationModel.\n   */\n  public void loadFromPMod() {\n    LOGGER.info(\"Load data from PresentationModel\");\n    txtArtist.setText(model.getArtist());\n    txtTitle.setText(model.getTitle());\n    chkClassical.setSelected(model.getIsClassical());\n    txtComposer.setEditable(model.getIsClassical());\n    txtComposer.setText(model.getComposer());\n  }\n\n  public void createView() {\n    // the detail of GUI information like size, listenser and so on.\n  }\n}\n```\n\nLa clase `Album` sirve para almacenar información de un álbum.\n\n```java\npublic class Album {\n    \n  private String title;\n  private String artist;\n  private boolean isClassical;\n  /**\n   * only when the album is classical,\n   * composer can have content.\n   */\n  private String composer;\n}\n\n```\n\nLa clase `DisplatedAlbums` almacena la información de todos los álbumes que se mostrarán en la GUI.\n\n```java\npublic class DisplayedAlbums {\n  private final List<Album> albums;\n\n  public DisplayedAlbums() {\n    this.albums = new ArrayList<>();\n  }\n\n  public void addAlbums(final String title,\n                        final String artist, final boolean isClassical,\n                        final String composer) {\n    if (isClassical) {\n      this.albums.add(new Album(title, artist, true, composer));\n    } else {\n      this.albums.add(new Album(title, artist, false, \"\"));\n    }\n  }\n}\n```\n\nClase `PresentationMod` se utiliza para controlar toda la acción de GUI.\n\n```java\npublic class PresentationModel {\n  private final DisplayedAlbums data;\n  \n  private int selectedAlbumNumber;\n  private Album selectedAlbum;\n\n  public PresentationModel(final DisplayedAlbums dataOfAlbums) {\n    this.data = dataOfAlbums;\n    this.selectedAlbumNumber = 1;\n    this.selectedAlbum = this.data.getAlbums().get(0);\n  }\n\n  /**\n   * Changes the value of selectedAlbumNumber.\n   *\n   * @param albumNumber the number of album which is shown on the view.\n   */\n  public void setSelectedAlbumNumber(final int albumNumber) {\n    LOGGER.info(\"Change select number from {} to {}\",\n            this.selectedAlbumNumber, albumNumber);\n    this.selectedAlbumNumber = albumNumber;\n    this.selectedAlbum = data.getAlbums().get(this.selectedAlbumNumber - 1);\n  }\n\n  public String getTitle() {\n    return selectedAlbum.getTitle();\n  }\n  // other get methods are like this, which are used to get information of selected album.\n\n  public void setTitle(final String value) {\n    LOGGER.info(\"Change album title from {} to {}\",\n            selectedAlbum.getTitle(), value);\n    selectedAlbum.setTitle(value);\n  }\n  // other set methods are like this, which are used to get information of selected album.\n\n  /**\n   * Gets a list of albums.\n   *\n   * @return the names of all the albums.\n   */\n  public String[] getAlbumList() {\n    var result = new String[data.getAlbums().size()];\n    for (var i = 0; i < result.length; i++) {\n      result[i] = data.getAlbums().get(i).getTitle();\n    }\n    return result;\n  }\n}\n```\n\nPodemos ejecutar la clase `App` para iniciar esta demo. la casilla de verificación es el álbum clásico; el primer campo de texto es el nombre del artista del álbum; el segundo es el nombre del título del álbum; el último es el nombre del compositor:\n\n![](./etc/result.png)\n\n\n## Diagrama de clases\n![](./etc/presentation-model.urm.png \"presentation model\")\n\n## Aplicabilidad\nUtilice el patrón de modelo de presentación cuando\n\n* Probar una presentación a través de una ventana GUI es a menudo incómodo, y en algunos casos imposible.\n* No determine qué GUI se utilizará.\n\n## Patrones relacionados\n\n- [Supervising Controller](https://martinfowler.com/eaaDev/SupervisingPresenter.html) \n- [Passive View](https://martinfowler.com/eaaDev/PassiveScreen.html)\n\n## Créditos\n\n* [Presentation Model Patterns](https://martinfowler.com/eaaDev/PresentationModel.html)\n\n"
  },
  {
    "path": "localization/es/priority-queue/README.md",
    "content": "---\ntitle: Priority Queue Pattern\nshortTitle: Priority Queue Pattern\ncategory: Behavioral\nlanguage: es\ntag:\n - Decoupling\n - Cloud distributed\n---\n\n## Propósito\nPriorizar las peticiones enviadas a los servicios de forma que las peticiones con mayor prioridad se reciban y procesen más rápidamente que las de menor prioridad. Este patrón es útil en aplicaciones que ofrecen diferentes garantías de nivel de servicio a clientes individuales.\n\n## Explicación\n\nLas aplicaciones pueden delegar tareas específicas en otros servicios; por ejemplo, para realizar procesamientos en segundo plano o para integrarse con otras aplicaciones o servicios. En la nube, se suele utilizar una cola de mensajes para delegar tareas al procesamiento en segundo plano. En muchos casos, el orden en que un servicio recibe las solicitudes no es importante. Sin embargo, en algunos casos puede ser necesario priorizar peticiones específicas. Estas peticiones deben ser procesadas antes que otras de menor prioridad que puedan haber sido enviadas previamente por la aplicación.\n\nEjemplo real\n\n> Imagine un servicio de procesamiento de vídeo con clientes gratuitos y premium. Las solicitudes procedentes de los clientes premium de pago deben tener prioridad sobre las demás.\n\nEn pocas palabras\n\n> La cola prioritaria permite procesar primero los mensajes de alta prioridad, independientemente del tamaño de la cola o de la antigüedad del mensaje.\n\nWikipedia dice\n\n> En informática, una cola prioritaria es un tipo de datos abstracto similar a una cola normal o a una estructura de datos de pila en la que cada elemento tiene además una \"prioridad\" asociada. En una cola de prioridad, un elemento con prioridad alta se sirve antes que un elemento con prioridad baja.\n\n**Ejemplo programático**\n\nSi observamos el ejemplo anterior de procesamiento de vídeo, veamos primero la estructura `Message`.\n\n```java\npublic class Message implements Comparable<Message> {\n\n  private final String message;\n  private final int priority; // define message priority in queue\n\n  public Message(String message, int priority) {\n    this.message = message;\n    this.priority = priority;\n  }\n\n  @Override\n  public int compareTo(Message o) {\n    return priority - o.priority;\n  }\n  ...\n}\n```\n\nAquí está `PriorityMessageQueue` que se encarga de almacenar los mensajes y servirlos en orden de prioridad.\n\n```java\npublic class PriorityMessageQueue<T extends Comparable> {\n\n  ...\n\n  public T remove() {\n    if (isEmpty()) {\n      return null;\n    }\n\n    final var root = queue[0];\n    queue[0] = queue[size - 1];\n    size--;\n    maxHeapifyDown();\n    return root;\n  }\n\n  public void add(T t) {\n    ensureCapacity();\n    queue[size] = t;\n    size++;\n    maxHeapifyUp();\n  }\n\n  ...\n}\n```\n\nEl `QueueManager` tiene una `PriorityMessageQueue` y facilita la publicación de mensajes `publishMessage` y la recepción de mensajes `receiveMessage`.\n\n```java\npublic class QueueManager {\n\n  private final PriorityMessageQueue<Message> messagePriorityMessageQueue;\n\n  public QueueManager(int initialCapacity) {\n    messagePriorityMessageQueue = new PriorityMessageQueue<>(new Message[initialCapacity]);\n  }\n\n  public void publishMessage(Message message) {\n    messagePriorityMessageQueue.add(message);\n  }\n\n  public Message receiveMessage() {\n    if (messagePriorityMessageQueue.isEmpty()) {\n      return null;\n    }\n    return messagePriorityMessageQueue.remove();\n  }\n}\n```\n\nEl `Worker` sondea constantemente el `QueueManager` en busca del mensaje de mayor prioridad y lo procesa.\n\n```java\n@Slf4j\npublic class Worker {\n\n  private final QueueManager queueManager;\n\n  public Worker(QueueManager queueManager) {\n    this.queueManager = queueManager;\n  }\n\n  public void run() throws Exception {\n    while (true) {\n      var message = queueManager.receiveMessage();\n      if (message == null) {\n        LOGGER.info(\"No Message ... waiting\");\n        Thread.sleep(200);\n      } else {\n        processMessage(message);\n      }\n    }\n  }\n\n  private void processMessage(Message message) {\n    LOGGER.info(message.toString());\n  }\n}\n```\n\nAquí está el ejemplo completo de cómo creamos una instancia de `QueueManager` y procesamos mensajes usando `Worker`.\n\n```java\n    var queueManager = new QueueManager(100);\n\n    for (var i = 0; i < 100; i++) {\n      queueManager.publishMessage(new Message(\"Low Message Priority\", 0));\n    }\n\n    for (var i = 0; i < 100; i++) {\n      queueManager.publishMessage(new Message(\"High Message Priority\", 1));\n    }\n\n    var worker = new Worker(queueManager);\n    worker.run();\n```\n\nSalida del programa:\n\n```\nMessage{message='High Message Priority', priority=1}\nMessage{message='High Message Priority', priority=1}\nMessage{message='High Message Priority', priority=1}\nMessage{message='High Message Priority', priority=1}\nMessage{message='High Message Priority', priority=1}\nMessage{message='High Message Priority', priority=1}\nMessage{message='High Message Priority', priority=1}\nMessage{message='High Message Priority', priority=1}\nMessage{message='High Message Priority', priority=1}\nMessage{message='High Message Priority', priority=1}\nMessage{message='Low Message Priority', priority=0}\nMessage{message='Low Message Priority', priority=0}\nMessage{message='Low Message Priority', priority=0}\nMessage{message='Low Message Priority', priority=0}\nMessage{message='Low Message Priority', priority=0}\nMessage{message='Low Message Priority', priority=0}\nMessage{message='Low Message Priority', priority=0}\nMessage{message='Low Message Priority', priority=0}\nMessage{message='Low Message Priority', priority=0}\nMessage{message='Low Message Priority', priority=0}\nNo Message ... waiting\nNo Message ... waiting\nNo Message ... waiting\n```\n\n\n## Diagrama de clases\n\n![alt text](./etc/priority-queue.urm.png \"Priority Queue pattern class diagram\")\n\n## Aplicabilidad\n\nUtilice el patrón de Cola Prioritaria cuando:\n\n* El sistema debe manejar múltiples tareas que pueden tener diferentes prioridades.\n* Diferentes usuarios o inquilinos deben ser atendidos con diferente prioridad.\n\n## Créditos\n\n* [Priority Queue pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/priority-queue)\n"
  },
  {
    "path": "localization/es/property/README.md",
    "content": "---\ntitle: Property\nshortTitle: Property\ncategory: Creational\nlanguage: es\ntag:\n  - Instantiation\n---\n\n## Propósito\n\nCrear jerarquía de objetos y nuevos objetos utilizando objetos existentes como padres.\n\n## Explicación\n\nEjemplo del mundo real\n\n> En la mística tierra de _\"Elandria\"_, los aventureros pueden aprovechar el poder de las reliquias antiguas para\n> personalizar sus habilidades. Cada reliquia representa una propiedad o habilidad única. A medida que los aventureros\n> exploran, descubren e integran nuevas reliquias, mejorando dinámicamente sus habilidades en función de las reliquias\n> que\n> poseen.\n\n> Considera un software moderno utilizado en el diseño y personalización de teléfonos inteligentes. Los diseñadores\n> pueden elegir entre una variedad de componentes como el tipo de procesador, las especificaciones de la cámara, la\n> capacidad de la batería y más. Cada componente representa una propiedad del teléfono inteligente. A medida que la\n> tecnología evoluciona y se disponen de nuevos componentes, los diseñadores pueden agregar o reemplazar propiedades sin\n> problemas para crear una configuración de teléfono inteligente única sin redefinir la estructura de diseño central.\n\nEn palabras simples\n\n> Define y gestiona un conjunto dinámico de propiedades para un objeto, permitiendo la personalización sin alterar su\n> estructura.\n\n**Ejemplo Programático**\n\n```java\nimport java.util.HashMap;\nimport java.util.Map;\n\n// Enumeration for possible properties or statistics a character can have\nenum Stats {\n    AGILITY, ATTACK_POWER, ARMOR, INTELLECT, SPIRIT, FURY, RAGE;\n}\n\n// Enumeration for different types or classes of characters\nenum Type {\n    WARRIOR, MAGE, ROGUE;\n}\n\n// Interface defining prototype operations on a character\ninterface Prototype {\n    Integer get(Stats stat);\n    boolean has(Stats stat);\n    void set(Stats stat, Integer value);\n    void remove(Stats stat);\n}\n\n// Implementation of the Character class\nclass Character implements Prototype {\n    private String name;\n    private Type type;\n    private Map<Stats, Integer> properties = new HashMap<>();\n\n    public Character() {}\n\n    public Character(Type type, Prototype prototype) {\n        this.type = type;\n        for (Stats stat : Stats.values()) {\n            if (prototype.has(stat)) {\n                this.set(stat, prototype.get(stat));\n            }\n        }\n    }\n\n    public Character(String name, Type type) {\n        this.name = name;\n        this.type = type;\n    }\n\n    @Override\n    public Integer get(Stats stat) {\n        return properties.get(stat);\n    }\n\n    @Override\n    public boolean has(Stats stat) {\n        return properties.containsKey(stat);\n    }\n\n    @Override\n    public void set(Stats stat, Integer value) {\n        properties.put(stat, value);\n    }\n\n    @Override\n    public void remove(Stats stat) {\n        properties.remove(stat);\n    }\n\n    @Override\n    public String toString() {\n        return \"Character{name='\" + name + \"', type=\" + type + \", properties=\" + properties + '}';\n    }\n}\n\n// Main class to demonstrate the pattern\npublic class PropertyPatternDemo {\n    public static void main(String[] args) {\n        // Create a prototype character\n        Character prototypeWarrior = new Character(\"Proto Warrior\", Type.WARRIOR);\n        prototypeWarrior.set(Stats.ATTACK_POWER, 10);\n        prototypeWarrior.set(Stats.ARMOR, 15);\n\n        // Create a new character using the prototype\n        Character newWarrior = new Character(Type.WARRIOR, prototypeWarrior);\n        newWarrior.set(Stats.AGILITY, 5);\n\n        System.out.println(prototypeWarrior);\n        System.out.println(newWarrior);\n    }\n}\n```\n\nSalida del programa:\n\n```\nCharacter{name='Proto Warrior', type=WARRIOR, properties={ARMOR=15, ATTACK_POWER=10}}\nCharacter{name='null', type=WARRIOR, properties={ARMOR=15, AGILITY=5, ATTACK_POWER=10}}\n```\n\n## Diagrama de Clases\n\n![alt text](./etc/property.png \"Property\")\n\n## Aplicabilidad\n\nUtilice el patrón Property cuando\n\n* Cuando desee tener objetos con un conjunto dinámico de campos y herencia de prototipos\n\n## Ejemplo del mundo real\n\n* [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain) prototipo\n  herencia\n"
  },
  {
    "path": "localization/es/prototype/README.md",
    "content": "---\ntitle: Prototype\nshortTitle: Prototype\ncategory: Creational\nlanguage: es\ntag:\n  - Gang Of Four\n  - Instantiation\n---\n\n## Propósito\n\nEspecificar los tipos de objetos a crear utilizando una instancia prototípica, y crear nuevos objetos copiando este\nprototipo\n\n## Explicación\n\nPrimero, debe notarse que el patrón Prototype no se utiliza para obtener beneficios de rendimiento. Solo se utiliza para\ncrear nuevos objetos a partir de instancias prototipo.\n\nEjemplo del mundo real\n\n> ¿Recuerdas a Dolly? ¡La oveja que fue clonada! No entremos en detalles, pero el punto clave aquí es que todo se trata\n> de clonación.\n\nEn palabras simples\n\n> Crea un objeto basado en un objeto existente a través de la clonación.\n\nWikipedia dice\n\n> El patrón de prototipo es un patrón de diseño de creación en el desarrollo de software. Se utiliza cuando el tipo de\n> objetos a crear está determinado por una instancia prototípica, que se clona para producir nuevos objetos.\n\nEn resumen, te permite crear una copia de un objeto existente y modificarla según tus necesidades, en lugar de pasar por\nel problema de crear un objeto desde cero y configurarlo.\n\n**Ejemplo Programático**\n\nEn Java, se recomienda implementar el patrón prototipo de la siguiente manera. En primer lugar, cree una interfaz con un\nmétodo para clonar objetos. En este ejemplo, la interfaz `Prototype` logra esto con su método `copy`.\n\n```java\npublic abstract class Prototype<T> implements Cloneable {\n    @SneakyThrows\n    public T copy() {\n        return (T) super.clone();\n    }\n}\n```\n\nNuestro ejemplo contiene una jerarquía de diferentes criaturas. Por ejemplo, veamos las clases `Beast` y `OrcBeast`.\n\n```java\n@EqualsAndHashCode(callSuper = false)\n@NoArgsConstructor\npublic abstract class Beast extends Prototype<Beast> {\n\n  public Beast(Beast source) {\n  }\n\n}\n\n@EqualsAndHashCode(callSuper = false)\n@RequiredArgsConstructor\npublic class OrcBeast extends Beast {\n\n  private final String weapon;\n\n  public OrcBeast(OrcBeast orcBeast) {\n    super(orcBeast);\n    this.weapon = orcBeast.weapon;\n  }\n\n  @Override\n  public String toString() {\n    return \"Orcish wolf attacks with \" + weapon;\n  }\n\n}\n```\n\nNo queremos entrar en demasiados detalles, pero el ejemplo completo contiene también las clases base `Mage` y `Warlord`\ny hay implementaciones especializadas para los elfos además de para los orcos.\n\nPara aprovechar al máximo el patrón prototipo, creamos las clases `HeroFactory` y `HeroFactoryImpl` para producir\ndiferentes tipos de criaturas a partir de prototipos.\n\n```java\npublic interface HeroFactory {\n  \n  Mage createMage();\n  Warlord createWarlord();\n  Beast createBeast();\n}\n\n@RequiredArgsConstructor\npublic class HeroFactoryImpl implements HeroFactory {\n\n  private final Mage mage;\n  private final Warlord warlord;\n  private final Beast beast;\n\n  public Mage createMage() {\n    return mage.copy();\n  }\n\n  public Warlord createWarlord() {\n    return warlord.copy();\n  }\n\n  public Beast createBeast() {\n    return beast.copy();\n  }\n}\n```\n\nAhora, somos capaces de mostrar el patrón prototipo completo en acción produciendo nuevas criaturas clonando instancias\nexistentes.\n\n```java\n    var factory = new HeroFactoryImpl(\n        new ElfMage(\"cooking\"),\n        new ElfWarlord(\"cleaning\"),\n        new ElfBeast(\"protecting\")\n    );\n    var mage = factory.createMage();\n    var warlord = factory.createWarlord();\n    var beast = factory.createBeast();\n    LOGGER.info(mage.toString());\n    LOGGER.info(warlord.toString());\n    LOGGER.info(beast.toString());\n\n    factory = new HeroFactoryImpl(\n        new OrcMage(\"axe\"),\n        new OrcWarlord(\"sword\"),\n        new OrcBeast(\"laser\")\n    );\n    mage = factory.createMage();\n    warlord = factory.createWarlord();\n    beast = factory.createBeast();\n    LOGGER.info(mage.toString());\n    LOGGER.info(warlord.toString());\n    LOGGER.info(beast.toString());\n```\n\nEsta es la salida de la consola al ejecutar el ejemplo.\n\n```\nElven mage helps in cooking\nElven warlord helps in cleaning\nElven eagle helps in protecting\nOrcish mage attacks with axe\nOrcish warlord attacks with sword\nOrcish wolf attacks with laser\n```\n\n## Diagrama de Clases\n\n![alt text](./etc/prototype.urm.png \"Prototype pattern class diagram\")\n\n## Aplicabilidad\n\nUtilice el patrón Prototipo cuando un sistema deba ser independiente de cómo se crean, componen, representan sus\nproductos y\n\n* Cuando las clases a instanciar se especifican en tiempo de ejecución, por ejemplo, mediante carga dinámica.\n* Para evitar construir una jerarquía de clases de fábricas paralela a la jerarquía de clases de productos.\n* Cuando las instancias de una clase solo pueden tener una de unas pocas combinaciones diferentes de estado. Puede ser\n  más conveniente instalar un número correspondiente de prototipos y clonarlos en lugar de instanciar la clase\n  manualmente, cada vez con el estado apropiado.\n* Cuando la creación de objetos es costosa en comparación con la clonación.\n\n## Usos conocidos\n\n* [java.lang.Object#clone()](http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone%28%29)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/es/proxy/README.md",
    "content": "---\ntitle: Proxy\nshortTitle: Proxy\ncategory: Structural\nlanguage: es\ntag:\n - Gang Of Four\n - Decoupling\n---\n\n## También conocido como\n\nSurrogate\n\n## Propósito\n\nProporcionar un sustituto o marcador de posición de otro objeto para controlar el acceso al mismo.\n\n## Explicación\n\nEjemplo real\n\n> Imagina una torre donde los magos locales van a estudiar sus hechizos. A la torre de marfil sólo se puede acceder a través de un proxy que asegura que sólo los tres primeros magos pueden entrar. Aquí el proxy representa la funcionalidad de la torre y le añade control de acceso.\n\nEn palabras sencillas\n\n> Usando el patrón proxy, una clase representa la funcionalidad de otra clase.\n\nWikipedia dice\n\n> Un proxy, en su forma más general, es una clase que funciona como interfaz de otra cosa. Un proxy es una envoltura o un objeto agente que está siendo llamado por el cliente para acceder al objeto real de servicio detrás de las escenas. El uso del proxy puede ser simplemente el reenvío al objeto real, o puede proporcionar lógica adicional. En el proxy se puede proporcionar funcionalidad adicional, por ejemplo, almacenamiento en caché cuando las operaciones en el objeto real consumen muchos recursos, o comprobación de condiciones previas antes de invocar operaciones en el objeto real.\n\n**Ejemplo programático**\n\nTomando el ejemplo anterior de nuestra torre de asistentes. En primer lugar tenemos la interfaz `WizardTower` y la clase `IvoryTower`.\n\n```java\npublic interface WizardTower {\n\n  void enter(Wizard wizard);\n}\n\n@Slf4j\npublic class IvoryTower implements WizardTower {\n\n  public void enter(Wizard wizard) {\n    LOGGER.info(\"{} enters the tower.\", wizard);\n  }\n\n}\n```\n\nA continuación, una simple clase `Wizard`.\n\n```java\npublic class Wizard {\n\n  private final String name;\n\n  public Wizard(String name) {\n    this.name = name;\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n}\n```\n\nLuego tenemos el `WizardTowerProxy` para añadir control de acceso a `WizardTower`.\n\n```java\n@Slf4j\npublic class WizardTowerProxy implements WizardTower {\n\n  private static final int NUM_WIZARDS_ALLOWED = 3;\n\n  private int numWizards;\n\n  private final WizardTower tower;\n\n  public WizardTowerProxy(WizardTower tower) {\n    this.tower = tower;\n  }\n\n  @Override\n  public void enter(Wizard wizard) {\n    if (numWizards < NUM_WIZARDS_ALLOWED) {\n      tower.enter(wizard);\n      numWizards++;\n    } else {\n      LOGGER.info(\"{} is not allowed to enter!\", wizard);\n    }\n  }\n}\n```\n\nY aquí está el escenario de entrada a la torre.\n\n```java\nvar proxy = new WizardTowerProxy(new IvoryTower());\nproxy.enter(new Wizard(\"Red wizard\"));\nproxy.enter(new Wizard(\"White wizard\"));\nproxy.enter(new Wizard(\"Black wizard\"));\nproxy.enter(new Wizard(\"Green wizard\"));\nproxy.enter(new Wizard(\"Brown wizard\"));\n```\n\nSalida del programa:\n\n```\nRed wizard enters the tower.\nWhite wizard enters the tower.\nBlack wizard enters the tower.\nGreen wizard is not allowed to enter!\nBrown wizard is not allowed to enter!\n```\n\n## Diagrama de clases\n\n![alt text](./etc/proxy.urm.png \"Proxy pattern class diagram\")\n\n## Aplicabilidad\n\nEl proxy es aplicable siempre que se necesite una referencia a un objeto más versátil o sofisticada que un simple puntero.\nque un simple puntero. He aquí varias situaciones comunes en las que el patrón Proxy es\naplicable.\n\n* Un proxy remoto proporciona un representante local para un objeto en un espacio de direcciones diferente.\n* El proxy virtual crea objetos caros bajo demanda.\n* Un proxy de protección controla el acceso al objeto original. Los proxies de protección son útiles cuando\n  objetos deben tener diferentes derechos de acceso.\n\nTípicamente, el patrón proxy se utiliza para\n\n* Controlar el acceso a otro objeto\n* Inicialización perezosa\n* Implementar el registro\n* Facilitar la conexión de red\n* Contar referencias a un objeto\n\n## Tutoriales\n\n* [Controlling Access With Proxy Pattern](http://java-design-patterns.com/blog/controlling-access-with-proxy-pattern/)\n\n## Usos conocidos\n\n* [java.lang.reflect.Proxy](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html)\n* [Apache Commons Proxy](https://commons.apache.org/proper/commons-proxy/)\n* Mocking frameworks [Mockito](https://site.mockito.org/), \n[Powermock](https://powermock.github.io/), [EasyMock](https://easymock.org/)\n* [UIAppearance](https://developer.apple.com/documentation/uikit/uiappearance)\n\n## Patrones relacionados\n\n* [Ambassador](https://java-design-patterns.com/patterns/ambassador/)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/es/registry/README.md",
    "content": "---\ntitle: Registry\nshortTitle: Registry\ncategory: Creational\nlanguage: es\ntag:\n  - Instantiation\n---\n\n## Propósito\n\nAlmacena los objetos de una única clase y proporciona un punto de acceso global a los mismos.\nSimilar al patrón Multiton, la única diferencia es que en un registro no hay restricción en el número de objetos.\n\n## Explicación\n\nEn pocas palabras\n\n> El registro es un objeto bien conocido que otros objetos pueden utilizar para encontrar objetos y servicios comunes.\n\n**Ejemplo Programático**\nA continuación se muestra una clase `Cliente\n\n```java\npublic class Customer {\n\n  private final String id;\n  private final String name;\n\n  public Customer(String id, String name) {\n    this.id = id;\n    this.name = name;\n  }\n\n  public String getId() {\n    return id;\n  }\n\n  public String getName() {\n    return name;\n  }\n\n}\n```\n\nEste registro de los objetos `Customer` es `CustomerRegistry`.\n\n```java\npublic final class CustomerRegistry {\n\n  private static final CustomerRegistry instance = new CustomerRegistry();\n\n  public static CustomerRegistry getInstance() {\n    return instance;\n  }\n\n  private final Map<String, Customer> customerMap;\n\n  private CustomerRegistry() {\n    customerMap = new ConcurrentHashMap<>();\n  }\n\n  public Customer addCustomer(Customer customer) {\n    return customerMap.put(customer.getId(), customer);\n  }\n\n  public Customer getCustomer(String id) {\n    return customerMap.get(id);\n  }\n\n}\n```\n\n## Diagrama de Clases\n\n![Registry](./etc/registry.png \"Registry pattern diagrama de clases\")\n\n## Aplicabilidad\n\nUsar el patrón Registry cuando\n\n* El cliente quiere una referencia de algún objeto, por lo que el cliente puede buscar ese objeto en el registro del\n  objeto.\n\n## Consecuencias\n\nUn gran número de objetos voluminosos añadidos al registro daría lugar a un gran consumo de memoria, ya que los objetos\ndel registro no se recogen de la basura.\n\n## Créditos\n\n* https://www.martinfowler.com/eaaCatalog/registry.html\n* https://wiki.c2.com/?RegistryPattern\n"
  },
  {
    "path": "localization/es/retry/README.md",
    "content": "---\ntitle: Retry\nshortTitle: Retry\ncategory: Behavioral\nlanguage: es\ntag:\n  - Performance\n  - Cloud distributed\n---\n\n## Propósito\n\nReintentar de forma transparente determinadas operaciones que implican la comunicación con recursos externos, en particular a través de la red, aislando el código de llamada de los detalles de implementación del reintento.\n\n## Explicación\n\nEl patrón de reintento consiste en reintentar operaciones sobre recursos remotos a través de la red un número determinado de veces. Depende estrechamente de los requisitos empresariales y técnicos: ¿Cuánto tiempo permitirá la empresa que espere el usuario final hasta que finalice la operación? ¿Cuáles son las características de rendimiento del recurso remoto durante los picos de carga, así como de nuestra aplicación a medida que más hilos esperan la disponibilidad del recurso remoto? Entre los errores devueltos por el servicio remoto, ¿cuáles pueden ignorarse con seguridad para volver a intentarlo? ¿Es la operación [idempotent](https://en.wikipedia.org/wiki/Idempotence)?\n\nOtra preocupación es el impacto en el código de llamada al implementar el mecanismo de reintento. Idealmente, la mecánica de reintento debería ser completamente transparente para el código de llamada (la interfaz del servicio permanece inalterada). Existen dos enfoques generales para este problema: desde el punto de vista de la arquitectura empresarial (estratégico) y desde el punto de vista de la biblioteca compartida (táctico).\n\nDesde un punto de vista estratégico, esto se resolvería redirigiendo las peticiones a un sistema intermediario separado, tradicionalmente un [ESB](https://en.wikipedia.org/wiki/Enterprise_service_bus), pero más recientemente un [Service Mesh](https://medium.com/microservices-in-practice/service-mesh-for-microservices-2953109a3c9a).\n\nDesde un punto de vista táctico, esto se resolvería reutilizando bibliotecas compartidas como [Hystrix](https://github.com/Netflix/Hystrix) (nótese que Hystrix es una implementación completa del patrón [Circuit Breaker](https://java-design-patterns.com/patterns/circuit-breaker/), del que el patrón Retry puede considerarse un subconjunto). Este es el tipo de solución que se muestra en el sencillo ejemplo que acompaña a este `README.md`.\n\nEjemplo real\n\n> Nuestra aplicación utiliza un servicio que proporciona información sobre clientes. De vez en cuando el servicio parece fallar y puede devolver errores o a veces simplemente se desconecta. Para evitar estos problemas aplicamos el patrón retry.\n\nEn palabras simples\n\n> El patrón de reintento reintenta de forma transparente las operaciones fallidas a través de la red.\n\n[Documentación de Microsoft](https://docs.microsoft.com/en-us/azure/architecture/patterns/retry) dice\n\n> Permite a una aplicación manejar fallos transitorios cuando intenta conectarse a un servicio o recurso de red, reintentando de forma transparente una operación fallida. Esto puede mejorar la estabilidad de la aplicación.\n\n**Ejemplo programático**\n\nEn nuestra aplicación hipotética, tenemos una interfaz genérica para todas las operaciones sobre interfaces remotas.\n\n```java\npublic interface BusinessOperation<T> {\n  T perform() throws BusinessException;\n}\n```\n\nY tenemos una implementación de esta interfaz que encuentra a nuestros clientes buscando en una base de datos.\n\n```java\npublic final class FindCustomer implements BusinessOperation<String> {\n  @Override\n  public String perform() throws BusinessException {\n    ...\n  }\n}\n```\n\nNuestra implementación de `FindCustomer` puede configurarse para lanzar `BusinessException`s antes de devolver el ID del cliente, simulando así un servicio defectuoso que falla intermitentemente. Algunas excepciones, como la `CustomerNotFoundException`, se consideran recuperables tras un hipotético análisis porque la causa raíz del error proviene de \"algún problema de bloqueo de la base de datos\". Sin embargo, la `DatabaseNotAvailableException` se considera definitivamente un showtopper - la aplicación no debe intentar recuperarse de este error.\n\nPodemos modelar un escenario recuperable instanciando `FindCustomer` así:\n\n```java\nfinal var op = new FindCustomer(\n    \"12345\",\n    new CustomerNotFoundException(\"not found\"),\n    new CustomerNotFoundException(\"still not found\"),\n    new CustomerNotFoundException(\"don't give up yet!\")\n);\n```\n\nEn esta configuración, `FindCustomer` lanzará `CustomerNotFoundException` tres veces, tras lo cual devolverá sistemáticamente el ID del cliente (`12345`).\n\nEn nuestro escenario hipotético, nuestros analistas indican que esta operación suele fallar entre 2 y 4 veces para una entrada determinada durante las horas punta, y que cada hilo de trabajo del subsistema de base de datos suele necesitar 50 ms para \"recuperarse de un error\". Aplicando estas políticas se obtendría algo así:\n\n```java\nfinal var op = new Retry<>(\n    new FindCustomer(\n        \"1235\",\n        new CustomerNotFoundException(\"not found\"),\n        new CustomerNotFoundException(\"still not found\"),\n        new CustomerNotFoundException(\"don't give up yet!\")\n    ),\n    5,\n    100,\n    e -> CustomerNotFoundException.class.isAssignableFrom(e.getClass())\n);\n```\n\nEjecutando `op` una vez se lanzarían automáticamente como máximo 5 intentos de reintento, con un retardo de 100 milisegundos entre intentos, ignorando cualquier `CustomerNotFoundException` lanzada durante el intento. En este escenario en particular, debido a la configuración de `FindCustomer`, habrá 1 intento inicial y 3 reintentos adicionales antes de devolver finalmente el resultado deseado `12345`.\n\nSi nuestra operación `FindCustomer` lanzara una fatal `DatabaseNotFoundException`, la cual se nos instruyó no ignorar, pero más importante aún, no instruimos a nuestro `Retry` ignorar, entonces la operación habría fallado inmediatamente al recibir el error, sin importar cuantos intentos quedaran.\n\n## Diagrama de clases\n\n![alt text](./etc/retry.png \"Retry\")\n\n## Aplicabilidad\n\nSiempre que una aplicación necesite comunicarse con un recurso externo, especialmente en un entorno de nube, y si los requisitos empresariales lo permiten.\n\n## Consecuencias\n\n**Pros:**\n\n* Resistencia\n* Proporciona datos concretos sobre fallos externos\n\n**Desventajas**\n\n* Complejidad\n* Mantenimiento de operaciones\n\n## Patrones relacionados\n\n\n* [Circuit Breaker](https://java-design-patterns.com/patterns/circuit-breaker/)\n\n## Créditos\n\n* [Retry pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/retry)\n* [Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications](https://www.amazon.com/gp/product/1621140369/ref=as_li_tl?ie=UTF8&tag=javadesignpat-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=1621140369&linkId=3e3f686af5e60a7a453b48adb286797b)\n"
  },
  {
    "path": "localization/es/role-object/README.md",
    "content": "---\ntitle: Role Object\nshortTitle: Role Object\ncategory: Structural\nlanguage: es\ntag:\n - Extensibility\n---\n\n## También conocido como\nPatrón Post, Patrón Extension Object\n\n## Propósito\nAdaptar un objeto a las necesidades de diferentes clientes mediante objetos de rol adjuntos de forma transparente, cada uno de los cuales representa un papel\nque el objeto debe desempeñar en el contexto de ese cliente. El objeto gestiona su conjunto de roles de forma dinámica. Al representar los roles como\nobjetos individuales, los distintos contextos se mantienen separados y se simplifica la configuración del sistema.\n\n## Diagrama de clases\n![alt text](./etc/role-object.urm.png \"Role Object pattern class diagram\")\n\n## Aplicabilidad\nUtiliza el patrón Objeto Rol, si:\n\n- Quieres manejar una abstracción clave en diferentes contextos y no quieres poner las interfaces específicas de contexto resultantes en la misma interfaz de clase.\n- Quieres manejar los roles disponibles dinámicamente para que puedan ser adjuntados y removidos bajo demanda, es decir en tiempo de ejecución, en lugar de fijarlos estáticamente en tiempo de compilación.\n- Quiere tratar las extensiones de forma transparente y necesita preservar la identidad lógica del objeto del conglomerado de objetos resultante.\n- Desea mantener los pares rol/cliente independientes entre sí, de modo que los cambios en un rol no afecten a los clientes que no estén interesados en ese rol.\n\n## Créditos\n\n- [Hillside - Role object pattern](https://hillside.net/plop/plop97/Proceedings/riehle.pdf)\n- [Role object](http://wiki.c2.com/?RoleObject)\n- [Fowler - Dealing with roles](https://martinfowler.com/apsupp/roles.pdf)\n"
  },
  {
    "path": "localization/es/separated-interface/README.md",
    "content": "---\ntitle: Separated Interface\nshortTitle: Separated Interface\ncategory: Structural\nlanguage: es\ntag:\n - Decoupling\n---\n\n\n## Propósito\n\nSepare la definición de la interfaz y su implementación en paquetes diferentes. Esto permite al cliente desconozca por completo la implementación.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Se puede crear un generador de facturas con capacidad para utilizar diferentes calculadoras de impuestos que se pueden añadir en la factura en función del tipo de compra, región, etc.\n\nEn pocas palabras\n\n> El patrón de interfaz separada anima a mantener las implementaciones de una interfaz desacopladas del cliente y su definición, para que el cliente no dependa de la implementación.\n\nUn código cliente puede abstraer algunas funcionalidades específicas a una interfaz, y definir la definición de\nla interfaz como una SPI ([Service Programming Interface](https://en.wikipedia.org/wiki/Service_provider_interface)\nes una API pensada y abierta para ser implementada o ampliada por terceros). Otro paquete puede\nimplementar esta definición de interfaz con una lógica concreta, que se inyectará en el código del cliente en tiempo de ejecución (con un tercero).\ncliente en tiempo de ejecución (con una tercera clase, inyectando la implementación en el cliente) o en tiempo de compilación\n(utilizando el patrón Plugin con algún archivo configurable).\n\n**Ejemplo programático**\n\n**Cliente**\n\nLa clase `InvoiceGenerator` acepta el coste del producto y calcula el importe total a pagar, impuestos incluidos.\ntotal a pagar, impuestos incluidos.\n\n```java\npublic class InvoiceGenerator {\n\n  private final TaxCalculator taxCalculator;\n\n  private final double amount;\n\n  public InvoiceGenerator(double amount, TaxCalculator taxCalculator) {\n    this.amount = amount;\n    this.taxCalculator = taxCalculator;\n  }\n\n  public double getAmountWithTax() {\n    return amount + taxCalculator.calculate(amount);\n  }\n\n}\n```\n\nLa lógica de cálculo de impuestos se delega en la interfaz `TaxCalculator`.\n\n```java\npublic interface TaxCalculator {\n\n  double calculate(double amount);\n\n}\n```\n\n**Paquete de aplicación**\n\nEn otro paquete (que el cliente desconoce por completo) existen múltiples implementaciones\nde la interfaz `TaxCalculator`. Una de ellas es `ForeignTaxCalculator`, que aplica un impuesto del 60\npara los productos internacionales.\n\n```java\npublic class ForeignTaxCalculator implements TaxCalculator {\n\n  public static final double TAX_PERCENTAGE = 60;\n\n  @Override\n  public double calculate(double amount) {\n    return amount * TAX_PERCENTAGE / 100.0;\n  }\n\n}\n```\n\nOtra es `DomesticTaxCalculator`, que grava con un 20% los productos internacionales.\n\n```java\npublic class DomesticTaxCalculator implements TaxCalculator {\n\n  public static final double TAX_PERCENTAGE = 20;\n\n  @Override\n  public double calculate(double amount) {\n    return amount * TAX_PERCENTAGE / 100.0;\n  }\n\n}\n```\n\nEstas dos implementaciones son instanciadas e inyectadas en la clase cliente por la clase `App.java`.\nen la clase cliente.\n\n```java\n    var internationalProductInvoice = new InvoiceGenerator(PRODUCT_COST, new ForeignTaxCalculator());\n\n    LOGGER.info(\"Foreign Tax applied: {}\", \"\" + internationalProductInvoice.getAmountWithTax());\n\n    var domesticProductInvoice = new InvoiceGenerator(PRODUCT_COST, new DomesticTaxCalculator());\n\n    LOGGER.info(\"Domestic Tax applied: {}\", \"\" + domesticProductInvoice.getAmountWithTax());\n```\n\n## Diagrama de clases\n\n![alt text](./etc/class_diagram.png \"Separated Interface\")\n\n## Aplicabilidad\n\nUtilice el patrón de interfaz separada cuando\n\n* Estás desarrollando un paquete de framework, y tu framework necesita llamar a algún código de aplicación a través de interfaces.\n* Tienes paquetes separados que implementan las funcionalidades que pueden ser conectadas a tu código cliente en tiempo de ejecución o de compilación.\n* Su código reside en una capa a la que no se le permite llamar a la capa de implementación de la interfaz por norma. Por ejemplo, una capa de dominio necesita llamar a un mapeador de datos.\n\n## Tutoriales\n\n* [Separated Interface Tutorial](https://www.youtube.com/watch?v=d3k-hOA7k2Y)\n\n## Créditos\n\n* [Martin Fowler](https://www.martinfowler.com/eaaCatalog/separatedInterface.html)\n* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0321127420&linkId=e08dfb7f2cf6153542ef1b5a00b10abc)\n"
  },
  {
    "path": "localization/es/servant/README.md",
    "content": "---\ntitle: Servant\nshortTitle: Servant\ncategory: Behavioral\nlanguage: es\ntag:\n- Decoupling\n---\n\n## Propósito\nServant se utiliza para proporcionar algún comportamiento a un grupo de clases.\nEn lugar de definir ese comportamiento en cada clase - o cuando no podemos factorizar\neste comportamiento en la clase padre común - se define una vez en el Servant.\n\n## Explicación\n\nEjemplo del mundo real\n\n> El Rey, la Reina y otros miembros reales de palacio necesitan sirvientes que les den de comer,\n> organizar bebidas, etc.\n\nEn otras palabras\n\n> Garantiza que un objeto servidor preste determinados servicios a un grupo de clases atendidas.\n\nWikipedia dice\n\n> En ingeniería de software, el patrón Servant define un objeto utilizado para ofrecer alguna funcionalidad\n> a un grupo de clases sin definir esa funcionalidad en cada una de ellas. Un Servant es una clase\n> cuya instancia (o incluso sólo clase) proporciona métodos que se encargan de un servicio deseado, mientras que\n> los objetos para los que (o con los que) el Servant hace algo, se toman como parámetros.\n\n**Ejemplo programático**\n\nLa clase Servant puede prestar servicios a otros miembros reales de palacio.\n\n```java\n/**\n * Servant.\n */\npublic class Servant {\n\n  public String name;\n\n  /**\n   * Constructor.\n   */\n  public Servant(String name) {\n    this.name = name;\n  }\n\n  public void feed(Royalty r) {\n    r.getFed();\n  }\n\n  public void giveWine(Royalty r) {\n    r.getDrink();\n  }\n\n  public void giveCompliments(Royalty r) {\n    r.receiveCompliments();\n  }\n\n  /**\n   * Check if we will be hanged.\n   */\n  public boolean checkIfYouWillBeHanged(List<Royalty> tableGuests) {\n    return tableGuests.stream().allMatch(Royalty::getMood);\n  }\n}\n```\n\nRoyalty es una interfaz. Es implementada por las clases King, y Queen para obtener servicios de servant.\n\n```java\ninterface Royalty {\n\n    void getFed();\n\n    void getDrink();\n\n    void changeMood();\n\n    void receiveCompliments();\n\n    boolean getMood();\n}\n```\nLa clase King implementa la interfaz Royalty.\n```java\npublic class King implements Royalty {\n\n    private boolean isDrunk;\n    private boolean isHungry = true;\n    private boolean isHappy;\n    private boolean complimentReceived;\n\n    @Override\n    public void getFed() {\n        isHungry = false;\n    }\n\n    @Override\n    public void getDrink() {\n        isDrunk = true;\n    }\n\n    public void receiveCompliments() {\n        complimentReceived = true;\n    }\n\n    @Override\n    public void changeMood() {\n        if (!isHungry && isDrunk) {\n            isHappy = true;\n        }\n        if (complimentReceived) {\n            isHappy = false;\n        }\n    }\n\n    @Override\n    public boolean getMood() {\n        return isHappy;\n    }\n}\n```\nLa clase Queen implementa la interfaz Royalty.\n```java\npublic class Queen implements Royalty {\n\n    private boolean isDrunk = true;\n    private boolean isHungry;\n    private boolean isHappy;\n    private boolean isFlirty = true;\n    private boolean complimentReceived;\n\n    @Override\n    public void getFed() {\n        isHungry = false;\n    }\n\n    @Override\n    public void getDrink() {\n        isDrunk = true;\n    }\n\n    public void receiveCompliments() {\n        complimentReceived = true;\n    }\n\n    @Override\n    public void changeMood() {\n        if (complimentReceived && isFlirty && isDrunk && !isHungry) {\n            isHappy = true;\n        }\n    }\n\n    @Override\n    public boolean getMood() {\n        return isHappy;\n    }\n\n    public void setFlirtiness(boolean f) {\n        this.isFlirty = f;\n    }\n\n}\n```\n\nLuego:\n\n```java\npublic class App {\n\n    private static final Servant jenkins = new Servant(\"Jenkins\");\n    private static final Servant travis = new Servant(\"Travis\");\n\n    /**\n     * Program entry point.\n     */\n    public static void main(String[] args) {\n        scenario(jenkins, 1);\n        scenario(travis, 0);\n    }\n\n    /**\n     * Can add a List with enum Actions for variable scenarios.\n     */\n    public static void scenario(Servant servant, int compliment) {\n        var k = new King();\n        var q = new Queen();\n\n        var guests = List.of(k, q);\n\n        // feed\n        servant.feed(k);\n        servant.feed(q);\n        // serve drinks\n        servant.giveWine(k);\n        servant.giveWine(q);\n        // compliment\n        servant.giveCompliments(guests.get(compliment));\n\n        // outcome of the night\n        guests.forEach(Royalty::changeMood);\n\n        // check your luck\n        if (servant.checkIfYouWillBeHanged(guests)) {\n            LOGGER.info(\"{} will live another day\", servant.name);\n        } else {\n            LOGGER.info(\"Poor {}. His days are numbered\", servant.name);\n        }\n    }\n}\n```\n\nLa salida de la consola\n\n```\nJenkins will live another day\nPoor Travis. His days are numbered\n```\n\n\n## Diagrama de clases\n![alt text](./etc/servant-pattern.png \"Servant\")\n\n## Aplicabilidad\nUtiliza el patrón Servant cuando\n\n* Cuando queremos que algunos objetos realicen una acción común y no queremos definir esta acción como un método en cada clase.\n\n## Créditos\n\n* [Let's Modify the Objects-First Approach into Design-Patterns-First](http://edu.pecinovsky.cz/papers/2006_ITiCSE_Design_Patterns_First.pdf)\n"
  },
  {
    "path": "localization/es/sharding/README.md",
    "content": "---\ntitle: Sharding \nshortTitle: Sharding \ncategory: Behavioral\nlanguage: es\ntag:  \n - Performance\n - Cloud distributed\n---  \n  \n## Propósito\nEl patrón sharding significa dividir el almacén de datos en particiones horizontales o shards. Cada fragmento tiene el mismo esquema, pero contiene su propio subconjunto de datos.\nUn fragmento es un almacén de datos en sí mismo (puede contener los datos de muchas entidades de diferentes tipos), que se ejecuta en un servidor que actúa como nodo de almacenamiento.\n\n## Diagrama de clases\n![alt text](./etc/sharding.urm.png \"Sharding pattern class diagram\")\n\n## Aplicabilidad\nEste patrón ofrece las siguientes ventajas:\n\n- Se puede ampliar el sistema añadiendo más fragmentos que se ejecuten en nodos de almacenamiento adicionales.\n- El sistema puede utilizar hardware comercial en lugar de ordenadores especializados (y caros) para cada nodo de almacenamiento.\n- Se puede reducir la contención y mejorar el rendimiento equilibrando la carga de trabajo entre los shards.\n- En la nube, los shards pueden ubicarse físicamente cerca de los usuarios que accederán a los datos.\n\n## Créditos\n  \n* [Sharding pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/sharding)"
  },
  {
    "path": "localization/es/single-table-inheritance/README.md",
    "content": "---\ntitle: Single Table Inheritance Pattern\nshortTitle: Single Table Inheritance Pattern\ncategory: Structural\nlanguage: es\ntag:\n  - Data access\n---\n\n## Single Table Inheritance(STI)\n\n## Propósito\n\nRepresenta una jerarquía hereditaria de clases como una única tabla que tiene columnas para todos los campos de las distintas clases.\n\n## Explicación\n\nUn ejemplo real\n\n> Puede haber muchos tipos diferentes de vehículos en este mundo pero todos ellos se engloban bajo el único paraguas de Vehículo\n\nEn palabras sencillas\n\n> Mapea cada instancia de clase de un árbol de herencia en una única tabla.\n\nWikipedia dice\n\n> La herencia de tabla única es una forma de emular la herencia orientada a objetos en una base de datos relacional. Al mapear desde una tabla de la base de datos a un objeto en un lenguaje orientado a objetos, un campo de la base de datos identifica a qué clase de la jerarquía pertenece el objeto. Todos los campos de todas las clases se almacenan en la misma tabla, de ahí el nombre de \"herencia de tabla única\".\n\n**Ejemplo programático**\n\nBaeldung - Herencia de Hibernate\n\n> Podemos definir la estrategia que queremos utilizar añadiendo la anotación @Inheritance a la superclase:\n\n```java\n@Entity\n@Inheritance(strategy = InheritanceType.SINGLE_TABLE)\npublic class MyProduct {\n  @Id\n  private long productId;\n  private String name;\n\n  // constructor, getters, setters\n}\n```\n\nEl identificador de las entidades también se define en la superclase.\n\nA continuación, podemos añadir las entidades de la subclase:\n\n```java\n@Entity\npublic class Book extends MyProduct {\n  private String author;\n}\n```\n\n```java\n@Entity\npublic class Pen extends MyProduct {\n  private String color;\n}\n```\nValores del discriminador\n\n- Dado que los registros de todas las entidades estarán en la misma tabla, Hibernate necesita una forma de diferenciarlos.\n\n- Por defecto, esto se hace a través de una columna discriminadora llamada DTYPE que tiene como valor el nombre de la entidad.\n\n- Para personalizar la columna discriminadora, podemos utilizar la anotación @DiscriminatorColumn:\n\n```java\n@Entity(name=\"products\")\n@Inheritance(strategy = InheritanceType.SINGLE_TABLE)\n@DiscriminatorColumn(name=\"product_type\",\n        discriminatorType = DiscriminatorType.INTEGER)\npublic class MyProduct {\n  // ...\n}\n```\n- Aquí hemos optado por diferenciar las entidades de la subclase MyProduct mediante una columna entera llamada product_type.\n\n- A continuación, tenemos que indicar a Hibernate qué valor tendrá cada registro de subclase para la columna product_type:\n\n```java\n@Entity\n@DiscriminatorValue(\"1\")\npublic class Book extends MyProduct {\n  // ...\n}\n```\n```java\n@Entity\n@DiscriminatorValue(\"2\")\npublic class Pen extends MyProduct {\n  // ...\n}\n```\n\n- Hibernate añade otros dos valores predefinidos que puede tomar la anotación: null y not null:\n\n  - @DiscriminatorValue(\"null\") significa que cualquier fila sin valor discriminador se asignará a la clase de entidad con esta anotación; esto puede aplicarse a la clase raíz de la jerarquía.\n  - @DiscriminatorValue(\"not null\"): cualquier fila con un valor discriminador que no coincida con ninguno de los asociados a las definiciones de entidad se asignará a la clase con esta anotación.\n\n## Diagrama de clases\n\n![alt text](./etc/single-table-inheritance.urm.png \"Singleton pattern class diagram\")\n\n## Aplicabilidad\n\nUtilice el patrón Singleton cuando\n\n## Use STI Cuando Las Subclases Tienen Los Mismos Campos/Columnas Pero Diferente Comportamiento\n- Una buena indicación de que STI es correcto es cuando las diferentes subclases tienen los mismos campos/columnas pero diferentes métodos. En el ejemplo de cuentas anterior, esperamos que todas las columnas de la base de datos sean utilizadas por cada subclase. De lo contrario, habrá muchas columnas nulas en la base de datos.\n  <br><br>\n* Utilizar STI cuando esperamos realizar consultas en todas las subclases\n  - Otra buena indicación de que STI es correcto es si esperamos realizar consultas a través de todas las clases. Por ejemplo, si queremos encontrar las 10 cuentas con los saldos más altos en todas las clases, STI nos permite utilizar sólo una consulta, mientras que MTI requerirá manipulación en memoria.\n\n### Tutoriales\n\n- <a href =\"https://www.youtube.com/watch?v=M5YrLtAHtOo\" >Cerebros de Java - Herencia de tabla única</a>\n\n## Consecuencias\n\n* Los campos a veces son relevantes y a veces no, lo que puede confundir a la gente que usa las tablas directamente.\n* Las columnas utilizadas sólo por algunas subclases hacen que se desperdicie espacio en la base de datos.\n  Hasta qué punto esto es realmente un problema depende de las características\n  específicas de los datos y de lo bien que la base de datos comprima las columnas vacías.\n  Oracle, por ejemplo, es muy eficiente en el recorte de espacio desperdiciado, particularmente columnas opcionales a la derecha de la tabla de la base de datos.\n  Cada base de datos tiene sus propios trucos para esto.\n* La tabla única puede acabar siendo demasiado grande, con muchos índices y frecuentes, lo que puede perjudicar el rendimiento. Puede evitar esto teniendo\n  tablas de índices separadas que o bien enumeran claves de filas que tienen una determinada propiedad o que copien un subconjunto de campos relevantes para un índice.\n* Sólo se dispone de un único espacio de nombres para los campos, por lo que hay que asegurarse de que\n  de no utilizar el mismo nombre para diferentes campos. Los nombres compuestos con el nombre de la clase como prefijo o sufijo.\n\n## Patrones relacionados\n\n* MappedSuperclass\n* Single Table\n* Joined Table\n* Table per Class\n\n## Créditos\n\n* [Single Table Inheritance - martinFowler.com](https://www.martinfowler.com/eaaCatalog/singleTableInheritance.html)\n* [Patterns of Enterprise Application Architecture](https://books.google.co.in/books?id=vqTfNFDzzdIC&pg=PA278&redir_esc=y#v=onepage&q&f=false)\n"
  },
  {
    "path": "localization/es/singleton/README.md",
    "content": "---\ntitle: Singleton\nshortTitle: Singleton\ncategory: Creational\nlanguage: es\ntag:\n - Gang of Four\n---\n\n## Propósito\n\nAsegurar que una clase solo tenga una instancia y proporcionar un punto de acceso global a ella.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Solo puede haber una torre de marfil donde los magos estudian su magia. La misma torre de marfil encantada\n> siempre es utilizada por los magos. La torre de marfil aquí es un singleton.\n\nEn otras palabras\n\n> Asegura que solo se cree un objeto de una clase en particular.\n\nWikipedia dice\n\n> En ingeniería de software, el patrón singleton es un patrón de diseño de software que limita la\n> instanciación de una clase a un solo objeto. Esto es útil cuando se necesita exactamente un objeto para\n> coordinar acciones en todo el sistema.\n\n\n**Ejemplo programático**\n\nJoshua Bloch, Effective Java 2nd Edition p.18\n\n> Un enum type con un solo elemento es la mejor forma de implementar un singleton\n\n```java\npublic enum EnumIvoryTower {\n  INSTANCE\n}\n```\n\nLuego,\n\n```java\n    var enumIvoryTower1 = EnumIvoryTower.INSTANCE;\n    var enumIvoryTower2 = EnumIvoryTower.INSTANCE;\n    LOGGER.info(\"enumIvoryTower1={}\", enumIvoryTower1);\n    LOGGER.info(\"enumIvoryTower2={}\", enumIvoryTower2);\n```\n\nLa salida de la consola\n\n```\nenumIvoryTower1=com.iluwatar.singleton.EnumIvoryTower@1221555852\nenumIvoryTower2=com.iluwatar.singleton.EnumIvoryTower@1221555852\n```\n\n## Diagrama de clases\n\n![alt text](./etc/singleton.urm.png \"Singleton pattern class diagram\")\n\n## Aplicabilidad\n\nUtilice el patrón Singleton cuando:\n\n* Debe haber exactamente una instancia de una clase, y debe ser accesible para los clientes desde un punto de acceso conocido\n* Cuando la única instancia debe ser extensible mediante herencia, y los clientes deben poder usar una instancia extendida sin modificar su código\n\nAlgunos casos típicos para Singleton:\n\n* La clase logging\n* Gestionar una conexión a una base de datos\n* Gestor de archivos\n\n## Usos conocidos\n\n* [java.lang.Runtime#getRuntime()](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime%28%29)\n* [java.awt.Desktop#getDesktop()](http://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#getDesktop--)\n* [java.lang.System#getSecurityManager()](http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getSecurityManager--)\n\n\n## Consecuencias\n\n* Viola el Principio de Responsabilidad Única (Single Responsibility Principle - SRP) al controlar su creación y ciclo de vida.\n* Fomenta el uso de una instancia compartida globalmente, lo que impide que un objeto y los recursos utilizados por este objeto se liberen.\n* Crea un código fuertemente acoplado. Los clientes del Singleton se vuelven difíciles de probar.\n* Hace casi imposible hacer subclases de un Singleton.\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/es/spatial-partition/README.md",
    "content": "---\ntitle: Spatial Partition\nshortTitle: Spatial Partition\ncategory: Behavioral\nlanguage: es\ntag:\n - Performance\n - Game programming\n---\n\n## Propósito\n\nComo se explica en el libro  [Game Programming Patterns](http://gameprogrammingpatterns.com/spatial-partition.html) \npor Bob Nystrom, spatial partition pattern ayuda a localizar eficazmente los objetos almacenándolos en una\nestructura de datos organizada por sus posiciones.\n\n## Explicación\n\nDigamos que usted está construyendo un juego de guerra con cientos, o incluso miles de jugadores, que se enfrentan en el campo de batalla.\nLa posición de cada jugador se actualiza en cada fotograma. La forma más sencilla de manejar\ntodas las interacciones que tienen lugar en el campo es comprobar la posición de cada jugador con la de todos los demás.\nposición de cada jugador:\n\n```java\npublic void handleMeLee(Unit units[], int numUnits) {\n  for (var a = 0; a < numUnits - 1; a++)\n  {\n    for (var b = a + 1; b < numUnits; b++)\n    {\n      if (units[a].position() == units[b].position())\n      {\n        handleAttack(units[a], units[b]);\n      }\n    }\n  }\n}\n```\n\nEsto incluirá un montón de controles innecesarios entre jugadores que están demasiado alejados como para tener alguna\ninfluencia entre ellos. Los bucles anidados dan a esta operación una complejidad O(n^2), que tiene que ser\ncada fotograma, ya que muchos de los objetos del campo pueden moverse en cada fotograma. La idea\ndetrás del patrón de diseño de Partición Espacial es permitir una rápida localización de los objetos utilizando una estructura de datos que está organizada por sus posiciones.\nque está organizada por sus posiciones, de modo que cuando se realiza una operación como la anterior,\nno es necesario cotejar la posición de cada objeto con la de todos los demás. La estructura de datos\npuede utilizarse para almacenar objetos en movimiento y estáticos, aunque para seguir la pista de los objetos en movimiento,\nsus posiciones tendrán que restablecerse cada vez que se muevan. Esto significaría tener que crear una nueva\ninstancia de la estructura de datos cada vez que un objeto se mueva, lo que consumiría memoria adicional. La dirección\nestructuras de datos comunes utilizadas para este patrón de diseño son:\n\n* Grid\n* Árbol Quad\n* Árbol K-d\n* BSP\n* Jerarquía de volúmenes límite\n\nEn nuestra implementación, utilizamos la estructura de datos Quadtree que reducirá la complejidad temporal de\nO(n^2) a O(nlogn), lo que reduce significativamente los cálculos necesarios en el caso de un gran número de objetos.\nsignificativamente en el caso de un gran número de objetos.\n\n## Diagrama de clases\n\n![alt text](./etc/spatial-partition.urm.png \"Spatial Partition pattern class diagram\")\n\n## Aplicabilidad\n\nUtilice el patrón Spatial Partition cuando:\n\n* Cuando se necesita mantener un registro de un gran número de posiciones de objetos, que se actualizan cada fotograma.\n* Cuando es aceptable cambiar memoria por velocidad, ya que la creación y actualización de la estructura de datos consumirá memoria extra.\n\n## Créditos\n\n* [Game Programming Patterns/Spatial Partition](http://gameprogrammingpatterns.com/spatial-partition.html) por Bob Nystrom\n* [Quadtree tutorial](https://www.youtube.com/watch?v=OJxEcs0w_kE) por Daniel Schiffman\n"
  },
  {
    "path": "localization/es/special-case/README.md",
    "content": "---\ntitle: Special Case\nshortTitle: Special Case\ncategory: Behavioral\nlanguage: es\ntag:\n - Extensibility\n---\n\n## Propósito\n\nDefine algunos casos especiales, y los encapsula en subclases que proporcionan diferentes comportamientos especiales.\n\n## Explicación\n\nEjemplo del mundo real\n\n> En un sistema de comercio electrónico, la capa de presentación espera que la capa de aplicación produzca cierto modelo de vista.\n> Tenemos un escenario de éxito, en el que el modelo de vista de recibo contiene datos reales de la compra,\n> y un par de escenarios de fracaso.\n\nEn otras palabras\n\n> El patrón Special Case permite devolver objetos reales no nulos que realizan comportamientos especiales.\n\nEn [Patterns of Enterprise Application Architecture](https://martinfowler.com/books/eaa.html) se dice\nla diferencia con el Patrón de Objeto Nulo\n\n> Si me perdonas el juego de palabras irresistible, yo veo el Objeto Nulo como un caso especial de Caso Especial.\n\n**Ejemplo programático**\n\nPara centrarnos en el patrón en sí, implementamos la BD y el bloqueo de mantenimiento del sistema de comercio electrónico mediante la instancia singleton.\n\n```java\npublic class Db {\n  private static Db instance;\n  private Map<String, User> userName2User;\n  private Map<User, Account> user2Account;\n  private Map<String, Product> itemName2Product;\n\n  public static Db getInstance() {\n    if (instance == null) {\n      synchronized (Db.class) {\n        if (instance == null) {\n          instance = new Db();\n          instance.userName2User = new HashMap<>();\n          instance.user2Account = new HashMap<>();\n          instance.itemName2Product = new HashMap<>();\n        }\n      }\n    }\n    return instance;\n  }\n\n  public void seedUser(String userName, Double amount) {\n    User user = new User(userName);\n    instance.userName2User.put(userName, user);\n    Account account = new Account(amount);\n    instance.user2Account.put(user, account);\n  }\n\n  public void seedItem(String itemName, Double price) {\n    Product item = new Product(price);\n    itemName2Product.put(itemName, item);\n  }\n\n  public User findUserByUserName(String userName) {\n    if (!userName2User.containsKey(userName)) {\n      return null;\n    }\n    return userName2User.get(userName);\n  }\n\n  public Account findAccountByUser(User user) {\n    if (!user2Account.containsKey(user)) {\n      return null;\n    }\n    return user2Account.get(user);\n  }\n\n  public Product findProductByItemName(String itemName) {\n    if (!itemName2Product.containsKey(itemName)) {\n      return null;\n    }\n    return itemName2Product.get(itemName);\n  }\n\n  public class User {\n    private String userName;\n\n    public User(String userName) {\n      this.userName = userName;\n    }\n\n    public String getUserName() {\n      return userName;\n    }\n\n    public ReceiptDto purchase(Product item) {\n      return new ReceiptDto(item.getPrice());\n    }\n  }\n\n  public class Account {\n    private Double amount;\n\n    public Account(Double amount) {\n      this.amount = amount;\n    }\n\n    public MoneyTransaction withdraw(Double price) {\n      if (price > amount) {\n        return null;\n      }\n      return new MoneyTransaction(amount, price);\n    }\n\n    public Double getAmount() {\n      return amount;\n    }\n  }\n\n  public class Product {\n    private Double price;\n\n    public Product(Double price) {\n      this.price = price;\n    }\n\n    public Double getPrice() {\n      return price;\n    }\n  }\n}\n\npublic class MaintenanceLock {\n  private static final Logger LOGGER = LoggerFactory.getLogger(MaintenanceLock.class);\n\n  private static MaintenanceLock instance;\n  private boolean lock = true;\n\n  public static MaintenanceLock getInstance() {\n    if (instance == null) {\n      synchronized (MaintenanceLock.class) {\n        if (instance == null) {\n          instance = new MaintenanceLock();\n        }\n      }\n    }\n    return instance;\n  }\n\n  public boolean isLock() {\n    return lock;\n  }\n\n  public void setLock(boolean lock) {\n    this.lock = lock;\n    LOGGER.info(\"Maintenance lock is set to: \" + lock);\n  }\n}\n```\n\nPrimero presentaremos la capa de presentación, la interfaz del modelo de vista de recibo y su implementación de un escenario exitoso.\n\n```java\npublic interface ReceiptViewModel {\n  void show();\n}\n\npublic class ReceiptDto implements ReceiptViewModel {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(ReceiptDto.class);\n\n  private Double price;\n\n  public ReceiptDto(Double price) {\n    this.price = price;\n  }\n\n  public Double getPrice() {\n    return price;\n  }\n\n  @Override\n  public void show() {\n    LOGGER.info(\"Receipt: \" + price + \" paid\");\n  }\n}\n```\n\nY aquí están las implementaciones de los escenarios de fracaso, que son los casos especiales.\n\n```java\npublic class DownForMaintenance implements ReceiptViewModel {\n  private static final Logger LOGGER = LoggerFactory.getLogger(DownForMaintenance.class);\n\n  @Override\n  public void show() {\n    LOGGER.info(\"Down for maintenance\");\n  }\n}\n\npublic class InvalidUser implements ReceiptViewModel {\n  private static final Logger LOGGER = LoggerFactory.getLogger(InvalidUser.class);\n\n  private final String userName;\n\n  public InvalidUser(String userName) {\n    this.userName = userName;\n  }\n\n  @Override\n  public void show() {\n    LOGGER.info(\"Invalid user: \" + userName);\n  }\n}\n\npublic class OutOfStock implements ReceiptViewModel {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(OutOfStock.class);\n\n  private String userName;\n  private String itemName;\n\n  public OutOfStock(String userName, String itemName) {\n    this.userName = userName;\n    this.itemName = itemName;\n  }\n\n  @Override\n  public void show() {\n    LOGGER.info(\"Out of stock: \" + itemName + \" for user = \" + userName + \" to buy\");\n  }\n}\n\npublic class InsufficientFunds implements ReceiptViewModel {\n  private static final Logger LOGGER = LoggerFactory.getLogger(InsufficientFunds.class);\n\n  private String userName;\n  private Double amount;\n  private String itemName;\n\n  public InsufficientFunds(String userName, Double amount, String itemName) {\n    this.userName = userName;\n    this.amount = amount;\n    this.itemName = itemName;\n  }\n\n  @Override\n  public void show() {\n    LOGGER.info(\"Insufficient funds: \" + amount + \" of user: \" + userName\n        + \" for buying item: \" + itemName);\n  }\n}\n```\n\nEn segundo lugar, está la capa de aplicación, la implementación de los servicios de aplicación y la implementación de los servicios de dominio.\n\n```java\npublic class ApplicationServicesImpl implements ApplicationServices {\n  private DomainServicesImpl domain = new DomainServicesImpl();\n\n  @Override\n  public ReceiptViewModel loggedInUserPurchase(String userName, String itemName) {\n    if (isDownForMaintenance()) {\n      return new DownForMaintenance();\n    }\n    return this.domain.purchase(userName, itemName);\n  }\n\n  private boolean isDownForMaintenance() {\n    return MaintenanceLock.getInstance().isLock();\n  }\n}\n\npublic class DomainServicesImpl implements DomainServices {\n  public ReceiptViewModel purchase(String userName, String itemName) {\n    Db.User user = Db.getInstance().findUserByUserName(userName);\n    if (user == null) {\n      return new InvalidUser(userName);\n    }\n\n    Db.Account account = Db.getInstance().findAccountByUser(user);\n    return purchase(user, account, itemName);\n  }\n\n  private ReceiptViewModel purchase(Db.User user, Db.Account account, String itemName) {\n    Db.Product item = Db.getInstance().findProductByItemName(itemName);\n    if (item == null) {\n      return new OutOfStock(user.getUserName(), itemName);\n    }\n\n    ReceiptDto receipt = user.purchase(item);\n    MoneyTransaction transaction = account.withdraw(receipt.getPrice());\n    if (transaction == null) {\n      return new InsufficientFunds(user.getUserName(), account.getAmount(), itemName);\n    }\n\n    return receipt;\n  }\n}\n```\n\nPor último, el cliente envía solicitudes a los servicios de la aplicación para obtener la vista de la presentación.\n\n```java\n    // DB seeding\n    LOGGER.info(\"Db seeding: \" + \"1 user: {\\\"ignite1771\\\", amount = 1000.0}, \"\n        + \"2 products: {\\\"computer\\\": price = 800.0, \\\"car\\\": price = 20000.0}\");\n    Db.getInstance().seedUser(\"ignite1771\", 1000.0);\n    Db.getInstance().seedItem(\"computer\", 800.0);\n    Db.getInstance().seedItem(\"car\", 20000.0);\n\n    var applicationServices = new ApplicationServicesImpl();\n    ReceiptViewModel receipt;\n\n    LOGGER.info(\"[REQUEST] User: \" + \"abc123\" + \" buy product: \" + \"tv\");\n    receipt = applicationServices.loggedInUserPurchase(\"abc123\", \"tv\");\n    receipt.show();\n    MaintenanceLock.getInstance().setLock(false);\n    LOGGER.info(\"[REQUEST] User: \" + \"abc123\" + \" buy product: \" + \"tv\");\n    receipt = applicationServices.loggedInUserPurchase(\"abc123\", \"tv\");\n    receipt.show();\n    LOGGER.info(\"[REQUEST] User: \" + \"ignite1771\" + \" buy product: \" + \"tv\");\n    receipt = applicationServices.loggedInUserPurchase(\"ignite1771\", \"tv\");\n    receipt.show();\n    LOGGER.info(\"[REQUEST] User: \" + \"ignite1771\" + \" buy product: \" + \"car\");\n    receipt = applicationServices.loggedInUserPurchase(\"ignite1771\", \"car\");\n    receipt.show();\n    LOGGER.info(\"[REQUEST] User: \" + \"ignite1771\" + \" buy product: \" + \"computer\");\n    receipt = applicationServices.loggedInUserPurchase(\"ignite1771\", \"computer\");\n    receipt.show();\n```\n\nSalida del programa de cada solicitud:\n\n```\n    Down for maintenance\n    Invalid user: abc123\n    Out of stock: tv for user = ignite1771 to buy\n    Insufficient funds: 1000.0 of user: ignite1771 for buying item: car\n    Receipt: 800.0 paid    \n```\n\n## Diagrama de clases\n\n![alt text](./etc/special_case_urm.png \"Special Case\")\n\n## Aplicabilidad\n\nUtilice el patrón Special Case cuando:\n\n* Tienes varios lugares en el sistema que tienen el mismo comportamiento después de una comprobación condicional\n  para una instancia de clase en particular, o el mismo comportamiento después de una comprobación nula.\n* Devuelve un objeto real que realiza el comportamiento real, en lugar de un objeto nulo que no realiza nada.\n\n## Tutorial \n\n* [Special Case Tutorial](https://www.codinghelmet.com/articles/reduce-cyclomatic-complexity-special-case)\n\n## Créditos\n\n* [How to Reduce Cyclomatic Complexity Part 2: Special Case Pattern](https://www.codinghelmet.com/articles/reduce-cyclomatic-complexity-special-case)\n* [Patterns of Enterprise Application Architecture](https://martinfowler.com/books/eaa.html)\n* [Special Case](https://www.martinfowler.com/eaaCatalog/specialCase.html)"
  },
  {
    "path": "localization/es/specification/README.md",
    "content": "---\ntitle: Specification\nshortTitle: Specification\ncategory: Behavioral\nlanguage: es\ntag:\n - Data access\n---\n\n## También conocido como\n\nFilter, Criteria\n\n## Propósito\n\nEl patrón de Specification separa la declaración de cómo emparejar un candidato, del objeto candidato\ncon el que se compara. Además de su utilidad en la selección, también es valioso para la\nvalidación y para la construcción por encargo.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Hay un conjunto de criaturas diferentes y a menudo necesitamos seleccionar algún subconjunto de ellas. Podemos\n> escribir nuestra especificación de búsqueda como \"criaturas que puedan volar\", \"criaturas de más de 500\n> kilogramos\", o como una combinación de otras especificaciones de búsqueda.\n> que realizará el filtrado.\n\nEn palabras sencillas\n\n> El patrón de especificación nos permite separar los criterios de búsqueda del objeto que realiza la\n> búsqueda.\n\nWikipedia dice\n\n> En programación informática, el patrón de especificación es un patrón particular de diseño de software,\n> por el cual las reglas de negocio pueden ser recombinadas encadenando las reglas de negocio usando lógica booleana\n> lógica booleana.\n\n**Ejemplo programático**\n\nSi nos fijamos en nuestro ejemplo anterior, tenemos un conjunto de criaturas con ciertas propiedades.\npropiedades. Esas propiedades pueden formar parte de un conjunto predefinido y limitado (representado aquí por los\nenums Tamaño, Movimiento y Color); pero también pueden ser valores continuos (por ejemplo, la masa de una\ncriatura). En este caso, es más apropiado utilizar lo que llamamos \"especificación parametrizada\",\nen la que el valor de la propiedad puede darse como argumento al instanciar la criatura, lo que permite\nmayor flexibilidad. Una tercera opción es combinar propiedades predefinidas y/o parametrizadas utilizando\nlógica booleana, lo que permite posibilidades de selección casi ilimitadas (esto se denomina \"especificación compuesta\", véase más adelante).\nespecificación compuesta\", véase más adelante). Los pros y los contras de cada enfoque se detallan en la tabla al final de este documento.\nde este documento.\n\n```java\npublic interface Creature {\n  String getName();\n  Size getSize();\n  Movement getMovement();\n  Color getColor();\n  Mass getMass();\n}\n```\n\nY la implementación de `Dragon` tiene este aspecto.\n\n```java\npublic class Dragon extends AbstractCreature {\n\n  public Dragon() {\n    super(\"Dragon\", Size.LARGE, Movement.FLYING, Color.RED, new Mass(39300.0));\n  }\n}\n```\n\nAhora que queremos seleccionar algún subconjunto de ellos, utilizamos selectores. Para seleccionar criaturas que vuelan\ndebemos usar `MovementSelector`.\n\n```java\npublic class MovementSelector extends AbstractSelector<Creature> {\n\n  private final Movement movement;\n\n  public MovementSelector(Movement m) {\n    this.movement = m;\n  }\n\n  @Override\n  public boolean test(Creature t) {\n    return t.getMovement().equals(movement);\n  }\n}\n```\n\nPor otro lado, cuando seleccionamos criaturas más pesadas que una cantidad elegida, usamos\n`MassGreaterThanSelector`.\n\n```java\npublic class MassGreaterThanSelector extends AbstractSelector<Creature> {\n\n  private final Mass mass;\n\n  public MassGreaterThanSelector(double mass) {\n    this.mass = new Mass(mass);\n  }\n\n  @Override\n  public boolean test(Creature t) {\n    return t.getMass().greaterThan(mass);\n  }\n}\n```\n\nCon estos elementos en su lugar, podemos realizar una búsqueda de criaturas rojas de la siguiente manera:\n\n```java\n    var redCreatures = creatures.stream().filter(new ColorSelector(Color.RED))\n      .collect(Collectors.toList());\n```\n\nPero también podríamos usar nuestro selector parametrizado así:\n\n```java\n    var heavyCreatures = creatures.stream().filter(new MassGreaterThanSelector(500.0)\n      .collect(Collectors.toList());\n```\n\nNuestra tercera opción es combinar varios selectores. La búsqueda de criaturas especiales\n(definidas como rojas, voladoras y no pequeñas) podría hacerse de la siguiente manera:\n\n```java\n    var specialCreaturesSelector = \n      new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING)).and(new SizeSelector(Size.SMALL).not());\n\n    var specialCreatures = creatures.stream().filter(specialCreaturesSelector)\n      .collect(Collectors.toList());\n```\n\n**Más información sobre las especificaciones de los compuestos**\n\nEn Composite Specification, crearemos instancias personalizadas de `AbstractSelector` combinando\notros selectores (llamados \"hojas\") utilizando los tres operadores lógicos básicos. Éstos se implementan en\nConjunctionSelector`, `DisjunctionSelector` y `NegationSelector`.\n\n```java\npublic abstract class AbstractSelector<T> implements Predicate<T> {\n\n  public AbstractSelector<T> and(AbstractSelector<T> other) {\n    return new ConjunctionSelector<>(this, other);\n  }\n\n  public AbstractSelector<T> or(AbstractSelector<T> other) {\n    return new DisjunctionSelector<>(this, other);\n  }\n\n  public AbstractSelector<T> not() {\n    return new NegationSelector<>(this);\n  }\n}\n```\n\n```java\npublic class ConjunctionSelector<T> extends AbstractSelector<T> {\n\n  private final List<AbstractSelector<T>> leafComponents;\n\n  @SafeVarargs\n  ConjunctionSelector(AbstractSelector<T>... selectors) {\n    this.leafComponents = List.of(selectors);\n  }\n\n  /**\n   * Tests if *all* selectors pass the test.\n   */\n  @Override\n  public boolean test(T t) {\n    return leafComponents.stream().allMatch(comp -> (comp.test(t)));\n  }\n}\n```\n\nTodo lo que queda por hacer ahora es crear selectores de hoja (ya sean de código duro o parametrizados) que\nsean lo más genéricos posible, y podremos instanciar la clase ``AbstractSelector`` combinando\ncualquier cantidad de selectores, como se ejemplificó anteriormente. Debemos tener cuidado, sin embargo, ya que es fácil\ncometer un error al combinar muchos operadores lógicos; en particular, debemos prestar atención a la prioridad de las operaciones.\nla prioridad de las operaciones. En general, la especificación compuesta es una gran manera de escribir más\ncódigo reutilizable, ya que no es necesario crear una clase Selector para cada operación de filtrado. En su lugar\nsimplemente creamos una instancia de ``AbstractSelector`` \"sobre la marcha\", utilizando selectores genéricos de \"hoja\" y algunos selectores booleanos básicos.\ny alguna lógica booleana básica.\n\n**Comparación de los distintos enfoques**\n\n| Patrón | Uso | Pros | Contras |\n|---|---|---|---|\n| Especificación Codificada | Los criterios de selección son pocos y se conocen de antemano | + Fácil de implementar | - Inflexible |\n| | | + Expresivo |\n| Especificación Parametrizada | Los criterios de selección abarcan un amplio rango de valores (por ejemplo, masa, velocidad,...) | + Alguna flexibilidad | - Aún requiere clases de propósito especial |\n| Especificación Compuesta | Hay muchos criterios de selección que se pueden combinar de múltiples maneras, por lo tanto, no es factible crear una clase para cada selector | + Muy flexible, sin requerir muchas clases especializadas | - Algo más difícil de comprender |\n| | | + Admite operaciones lógicas | - Todavía necesitas crear las clases base utilizadas como hojas |\n## Class diagram\n\n![alt text](./etc/specification.png \"Specification\")\n\n## Diagrama de clases\n\nUtilice el patrón Specification cuando\n\n* Necesitas seleccionar un subconjunto de objetos basándote en algún criterio, y refrescar la selección en varios momentos.\n* Necesita comprobar que sólo se utilizan objetos adecuados para una determinada función (validación).\n\n## Patrones relacionados\n\n* Repository\n\n## Créditos\n\n* [Martin Fowler - Specifications](http://martinfowler.com/apsupp/spec.pdf)\n"
  },
  {
    "path": "localization/es/state/README.md",
    "content": "---\ntitle: State\nshortTitle: State\ncategory: Behavioral\nlanguage: es\ntag:\n - Gang of Four\n---\n\n## También conocido como\n\nObjects for States\n\n## Propósito\n\nPermite que un objeto altere su comportamiento cuando cambia su estado interno. El objeto parecerá\ncambiar de clase.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Al observar un mamut en su hábitat natural parece cambiar su comportamiento en función de la\n> situación. Al principio puede parecer tranquilo, pero con el tiempo, cuando detecta una amenaza, se enfada y se vuelve peligroso para su entorno.\n> peligroso para su entorno.\n\nEn palabras sencillas\n\n> El patrón de estado permite a un objeto cambiar su comportamiento.\n\nWikipedia dice\n\n> El patrón de estado es un patrón de diseño de software de comportamiento que permite a un objeto alterar su\n> comportamiento cuando cambia su estado interno. Este patrón es cercano al concepto de máquinas de estado finito.\n> máquinas de estado finito. El patrón de estado puede ser interpretado como un patrón de estrategia, que es capaz de cambiar una estrategia a través de invocaciones de métodos definidos por el usuario.\n> estrategia a través de invocaciones de métodos definidos en la interfaz del patrón.\n\n**Ejemplo programático**\n\nEsta es la interfaz de estado y sus implementaciones concretas.\n\n```java\npublic interface State {\n\n  void onEnterState();\n\n  void observe();\n}\n\n@Slf4j\npublic class PeacefulState implements State {\n\n  private final Mammoth mammoth;\n\n  public PeacefulState(Mammoth mammoth) {\n    this.mammoth = mammoth;\n  }\n\n  @Override\n  public void observe() {\n    LOGGER.info(\"{} is calm and peaceful.\", mammoth);\n  }\n\n  @Override\n  public void onEnterState() {\n    LOGGER.info(\"{} calms down.\", mammoth);\n  }\n}\n\n@Slf4j\npublic class AngryState implements State {\n\n  private final Mammoth mammoth;\n\n  public AngryState(Mammoth mammoth) {\n    this.mammoth = mammoth;\n  }\n\n  @Override\n  public void observe() {\n    LOGGER.info(\"{} is furious!\", mammoth);\n  }\n\n  @Override\n  public void onEnterState() {\n    LOGGER.info(\"{} gets angry!\", mammoth);\n  }\n}\n```\n\nY aquí está el mammoth que contiene el Estado.\n\n```java\npublic class Mammoth {\n\n  private State state;\n\n  public Mammoth() {\n    state = new PeacefulState(this);\n  }\n\n  public void timePasses() {\n    if (state.getClass().equals(PeacefulState.class)) {\n      changeStateTo(new AngryState(this));\n    } else {\n      changeStateTo(new PeacefulState(this));\n    }\n  }\n\n  private void changeStateTo(State newState) {\n    this.state = newState;\n    this.state.onEnterState();\n  }\n\n  @Override\n  public String toString() {\n    return \"The mammoth\";\n  }\n\n  public void observe() {\n    this.state.observe();\n  }\n}\n```\n\nHe aquí el ejemplo completo de cómo se comporta el mammoth a lo largo del tiempo.\n\n```java\n    var mammoth = new Mammoth();\n    mammoth.observe();\n    mammoth.timePasses();\n    mammoth.observe();\n    mammoth.timePasses();\n    mammoth.observe();\n```\n\nSalida del programa:\n\n```java\n    The mammoth gets angry!\n    The mammoth is furious!\n    The mammoth calms down.\n    The mammoth is calm and peaceful.\n```\n\n## Diagrama de clases\n\n![alt text](./etc/state_urm.png \"State\")\n\n## Aplicabilidad\n\nUtiliza el patrón State en cualquiera de los siguientes casos:\n\n* El comportamiento de un objeto depende de su estado, y debe cambiar su comportamiento en tiempo de ejecución dependiendo de ese estado.\n* Las operaciones tienen grandes sentencias condicionales multiparte que dependen del estado del objeto. Este estado suele estar representado por una o más constantes enumeradas. A menudo, varias operaciones contendrán esta misma estructura condicional. El patrón State coloca cada rama de la condicional en una clase separada. Esto permite tratar el estado del objeto como un objeto en sí mismo que puede variar independientemente de otros objetos.\n\nTraducción realizada con la versión gratuita del traductor www.DeepL.com/Translator\n\n## Usos conocidos\n\n* [javax.faces.lifecycle.Lifecycle#execute()](http://docs.oracle.com/javaee/7/api/javax/faces/lifecycle/Lifecycle.html#execute-javax.faces.context.FacesContext-) controlled by [FacesServlet](http://docs.oracle.com/javaee/7/api/javax/faces/webapp/FacesServlet.html), the behavior is dependent on current phase of lifecycle.\n* [JDiameter - Diameter State Machine](https://github.com/npathai/jdiameter/blob/master/core/jdiameter/api/src/main/java/org/jdiameter/api/app/State.java)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/es/step-builder/README.md",
    "content": "---\ntitle: Step Builder\nshortTitle: Step Builder\ncategory: Creational\nlanguage: es\ntag:\n  - Instantiation\n---\n\n# Step Builder Pattern\n\n## Explicación\n\nEl patrón Step Builder es un patrón de diseño de creación utilizado para construir un objeto complejo paso a paso.\nProporciona una interfaz fluida para crear un objeto con un gran número de configuraciones posibles, haciendo el código\nmás legible y reduciendo la necesidad de múltiples constructores o métodos setter.\n\n## Propósito\n\nUna extensión del patrón Builder que guía completamente al usuario a través de la creación del objeto sin posibilidades\nde confusión.\nLa experiencia del usuario será mucho más mejorada por el hecho de que solo verá los métodos del siguiente paso\ndisponibles, NINGÚN método constructor hasta que sea el momento adecuado para construir el objeto.\n\n## Ejemplo del mundo real\n\nImagine que está construyendo un objeto de configuración para una conexión a una base de datos. La conexión tiene varios\nparámetros opcionales como host, puerto, nombre de usuario, contraseña y otros. Usando el patrón Step Builder, puedes\nestablecer estos parámetros de una forma limpia y legible:\n\n```java\nDatabaseConnection connection = new DatabaseConnection.Builder()\n    .setHost(\"localhost\")\n    .setPort(3306)\n    .setUsername(\"user\")\n    .setPassword(\"password\")\n    .setSSL(true)\n    .build();\n```\n\n## En pocas palabras\n\nEl patrón Step Builder permite construir objetos complejos dividiendo el proceso de construcción en una serie de pasos.\nCada paso corresponde a la configuración de un atributo particular u opción de configuración del objeto. Esto resulta en\nun código más legible y mantenible, especialmente cuando se trata de objetos que tienen numerosas opciones de\nconfiguración.\n\n## Wikipedia dice\n\nSegún Wikipedia, el patrón Step Builder es un patrón de diseño de creación en el que un objeto se construye paso a paso.\nImplica una clase 'director' dedicada, que orquesta el proceso de construcción a través de una serie de clases '\nconstructoras', cada una responsable de un aspecto específico de la configuración del objeto. Este patrón es\nparticularmente útil cuando se trata de objetos que tienen un gran número de parámetros opcionales.\n\n## Ejemplo programático\n\nSuponiendo que tienes una clase `Producto` con varios atributos configurables, un Step Builder para ella podría tener\neste aspecto:\n\n```java\npublic class Product {\n    private String name;\n    private double price;\n    private int quantity;\n\n    // private constructor to force the use of the builder\n    private Product(String name, double price, int quantity) {\n\n        this.name = name;\n        this.price = price;\n        this.quantity = quantity;\n\n    }\n\n    public static class Builder {\n        private String name;\n        private double price;\n        private int quantity;\n\n        public Builder setName(String name) {\n            this.name = name;\n            return this;\n        }\n\n        public Builder setPrice(double price) {\n            this.price = price;\n            return this;\n        }\n\n        public Builder setQuantity(int quantity) {\n            this.quantity = quantity;\n            return this;\n        }\n\n        public Product build() {\n            return new Product(name, price, quantity);\n        }\n    }\n}\n\n// Usage\nProduct product = new Product.Builder()\n    .setName(\"Example Product\")\n    .setPrice(29.99)\n    .setQuantity(100)\n    .build();\n```\n\nEste ejemplo muestra cómo utilizar el patrón Constructor por pasos para crear un objeto `Producto` con un conjunto de\natributos personalizables. Cada método del constructor corresponde a un paso del proceso de construcción.\n\n## Aplicabilidad\n\nUtilice el patrón Step Builder cuando el algoritmo para crear un objeto complejo debe ser independiente de las partes\nque componen el objeto y de cómo se ensamblan el proceso de construcción debe permitir diferentes representaciones para\nel objeto que se construye cuando en el proceso de construcción el orden es importante.\n\n## Otro ejemplo con diagrama de clases\n\n![alt text](./etc/step-builder.png \"Step Builder pattern\")\n\n## Créditos\n\n* [Marco Castigliego - Step Builder](http://rdafbn.blogspot.co.uk/2012/07/step-builder-pattern_28.html)\n"
  },
  {
    "path": "localization/es/strangler/README.md",
    "content": "---\ntitle: Strangler\nshortTitle: Strangler\ncategory: Structural\nlanguage: es\ntag:\n - Extensibility\n - Cloud distributed\n---\n\n## Propósito\nMigrar de forma incremental un sistema heredado sustituyendo gradualmente piezas específicas de funcionalidad\ncon nuevas aplicaciones y servicios. A medida que se sustituyen las funciones del sistema heredado, el nuevo\nsistema acaba cubriendo todas las funciones del sistema antiguo y puede tener sus propias funciones nuevas, con lo que\nestrangulando el sistema antiguo y permitiéndole retirarlo del servicio.\n\n## Diagrama de clases\n![alt text](./etc/strangler.png \"Strangler\")\n\n## Aplicabilidad\nEste patrón estrangulador es una manera segura de eliminar gradualmente una cosa por algo mejor, más barato, o\nmás expandible. Especialmente cuando se quiere actualizar el sistema heredado con nuevas técnicas y se necesita\ndesarrollar continuamente nuevas características al mismo tiempo. Tenga en cuenta que este patrón requiere un esfuerzo adicional,\npor lo que normalmente se utiliza cuando el sistema no es tan simple.\n\n## Créditos\n\n* [Strangler pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/strangler)\n* [Legacy Application Strangulation : Case Studies](https://paulhammant.com/2013/07/14/legacy-application-strangulation-case-studies/)\n"
  },
  {
    "path": "localization/es/strategy/README.md",
    "content": "---\ntitle: Strategy\nshortTitle: Strategy\ncategory: Behavioral\nlanguage: es\ntag:\n - Gang of Four\n---\n\n## También conocido como\n\nPolicy\n\n## Propósito\n\nDefinir una familia de algoritmos, encapsular cada uno de ellos y hacerlos intercambiables. La estrategia permite\nque el algoritmo varíe independientemente de los clientes que lo utilicen.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Matar dragones es un trabajo peligroso. Con la experiencia, se hace más fácil. Los veteranos de\n> Los matadragones han desarrollado diferentes estrategias de lucha contra distintos tipos de dragones.\n\nEn palabras sencillas\n\n> El patrón de estrategia permite elegir el algoritmo más adecuado en tiempo de ejecución.\n\nWikipedia dice\n\n> En programación informática, el patrón de estrategia (también conocido como patrón de política) es un patrón de > diseño de software de comportamiento que permite seleccionar un algoritmo en tiempo de ejecución.\n> patrón de diseño de software que permite seleccionar un algoritmo en tiempo de ejecución.\n\n**Ejemplo programático**\n\nPresentemos primero la interfaz de la estrategia para matar dragones y sus implementaciones.\n\n```java\n@FunctionalInterface\npublic interface DragonSlayingStrategy {\n\n  void execute();\n}\n\n@Slf4j\npublic class MeleeStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"With your Excalibur you sever the dragon's head!\");\n  }\n}\n\n@Slf4j\npublic class ProjectileStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"You shoot the dragon with the magical crossbow and it falls dead on the ground!\");\n  }\n}\n\n@Slf4j\npublic class SpellStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\");\n  }\n}\n```\n\nY aquí está el poderoso cazador de dragones, que puede elegir su estrategia de lucha en función del\noponente.\n\n```java\npublic class DragonSlayer {\n\n  private DragonSlayingStrategy strategy;\n\n  public DragonSlayer(DragonSlayingStrategy strategy) {\n    this.strategy = strategy;\n  }\n\n  public void changeStrategy(DragonSlayingStrategy strategy) {\n    this.strategy = strategy;\n  }\n\n  public void goToBattle() {\n    strategy.execute();\n  }\n}\n```\n\nPor último, aquí está el cazador de dragones en acción.\n\n```java\n    LOGGER.info(\"Green dragon spotted ahead!\");\n    var dragonSlayer = new DragonSlayer(new MeleeStrategy());\n    dragonSlayer.goToBattle();\n    LOGGER.info(\"Red dragon emerges.\");\n    dragonSlayer.changeStrategy(new ProjectileStrategy());\n    dragonSlayer.goToBattle();\n    LOGGER.info(\"Black dragon lands before you.\");\n    dragonSlayer.changeStrategy(new SpellStrategy());\n    dragonSlayer.goToBattle();\n```\n\nSalida del programa:\n\n```\n    Green dragon spotted ahead!\n    With your Excalibur you sever the dragon's head!\n    Red dragon emerges.\n    You shoot the dragon with the magical crossbow and it falls dead on the ground!\n    Black dragon lands before you.\n    You cast the spell of disintegration and the dragon vaporizes in a pile of dust!    \n```\n\nAdemás, las expresiones lambda de Java 8 proporcionan otro enfoque para la implementación:\n\n```java\npublic class LambdaStrategy {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(LambdaStrategy.class);\n\n  public enum Strategy implements DragonSlayingStrategy {\n    MeleeStrategy(() -> LOGGER.info(\n        \"With your Excalibur you sever the dragon's head!\")),\n    ProjectileStrategy(() -> LOGGER.info(\n        \"You shoot the dragon with the magical crossbow and it falls dead on the ground!\")),\n    SpellStrategy(() -> LOGGER.info(\n        \"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\"));\n\n    private final DragonSlayingStrategy dragonSlayingStrategy;\n\n    Strategy(DragonSlayingStrategy dragonSlayingStrategy) {\n      this.dragonSlayingStrategy = dragonSlayingStrategy;\n    }\n\n    @Override\n    public void execute() {\n      dragonSlayingStrategy.execute();\n    }\n  }\n}\n```\n\nY aquí está el cazador de dragones en acción.\n\n```java\n    LOGGER.info(\"Green dragon spotted ahead!\");\n    dragonSlayer.changeStrategy(LambdaStrategy.Strategy.MeleeStrategy);\n    dragonSlayer.goToBattle();\n    LOGGER.info(\"Red dragon emerges.\");\n    dragonSlayer.changeStrategy(LambdaStrategy.Strategy.ProjectileStrategy);\n    dragonSlayer.goToBattle();\n    LOGGER.info(\"Black dragon lands before you.\");\n    dragonSlayer.changeStrategy(LambdaStrategy.Strategy.SpellStrategy);\n    dragonSlayer.goToBattle();\n```\n\nLa salida del programa es la misma que la anterior.\n\n## Diagrama de clases\n\n![alt text](./etc/strategy_urm.png \"Strategy\")\n\n## Aplicabilidad\n\nUtilice el patrón Strategy cuando\n\n* Muchas clases relacionadas sólo difieren en su comportamiento. Las estrategias proporcionan una forma de configurar una clase con uno de varios comportamientos\n* Necesita diferentes variantes de un algoritmo. Por ejemplo, puede definir algoritmos que reflejen diferentes compensaciones espacio/tiempo. Las estrategias pueden utilizarse cuando estas variantes se implementan como una jerarquía de clases de algoritmos\n* Un algoritmo utiliza datos que los clientes no deberían conocer. Utilice el patrón Strategy para evitar exponer estructuras de datos complejas específicas del algoritmo.\n* Una clase define muchos comportamientos, y éstos aparecen como múltiples sentencias condicionales en sus operaciones. En lugar de muchas condicionales, mueva las ramas condicionales relacionadas a su propia clase Strategy.\n\n## Tutorial \n\n* [Strategy Pattern Tutorial](https://www.journaldev.com/1754/strategy-design-pattern-in-java-example-tutorial)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/es/subclass-sandbox/README.md",
    "content": "---  \ntitle: Subclass Sandbox \nshortTitle: Subclass Sandbox \ncategory: Behavioral\nlanguage: es\ntag:  \n - Game programming\n---  \n\n## Propósito \nEl patrón Subclass Sandbox describe una idea básica, aunque no tiene una mecánica muy detallada. Necesitarás el patrón cuando tengas varias subclases similares. Si tienes que hacer un pequeño cambio, entonces cambia la clase base, mientras que todas las subclases no deberían tener que ser tocadas. Así que la clase base tiene que ser capaz de proporcionar todas las operaciones que una clase derivada necesita realizar.\n\n## Explicación\nEjemplo del mundo real\n> Consideremos que queremos crear algunos superpoderes en el juego, y necesitan moverse acompañados de un efecto de sonido y desovar partículas. ¿Crear muchas clases que contengan métodos similares o necesitar una clase base para derivarlos? El patrón subclase-base te permite tratar este problema de la segunda manera.\n\nEn palabras sencillas\n> El subclass-sandbox consiste en trasladar los métodos solapados en las subclases a una clase base que reduzca la tasa de redundancia en las clases.\n\nWikipedia dice\n> A base class defines an abstract sandbox method and several provided operations. Marking them protected makes it clear that they are for use by derived classes. Each derived sandboxed subclass implements the sandbox method using the provided operations.\n\n**Ejemplo programático**  \nComenzamos con la clase base `Superpower`. Contiene un método abstracto sandbox `active()` y algunas operaciones proporcionadas.\n\n```\npublic abstract class Superpower {\n\n  protected Logger logger;\n\n  protected abstract void activate();\n\n  protected void move(double x, double y, double z) {\n    logger.info(\"Move to ( \" + x + \", \" + y + \", \" + z + \" )\");\n  }\n\n  protected void playSound(String soundName, int volume) {\n    logger.info(\"Play \" + soundName + \" with volume \" + volume);\n  }\n\n  protected void spawnParticles(String particleType, int count) {\n    logger.info(\"Spawn \" + count + \" particle with type \" + particleType);\n  }\n}\n```\nA continuación podemos crear una subclase derivada sandboxed que implemente el método sandbox usando las operaciones proporcionadas. Aquí está la primera Superpower:\n```\npublic class SkyLaunch extends Superpower {\n\n  public SkyLaunch() {\n    super();\n    logger = LoggerFactory.getLogger(SkyLaunch.class);\n  }\n\n  @Override\n  protected void activate() {\n    move(0, 0, 20);\n    playSound(\"SKYLAUNCH_SOUND\", 1);\n    spawnParticles(\"SKYLAUNCH_PARTICLE\", 100);\n  }\n}\n```\nAquí está la segunda Superpower.\n```\npublic class GroundDive extends Superpower {\n\n  public GroundDive() {\n    super();\n    logger = LoggerFactory.getLogger(GroundDive.class);\n  }\n\n  @Override\n  protected void activate() {\n    move(0, 0, -20);\n    playSound(\"GROUNDDIVE_SOUND\", 5);\n    spawnParticles(\"GROUNDDIVE_PARTICLE\", 20);\n  }\n}\n```\nPor último, aquí están los superpower en activo.\n```\n    LOGGER.info(\"Use superpower: sky launch\");\n    var skyLaunch = new SkyLaunch();\n    skyLaunch.activate();\n    LOGGER.info(\"Use superpower: ground dive\");\n    var groundDive = new GroundDive();\n    groundDive.activate();\n```\nSalida del programa:\n```\n// Use superpower: sky launch\n// Move to ( 0.0, 0.0, 20.0 )\n// Play SKYLAUNCH_SOUND with volume 1\n// Spawn 100 particle with type SKYLAUNCH_PARTICLE\n// Use superpower: ground dive\n// Move to ( 0.0, 0.0, -20.0 )\n// Play GROUNDDIVE_SOUND with volume 5\n// Spawn 20 particle with type GROUNDDIVE_PARTICLE\n```\n## Diagrama de clases\n![alt text](./etc/subclass-sandbox.urm.png \"Subclass Sandbox pattern class diagram\")\n  \n## Aplicabilidad\nEl patrón Subclass Sandbox es un patrón muy simple y común que se encuentra en muchas bases de código, incluso fuera de los juegos. Si tienes un método protegido no virtual por ahí, probablemente ya estés usando algo como esto. Subclass Sandbox es un buen ajuste cuando:\n\n- Usted tiene una clase base con un número de clases derivadas.\n- La clase base es capaz de proporcionar todas las operaciones que una clase derivada puede necesitar realizar.\n- Hay solapamiento de comportamiento en las subclases y desea que sea más fácil compartir código entre ellas.\n- Usted quiere minimizar el acoplamiento entre las clases derivadas y el resto del programa\n  \n## Créditos \n  \n* [Game Programming Patterns - Subclass Sandbox](https://gameprogrammingpatterns.com/subclass-sandbox.html)\n"
  },
  {
    "path": "localization/es/table-module/README.md",
    "content": "---\ntitle: Table Module\nshortTitle: Table Module\ncategory: Structural\nlanguage: es\ntag:\n - Data access\n---\n\n## Propósito\nEl módulo de tablas organiza la lógica del dominio con una clase por tabla de la base de datos, y una única instancia de una clase contiene los distintos procedimientos que actuarán sobre los datos.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Cuando tratamos con un sistema de usuarios, necesitamos algunas operaciones sobre la tabla de usuarios. Podemos utilizar el patrón de módulo de tabla en este escenario. Podemos crear una clase llamada UserTableModule e inicializar una instancia de esa clase para manejar la lógica de negocio para todas las filas de la tabla de usuarios.\n\nEn palabras simples\n\n> Una única instancia que maneja la lógica de negocio para todas las filas de una tabla o vista de la base de datos.\n\n**Ejemplo programático**\n\nEn el ejemplo del sistema de usuarios, necesitamos manejar la lógica de dominio del login y registro de usuarios. Podemos utilizar el patrón de módulo de tabla y crear una instancia de la clase `UserTableModule` para manejar la lógica de negocio de todas las filas de la tabla de usuarios.\n\nAquí está la entidad básica `User`.\n\n```java\n@Setter\n@Getter\n@ToString\n@EqualsAndHashCode\n@AllArgsConstructor\npublic class User {\n  private int id;\n  private String username;\n  private String password;\n}\n```\n\nAquí está la clase `UserTableModule`.\n\n```java\npublic class UserTableModule {\n  private final DataSource dataSource;\n  private Connection connection = null;\n  private ResultSet resultSet = null;\n  private PreparedStatement preparedStatement = null;\n\n  public UserTableModule(final DataSource userDataSource) {\n    this.dataSource = userDataSource;\n  }\n  \n  /**\n   * Login using username and password.\n   *\n   * @param username the username of a user\n   * @param password the password of a user\n   * @return the execution result of the method\n   * @throws SQLException if any error\n   */\n  public int login(final String username, final String password) throws SQLException {\n  \t\t// Method implementation.\n\n  }\n\n  /**\n   * Register a new user.\n   *\n   * @param user a user instance\n   * @return the execution result of the method\n   * @throws SQLException if any error\n   */\n  public int registerUser(final User user) throws SQLException {\n  \t\t// Method implementation.\n  }\n}\n```\n\nEn la clase `App`, usamos una instancia del `UserTableModule` para manejar el login y registro de usuarios.\n\n```java\n// Create data source and create the user table.\nfinal var dataSource = createDataSource();\ncreateSchema(dataSource);\nuserTableModule = new UserTableModule(dataSource);\n\n//Initialize two users.\nvar user1 = new User(1, \"123456\", \"123456\");\nvar user2 = new User(2, \"test\", \"password\");\n\n//Login and register using the instance of userTableModule.\nuserTableModule.registerUser(user1);\nuserTableModule.login(user1.getUsername(), user1.getPassword());\nuserTableModule.login(user2.getUsername(), user2.getPassword());\nuserTableModule.registerUser(user2);\nuserTableModule.login(user2.getUsername(), user2.getPassword());\n\ndeleteSchema(dataSource);\n```\n\nLa salida del programa:\n\n```java\n12:22:13.095 [main] INFO com.iluwatar.tablemodule.UserTableModule - Register successfully!\n12:22:13.117 [main] INFO com.iluwatar.tablemodule.UserTableModule - Login successfully!\n12:22:13.128 [main] INFO com.iluwatar.tablemodule.UserTableModule - Fail to login!\n12:22:13.136 [main] INFO com.iluwatar.tablemodule.UserTableModule - Register successfully!\n12:22:13.144 [main] INFO com.iluwatar.tablemodule.UserTableModule - Login successfully!\n```\n\n## Diagrama de clases\n\n![](./etc/table-module.urm.png \"table module\")\n\n## Aplicabilidad\n\nUtilice el patrón de módulo de tabla cuando\n\n- La lógica del dominio es simple y los datos están en forma tabular.\n- La aplicación sólo utiliza unas pocas estructuras de datos comunes compartidas orientadas a tablas.\n\n## Patrones relacionados\n\n- [Transaction Script](https://java-design-patterns.com/patterns/transaction-script/)\n\n- [Domain Model](https://java-design-patterns.com/patterns/domain-model/)\n\n## Créditos\n\n* [Table Module Pattern](http://wiki3.cosc.canterbury.ac.nz/index.php/Table_module_pattern)\n* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0321127420&linkId=18acc13ba60d66690009505577c45c04)\n* [Architecture patterns: domain model and friends](https://inviqa.com/blog/architecture-patterns-domain-model-and-friends)"
  },
  {
    "path": "localization/es/template-method/README.md",
    "content": "---\ntitle: Template method\nshortTitle: Template method\ncategory: Behavioral\nlanguage: es\ntag:\n - Gang of Four\n---\n\n## Propósito\n\nDefine el esqueleto de un algoritmo en una operación, difiriendo algunos pasos a subclases. Plantilla\nMétodo que permite a las subclases redefinir ciertos pasos de un algoritmo sin cambiar la estructura del algoritmo.\ndel algoritmo.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Los pasos generales para robar un objeto son los mismos. Primero, eliges al objetivo, luego lo confundes...\n> y finalmente, robas el objeto. Sin embargo, hay muchas maneras de implementar estos\n> pasos.\n\nEn palabras sencillas\n\n> El patrón Template Method esboza los pasos generales en la clase padre y deja que las implementaciones hijas concretas definan los detalles.\n\nWikipedia dice\n\n> En programación orientada a objetos, el método de plantillas es uno de los patrones de diseño de comportamiento\n> identificados por Gamma et al. en el libro Design Patterns. El método de plantilla es un método en una\n> superclase, normalmente una superclase abstracta, y define el esqueleto de una operación en términos de\n> una serie de pasos de alto nivel. Estos pasos son a su vez implementados por métodos de ayuda adicionales\n> en la misma clase que el método de plantilla.\n\n**Ejemplo programático**\n\nPresentemos primero la clase de método de plantilla junto con sus implementaciones concretas.\nPara asegurarse de que las subclases no sobrescriben el método de plantilla, el método de plantilla (en nuestro caso\nmétodo `steal`) debe ser declarado `final`, de lo contrario el esqueleto definido en la clase base podría\nser sobreescrito en subclases.\n\n```java\n@Slf4j\npublic abstract class StealingMethod {\n\n  protected abstract String pickTarget();\n\n  protected abstract void confuseTarget(String target);\n\n  protected abstract void stealTheItem(String target);\n\n  public final void steal() {\n    var target = pickTarget();\n    LOGGER.info(\"The target has been chosen as {}.\", target);\n    confuseTarget(target);\n    stealTheItem(target);\n  }\n}\n\n@Slf4j\npublic class SubtleMethod extends StealingMethod {\n\n  @Override\n  protected String pickTarget() {\n    return \"shop keeper\";\n  }\n\n  @Override\n  protected void confuseTarget(String target) {\n    LOGGER.info(\"Approach the {} with tears running and hug him!\", target);\n  }\n\n  @Override\n  protected void stealTheItem(String target) {\n    LOGGER.info(\"While in close contact grab the {}'s wallet.\", target);\n  }\n}\n\n@Slf4j\npublic class HitAndRunMethod extends StealingMethod {\n\n  @Override\n  protected String pickTarget() {\n    return \"old goblin woman\";\n  }\n\n  @Override\n  protected void confuseTarget(String target) {\n    LOGGER.info(\"Approach the {} from behind.\", target);\n  }\n\n  @Override\n  protected void stealTheItem(String target) {\n    LOGGER.info(\"Grab the handbag and run away fast!\");\n  }\n}\n```\n\nAquí está la clase ladrón halfling que contiene el método de plantilla.\n\n```java\npublic class HalflingThief {\n\n  private StealingMethod method;\n\n  public HalflingThief(StealingMethod method) {\n    this.method = method;\n  }\n\n  public void steal() {\n    method.steal();\n  }\n\n  public void changeMethod(StealingMethod method) {\n    this.method = method;\n  }\n}\n```\n\nY por último, mostramos cómo el ladrón halfling utiliza los diferentes métodos de robo.\n\n```java\n    var thief = new HalflingThief(new HitAndRunMethod());\n    thief.steal();\n    thief.changeMethod(new SubtleMethod());\n    thief.steal();\n```\n\n## Diagrama de clases\n\n![alt text](./etc/template_method_urm.png \"Template Method\")\n\n## Aplicabilidad\n\nEl patrón Template Method debería utilizarse\n\n* Para implementar las partes invariantes de un algoritmo una vez y dejar que las subclases implementen el comportamiento que puede variar.\n* Cuando el comportamiento común entre subclases debe ser factorizado y localizado en una clase común para evitar la duplicación de código. Este es un buen ejemplo de \"refactorizar para generalizar\", tal y como lo describen Opdyke y Johnson. Primero se identifican las diferencias en el código existente y luego se separan las diferencias en nuevas operaciones. Por último, se sustituye el código diferente por un método de plantilla que llama a una de estas nuevas operaciones\n* Para controlar las extensiones de las subclases. Puede definir un método de plantilla que llame a operaciones \"gancho\" en puntos específicos, permitiendo así extensiones sólo en esos puntos\n\n## Tutoriales\n\n* [Template-method Pattern Tutorial](https://www.journaldev.com/1763/template-method-design-pattern-in-java)\n\n## Usos conocidos\n\n* [javax.servlet.GenericServlet.init](https://jakarta.ee/specifications/servlet/4.0/apidocs/javax/servlet/GenericServlet.html#init--):\nEl método `GenericServlet.init(ServletConfig config)` llama al método sin parámetros `GenericServlet.init()` que está pensado para ser sobreescrito en subclases.\nEl método `GenericServlet.init(ServletConfig config)` es el método plantilla en este ejemplo.\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/es/throttling/README.md",
    "content": "---\ntitle: Throttling\nshortTitle: Throttling\ncategory: Behavioral\nlanguage: es\ntag:\n - Performance\n - Cloud distributed\n---\n\n## Propósito\n\nGarantizar que un cliente determinado no pueda acceder a los recursos del servicio más allá del límite asignado.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Un joven humano y un viejo enano entran en un bar. Empiezan a pedir cervezas al camarero.\n> El camarero se da cuenta inmediatamente de que el joven humano no debe consumir demasiadas bebidas demasiado rápido\n> y se niega a servir si no ha pasado suficiente tiempo. Para el viejo enano, el ritmo de servicio puede ser mayor.\n> ser mayor.\n\nEn palabras sencillas\n\n> El patrón de Throttling se utiliza para limitar la velocidad de acceso a un recurso.\n\n[Microsoft documentation](https://docs.microsoft.com/en-us/azure/architecture/patterns/throttling) dice\n\n> Controlar el consumo de recursos utilizados por una instancia de una aplicación, un tenant individual,\n> o un servicio completo. Esto puede permitir que el sistema continúe funcionando y cumpla con los acuerdos de nivel de servicio, incluso cuando un aumento de la demanda impone una carga extrema sobre los recursos.\n\n**Ejemplo programático**\n\nLa clase `BarCustomer` presenta los clientes de la API `Bartender`. La clase `CallsCount` registra el número de\nllamadas por `BarCustomer`.\n\n```java\npublic class BarCustomer {\n\n    @Getter\n    private final String name;\n    @Getter\n    private final int allowedCallsPerSecond;\n\n    public BarCustomer(String name, int allowedCallsPerSecond, CallsCount callsCount) {\n        if (allowedCallsPerSecond < 0) {\n            throw new InvalidParameterException(\"Number of calls less than 0 not allowed\");\n        }\n        this.name = name;\n        this.allowedCallsPerSecond = allowedCallsPerSecond;\n        callsCount.addTenant(name);\n    }\n}\n\n@Slf4j\npublic final class CallsCount {\n  private final Map<String, AtomicLong> tenantCallsCount = new ConcurrentHashMap<>();\n\n  public void addTenant(String tenantName) {\n    tenantCallsCount.putIfAbsent(tenantName, new AtomicLong(0));\n  }\n\n  public void incrementCount(String tenantName) {\n    tenantCallsCount.get(tenantName).incrementAndGet();\n  }\n\n  public long getCount(String tenantName) {\n    return tenantCallsCount.get(tenantName).get();\n  }\n\n  public void reset() {\n    tenantCallsCount.replaceAll((k, v) -> new AtomicLong(0));\n    LOGGER.info(\"reset counters\");\n  }\n}\n```\n\nA continuación, se introduce el servicio al que llaman los inquilinos. Para realizar un seguimiento del número de llamadas, se utiliza un temporizador de estrangulamiento.\n\n```java\npublic interface Throttler {\n\n  void start();\n}\n\npublic class ThrottleTimerImpl implements Throttler {\n\n  private final int throttlePeriod;\n  private final CallsCount callsCount;\n\n  public ThrottleTimerImpl(int throttlePeriod, CallsCount callsCount) {\n    this.throttlePeriod = throttlePeriod;\n    this.callsCount = callsCount;\n  }\n\n  @Override\n  public void start() {\n    new Timer(true).schedule(new TimerTask() {\n      @Override\n      public void run() {\n        callsCount.reset();\n      }\n    }, 0, throttlePeriod);\n  }\n}\n```\n\nEl `Bartender` ofrece el servicio `orderDrink` a los `BarCustomer`s. Los clientes probablemente no\nsaben que la tasa de servicio de cerveza está limitada por su apariencia.\n\n```java\nclass Bartender {\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(Bartender.class);\n    private final CallsCount callsCount;\n\n    public Bartender(Throttler timer, CallsCount callsCount) {\n        this.callsCount = callsCount;\n        timer.start();\n    }\n\n    public int orderDrink(BarCustomer barCustomer) {\n        var tenantName = barCustomer.getName();\n        var count = callsCount.getCount(tenantName);\n        if (count >= barCustomer.getAllowedCallsPerSecond()) {\n            LOGGER.error(\"I'm sorry {}, you've had enough for today!\", tenantName);\n            return -1;\n        }\n        callsCount.incrementCount(tenantName);\n        LOGGER.debug(\"Serving beer to {} : [{} consumed] \", barCustomer.getName(), count+1);\n        return getRandomCustomerId();\n    }\n\n    private int getRandomCustomerId() {\n        return ThreadLocalRandom.current().nextInt(1, 10000);\n    }\n}\n```\n\nAhora es posible ver el ejemplo completo en acción. BarCustomer` el joven humano está limitado a 2\nllamadas por segundo y el viejo enano a 4.\n\n```java\npublic static void main(String[] args) {\n    var callsCount = new CallsCount();\n    var human = new BarCustomer(\"young human\", 2, callsCount);\n    var dwarf = new BarCustomer(\"dwarf soldier\", 4, callsCount);\n\n    var executorService = Executors.newFixedThreadPool(2);\n\n    executorService.execute(() -> makeServiceCalls(human, callsCount));\n    executorService.execute(() -> makeServiceCalls(dwarf, callsCount));\n\n    executorService.shutdown();\n    try {\n        executorService.awaitTermination(10, TimeUnit.SECONDS);\n    } catch (InterruptedException e) {\n        LOGGER.error(\"Executor service terminated: {}\", e.getMessage());\n    }\n}\n\nprivate static void makeServiceCalls(BarCustomer barCustomer, CallsCount callsCount) {\n    var timer = new ThrottleTimerImpl(1000, callsCount);\n    var service = new Bartender(timer, callsCount);\n    // Sleep is introduced to keep the output in check and easy to view and analyze the results.\n    IntStream.range(0, 50).forEach(i -> {\n        service.orderDrink(barCustomer);\n        try {\n            Thread.sleep(100);\n        } catch (InterruptedException e) {\n            LOGGER.error(\"Thread interrupted: {}\", e.getMessage());\n        }\n    });\n}\n```\n\nUn extracto de la salida de consola del ejemplo:\n\n```\n18:46:36.218 [Timer-0] INFO com.iluwatar.throttling.CallsCount - reset counters\n18:46:36.218 [Timer-1] INFO com.iluwatar.throttling.CallsCount - reset counters\n18:46:36.242 [pool-1-thread-2] DEBUG com.iluwatar.throttling.Bartender - Serving beer to dwarf soldier : [1 consumed] \n18:46:36.242 [pool-1-thread-1] DEBUG com.iluwatar.throttling.Bartender - Serving beer to young human : [1 consumed] \n18:46:36.342 [pool-1-thread-2] DEBUG com.iluwatar.throttling.Bartender - Serving beer to dwarf soldier : [2 consumed] \n18:46:36.342 [pool-1-thread-1] DEBUG com.iluwatar.throttling.Bartender - Serving beer to young human : [2 consumed] \n18:46:36.443 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:36.443 [pool-1-thread-2] DEBUG com.iluwatar.throttling.Bartender - Serving beer to dwarf soldier : [3 consumed] \n18:46:36.544 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:36.544 [pool-1-thread-2] DEBUG com.iluwatar.throttling.Bartender - Serving beer to dwarf soldier : [4 consumed] \n18:46:36.645 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!\n18:46:36.645 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:36.745 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:36.745 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!\n18:46:36.846 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:36.846 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!\n18:46:36.947 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!\n18:46:36.947 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:37.048 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!\n18:46:37.048 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:37.148 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:37.148 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!\n```\n\n## Diagrama de clases\n\n![alt text](./etc/throttling_urm.png \"Throttling pattern class diagram\")\n\n## Aplicabilidad\n\nEl patrón Throttling debe utilizarse:\n\n* Cuando se necesita restringir el acceso al servicio para no tener un alto impacto en el rendimiento del mismo.\n* Cuando varios clientes consumen los mismos recursos del servicio y la restricción debe hacerse en función del uso por cliente.\n\n## Créditos\n\n* [Throttling pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/throttling)\n* [Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications (Microsoft patterns & practices)](https://www.amazon.com/gp/product/B00ITGHBBS/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=B00ITGHBBS&linkId=12aacdd0cec04f372e7152689525631a)\n"
  },
  {
    "path": "localization/es/trampoline/README.md",
    "content": "---\ntitle: Trampoline\nshortTitle: Trampoline\ncategory: Behavioral\nlanguage: es\ntag:\n - Performance\n---\n\n## Propósito\n\nEl patrón Trampoline se utiliza para implementar algoritmos recursivamente en Java sin volar la pila\ny para intercalar la ejecución de funciones sin codificarlas juntas.\n\n## Explicación\n\nLa recursión es una técnica frecuentemente adoptada para resolver problemas algorítmicos en un estilo de divide y vencerás.\nPor ejemplo, el cálculo de la suma acumulativa de Fibonacci y los factoriales. En este tipo de\nproblemas, la recursividad es más directa que su homóloga de bucle. Además, la recursividad puede\nnecesitar menos código y parecer más concisa. Hay un dicho que dice que todo problema de recursión puede resolverse\nutilizando un bucle a costa de escribir código más difícil de entender.\n\nSin embargo, las soluciones de tipo recursivo tienen una gran advertencia. Para cada llamada recursiva, normalmente se necesita\nun valor intermedio almacenado y hay una cantidad limitada de memoria de pila disponible. Quedarse sin\nmemoria de pila crea un error de desbordamiento de pila y detiene la ejecución del programa.\n\nTrampoline pattern es un truco que permite definir algoritmos recursivos en Java sin desbordar la\npila.\n\nEjemplo del mundo real\n\n> Un cálculo Fibonacci recursivo sin el problema de desbordamiento de pila utilizando el patrón Trampoline.       \n\nEn palabras sencillas\n\n> El patrón Trampoline permite la recursión sin agotar la memoria de la pila.\n\nWikipedia dice\n\n> En Java, trampoline se refiere al uso de reflection para evitar el uso de clases internas, por ejemplo en\n> eventos. La sobrecarga de tiempo de una llamada a reflection se intercambia por la sobrecarga de espacio de una clase interna.\n> Trampolines en Java generalmente implican la creación de un GenericListener para pasar eventos a una clase externa.\n\n**Ejemplo programático**\n\nEsta es la implementación de `Trampoline` en Java.\n\nCuando se llama a `get` sobre el Trampoline devuelto, internamente se itera llamando a `jump` sobre el\nsiempre que la instancia concreta devuelta sea `Trampoline`, deteniéndose una vez que la instancia\ninstancia devuelta sea `done`.\n\n```java\npublic interface Trampoline<T> {\n\n  T get();\n\n  default Trampoline<T> jump() {\n    return this;\n  }\n\n  default T result() {\n    return get();\n  }\n\n  default boolean complete() {\n    return true;\n  }\n\n  static <T> Trampoline<T> done(final T result) {\n    return () -> result;\n  }\n\n  static <T> Trampoline<T> more(final Trampoline<Trampoline<T>> trampoline) {\n    return new Trampoline<T>() {\n      @Override\n      public boolean complete() {\n        return false;\n      }\n\n      @Override\n      public Trampoline<T> jump() {\n        return trampoline.result();\n      }\n\n      @Override\n      public T get() {\n        return trampoline(this);\n      }\n\n      T trampoline(final Trampoline<T> trampoline) {\n        return Stream.iterate(trampoline, Trampoline::jump)\n            .filter(Trampoline::complete)\n            .findFirst()\n            .map(Trampoline::result)\n            .orElseThrow();\n      }\n    };\n  }\n}\n```\n\nUso del `Trampoline` para obtener valores Fibonacci.\n\n```java\npublic static void main(String[] args) {\n    LOGGER.info(\"Start calculating war casualties\");\n    var result = loop(10, 1).result();\n    LOGGER.info(\"The number of orcs perished in the war: {}\", result);\n}\n\npublic static Trampoline<Integer> loop(int times, int prod) {\n    if (times == 0) {\n        return Trampoline.done(prod);\n    } else {\n        return Trampoline.more(() -> loop(times - 1, prod * times));\n    }\n}\n```\n\nSalida del programa:\n\n```\n19:22:24.462 [main] INFO com.iluwatar.trampoline.TrampolineApp - Start calculating war casualties\n19:22:24.472 [main] INFO com.iluwatar.trampoline.TrampolineApp - The number of orcs perished in the war: 3628800\n```\n\n## Diagrama de clases\n\n![alt text](./etc/trampoline.urm.png \"Trampoline pattern class diagram\")\n\n## Aplicabilidad\n\nUtilice el patrón Trampoline cuando:\n\n* Para implementar funciones recursivas de cola. Este patrón permite encender una operación sin pila.\n* Para intercalar la ejecución de dos o más funciones en el mismo hilo.\n\n## Usos conocidos\n\n* [cyclops-react](https://github.com/aol/cyclops-react)\n\n## Créditos\n\n* [Trampolining: a practical guide for awesome Java Developers](https://medium.com/@johnmcclean/trampolining-a-practical-guide-for-awesome-java-developers-4b657d9c3076)\n* [Trampoline in java ](http://mindprod.com/jgloss/trampoline.html)\n* [Laziness, trampolines, monoids and other functional amenities: this is not your father's Java](https://www.slideshare.net/mariofusco/lazine)\n* [Trampoline implementation](https://github.com/bodar/totallylazy/blob/master/src/com/googlecode/totallylazy/Trampoline.java)\n* [What is a trampoline function?](https://stackoverflow.com/questions/189725/what-is-a-trampoline-function)\n* [Modern Java in Action: Lambdas, streams, functional and reactive programming](https://www.amazon.com/gp/product/1617293563/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617293563&linkId=ad53ae6f9f7c0982e759c3527bd2595c)\n* [Java 8 in Action: Lambdas, Streams, and functional-style programming](https://www.amazon.com/gp/product/1617291994/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617291994&linkId=e3e5665b0732c59c9d884896ffe54f4f)\n"
  },
  {
    "path": "localization/es/transaction-script/README.md",
    "content": "---\ntitle: Transaction Script\nshortTitle: Transaction Script\ncategory: Behavioral\nlanguage: es\ntag:\n - Data access\n---\n\n## Propósito\n\nTransaction Script organiza la lógica de negocio por procedimientos donde cada procedimiento maneja una única\nsolicitud de la presentación.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Necesitas crear un sistema de reservas de habitaciones de hotel. Dado que los requisitos son bastante simples\n> utilizar el patrón Transaction Script.\n\nEn palabras sencillas\n\n> Transaction Script organiza la lógica de negocio en transacciones que el sistema necesita llevar a cabo.\n\nEjemplo programático\n\nLa clase `Hotel` se encarga de reservar y cancelar las reservas de habitaciones.\n\n```java\n@Slf4j\npublic class Hotel {\n\n  private final HotelDaoImpl hotelDao;\n\n  public Hotel(HotelDaoImpl hotelDao) {\n    this.hotelDao = hotelDao;\n  }\n\n  public void bookRoom(int roomNumber) throws Exception {\n\n    Optional<Room> room = hotelDao.getById(roomNumber);\n\n    if (room.isEmpty()) {\n      throw new Exception(\"Room number: \" + roomNumber + \" does not exist\");\n    } else {\n      if (room.get().isBooked()) {\n        throw new Exception(\"Room already booked!\");\n      } else {\n        Room updateRoomBooking = room.get();\n        updateRoomBooking.setBooked(true);\n        hotelDao.update(updateRoomBooking);\n      }\n    }\n  }\n\n  public void cancelRoomBooking(int roomNumber) throws Exception {\n\n    Optional<Room> room = hotelDao.getById(roomNumber);\n\n    if (room.isEmpty()) {\n      throw new Exception(\"Room number: \" + roomNumber + \" does not exist\");\n    } else {\n      if (room.get().isBooked()) {\n        Room updateRoomBooking = room.get();\n        updateRoomBooking.setBooked(false);\n        int refundAmount = updateRoomBooking.getPrice();\n        hotelDao.update(updateRoomBooking);\n\n        LOGGER.info(\"Booking cancelled for room number: \" + roomNumber);\n        LOGGER.info(refundAmount + \" is refunded\");\n      } else {\n        throw new Exception(\"No booking for the room exists\");\n      }\n    }\n  }\n}\n```\n\nLa clase `Hotel` tiene dos métodos, uno para reservar y otro para cancelar una habitación respectivamente. Cada uno de ellos\ntransacción en el sistema, haciendo que `Hotel` implemente el patrón Transaction Script\nTransaction Script.\n\nEl método `bookRoom` consolida todos los pasos necesarios como comprobar si la habitación ya está reservada\no no, si no está reservada entonces reserva la habitación y actualiza la base de datos utilizando el DAO.\n\nEl método `cancelRoom` consolida pasos como comprobar si la habitación está reservada o no,\nsi está reservada, calcula el importe del reembolso y actualiza la base de datos utilizando el DAO.\n\n## Diagrama de clases\n\n![alt text](./etc/transaction-script.png \"Transaction script model\")\n\n## Aplicabilidad\n\nUtilice el patrón Transaction Script cuando la aplicación tenga sólo una pequeña cantidad de lógica y esa\nlógica no será extendida en el futuro.\n\n## Consecuencias\n\n* A medida que la lógica de negocio se complica,\n  se hace progresivamente más difícil mantener el script de transacción\n  en un estado bien diseñado.\n* Puede ocurrir duplicación de código entre scripts de transacciones.\n* Normalmente no es fácil refactorizar el script de transacciones a otros patrones de lógica de dominio.\n  del dominio.\n\n## Patrones relacionados\n\n* Domain Model\n* Table Module\n* Service Layer\n\n## Créditos\n\n* [Transaction Script Pattern](https://dzone.com/articles/transaction-script-pattern#:~:text=Transaction%20Script%20(TS)%20is%20the,need%20big%20architecture%20behind%20them.)\n* [Transaction Script](https://www.informit.com/articles/article.aspx?p=1398617)\n* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0321127420&linkId=18acc13ba60d66690009505577c45c04)\n"
  },
  {
    "path": "localization/es/twin/README.md",
    "content": "---\ntitle: Twin\nshortTitle: Twin\ncategory: Structural\nlanguage: es\ntag:\n - Extensibility\n---\n\n## Propósito\nTwin pattern es un patrón de diseño que proporciona una solución estándar para simular herencia múltiple en java\n\n## Explicación\n\nEjemplo real\n\n> Consideremos un juego con una pelota que necesita características de dos tipos, Game Item, e hilos para funcionar sin problemas en el juego. Podemos utilizar dos objetos, con un objeto compatible con el primer tipo y el otro compatible con el segundo tipo. El par de objetos juntos pueden funcionar como una pelota en el juego.\n\nEn palabras sencillas\n\n> Proporciona una forma de formar dos subclases estrechamente acopladas que pueden actuar como una clase gemela que tiene dos extremos.\n\nWikipedia dice\n\n> En ingeniería de software, el patrón Gemelo es un patrón de diseño de software que permite a los desarrolladores modelar herencia múltiple en lenguajes de programación que no soportan herencia múltiple. Este patrón evita muchos de los problemas de la herencia múltiple.\n\n**Ejemplo programático**\n\nTomemos nuestro ejemplo anterior de la bola de juego. Consideremos que tenemos un juego en el que la pelota necesita ser tanto un `GameItem` como un `Thread`.\nEn primer lugar, tenemos la clase `GameItem` dada a continuación y la clase `Thread`.\n\n\n```java\n\n@Slf4j\npublic abstract class GameItem {\n\n  public void draw() {\n    LOGGER.info(\"draw\");\n    doDraw();\n  }\n\n  public abstract void doDraw();\n\n\n  public abstract void click();\n}\n\n```\n\nA continuación, tenemos las subclases `BallItem` y `BallThread` que las heredan, respectivamente.\n\n```java\n\n@Slf4j\npublic class BallItem extends GameItem {\n\n  private boolean isSuspended;\n\n  @Setter\n  private BallThread twin;\n\n  @Override\n  public void doDraw() {\n\n    LOGGER.info(\"doDraw\");\n  }\n\n  public void move() {\n    LOGGER.info(\"move\");\n  }\n\n  @Override\n  public void click() {\n\n    isSuspended = !isSuspended;\n\n    if (isSuspended) {\n      twin.suspendMe();\n    } else {\n      twin.resumeMe();\n    }\n  }\n}\n\n\n@Slf4j\npublic class BallThread extends Thread {\n\n  @Setter\n  private BallItem twin;\n\n  private volatile boolean isSuspended;\n\n  private volatile boolean isRunning = true;\n\n  /**\n   * Run the thread.\n   */\n  public void run() {\n\n    while (isRunning) {\n      if (!isSuspended) {\n        twin.draw();\n        twin.move();\n      }\n      try {\n        Thread.sleep(250);\n      } catch (InterruptedException e) {\n        throw new RuntimeException(e);\n      }\n    }\n  }\n\n  public void suspendMe() {\n    isSuspended = true;\n    LOGGER.info(\"Begin to suspend BallThread\");\n  }\n\n  public void resumeMe() {\n    isSuspended = false;\n    LOGGER.info(\"Begin to resume BallThread\");\n  }\n\n  public void stopMe() {\n    this.isRunning = false;\n    this.isSuspended = true;\n  }\n}\n\n``` \n\nAhora, cuando necesitemos la pelota, podemos instanciar objetos tanto del `BallThread` como del `BallItem` como un par y pasarlos a su objeto par para que puedan actuar juntos según convenga.\n\n```java\n\nvar ballItem = new BallItem();\nvar ballThread = new BallThread();\n\nballItem.setTwin(ballThread);\nballThread.setTwin(ballItem);\n\n```\n\n\n## Diagrama de clases\n![alt text](./etc/twin.png \"Twin\")\n\n## Aplicabilidad\nUtilice el lenguaje Twin\n\n* Para simular herencia múltiple en un lenguaje que no soporta esta característica.\n* Para evitar ciertos problemas de la herencia múltiple como los choques de nombres.\n\n## Créditos\n\n* [Twin – A Design Pattern for Modeling Multiple Inheritance](http://www.ssw.uni-linz.ac.at/Research/Papers/Moe99/Paper.pdf)\n"
  },
  {
    "path": "localization/es/typeobjectpattern/README.md",
    "content": "---\ntitle: Type-Object\nshortTitle: Type-Object\ncategory: Behavioral\nlanguage: es\ntag:\n - Game programming\n - Extensibility\n---\n\n## Propósito\nComo se explica en el libro Game Programming Patterns de Robert Nystrom, el patrón objeto tipo ayuda a\n\n> Permitir la creación flexible de nuevas \"clases\" mediante la creación de una única clase, cada instancia de la cual representa un tipo diferente de objeto\n\n## Explicación\nEjemplo del mundo real\n> Estás trabajando en un juego con muchas razas diferentes de monstruos. Cada raza de monstruo tiene diferentes valores para los atributos, como ataque, salud, inteligencia, etc. Quieres crear nuevas razas de monstruos, o modificar los atributos de una raza existente, sin necesidad de modificar el código y recompilar el juego.\n\nEn palabras sencillas\n> Definimos una clase de objeto de tipo y una clase de objeto tipado. Damos a cada instancia de objeto de tipo una referencia a un objeto tipado, que contiene la información para ese tipo.\n\n**Ejemplo programático**\n\nSupongamos que estamos desarrollando un juego de Candy Crush. Hay muchos tipos de caramelos diferentes, y es posible que queramos editar o crear nuevos con el tiempo a medida que desarrollamos el juego.\n\nEn primer lugar, tenemos un tipo para los caramelos, con un nombre de campo, padre, puntos y Tipo.\n\n```java\n@Getter(AccessLevel.PACKAGE)\npublic class Candy {\n\n  enum Type {\n    CRUSHABLE_CANDY,\n    REWARD_FRUIT\n  }\n\n  String name;\n  Candy parent;\n  String parentName;\n\n  @Setter\n  private int points;\n  private final Type type;\n\n  Candy(String name, String parentName, Type type, int points) {\n    this.name = name;\n    this.parent = null;\n    this.type = type;\n    this.points = points;\n    this.parentName = parentName;\n  }\n\n}\n```\n\nLos datos de campo de los tipos de caramelos se almacenan en el archivo JSON ``candy.json``. Se pueden añadir nuevos caramelos simplemente añadiéndolos a este archivo.\n\n```json\n{\"candies\" : [\n  {\n    \"name\" : \"fruit\",\n    \"parent\" : \"null\",\n    \"type\" : \"rewardFruit\",\n    \"points\" : 20\n  },\n  {\n    \"name\" : \"candy\",\n    \"parent\" : \"null\",\n    \"type\" : \"crushableCandy\",\n    \"points\" : 10\n  },\n  {\n    \"name\" : \"cherry\",\n    \"parent\" : \"fruit\",\n    \"type\" : \"rewardFruit\",\n    \"points\" : 0\n  },\n  {\n    \"name\" : \"mango\",\n    \"parent\" : \"fruit\",\n    \"type\" : \"rewardFruit\",\n    \"points\" : 0\n  },\n  {\n    \"name\" : \"purple popsicle\",\n    \"parent\" : \"candy\",\n    \"type\" : \"crushableCandy\",\n    \"points\" : 0\n  },\n  {\n    \"name\" : \"green jellybean\",\n    \"parent\" : \"candy\",\n    \"type\" : \"crushableCandy\",\n    \"points\" : 0\n  },\n  {\n    \"name\" : \"orange gum\",\n    \"parent\" : \"candy\",\n    \"type\" : \"crushableCandy\",\n    \"points\" : 0\n  }\n  ]\n}\n```\n\nEl archivo JSON se analiza, instanciando cada tipo de caramelo y almacenándolo en una tabla hash. El campo ``type`` se compara con el enum ``Type`` definido en la clase Candy.\n\n```java\npublic class JsonParser {\n  Hashtable<String, Candy> candies;\n\n  JsonParser() {\n    this.candies = new Hashtable<>();\n  }\n\n  void parse() throws JsonParseException {\n    var is = this.getClass().getClassLoader().getResourceAsStream(\"candy.json\");\n    var reader = new InputStreamReader(is);\n    var json = (JsonObject) com.google.gson.JsonParser.parseReader(reader);\n    var array = (JsonArray) json.get(\"candies\");\n    for (var item : array) {\n      var candy = (JsonObject) item;\n      var name = candy.get(\"name\").getAsString();\n      var parentName = candy.get(\"parent\").getAsString();\n      var t = candy.get(\"type\").getAsString();\n      var type = Type.CRUSHABLE_CANDY;\n      if (t.equals(\"rewardFruit\")) {\n        type = Type.REWARD_FRUIT;\n      }\n      var points = candy.get(\"points\").getAsInt();\n      var c = new Candy(name, parentName, type, points);\n      this.candies.put(name, c);\n    }\n    setParentAndPoints();\n  }\n\n  void setParentAndPoints() {\n    for (var e = this.candies.keys(); e.hasMoreElements(); ) {\n      var c = this.candies.get(e.nextElement());\n      if (c.parentName == null) {\n        c.parent = null;\n      } else {\n        c.parent = this.candies.get(c.parentName);\n      }\n      if (c.getPoints() == 0 && c.parent != null) {\n        c.setPoints(c.parent.getPoints());\n      }\n    }\n  }\n}\n```\n\n## En palabras sencillas\n\nEl patrón Tipo-Objeto en Java es un método para encapsular propiedades y comportamientos específicos de un tipo dentro de un objeto. Este patrón de diseño facilita la adición de nuevos tipos sin necesidad de realizar cambios en el código existente, mejorando así la expansión y el mantenimiento de la base de código.\n\n## Wikipedia dice\n\nAunque no existe una entrada específica en Wikipedia para el patrón Tipo-Objeto, se trata de una técnica de uso común en la programación orientada a objetos. Este patrón ayuda a gestionar objetos que comparten características similares pero tienen valores diferentes para esas características. Su uso está muy extendido en el desarrollo de juegos, donde numerosos tipos de objetos (como los enemigos) comparten un comportamiento común pero tienen propiedades diferentes.\n\n## Ejemplo programático\n\nConsideremos un ejemplo en el que intervienen distintos tipos de enemigos en un juego. Cada tipo de enemigo tiene propiedades distintas, como velocidad, salud y daño.\n\n```java\npublic class EnemyType {\n    private String name;\n    private int speed;\n    private int health;\n    private int damage;\n    \n    public EnemyType(String name, int speed, int health, int damage) {\n        this.name = name;\n        this.speed = speed;\n        this.health = health;\n        this.damage = damage;\n    }\n\n    // getters and setters\n}\n\npublic class Enemy {\n    private EnemyType type;\n\n    // Encapsulating type information in an object\n    public Enemy(EnemyType type) {\n        this.type = type;\n    }\n\n    // other methods\n}\n```\n\nEn el ejemplo anterior, `EnemyType` encapsula propiedades específicas del tipo (nombre, velocidad, salud, daño), y `Enemy` utiliza una instancia de `EnemyType` para definir su tipo. De esta forma, puedes añadir tantos tipos de enemigos como quieras sin modificar la clase \"Enemigo\".\n\n## Aplicabilidad\nEste patrón puede utilizarse cuando:\n\n* No sabemos de antemano qué tipos vamos a necesitar.\n* Queremos ser capaces de modificar o añadir nuevos tipos sin tener que recompilar o cambiar el código.\n* La única diferencia entre los diferentes \"tipos\" de objetos son los datos, no el comportamiento.\n\n## Otro ejemplo con diagrama de clases\n![alt text](./etc/typeobjectpattern.urm.png \"Type-Object pattern class diagram\")\n\n## Créditos\n\n* [Game Programming Patterns - Type Object](http://gameprogrammingpatterns.com/type-object.html)\n* [Types as Objects Pattern](http://www.cs.sjsu.edu/~pearce/modules/patterns/analysis/top.htm)\n"
  },
  {
    "path": "localization/es/update-method/README.md",
    "content": "---  \ntitle: Update Method\nshortTitle: Update Method\ncategory: Behavioral\nlanguage: es\ntag:  \n - Game programming\n---  \n  \n## Propósito\nEl patrón de método de actualización simula una colección de objetos independientes indicando a cada uno que procese un fotograma de comportamiento a la vez.\n\n## Explicación\nEl mundo del juego mantiene una colección de objetos. Cada objeto implementa un método de actualización que simula un fotograma del comportamiento del objeto. En cada fotograma, el juego actualiza cada objeto de la colección.\n\nPara obtener más información sobre cómo se ejecuta el bucle de juego y cuándo se invocan los métodos de actualización, consulte Patrón de bucle de juego.\n\n## Diagrama de clases\n![alt text](./etc/update-method.urm.png \"Update Method pattern class diagram\")\n\n## Aplicabilidad\nSi el patrón Game Loop es lo mejor desde el pan rebanado, entonces el patrón Update Method es su mantequilla. Una amplia gama de juegos con entidades vivas con las que el jugador interactúa utilizan este patrón de una forma u otra. Si el juego tiene marines espaciales, dragones, marcianos, fantasmas o atletas, es muy probable que utilice este patrón.\n\nSin embargo, si el juego es más abstracto y las piezas móviles se parecen menos a actores vivos y más a piezas de un tablero de ajedrez, este patrón no suele encajar. En un juego como el ajedrez, no necesitas simular todas las piezas concurrentemente, y probablemente no necesites decirle a los peones que se actualicen a sí mismos en cada frame.\n\nLos métodos de actualización funcionan bien cuando:\n\n- Su juego tiene un número de objetos o sistemas que necesitan ejecutarse simultáneamente.\n- El comportamiento de cada objeto es independiente de los demás.\n- Los objetos necesitan ser simulados en el tiempo.\n\n## Créditos \n  \n* [Game Programming Patterns - Update Method](http://gameprogrammingpatterns.com/update-method.html)\n"
  },
  {
    "path": "localization/es/value-object/README.md",
    "content": "---\ntitle: Value Object\nshortTitle: Value Object\ncategory: Creational\nlanguage: es\ntag:\n  - Instantiation\n---\n\n## Propósito\n\nProporcionar objetos que siguen la semántica de valor en lugar de la semántica de referencia. Esto significa que la\nigualdad de los objetos de valor no se basa en la identidad. Dos objetos de valor son iguales cuando tienen el mismo\nvalor, no necesariamente siendo el mismo objeto.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Existe una clase para las estadísticas de héroes en un juego de rol. Las estadísticas contienen atributos como fuerza,\n> inteligencia y suerte. Las estadísticas de diferentes héroes deben ser iguales cuando todos los atributos son iguales.\n\nEn palabras simples\n\n> Los objetos de valor son iguales cuando sus atributos tienen el mismo valor.\n\nWikipedia dice\n\n> En informática, un objeto de valor es un objeto pequeño que representa una entidad simple cuya igualdad no se basa en\n> la identidad: es decir, dos objetos de valor son iguales cuando tienen el mismo valor, no necesariamente siendo el mismo\n> objeto.\n\n**Ejemplo Programático**\n\nAquí está la clase `HeroStat` que es el objeto valor. Fíjate en el uso de la\nanotación [Lombok's `@Value`](https://projectlombok.org/features/Value).\n\n```java\n@Value(staticConstructor = \"valueOf\")\nclass HeroStat {\n\n    int strength;\n    int intelligence;\n    int luck;\n}\n```\n\nEl ejemplo crea tres `HeroStat` diferentes y compara su igualdad.\n\n```java\nvar statA = HeroStat.valueOf(10, 5, 0);\nvar statB = HeroStat.valueOf(10, 5, 0);\nvar statC = HeroStat.valueOf(5, 1, 8);\n\nLOGGER.info(statA.toString());\nLOGGER.info(statB.toString());\nLOGGER.info(statC.toString());\n\nLOGGER.info(\"Is statA and statB equal : {}\", statA.equals(statB));\nLOGGER.info(\"Is statA and statC equal : {}\", statA.equals(statC));\n```\n\nAquí está la salida de la consola.\n\n```\n20:11:12.199 [main] INFO com.iluwatar.value.object.App - HeroStat(strength=10, intelligence=5, luck=0)\n20:11:12.202 [main] INFO com.iluwatar.value.object.App - HeroStat(strength=10, intelligence=5, luck=0)\n20:11:12.202 [main] INFO com.iluwatar.value.object.App - HeroStat(strength=5, intelligence=1, luck=8)\n20:11:12.202 [main] INFO com.iluwatar.value.object.App - Is statA and statB equal : true\n20:11:12.203 [main] INFO com.iluwatar.value.object.App - Is statA and statC equal : false\n```\n\n## Diagrama de Clases\n\n![alt text](./etc/value-object.png \"Value Object\")\n\n## Aplicabilidad\n\nUtilice el objeto Valor cuando\n\n* La igualdad del objeto debe basarse en su valor.\n\n## Usos conocidos\n\n* [java.util.Optional](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html)\n* [java.time.LocalDate](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html)\n* [joda-time, money, beans](http://www.joda.org/)\n\n## Créditos\n\n* [Patterns of Enterprise Application Architecture](http://www.martinfowler.com/books/eaa.html)\n* [ValueObject](https://martinfowler.com/bliki/ValueObject.html)\n* [VALJOs - Value Java Objects : Stephen Colebourne's blog](http://blog.joda.org/2014/03/valjos-value-java-objects.html)\n* [Value Object : Wikipedia](https://en.wikipedia.org/wiki/Value_object)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n"
  },
  {
    "path": "localization/es/visitor/README.md",
    "content": "---\ntitle: Visitor\nshortTitle: Visitor\ncategory: Behavioral\nlanguage: es\ntag:\n - Gang of Four\n---\n\n## Propósito\n\nRepresentar una operación a realizar sobre los elementos de una estructura de objetos. Visitante permite\ndefinir una nueva operación sin cambiar las clases de los elementos sobre los que opera.\n\n## Explicación\n\nEjemplo del mundo real\n\n> Considere una estructura de árbol con unidades del ejército. El comandante tiene dos sargentos bajo él y cada sargento\n> tiene tres soldados bajo él. Dado que la jerarquía implementa el patrón visitante, podemos\n> crear fácilmente nuevos objetos que interactúen con el comandante, los sargentos, los soldados, o todos ellos. \n\n\nEjemplo del mundo real\n\n> El patrón Visitante define las operaciones que se pueden realizar en los nodos de la estructura de datos.\n\nWikipedia dice\n\n> En programación orientada a objetos e ingeniería de software, el patrón de diseño visitante es una forma de\n> separar un algoritmo de una estructura de objetos sobre la que opera. Un resultado práctico de esta\n> separación es la capacidad de añadir nuevas operaciones a estructuras de objetos existentes sin modificarlas.\n> las estructuras.\n\n**Ejemplo programático**\n\nDado el ejemplo anterior de la unidad del ejército, primero tenemos los tipos básicos Unit y UnitVisitor.\n\n```java\npublic abstract class Unit {\n\n  private final Unit[] children;\n\n  public Unit(Unit... children) {\n    this.children = children;\n  }\n\n  public void accept(UnitVisitor visitor) {\n    Arrays.stream(children).forEach(child -> child.accept(visitor));\n  }\n}\n\npublic interface UnitVisitor {\n\n  void visit(Soldier soldier);\n\n  void visit(Sergeant sergeant);\n\n  void visit(Commander commander);\n}\n```\n\nLuego tenemos las unidades de hormigón.\n\n```java\npublic class Commander extends Unit {\n\n  public Commander(Unit... children) {\n    super(children);\n  }\n\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visit(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"commander\";\n  }\n}\n\npublic class Sergeant extends Unit {\n\n  public Sergeant(Unit... children) {\n    super(children);\n  }\n\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visit(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"sergeant\";\n  }\n}\n\npublic class Soldier extends Unit {\n\n  public Soldier(Unit... children) {\n    super(children);\n  }\n\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visit(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"soldier\";\n  }\n}\n```\n\nHe aquí, pues, algunos visitantes concretos.\n\n```java\n@Slf4j\npublic class CommanderVisitor implements UnitVisitor {\n\n  @Override\n  public void visit(Soldier soldier) {\n    // Do nothing\n  }\n\n  @Override\n  public void visit(Sergeant sergeant) {\n    // Do nothing\n  }\n\n  @Override\n  public void visit(Commander commander) {\n    LOGGER.info(\"Good to see you {}\", commander);\n  }\n}\n\n@Slf4j\npublic class SergeantVisitor implements UnitVisitor {\n\n  @Override\n  public void visit(Soldier soldier) {\n    // Do nothing\n  }\n\n  @Override\n  public void visit(Sergeant sergeant) {\n    LOGGER.info(\"Hello {}\", sergeant);\n  }\n\n  @Override\n  public void visit(Commander commander) {\n    // Do nothing\n  }\n}\n\n@Slf4j\npublic class SoldierVisitor implements UnitVisitor {\n\n  @Override\n  public void visit(Soldier soldier) {\n    LOGGER.info(\"Greetings {}\", soldier);\n  }\n\n  @Override\n  public void visit(Sergeant sergeant) {\n    // Do nothing\n  }\n\n  @Override\n  public void visit(Commander commander) {\n    // Do nothing\n  }\n}\n```\n\nPor último, podemos mostrar el poder de los visitantes en acción.\n\n```java\ncommander.accept(new SoldierVisitor());\ncommander.accept(new SergeantVisitor());\ncommander.accept(new CommanderVisitor());\n```\n\nSalida del programa:\n\n```\nGreetings soldier\nGreetings soldier\nGreetings soldier\nGreetings soldier\nGreetings soldier\nGreetings soldier\nHello sergeant\nHello sergeant\nGood to see you commander\n```\n\n## Diagrama de clases\n\n![alt text](./etc/visitor_1.png \"Visitor\")\n\n## Aplicabilidad\n\nUtilice el patrón Visitor cuando\n\n* Una estructura de objetos contiene muchas clases de objetos con diferentes interfaces, y desea realizar operaciones en estos objetos que dependen de sus clases concretas.\n* Es necesario realizar muchas operaciones distintas y no relacionadas en los objetos de una estructura de objetos, y se desea evitar \"contaminar\" sus clases con estas operaciones. Visitor permite mantener juntas las operaciones relacionadas definiéndolas en una clase. Cuando la estructura de objetos es compartida por muchas aplicaciones, utilice Visitor para poner las operaciones sólo en aquellas aplicaciones que las necesiten.\n* Las clases que definen la estructura del objeto raramente cambian, pero a menudo se quieren definir nuevas operaciones sobre la estructura. Cambiar las clases de la estructura del objeto requiere redefinir la interfaz para todos los visitantes, lo que es potencialmente costoso. Si las clases de la estructura del objeto cambian a menudo, probablemente sea mejor definir las operaciones en esas clases.\n\n## Tutoriales\n\n* [Refactoring Guru](https://refactoring.guru/design-patterns/visitor)\n* [Dzone](https://dzone.com/articles/design-patterns-visitor)\n* [Sourcemaking](https://sourcemaking.com/design_patterns/visitor)\n\n## Usos conocidos\n\n* [Apache Wicket](https://github.com/apache/wicket) component tree, Mire [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)\n* [javax.lang.model.element.AnnotationValue](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValue.html) y [AnnotationValueVisitor](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValueVisitor.html)\n* [javax.lang.model.element.Element](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/Element.html) y [Element Visitor](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/ElementVisitor.html)\n* [java.nio.file.FileVisitor](http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileVisitor.html)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/fa/abstract-document/README.md",
    "content": "---\ntitle: \"الگوی Abstract Document در جاوا: ساده‌سازی مدیریت داده با انعطاف‌پذیری\"\nshortTitle: Abstract Document\ndescription: \"الگوی طراحی Abstract Document در جاوا را بررسی کنید. با هدف، توضیح، کاربرد، مزایا و نمونه‌های دنیای واقعی برای پیاده‌سازی ساختارهای داده‌ای پویا و انعطاف‌پذیر آشنا شوید.\"\ncategory: Structural\nlanguage: fa\ntag:\n  - Abstraction\n  - Decoupling\n  - Dynamic typing\n  - Encapsulation\n  - Extensibility\n  - Polymorphism\n---\n\n## هدف الگوی طراحی Abstract Document\n\nالگوی طراحی Abstract Document در جاوا یک الگوی طراحی ساختاری مهم است که راهی یکپارچه برای مدیریت ساختارهای داده‌ای سلسله‌مراتبی و درخت‌ی فراهم می‌کند، با تعریف یک واسط مشترک برای انواع مختلف اسناد. این الگو ساختار اصلی سند را از فرمت‌های خاص داده جدا می‌کند، که باعث به‌روزرسانی پویا و نگهداری ساده‌تر می‌شود.\n\n## توضیح دقیق الگوی Abstract Document با نمونه‌های دنیای واقعی\n\nالگوی طراحی Abstract Document در جاوا امکان مدیریت پویا ویژگی‌های پویا(غیر استاتیک) را فراهم می‌کند. این الگو از مفهوم traits استفاده می‌کند تا ایمنی نوع‌داده (type safety) را فراهم کرده و ویژگی‌های کلاس‌های مختلف را به مجموعه‌ای از واسط‌ها تفکیک کند.\n\nمثال دنیای واقعی\n\n> فرض کنید یک سیستم کتابخانه از الگوی Abstract Document در جاوا استفاده می‌کند، جایی که کتاب‌ها می‌توانند فرمت‌ها و ویژگی‌های متنوعی داشته باشند: کتاب‌های فیزیکی، کتاب‌های الکترونیکی، و کتاب‌های صوتی. هر فرمت ویژگی‌های خاص خود را دارد، مانند تعداد صفحات برای کتاب‌های فیزیکی، حجم فایل برای کتاب‌های الکترونیکی، و مدت‌زمان برای کتاب‌های صوتی. الگوی Abstract Document به سیستم کتابخانه اجازه می‌دهد تا این فرمت‌های متنوع را به‌صورت انعطاف‌پذیر مدیریت کند. با استفاده از این الگو، سیستم می‌تواند ویژگی‌ها را به‌صورت پویا ذخیره و بازیابی کند، بدون نیاز به ساختار سفت و سخت برای هر نوع کتاب، و این کار افزودن فرمت‌ها یا ویژگی‌های جدید را در آینده بدون تغییرات عمده در کد آسان می‌سازد.\n\nبه زبان ساده\n\n> الگوی Abstract Document اجازه می‌دهد ویژگی‌هایی به اشیاء متصل شوند بدون اینکه خود آن اشیاء از آن اطلاع داشته باشند.\n\nویکی‌پدیا می‌گوید\n\n> یک الگوی طراحی ساختاری شی‌ء‌گرا برای سازماندهی اشیاء در کلید-مقدارهایی با تایپ آزاد و ارائه داده‌ها از طریق نمای تایپ است. هدف این الگو دستیابی به انعطاف‌پذیری بالا بین اجزا در یک زبان strongly typed است که در آن بتوان ویژگی‌های جدیدی را به‌صورت پویا به ساختار درختی اشیاء اضافه کرد، بدون از دست دادن پشتیبانی از type safety. این الگو از traits برای جداسازی ویژگی‌های مختلف یک کلاس در اینترفیس‌های متفاوت استفاده می‌کند.\n\nنمودار کلاس\n\n![Abstract Document class diagram](./etc/abstract-document.png \"Abstract Document class diagram\")\n\n## مثال برنامه‌نویسی از الگوی Abstract Document در جاوا\n\nفرض کنید یک خودرو داریم که از قطعات مختلفی تشکیل شده است. اما نمی‌دانیم آیا این خودرو خاص واقعاً همه قطعات را دارد یا فقط برخی از آن‌ها. خودروهای ما پویا و بسیار انعطاف‌پذیر هستند.\n\nبیایید ابتدا کلاس‌های پایه `Document` و `AbstractDocument` را تعریف کنیم. این کلاس‌ها اساساً یک شیء را قادر می‌سازند تا یک نقشه از ویژگی‌ها و هر تعداد شیء فرزند را نگه دارد.\n\n```java\npublic interface Document {\n\n    Void put(String key, Object value);\n\n    Object get(String key);\n\n    <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);\n}\n\npublic abstract class AbstractDocument implements Document {\n\n    private final Map<String, Object> properties;\n\n    protected AbstractDocument(Map<String, Object> properties) {\n        Objects.requireNonNull(properties, \"properties map is required\");\n        this.properties = properties;\n    }\n\n    @Override\n    public Void put(String key, Object value) {\n        properties.put(key, value);\n        return null;\n    }\n\n    @Override\n    public Object get(String key) {\n        return properties.get(key);\n    }\n\n    @Override\n    public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {\n        return Stream.ofNullable(get(key))\n                .filter(Objects::nonNull)\n                .map(el -> (List<Map<String, Object>>) el)\n                .findAny()\n                .stream()\n                .flatMap(Collection::stream)\n                .map(constructor);\n    }\n    \n    // Other properties and methods...\n}\n```\nدر ادامه، یک enum به نام Property و مجموعه‌ای از واسط‌ها برای type، price، model و parts تعریف می‌کنیم. این کار به ما اجازه می‌دهد یک واسط با ظاهر استاتیک برای کلاس Car ایجاد کنیم.\n```java\npublic enum Property {\n\n    PARTS, TYPE, PRICE, MODEL\n}\n\npublic interface HasType extends Document {\n\n    default Optional<String> getType() {\n        return Optional.ofNullable((String) get(Property.TYPE.toString()));\n    }\n}\n\npublic interface HasPrice extends Document {\n\n    default Optional<Number> getPrice() {\n        return Optional.ofNullable((Number) get(Property.PRICE.toString()));\n    }\n}\n\npublic interface HasModel extends Document {\n\n    default Optional<String> getModel() {\n        return Optional.ofNullable((String) get(Property.MODEL.toString()));\n    }\n}\n\npublic interface HasParts extends Document {\n\n    default Stream<Part> getParts() {\n        return children(Property.PARTS.toString(), Part::new);\n    }\n}\n\npublic class Part extends AbstractDocument implements HasType, HasModel, HasPrice {\n\n    public Part(Map<String, Object> properties) {\n        super(properties);\n    }\n}\n```\nاکنون آماده‌ایم تا کلاس Car را معرفی کنیم.\n```java\npublic class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {\n\n    public Car(Map<String, Object> properties) {\n        super(properties);\n    }\n}\n```\nو در نهایت، نحوه ساخت و استفاده از Car را در یک مثال کامل می‌بینید.\n```java\n  public static void main(String[] args) {\n    LOGGER.info(\"Constructing parts and car\");\n\n    var wheelProperties = Map.of(\n            Property.TYPE.toString(), \"wheel\",\n            Property.MODEL.toString(), \"15C\",\n            Property.PRICE.toString(), 100L);\n\n    var doorProperties = Map.of(\n            Property.TYPE.toString(), \"door\",\n            Property.MODEL.toString(), \"Lambo\",\n            Property.PRICE.toString(), 300L);\n\n    var carProperties = Map.of(\n            Property.MODEL.toString(), \"300SL\",\n            Property.PRICE.toString(), 10000L,\n            Property.PARTS.toString(), List.of(wheelProperties, doorProperties));\n\n    var car = new Car(carProperties);\n\n    LOGGER.info(\"Here is our car:\");\n    LOGGER.info(\"-> model: {}\", car.getModel().orElseThrow());\n    LOGGER.info(\"-> price: {}\", car.getPrice().orElseThrow());\n    LOGGER.info(\"-> parts: \");\n    car.getParts().forEach(p -> LOGGER.info(\"\\t{}/{}/{}\",\n            p.getType().orElse(null),\n            p.getModel().orElse(null),\n            p.getPrice().orElse(null))\n    );\n}\n```\nخروجی برنامه:\n```\n07:21:57.391 [main] INFO com.iluwatar.abstractdocument.App -- Constructing parts and car\n07:21:57.393 [main] INFO com.iluwatar.abstractdocument.App -- Here is our car:\n07:21:57.393 [main] INFO com.iluwatar.abstractdocument.App -- -> model: 300SL\n07:21:57.394 [main] INFO com.iluwatar.abstractdocument.App -- -> price: 10000\n07:21:57.394 [main] INFO com.iluwatar.abstractdocument.App -- -> parts: \n07:21:57.395 [main] INFO com.iluwatar.abstractdocument.App -- \twheel/15C/100\n07:21:57.395 [main] INFO com.iluwatar.abstractdocument.App -- \tdoor/Lambo/300\n```\n\n ### چه زمانی از الگوی Abstract Document در جاوا استفاده کنیم؟\n\nالگوی طراحی Abstract Document به‌ویژه در سناریوهایی مفید است که نیاز به مدیریت انواع مختلفی از اسناد در جاوا وجود دارد که برخی ویژگی‌ها یا رفتارهای مشترک دارند، ولی ویژگی‌ها یا رفتارهای خاص خود را نیز دارند. در ادامه چند سناریوی مناسب برای این الگو آورده شده است:\n\n* سیستم‌های مدیریت محتوا (CMS): ممکن است انواع مختلفی از محتوا مانند مقاله، تصویر، ویدئو و... وجود داشته باشد. هر نوع محتوا ویژگی‌های مشترکی مثل تاریخ ایجاد، نویسنده و تگ‌ها دارد، ولی همچنین ویژگی‌های خاصی مثل ابعاد تصویر یا مدت‌زمان ویدئو.\n\n*    سیستم‌های فایل: اگر یک سیستم فایل طراحی می‌کنید که باید انواع مختلف فایل مانند اسناد، تصاویر، فایل‌های صوتی و دایرکتوری‌ها را مدیریت کند، این الگو می‌تواند راهی یکپارچه برای دسترسی به ویژگی‌هایی مانند اندازه فایل یا تاریخ ایجاد، فراهم کند و در عین حال ویژگی‌های خاص هر نوع فایل را هم مدیریت کند.\n\n*    سیستم‌های تجارت الکترونیک: یک پلتفرم فروش آنلاین ممکن است محصولات مختلفی داشته باشد مثل محصولات فیزیکی، فایل‌های دیجیتال، و اشتراک‌ها. این محصولات ویژگی‌هایی مثل نام، قیمت و توضیح را به اشتراک می‌گذارند، ولی ویژگی‌های خاصی هم دارند مانند وزن حمل برای محصولات فیزیکی یا لینک دانلود برای دیجیتال‌ها.\n\n*    سیستم‌های سوابق پزشکی: در مراقبت سلامت، پرونده بیماران ممکن است داده‌های مختلفی مثل مشخصات فردی، سوابق پزشکی، نتایج آزمایش‌ها و نسخه‌ها را شامل شود. این الگو می‌تواند ویژگی‌های مشترک مثل شماره بیمار یا تاریخ تولد را مدیریت کند و هم‌زمان ویژگی‌های خاصی مثل نتایج آزمایش یا داروهای تجویزی را هم پوشش دهد.\n\n*    مدیریت پیکربندی: هنگام کار با تنظیمات پیکربندی نرم‌افزار، ممکن است انواع مختلفی از عناصر پیکربندی وجود داشته باشد، هر یک با ویژگی‌های خاص خود. این الگو می‌تواند برای مدیریت این عناصر مفید باشد.\n\n*    پلتفرم‌های آموزشی: سیستم‌های آموزشی ممکن است انواع مختلفی از منابع یادگیری داشته باشند مثل محتوای متنی، ویدیوها، آزمون‌ها و تمرین‌ها. ویژگی‌های مشترکی مثل عنوان، نویسنده و تاریخ انتشار وجود دارد، ولی ویژگی‌های خاصی مانند مدت ویدیو یا مهلت تحویل تمرین نیز ممکن است وجود داشته باشد.\n\n*    ابزارهای مدیریت پروژه: در برنامه‌های مدیریت پروژه، ممکن است انواع مختلفی از وظایف مانند آیتم‌های to-do، milestoneها و issueها داشته باشید. این الگو می‌تواند برای مدیریت ویژگی‌های عمومی مانند نام وظیفه و مسئول آن استفاده شود و در عین حال ویژگی‌های خاص مانند تاریخ milestone یا اولویت issue را نیز پوشش دهد.\n\n*    اسناد ساختار ویژگی‌های متنوع و در حال تحول دارند.\n\n*    افزودن ویژگی‌های جدید به‌صورت پویا یک نیاز رایج است.\n\n*    جداسازی دسترسی به داده از فرمت‌های خاص حیاتی است.\n\n*    نگهداری‌پذیری و انعطاف‌پذیری برای کد اهمیت دارد.\n\nایده اصلی پشت الگوی Abstract Document فراهم کردن روشی انعطاف‌پذیر و قابل توسعه برای مدیریت انواع مختلف اسناد یا موجودیت‌ها با ویژگی‌های مشترک و خاص است. با تعریف یک واسط مشترک و پیاده‌سازی آن در انواع مختلف اسناد، می‌توان به شیوه‌ای منظم و یکپارچه برای مدیریت ساختارهای پیچیده داده دست یافت.\n### مزایا و معایب الگوی Abstract Document\n<div dir=\"rtl\">\nمزایا:\n\n*    انعطاف‌پذیری: پشتیبانی از ساختارهای متنوع اسناد و ویژگی‌ها.\n\n*    قابلیت توسعه: افزودن ویژگی‌های جدید بدون شکستن کد موجود.\n\n*    نگهداری‌پذیری: ارتقاء کد تمیز و قابل تطبیق به‌واسطه جداسازی وظایف.\n\n*    قابلیت استفاده مجدد: نمای دید تایپ‌شده باعث استفاده مجدد از کد برای دسترسی به نوع خاصی از ویژگی می‌شود.\n\nمعایب:\n\n*    پیچیدگی: نیاز به تعریف واسط‌ها و نماها، که باعث اضافه شدن سربار پیاده‌سازی می‌شود.\n\n*    کارایی: ممکن است سربار کمی نسبت به دسترسی مستقیم به داده داشته باشد.\n</div>\n\nمنابع و اعتبارها\n\n*    [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n\n*    [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n\n*    [Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4)] (https://amzn.to/49zRP4R)\n\n*    [Patterns of Enterprise Application Architecture] (https://amzn.to/3WfKBPR)\n\n*    [Abstract Document Pattern (Wikipedia)] (https://en.wikipedia.org/wiki/Abstract_Document_Pattern)\n\n*    [Dealing with Properties (Martin Fowler)] (http://martinfowler.com/apsupp/properties.pdf)\n"
  },
  {
    "path": "localization/fa/abstract-factory/README.md",
    "content": "---\ntitle: \"الگوی طراحی Abstract Factory در جاوا: مهارت در ایجاد شیء با ظرافت\"\nshortTitle: Abstract Factory\ndescription: \"با مثال‌های دنیای واقعی، دیاگرام‌های کلاس و آموزش‌ها، الگوی Abstract Factory را در جاوا بیاموزید. منظور، کاربرد، مزایا و نمونه‌های واقعی آن را درک کنید و دانش طراحی الگوهایتان را افزایش دهید.\"\ncategory: Creational\nlanguage: fa\ntag:\n  - Abstraction\n  - Decoupling\n  - Gang of Four\n  - Instantiation\n  - Polymorphism\n---\n\n## همچنین به این عنوان شناخته می‌شود\n\n* کیت\n\n## هدف از الگوی طراحی Abstract Factory\n\nالگوی Abstract Factory در جاوا یک واسط برای ایجاد خانواده‌هایی از اشیای مرتبط یا وابسته فراهم می‌کند بدون آنکه کلاس‌های مشخص آن‌ها را تعیین کند، و این کار موجب افزایش مدولاریتی و انعطاف‌پذیری در طراحی نرم‌افزار می‌شود.\n\n## توضیح دقیق الگوی Abstract Factory با مثال‌های دنیای واقعی\n\nمثال دنیای واقعی\n\n> تصور کنید یک شرکت مبلمان وجود دارد که از الگوی Abstract Factory در جاوا برای تولید سبک‌های مختلف مبلمان استفاده می‌کند: مدرن، ویکتوریایی و روستایی. هر سبک شامل محصولاتی مانند صندلی‌ها، میزها و کاناپه‌ها است. برای اطمینان از یکنواختی در هر سبک، شرکت از یک الگوی Abstract Factory استفاده می‌کند.\n> \n> در این سناریو، Abstract Factory یک واسط برای ایجاد خانواده‌هایی از اشیای مبلمان مرتبط (صندلی‌ها، میزها، کاناپه‌ها) است. هر Factory مشخص (کارخانه‌ی مبلمان مدرن، کارخانه‌ی مبلمان ویکتوریایی، کارخانه‌ی مبلمان روستایی) این واسط را پیاده‌سازی می‌کند و مجموعه‌ای از محصولات مطابق با سبک خاص ایجاد می‌کند. به این ترتیب، مشتریان می‌توانند یک مجموعه کامل از مبلمان مدرن یا ویکتوریایی ایجاد کنند بدون اینکه نگران جزئیات ساخت آن‌ها باشند. این باعث حفظ یکنواختی سبک می‌شود و امکان تغییر آسان سبک مبلمان را فراهم می‌کند.\n\nبه زبان ساده\n\n> کارخانه‌ای از کارخانه‌ها؛ یک Factory یا کارخانه که مجموعه‌ای از کارخانه‌های مرتبط یا وابسته را بدون مشخص کردن کلاس‌های concrete آن‌ها گروه‌بندی می‌کند.\n\nویکی‌پدیا می‌گوید\n\n> الگوی Abstract Factory راهی برای کپسوله کردن مجموعه‌ای از کارخانه‌های منحصر به فرد با یک تم مشترک بدون تعیین کلاس‌های concrete آن‌ها فراهم می‌کند.\n\nدیاگرام کلاس\n\n![Abstract Factory class diagram](./etc/abstract-factory.urm.png \"Abstract Factory class diagram\")\n\n## مثال برنامه‌نویسی از Abstract Factory در جاوا\n\nبرای ایجاد یک پادشاهی با استفاده از الگوی Abstract Factory در جاوا، ما به اشیایی با یک تم مشترک نیاز داریم. یک پادشاهی اِلف (Elf) به یک پادشاه اِلف، یک قلعه‌ی اِلف، و یک ارتش اِلف نیاز دارد، در حالی که یک پادشاهی اورک (Orc) به یک پادشاه اورک، یک قلعه‌ی اورک، و یک ارتش اورک نیاز دارد. بین اشیای موجود در پادشاهی وابستگی وجود دارد.\n\nترجمه‌ی مثال پادشاهی بالا. ابتدا ما برخی واسط‌ها و پیاده‌سازی‌هایی برای اشیای موجود در پادشاهی داریم:\n\n```java\npublic interface Castle {\n    String getDescription();\n}\n\npublic interface King {\n    String getDescription();\n}\n\npublic interface Army {\n    String getDescription();\n}\n\n// Elven implementations ->\npublic class ElfCastle implements Castle {\n    static final String DESCRIPTION = \"This is the elven castle!\";\n\n    @Override\n    public String getDescription() {\n        return DESCRIPTION;\n    }\n}\n\npublic class ElfKing implements King {\n    static final String DESCRIPTION = \"This is the elven king!\";\n\n    @Override\n    public String getDescription() {\n        return DESCRIPTION;\n    }\n}\n\npublic class ElfArmy implements Army {\n    static final String DESCRIPTION = \"This is the elven Army!\";\n\n    @Override\n    public String getDescription() {\n        return DESCRIPTION;\n    }\n}\n\n// Orcish implementations similarly -> ...\n```\n\nسپس واسط و پیاده‌سازی‌های کارخانه‌ی پادشاهی را داریم:\n\n```java\npublic interface KingdomFactory {\n    Castle createCastle();\n    King createKing();\n    Army createArmy();\n}\n\npublic class ElfKingdomFactory implements KingdomFactory {\n\n    @Override\n    public Castle createCastle() {\n        return new ElfCastle();\n    }\n\n    @Override\n    public King createKing() {\n        return new ElfKing();\n    }\n\n    @Override\n    public Army createArmy() {\n        return new ElfArmy();\n    }\n}\n\n// Orcish implementations similarly -> ...\n```\n\nاکنون می‌توانیم یک کارخانه برای کارخانه‌های مختلف پادشاهی طراحی کنیم. در این مثال، ما `FactoryMaker` را ایجاد کردیم که مسئول برگرداندن یک نمونه از `ElfKingdomFactory` یا `OrcKingdomFactory` است. مشتری می تواند از `FactoryMaker` برای ایجاد کارخانه concrete مورد نظر استفاده کند که به نوبه خود اشیاء concrete مختلف (مشتق شده از ارتش، پادشاه، قلعه) را تولید می‌کند. در این مثال، ما همچنین از یک enum برای پارامتری کردن نوع کارخانه پادشاهی که مشتری درخواست خواهد کرد استفاده کردیم.\n\n```java\npublic static class FactoryMaker {\n\n    public enum KingdomType {\n        ELF, ORC\n    }\n\n    public static KingdomFactory makeFactory(KingdomType type) {\n        return switch (type) {\n            case ELF -> new ElfKingdomFactory();\n            case ORC -> new OrcKingdomFactory();\n        };\n    }\n}\n```\n\nنمونه‌ای از تابع اصلی برنامه:\n\n```java\nLOGGER.info(\"elf kingdom\");\ncreateKingdom(Kingdom.FactoryMaker.KingdomType.ELF);\nLOGGER.info(kingdom.getArmy().getDescription());\nLOGGER.info(kingdom.getCastle().getDescription());\nLOGGER.info(kingdom.getKing().getDescription());\n\nLOGGER.info(\"orc kingdom\");\ncreateKingdom(Kingdom.FactoryMaker.KingdomType.ORC);\nLOGGER.info(kingdom.getArmy().getDescription());\nLOGGER.info(kingdom.getCastle().getDescription());\nLOGGER.info(kingdom.getKing().getDescription());\n```\n\nخروجی برنامه:\n\n```\n07:35:46.340 [main] INFO com.iluwatar.abstractfactory.App -- elf kingdom\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven army!\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven castle!\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven king!\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- orc kingdom\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc army!\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc castle!\n07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc king!\n```\n\n## چه زمانی باید از الگوی Abstract Factory در جاوا استفاده کرد؟\n\n* زمانی که سیستم باید مستقل از نحوه‌ی ایجاد، ترکیب و نمایش محصولاتش باشد.\n* زمانی که نیاز به پیکربندی سیستم با یکی از چند خانواده محصول دارید.\n* زمانی که باید خانواده‌ای از اشیای مرتبط با هم استفاده شوند، برای اطمینان از یکنواختی.\n* زمانی که می‌خواهید کتابخانه‌ای از محصولات را فراهم کنید و فقط واسط‌های آن‌ها را نمایان کنید، نه پیاده‌سازی‌ها را.\n* زمانی که طول عمر وابستگی‌ها کوتاه‌تر از مصرف‌کننده باشد.\n* زمانی که نیاز به ساخت وابستگی‌ها با مقادیر یا پارامترهای زمان اجرا باشد.\n* زمانی که باید در زمان اجرا انتخاب کنید که کدام خانواده از محصول را استفاده کنید.\n* زمانی که افزودن محصولات یا خانواده های جدید نباید نیاز به تغییر در کد موجود داشته باشد.\n\n## آموزش‌های الگوی Abstract Factory در جاوا\n\n* [Abstract Factory Design Pattern in Java (DigitalOcean)](https://www.digitalocean.com/community/tutorials/abstract-factory-design-pattern-in-java)\n* [Abstract Factory (Refactoring Guru)](https://refactoring.guru/design-patterns/abstract-factory)\n\n## مزایا و معایب الگوی Abstract Factory\n\nمزایا:\n\n> * انعطاف‌پذیری: به راحتی می‌توان خانواده‌های محصول را تعویض کرد بدون تغییر کد.\n\n> * جداسازی (Decoupling): کد مشتری فقط با واسط‌های انتزاعی کار می‌کند که باعث قابلیت حمل و نگهداری می‌شود.\n\n> * قابلیت استفاده مجدد: کارخانه‌های انتزاعی و محصولات امکان استفاده مجدد از مؤلفه‌ها را فراهم می‌کنند.\n\n> * قابلیت نگهداری: تغییرات در خانواده‌های محصول محلی شده و به‌روزرسانی را ساده‌تر می‌کند.\n\nمعایب:\n\n> * پیچیدگی: تعریف واسط‌های انتزاعی و کارخانه‌های مشخص سربار اولیه ایجاد می‌کند.\n\n> * غیرمستقیم بودن: کد مشتری از طریق کارخانه‌ها با محصولات کار می‌کند که ممکن است شفافیت را کاهش دهد.\n\n## نمونه‌های واقعی استفاده از الگوی Abstract Factory در جاوا\n\n* کلاس‌های `LookAndFeel` در Java Swing برای ارائه گزینه های مختلف look-and-feel\n* پیاده‌سازی‌های مختلف در Java AWT برای ایجاد اجزای مختلف GUI\n* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)\n* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)\n* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)\n\n## الگوهای طراحی مرتبط با جاوا\n\n* الگوی [Factory Method](https://java-design-patterns.com/patterns/factory-method/): الگوی کارخانه‌ی انتزاعی از روش‌های کارخانه‌ای برای ایجاد محصولات استفاده می‌کند.\n* الگوی [Singleton](https://java-design-patterns.com/patterns/singleton/): کلاس‌های کارخانه‌ی انتزاعی اغلب به صورت Singleton پیاده‌سازی می‌شوند.\n* الگوی [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/): مشابه کارخانه‌ی انتزاعی اما بر پیکربندی و مدیریت مجموعه‌ای از اشیای مرتبط تمرکز دارد.\n\n## منابع و ارجاعات\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Design Patterns in Java](https://amzn.to/3Syw0vC)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3HWNf4U)\n"
  },
  {
    "path": "localization/fa/active-object/README.md",
    "content": "---\ntitle: \"الگوی Active Object در جاوا: دستیابی به پردازش ناهمگام کارآمد\"\nshortTitle: Active Object\ndescription: \"با الگوی طراحی Active Object در جاوا آشنا شوید. این راهنما رفتار ناهمگام، هم‌زمانی (concurrency) و مثال‌های کاربردی برای بهبود عملکرد برنامه‌های جاوای شما را پوشش می‌دهد.\"\ncategory: Concurrency\nlanguage: fa\ntag:\n  - Asynchronous\n  - Decoupling\n  - Messaging\n  - Synchronization\n  - Thread management\n---\n\n## هدف الگوی طراحی Active Object\n\nالگوی Active Object روشی مطمئن برای پردازش ناهمگام در جاوا فراهم می‌کند که به پاسخ‌گو بودن برنامه‌ها و مدیریت مؤثر threadها کمک می‌کند. این الگو با محصور کردن وظایف در شیءهایی که هر کدام thread و صف پیام مخصوص خود را دارند، به این هدف می‌رسد. این جداسازی باعث می‌شود thread اصلی پاسخ‌گو باقی بماند و مشکلاتی مانند دست‌کاری مستقیم threadها یا دسترسی به وضعیت مشترک (shared state) به وجود نیاید.\n\n## توضیح کامل الگوی Active Object با مثال‌های دنیای واقعی\n\nمثال دنیای واقعی\n\n> تصور کنید در یک رستوران شلوغ، مشتریان سفارش خود را به گارسون‌ها می‌سپارند. به‌جای آنکه گارسون‌ها خودشان به آشپزخانه بروند و غذا را آماده کنند، سفارش‌ها را روی کاغذهایی می‌نویسند و به یک هماهنگ‌کننده می‌دهند. این هماهنگ‌کننده گروهی از سرآشپزها را مدیریت می‌کند که غذاها را به صورت ناهمگام آماده می‌کنند. هرگاه آشپزی آزاد شود، سفارش بعدی را از صف برمی‌دارد، غذا را آماده می‌کند و پس از آن گارسون را برای سرو غذا مطلع می‌سازد.\n>\n> در این قیاس، گارسون‌ها نماینده threadهای کلاینت هستند، هماهنگ‌کننده نقش زمان‌بند (scheduler) را ایفا می‌کند، و آشپزها نمایان‌گر اجرای متدها در threadهای جداگانه هستند. این ساختار باعث می‌شود گارسون‌ها بتوانند بدون مسدود شدن توسط فرایند آماده‌سازی غذا، سفارش‌های بیشتری دریافت کنند—درست مانند اینکه الگوی Active Object، فراخوانی متد را از اجرای آن جدا می‌کند تا هم‌زمانی (concurrency) را افزایش دهد.\n\nبه زبان ساده\n\n> الگوی Active Object، اجرای متد را از فراخوانی آن جدا می‌کند تا در برنامه‌های چندریسمانی (multithreaded)، هم‌زمانی و پاسخ‌گویی بهتری فراهم شود.\n\nطبق تعریف ویکی‌پدیا\n\n> الگوی طراحی Active Object اجرای متد را از فراخوانی آن جدا می‌کند، برای شیءهایی که هرکدام thread کنترل مخصوص به خود را دارند. هدف، معرفی هم‌زمانی با استفاده از فراخوانی متد به‌صورت ناهمگام و یک زمان‌بند برای مدیریت درخواست‌ها است.\n>\n> این الگو شامل شش جزء کلیدی است:\n>\n> * یک proxy، که رابطی برای کلاینت‌ها با متدهای عمومی فراهم می‌کند.\n> * یک interface که درخواست متد برای شیء فعال (active object) را تعریف می‌کند.\n> * فهرستی از درخواست‌های معلق از سوی کلاینت‌ها.\n> * یک زمان‌بند (scheduler) که تصمیم می‌گیرد کدام درخواست بعدی اجرا شود.\n> * پیاده‌سازی متد شیء فعال.\n> * یک callback یا متغیر برای اینکه کلاینت نتیجه را دریافت کند.\n\nنمودار توالی\n\n![Active Object sequence diagram](./etc/active-object-sequence-diagram.png)\n\n## مثال برنامه‌نویسی از Active Object در جاوا\n\nاین بخش نحوه عملکرد الگوی Active Object در جاوا را توضیح می‌دهد و کاربرد آن در مدیریت وظایف ناهمگام و کنترل هم‌زمانی را نشان می‌دهد.\n\nاورک‌ها به دلیل ذات وحشی و غیرقابل مهارشان شناخته می‌شوند. به‌نظر می‌رسد هرکدام thread کنترل مخصوص خود را دارند. برای پیاده‌سازی یک موجود که دارای سازوکار thread مستقل خود باشد و فقط API را در اختیار قرار دهد نه اجرای داخلی را، می‌توان از الگوی Active Object استفاده کرد.\n\n```java\npublic abstract class ActiveCreature {\n    private final Logger logger = LoggerFactory.getLogger(ActiveCreature.class.getName());\n\n    private BlockingQueue<Runnable> requests;\n\n    private String name;\n\n    private Thread thread;\n\n    public ActiveCreature(String name) {\n        this.name = name;\n        this.requests = new LinkedBlockingQueue<Runnable>();\n        thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                while (true) {\n                    try {\n                        requests.take().run();\n                    } catch (InterruptedException e) {\n                        logger.error(e.getMessage());\n                    }\n                }\n            }\n        }\n        );\n        thread.start();\n    }\n\n    public void eat() throws InterruptedException {\n        requests.put(new Runnable() {\n                         @Override\n                         public void run() {\n                             logger.info(\"{} is eating!\", name());\n                             logger.info(\"{} has finished eating!\", name());\n                         }\n                     }\n        );\n    }\n\n    public void roam() throws InterruptedException {\n        requests.put(new Runnable() {\n                         @Override\n                         public void run() {\n                             logger.info(\"{} has started to roam the wastelands.\", name());\n                         }\n                     }\n        );\n    }\n\n    public String name() {\n        return this.name;\n    }\n}\n```\n\nمی‌توان دید هر کلاسی که از ActiveCreature ارث‌بری کند، دارای thread کنترل مختص به خود برای فراخوانی و اجرای متدها خواهد بود.\n\nبرای مثال، کلاس Orc:\n\n```java\npublic class Orc extends ActiveCreature {\n\n    public Orc(String name) {\n        super(name);\n    }\n}\n```\nاکنون می‌توان چند موجود مانند orc ایجاد کرد، به آن‌ها دستور داد که بخورند و پرسه بزنند، و آن‌ها این دستورات را در thread مختص به خود اجرا می‌کنند:\n\n```java\npublic class App implements Runnable {\n\n    private static final Logger logger = LoggerFactory.getLogger(App.class.getName());\n\n    private static final int NUM_CREATURES = 3;\n\n    public static void main(String[] args) {\n        var app = new App();\n        app.run();\n    }\n\n    @Override\n    public void run() {\n        List<ActiveCreature> creatures = new ArrayList<>();\n        try {\n            for (int i = 0; i < NUM_CREATURES; i++) {\n                creatures.add(new Orc(Orc.class.getSimpleName() + i));\n                creatures.get(i).eat();\n                creatures.get(i).roam();\n            }\n            Thread.sleep(1000);\n        } catch (InterruptedException e) {\n            logger.error(e.getMessage());\n            Thread.currentThread().interrupt();\n        } finally {\n            for (int i = 0; i < NUM_CREATURES; i++) {\n                creatures.get(i).kill(0);\n            }\n        }\n    }\n}\n```\n\nخروجی برنامه:\n\n```\n09:00:02.501 [Thread-0] INFO com.iluwatar.activeobject.ActiveCreature -- Orc0 is eating!\n09:00:02.501 [Thread-2] INFO com.iluwatar.activeobject.ActiveCreature -- Orc2 is eating!\n09:00:02.501 [Thread-1] INFO com.iluwatar.activeobject.ActiveCreature -- Orc1 is eating!\n09:00:02.504 [Thread-0] INFO com.iluwatar.activeobject.ActiveCreature -- Orc0 has finished eating!\n09:00:02.504 [Thread-1] INFO com.iluwatar.activeobject.ActiveCreature -- Orc1 has finished eating!\n09:00:02.504 [Thread-0] INFO com.iluwatar.activeobject.ActiveCreature -- Orc0 has started to roam in the wastelands.\n09:00:02.504 [Thread-2] INFO com.iluwatar.activeobject.ActiveCreature -- Orc2 has finished eating!\n09:00:02.504 [Thread-1] INFO com.iluwatar.activeobject.ActiveCreature -- Orc1 has started to roam in the wastelands.\n09:00:02.504 [Thread-2] INFO com.iluwatar.activeobject.ActiveCreature -- Orc2 has started to roam in the wastelands.\n```\n\nچه زمانی از الگوی Active Object در جاوا استفاده کنیم؟\n\nاز الگوی Active Object در جاوا استفاده کنید زمانی که:\n> * نیاز دارید وظایف ناهمگام را بدون مسدود کردن thread اصلی مدیریت کنید تا عملکرد و پاسخ‌گویی بهتری داشته باشید.\n> * نیاز به تعامل ناهمگام با منابع خارجی دارید.\n> * می‌خواهید پاسخ‌گویی برنامه را افزایش دهید.\n> * نیاز به مدیریت وظایف هم‌زمان به‌صورت ماژولار و قابل نگهداری دارید.\n\nآموزش‌های Java برای الگوی Active Object\n> [Android and Java Concurrency: The Active Object Pattern (Douglas Schmidt)]((https://www.youtube.com/watch?v=Cd8t2u5Qmvc))\n\nکاربردهای دنیای واقعی الگوی Active Object در جاوا\n\n>    سیستم‌های معاملات بلادرنگ که درخواست‌ها به‌صورت ناهمگام پردازش می‌شوند.\n> که در آن وظایف طولانی در پس‌زمینه اجرا می‌شوند بدون آنکه رابط کاربری را متوقف کنند. \n> رابط‌های کاربری گرافیکی (GUI) \n>     برنامه‌نویسی بازی‌ها برای مدیریت به‌روزرسانی‌های هم‌زمان وضعیت بازی یا محاسبات هوش مصنوعی. \n\nمزایا و ملاحظات الگوی Active Object\n\nبا مزایا و معایب استفاده از الگوی Active Object در جاوا آشنا شوید؛ از جمله بهبود ایمنی threadها و ملاحظات سربار احتمالی (overhead).\n\n> مزایا:\n> \n> * پاسخ‌گویی بهتر thread اصلی.\n> * محصورسازی مسائل مربوط به هم‌زمانی درون شیءها.\n> *   بهبود سازمان‌دهی کد و قابلیت نگهداری.\n> * فراهم‌سازی ایمنی در برابر شرایط بحرانی (thread safety) و جلوگیری از مشکلات وضعیت مشترک.\n\n> معایب:\n> \n> * سربار اضافی به دلیل ارسال پیام و مدیریت threadها.\n> * برای تمام سناریوهای هم‌زمانی مناسب نیست.\n\nالگوهای طراحی مرتبط در جاوا\n\n>    * [Command](https://java-design-patterns.com/patterns/command/): درخواست را به‌عنوان یک شیء کپسوله می‌کند، مشابه روشی که Active Object فراخوانی متد را کپسوله می‌کند.\n>    * [Promise](https://java-design-patterns.com/patterns/promise/): راهی برای دریافت نتیجه یک فراخوانی متد ناهمگام فراهم می‌کند؛ اغلب همراه با Active Object استفاده می‌شود.\n>    * [Proxy](https://java-design-patterns.com/patterns/proxy/): الگوی Active Object می‌تواند از proxy برای مدیریت فراخوانی‌های متد به‌صورت ناهمگام استفاده کند.\n\nمنابع و مراجع\n\n>    * [Design Patterns: Elements of Reusable Object Software](https://amzn.to/3HYqrBE)\n>    * [Concurrent Programming in Java: Design Principles and Patterns](https://amzn.to/498SRVq)\n>    * [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n>    * [Learning Concurrent Programming in Scala](https://amzn.to/3UE07nV)\n>    * [Pattern Languages of Program Design 3](https://amzn.to/3OI1j61)\n>    * [Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects](https://amzn.to/3UgC24V)\n\n"
  },
  {
    "path": "localization/fa/active-object/etc/active-object.urm.puml",
    "content": "@startuml\npackage com.iluwatar.activeobject {\n  abstract class ActiveCreature {\n    - logger : Logger\n    - name : String\n    - requests : BlockingQueue<Runnable>\n    - thread : Thread\n    + ActiveCreature(name : String)\n    + eat()\n    + name() : String\n    + roam()\n  }\n  class App {\n    - creatures : Integer\n    - logger : Logger\n    + App()\n    + main(args : String[]) {static}\n    + run()\n  }\n  class Orc {\n    + Orc(name : String)\n  }\n}\nOrc --|> ActiveCreature \n@enduml"
  },
  {
    "path": "localization/fa/factory/README.md",
    "content": "---\ntitle: \"الگوی factory در جاوا: ساده‌سازی ایجاد اشیاء\"\nshortTitle: factory\ndescription: \"الگوی طراحی factory در جاوا را با مثال‌ها و توضیحات دقیق بیاموزید. یاد بگیرید چگونه با استفاده از الگوی factory کدی انعطاف‌پذیر و مقیاس‌پذیر ایجاد کنید. مناسب برای توسعه‌دهندگانی که به دنبال بهبود مهارت‌های طراحی شیءگرا هستند.\"\ncategory: structural\nlanguage: fa\ntag:\n    - Abstraction\n    - Encapsulation\n    - Gang of Four\n    - Instantiation\n    - Polymorphism\n---\n\n## هدف از الگوی طراحی factory\n\nالگوی طراحی factory در جاوا یک الگوی ساختاری است که یک رابط برای ایجاد یک شیء تعریف می‌کند اما به زیرکلاس‌ها اجازه می‌دهد نوع اشیائی را که ایجاد خواهند شد تغییر دهند. این الگو انعطاف‌پذیری و مقیاس‌پذیری را در کد شما ترویج می‌دهد.\n\n## توضیح دقیق الگوی factory با مثال‌های دنیای واقعی\n\n### مثال دنیای واقعی\n\n> تصور کنید در یک نانوایی انواع مختلف کیک‌ها با استفاده از الگوی طراحی factory ساخته می‌شوند. `CakeFactory` فرآیند ایجاد را مدیریت می‌کند و امکان افزودن آسان انواع جدید کیک‌ها را بدون تغییر در فرآیند اصلی فراهم می‌کند. `CakeFactory` می‌تواند انواع مختلفی از کیک‌ها مانند کیک شکلاتی، کیک وانیلی و کیک توت‌فرنگی تولید کند. به جای اینکه کارکنان نانوایی به صورت دستی مواد اولیه را انتخاب کنند و دستورالعمل‌های خاصی را برای هر نوع کیک دنبال کنند، از `CakeFactory` برای مدیریت فرآیند استفاده می‌کنند. مشتری فقط نوع کیک را درخواست می‌کند و `CakeFactory` مواد اولیه و دستورالعمل مناسب را تعیین کرده و نوع خاصی از کیک را ایجاد می‌کند. این تنظیم به نانوایی اجازه می‌دهد تا انواع جدید کیک‌ها را به راحتی اضافه کند بدون اینکه فرآیند اصلی تغییر کند، که این امر انعطاف‌پذیری و مقیاس‌پذیری را ترویج می‌دهد.\n\n### تعریف ویکی‌پدیا\n\n> الگوی factory یک شیء برای ایجاد اشیاء دیگر است – به طور رسمی، factory یک تابع یا متدی است که اشیاء با نمونه‌ها یا کلاس‌های مختلف را بازمی‌گرداند.\n\n### نمودار توالی\n\n![نمودار توالی factory](./etc/factory-sequence-diagram.png)\n\n## مثال برنامه‌نویسی از الگوی factory در جاوا\n\nتصور کنید یک کیمیاگر قصد دارد سکه‌هایی تولید کند. کیمیاگر باید بتواند هم سکه‌های طلا و هم سکه‌های مسی ایجاد کند و تغییر بین آن‌ها باید بدون تغییر در کد موجود امکان‌پذیر باشد. الگوی factory این امکان را فراهم می‌کند با ارائه یک متد ایجاد استاتیک که می‌توان آن را با پارامترهای مرتبط فراخوانی کرد.\n\nدر جاوا، می‌توانید الگوی factory را با تعریف یک رابط `Coin` و پیاده‌سازی‌های آن `GoldCoin` و `CopperCoin` پیاده‌سازی کنید. کلاس `CoinFactory` یک متد استاتیک `getCoin` ارائه می‌دهد تا اشیاء سکه را بر اساس نوع ایجاد کند.\n\n```java\npublic interface Coin {\n    String getDescription();\n}\n```\n\n```java\npublic class GoldCoin implements Coin {\n\n    static final String DESCRIPTION = \"This is a gold coin.\";\n\n    @Override\n    public String getDescription() {\n        return DESCRIPTION;\n    }\n}\n```\n\n```java\npublic class CopperCoin implements Coin {\n     \n    static final String DESCRIPTION = \"This is a copper coin.\";\n\n    @Override\n    public String getDescription() {\n        return DESCRIPTION;\n    }\n}\n```\n\nکد زیر انواع سکه‌هایی که پشتیبانی می‌شوند (`GoldCoin` و `CopperCoin`) را نشان می‌دهد.\n\n```java\n@RequiredArgsConstructor\n@Getter\npublic enum CoinType {\n\n    COPPER(CopperCoin::new),\n    GOLD(GoldCoin::new);\n\n    private final Supplier<Coin> constructor;\n}\n```\n\nسپس متد استاتیک `getCoin` برای ایجاد اشیاء سکه در کلاس factory `CoinFactory` کپسوله شده است.\n\n```java\npublic class CoinFactory {\n\n    public static Coin getCoin(CoinType type) {\n        return type.getConstructor().get();\n    }\n}\n```\n\nاکنون، در کد کلاینت، می‌توانیم انواع مختلفی از سکه‌ها را با استفاده از کلاس factory تولید کنیم.\n\n```java\npublic static void main(String[] args) {\n        LOGGER.info(\"The alchemist begins his work.\");\n        var coin1 = CoinFactory.getCoin(CoinType.COPPER);\n        var coin2 = CoinFactory.getCoin(CoinType.GOLD);\n        LOGGER.info(coin1.getDescription());\n        LOGGER.info(coin2.getDescription());\n}\n```\n\nخروجی برنامه:\n\n```\n06:19:53.530 [main] INFO com.iluwatar.factory.App -- The alchemist begins his work.\n06:19:53.533 [main] INFO com.iluwatar.factory.App -- This is a copper coin.\n06:19:53.533 [main] INFO com.iluwatar.factory.App -- This is a gold coin.\n```\n\n## زمان استفاده از الگوی factory در جاوا\n\n* از الگوی طراحی factory در جاوا زمانی استفاده کنید که کلاس از قبل نوع دقیق و وابستگی‌های اشیائی که نیاز به ایجاد آن دارد را نمی‌داند.\n* زمانی که یک متد یکی از چندین کلاس ممکن که یک کلاس والد مشترک دارند را بازمی‌گرداند و می‌خواهد منطق انتخاب شیء را کپسوله کند.\n* این الگو معمولاً هنگام طراحی فریم‌ورک‌ها یا کتابخانه‌ها برای ارائه بهترین انعطاف‌پذیری و جداسازی از انواع کلاس‌های خاص استفاده می‌شود.\n\n## کاربردهای دنیای واقعی الگوی factory در جاوا\n\n> * [java.util.Calendar#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)\n> * [java.util.ResourceBundle#getBundle()](https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)\n> * [java.text.NumberFormat#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)\n> * [java.nio.charset.Charset#forName()](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)\n> * این مورد [java.net.URLStreamHandlerFactory#createURLStreamHandler(String)](https://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html) اشیاء singleton مختلف را بر اساس یک پروتکل بازمی‌گرداند\n> * [java.util.EnumSet#of()](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of(E))\n> * [javax.xml.bind.JAXBContext#createMarshaller()](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--) و متدهای مشابه دیگر.\n>\n> * کتابخانه‌ی JavaFX از الگوهای factory برای ایجاد کنترل‌های مختلف رابط کاربری متناسب با نیازهای محیط کاربر استفاده می‌کند.\n\n## مزایا و معایب الگوی factory\n\n### مزایا:\n\n> * پیاده‌سازی الگوی factory در برنامه جاوای شما، وابستگی بین پیاده‌سازی و کلاس‌هایی که استفاده می‌کند را کاهش می‌دهد.\n> * از [اصل Open/Closed](https://java-design-patterns.com/principles/#open-closed-principle) پشتیبانی می‌کند، زیرا سیستم می‌تواند انواع جدیدی را بدون تغییر کد موجود معرفی کند.\n\n### معایب:\n\n> * کد می‌تواند به دلیل معرفی چندین کلاس اضافی پیچیده‌تر شود.\n> * استفاده بیش از حد می‌تواند کد را کمتر خوانا کند اگر پیچیدگی ایجاد اشیاء کم یا غیرضروری باشد.\n\n## الگوهای طراحی مرتبط با جاوا\n\n> * الگوی [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): می‌توان آن را نوعی factory در نظر گرفت که با گروهی از محصولات کار می‌کند.\n> * الگوی [Singleton](https://java-design-patterns.com/patterns/singleton/): اغلب همراه با factory استفاده می‌شود تا اطمینان حاصل شود که یک کلاس تنها یک نمونه دارد.\n> * الگوی [Builder](https://java-design-patterns.com/patterns/builder/): ساخت یک شیء پیچیده را از نمایش آن جدا می‌کند، مشابه نحوه‌ای که factoryها مدیریت نمونه‌سازی را انجام می‌دهند.\n> * الگوی [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/): یک factory از محتوای غیرقابل تغییر با رابط‌های builder و factory جداگانه است.\n\n## منابع و اعتبارات\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0Rk5y)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/3UpTLrG)\n"
  },
  {
    "path": "localization/fr/README.md",
    "content": "<!-- Cette ligne doit restée vide pour des raisons de formatage\n    afin qu’on puisse avoir un affichage agréable comme sur un \n    site web par exemple -->\n\n# Les patrons de conception implémentés en Java\n\n![Java CI with Maven](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI%20with%20Maven/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-148-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n# Introduction\n\nLes patrons de conception (design patterns) sont les meilleures \npratiques formalisées qu’un programmeur peut utiliser pour résoudre\ndes problèmes courants lors de la conception d’une application \nou d’un système.\n\nLes patrons de conception peuvent accélérer le processus de\ndéveloppement en fournissant des paradigmes éprouvés.\n\nLa réutilisation de patrons de conception aide à se prémunir des problèmes subtils\nqui causent des problèmes majeurs, et cette pratique augmente la lisibilité\ndu code pour les développeurs et architectes familiers de ces concepts.\n\n# Commencer\n\nCe site présente des patrons de conception Java. Les solutions ont été développées \npar des développeurs et architectes expérimentés de la communauté open source.\nLes modèles peuvent être parcourus par leurs descriptions de haut niveau ou\nen regardant leur code source.\nLes exemples de code source sont bien commentés et peuvent être considérés\ncomme tutoriels de programmation sur la façon d’implémenter un modèle spécifique.\nNous utilisons les technologies Java open source les plus populaires et éprouvées.\n\nAvant de vous plonger dans le contenu, vous devriez vous familiariser avec divers\n[Principes de conception de logiciels](https://java-design-patterns.com/principles/).\n\nTous les modèles doivent être aussi simples que possible.\nVous devriez commencer par les principes KISS, YAGNI et \nFaites La Chose La Plus Simple Qui Fonctionne.\nLa complexité et les modèles ne devraient être introduits\nque lorsqu’ils sont nécessaires pour une extensibilité pratique.\n\nUne fois que vous êtes familiarisé avec ces concepts, vous pouvez commencer à explorer les\n[modèles de conception disponibles](https://java-design-patterns.com/patterns/)\npar n’importe laquelle des approches suivantes&nbsp;:\n\n- Recherchez un modèle spécifique par son nom.\n  Vous n’en trouvez pas&nbsp;? Veuillez signaler un nouveau modèle [ici](https://github.com/iluwatar/java-design-patterns/issues).\n- Utilisation de balises telles que `Performance`, `Gang of Four` ou `Data access`.\n- Utilisation des catégories de modèles, `Creational`, `Behavioral` et autres.\n\nNous espérons que vous trouverez les solutions orientées objet présentées\nsur ce site utiles dans vos architectures et que vous aurez autant \nde plaisir à les apprendre que nous en avons eu à les développer.\n\n# Comment contribuer\n\nSi vous souhaitez contribuer au projet, vous trouverez les informations pertinentes dans\nnotre [wiki développeur](https://github.com/iluwatar/java-design-patterns/wiki).\nNous vous aiderons répondrons à vos questions dans le [Gitter chatroom](https://gitter.im/iluwatar/java-design-patterns).\n\n# Licence\n\nCe projet est concédé sous les termes de la licence MIT.\n\n"
  },
  {
    "path": "localization/fr/abstract-document/README.md",
    "content": "---\ntitle: Abstract Document\ncategory: Structural\nlanguage: fr\ntag: \n - Extensibility\n---\n\n## Intention\n\nLe patron de conception \"Abstract Document\" est un modèle de conception structurelle qui vise à fournir un moyen\ncohérent de gérer les structures de données hiérarchiques et arborescentes en définissant une interface commune pour\ndifférents types de documents.\n\n## Explication\n\nLe patron de conception \"Abstract Document\" permet de gérer des propriétés supplémentaires non statiques. Ce modèle\nutilise le concept de traits pour assurer la sécurité des types et séparer les propriétés des différentes \nclasses dans un ensemble d'interfaces\n\nExemple concret\n\n>  Prenons l'exemple d'une voiture composée de plusieurs pièces. Cependant, nous ne savons pas si la voiture en question possède réellement toutes les pièces ou seulement certaines d'entre elles. Nos voitures sont dynamiques et extrêmement flexibles.\n\nEn clair\n\n> Le modèle de document abstrait permet d'attacher des propriétés à des objets indépendament de ces derniers.\n\nWikipedia dit\n\n> Un patron de conception structurelle orienté objet pour organiser des objets comme clé-valeur faiblement typés et exposer des données à l'aide de vues typées. L'objectif de ce modèle est d'atteindre un haut degré de flexibilité entre les composants\ndans un langage fortement typé où de nouvelles propriétés peuvent être ajoutées à l'arbre d'objets à la volée, sans perdre le soutien de la sécurité de type.\n\n**Exemple de programme**\n\nDéfinissons en premier les classes de base `Document` et `AbstractDocument`. Ils font en sorte que l'objet contienne une carte(map) de propriétés et un nombre quelconque d'objets enfants.\n\n```java\npublic interface Document {\n\n  Void put(String key, Object value);\n\n  Object get(String key);\n\n  <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);\n}\n\npublic abstract class AbstractDocument implements Document {\n\n  private final Map<String, Object> properties;\n\n  protected AbstractDocument(Map<String, Object> properties) {\n    Objects.requireNonNull(properties, \"properties map is required\");\n    this.properties = properties;\n  }\n\n  @Override\n  public Void put(String key, Object value) {\n    properties.put(key, value);\n    return null;\n  }\n\n  @Override\n  public Object get(String key) {\n    return properties.get(key);\n  }\n\n  @Override\n  public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {\n    return Stream.ofNullable(get(key))\n        .filter(Objects::nonNull)\n        .map(el -> (List<Map<String, Object>>) el)\n        .findAny()\n        .stream()\n        .flatMap(Collection::stream)\n        .map(constructor);\n  }\n  ...\n}\n```\nEnsuite, nous définissons une enumération  `Property` et un ensemble d'interfaces pour le type, le prix, le modèle et les pièces. Cela nous permet de créer une interface statique pour notre classe `Car`.\n\n```java\npublic enum Property {\n\n  PARTS, TYPE, PRICE, MODEL\n}\n\npublic interface HasType extends Document {\n\n  default Optional<String> getType() {\n    return Optional.ofNullable((String) get(Property.TYPE.toString()));\n  }\n}\n\npublic interface HasPrice extends Document {\n\n  default Optional<Number> getPrice() {\n    return Optional.ofNullable((Number) get(Property.PRICE.toString()));\n  }\n}\npublic interface HasModel extends Document {\n\n  default Optional<String> getModel() {\n    return Optional.ofNullable((String) get(Property.MODEL.toString()));\n  }\n}\n\npublic interface HasParts extends Document {\n\n  default Stream<Part> getParts() {\n    return children(Property.PARTS.toString(), Part::new);\n  }\n}\n```\n\nNous sommes maintenant prêts à présenter la classe `Car`.\n\n```java\npublic class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {\n\n  public Car(Map<String, Object> properties) {\n    super(properties);\n  }\n}\n```\n\nEnfin, voici comment nous construisons et utilisons la \"voiture\" dans un exemple complet.\n\n```java\n    LOGGER.info(\"Constructing parts and car\");\n\n    var wheelProperties = Map.of(\n        Property.TYPE.toString(), \"wheel\",\n        Property.MODEL.toString(), \"15C\",\n        Property.PRICE.toString(), 100L);\n\n    var doorProperties = Map.of(\n        Property.TYPE.toString(), \"door\",\n        Property.MODEL.toString(), \"Lambo\",\n        Property.PRICE.toString(), 300L);\n\n    var carProperties = Map.of(\n        Property.MODEL.toString(), \"300SL\",\n        Property.PRICE.toString(), 10000L,\n        Property.PARTS.toString(), List.of(wheelProperties, doorProperties));\n\n    var car = new Car(carProperties);\n\n    LOGGER.info(\"Here is our car:\");\n    LOGGER.info(\"-> model: {}\", car.getModel().orElseThrow());\n    LOGGER.info(\"-> price: {}\", car.getPrice().orElseThrow());\n    LOGGER.info(\"-> parts: \");\n    car.getParts().forEach(p -> LOGGER.info(\"\\t{}/{}/{}\",\n        p.getType().orElse(null),\n        p.getModel().orElse(null),\n        p.getPrice().orElse(null))\n    );\n\n    // Constructing parts and car\n    // Here is our car:\n    // model: 300SL\n    // price: 10000\n    // parts: \n    // wheel/15C/100\n    // door/Lambo/300\n```\n\n## Diagramme de classes\n\n![alt text](../../../abstract-document/etc/abstract-document.png \"Abstract Document Traits and Domain\")\n\n## Application\n\nCe modèle est particulièrement utile dans les scénarios où vous avez différents types de documents qui partagent des attributs ou des comportements communs, mais qui ont également des attributs ou des comportements uniques,  spécifiques à leurs types individuels. Voici quelques\nVoici quelques scénarios dans lesquels le patron de conception Abstract Document peut s'appliquer :\n\n* Systèmes de gestion de contenu (SGC) : dans un SGC (CMS en anglais), vous pouvez avoir différents types de contenu tels que des articles, des images, des vidéos, etc. Chaque type de contenu peut avoir des attributs communs tels que la date de création, l'auteur et les balises, mais aussi des attributs spécifiques tels que les dimensions de l'image pour les images ou la durée de la vidéo pour les vidéos.\n\n* Systèmes de gestion de fichiers : Si vous concevez un système de gestion de fichiers dans lequel différents types de fichiers doivent être gérés; tels que des documents, des images, des fichiers audio et des répertoires, le patron \"Abstract Document\" peut vous aider à fournir un moyen cohérent d'accéder à des attributs tels que la taille du fichier, la date de création, etc., tout en autorisant des attributs spécifiques tels que la résolution de l'image ou la durée de l'audio.\n\n* Systèmes de commerce électronique ou vente en ligne : Une plateforme de commerce électronique peut avoir différents types de produits tels que des produits physiques, des téléchargements numériques et des abonnements. Chaque type peut partager des attributs communs tels que le nom, le prix et la description, tout en ayant des attributs uniques tels que le poids d'expédition pour les produits physiques ou le lien de téléchargement pour les produits numériques.\n\n* Systèmes de dossiers médicaux : En médécine, les dossiers des patients peuvent inclure différents types de données telles que des données démographiques, des antécédents médicaux, des résultats d'examens et des prescriptions. Le patron de conception \"abstract document\" peut aider à gérer des attributs partagés tels que l'ID du patient et sa date de naissance, tout en s'adaptant à des attributs spécialisés tels que les résultats d'examens ou les médicaments prescrits.\n\n* Gestion de la configuration : Lorsqu'il s'agit de paramètres de configuration pour des applications logicielles, il peut y avoir différents types d'éléments de configuration, chacun avec son propre ensemble d'attributs. Le patron de conception \"abstract document\" peut être utilisé pour gérer ces éléments de configuration tout en garantissant une manière cohérente d'accéder à leurs attributs et de les manipuler.\n\n* Plateformes éducatives : Les systèmes éducatifs peuvent disposer de différents types de matériel pédagogique, tels que des contenus textuels, des vidéos, des quiz et des devoirs. Les attributs communs tels que le titre, l'auteur et la date de publication peuvent être partagés, tandis que les attributs uniques tels que la durée des vidéos ou les dates d'échéance des devoirs peuvent être spécifiques à chaque type.\n\n* Outils de gestion de projet : Dans les applications de gestion de projet, vous pouvez avoir différents types de tâches comme les tâches à faire, les étapes et les problèmes. Le modèle de document abstrait peut être utilisé pour gérer des attributs généraux tels que le nom de la tâche et le destinataire, tout en autorisant des attributs spécifiques tels que la date du jalon ou la priorité du problème.\n\nL'idée principale du patron de conception Abstract Document est de fournir un moyen flexible et extensible de gérer différents types de documents ou d'entités avec des attributs partagés et distincts. En définissant une interface commune et en l'implémentant\ndans les différents types de documents, vous pouvez obtenir une approche plus organisée et cohérente de la manipulation de structures de données complexes.\n\n## Crédits\n\n* [Wikipedia: Abstract Document Pattern](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)\n* [Martin Fowler: Dealing with properties](http://martinfowler.com/apsupp/properties.pdf)\n* [Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4)](https://www.amazon.com/gp/product/0470059028/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0470059028&linkId=e3aacaea7017258acf184f9f3283b492)\n"
  },
  {
    "path": "localization/fr/abstract-factory/README.md",
    "content": "---\ntitle: Abstract Factory\ncategory: Creational\nlanguage: fr\ntag:\n - Gang of Four\n---\n\n## Également connu sous le nom de\n\nKit\n\n## Intention\n\nFournir une interface permettant de créer des familles d'objets liés ou dépendants\nsans spécifier leurs classes concrètes.\n\n## Explication\n\nExemple concret\n\n> Pour créer un royaume, nous avons besoin d'objets ayant un thème commun. Le royaume elfique a besoin d'un roi elfique, d'un château elfique et d'une armée elfique, tandis que le royaume orque a besoin d'un roi orque, d'un château orque et d'une armée orque. Il existe une dépendance entre les objets du royaume.\n\nEn clair\n\n> Une usine d'usines ; une usine qui regroupe les usines individuelles mais liées/dépendantes sans spécifier leurs classes concrètes.\n\nWikipedia dit\n\n> Le modèle d'usine abstraite permet d'encapsuler un groupe d'usines individuelles ayant un thème commun sans spécifier leurs classes concrètes.\n\n**Exemple de programme**\n\nTraduction de l'exemple du royaume ci-dessus. Tout d'abord, nous avons quelques interfaces et implémentations pour les objets du royaume.\n\n```java\npublic interface Castle {\n  String getDescription();\n}\n\npublic interface King {\n  String getDescription();\n}\n\npublic interface Army {\n  String getDescription();\n}\n\n// Elven implementations ->\npublic class ElfCastle implements Castle {\n  static final String DESCRIPTION = \"This is the elven castle!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfKing implements King {\n  static final String DESCRIPTION = \"This is the elven king!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfArmy implements Army {\n  static final String DESCRIPTION = \"This is the elven Army!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\n// Orcish implementations similarly -> ...\n\n```\n\nEnsuite, nous avons l'abstraction et les implémentations de la fabrique de royaume.\n\n```java\npublic interface KingdomFactory {\n  Castle createCastle();\n  King createKing();\n  Army createArmy();\n}\n\npublic class ElfKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new ElfCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new ElfKing();\n  }\n\n  @Override\n  public Army createArmy() {\n    return new ElfArmy();\n  }\n}\n\npublic class OrcKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new OrcCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new OrcKing();\n  }\n  \n  @Override\n  public Army createArmy() {\n    return new OrcArmy();\n  }\n}\n```\n\nNous disposons maintenant d'une fabrique abstraite qui nous permet de créer une famille d'objets apparentés, par exemple la fabrique de royaume elfique crée un château elfique, un roi et une armée, etc.\n\n```java\nvar factory = new ElfKingdomFactory();\nvar castle = factory.createCastle();\nvar king = factory.createKing();\nvar army = factory.createArmy();\n\ncastle.getDescription();\nking.getDescription();\narmy.getDescription();\n```\n\nSortie du programme :\n\n```java\nThis is the elven castle!\nThis is the elven king!\nThis is the elven Army!\n```\n\nMaintenant, nous pouvons concevoir une fabrique pour nos différentes fabriques de royaumes. Dans cet exemple, nous avons créé `FactoryMaker`, responsable de retourner une instance de `ElfKingdomFactory` ou de `OrcKingdomFactory`.  \nLe client peut utiliser `FactoryMaker` pour créer la fabrique concrète désirée qui, à son tour, produira différents objets concrets (dérivés de `Army`, `King`, `Castle`).  \nDans cet exemple, nous avons également utilisé une énumération pour paramétrer le type de fabrique de royaume que le client va demander.\n```java\npublic static class FactoryMaker {\n\n    public enum KingdomType {\n        ELF, ORC\n    }\n\n    public static KingdomFactory makeFactory(KingdomType type) {\n        return switch (type) {\n            case ELF -> new ElfKingdomFactory();\n            case ORC -> new OrcKingdomFactory();\n            default -> throw new IllegalArgumentException(\"KingdomType not supported.\");\n        };\n    }\n}\n\n    public static void main(String[] args) {\n        var app = new App();\n\n        LOGGER.info(\"Elf Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));\n        LOGGER.info(app.getArmy().getDescription());\n        LOGGER.info(app.getCastle().getDescription());\n        LOGGER.info(app.getKing().getDescription());\n\n        LOGGER.info(\"Orc Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));\n        --similar use of the orc factory\n    }\n```\n\n## Diagramme de classes\n\n![alt text](../../../abstract-factory/etc/abstract-factory.urm.png \"Abstract Factory class diagram\")\n\n\n## Application\n\nUtiliser le patron de conception  \"abstract factory\" lorsque\n\n* Le système doit être indépendant de la manière dont ses produits sont créés, composés et représentés.\n* Le système doit être configuré avec l'une des multiples familles de produits.\n* La famille d'objets produits apparentés est conçue pour être utilisée ensemble, et vous devez faire respecter cette contrainte\n* Vous voulez fournir une bibliothèque de classes de produits, et vous voulez révéler seulement leurs interfaces, pas leurs implémentations.\n* La durée de vie de la dépendance est conceptuellement plus courte que la durée de vie du consommateur.\n* Vous avez besoin d'une valeur d'exécution pour construire une dépendance particulière.\n* Vous voulez décider quel produit appeler à partir d'une famille au moment de l'exécution.\n* Vous devez fournir un ou plusieurs paramètres qui ne sont connus qu'au moment de l'exécution avant de pouvoir résoudre une dépendance.\n* Lorsque vous avez besoin d'une cohérence entre les produits.\n* Vous ne voulez pas modifier le code existant lorsque vous ajoutez de nouveaux produits ou de nouvelles familles de produits au programme.\n\nExemples de cas d'utilisation\n\n* Choisir d'appeler l'implémentation appropriée de FileSystemAcmeService ou DatabaseAcmeService ou NetworkAcmeService au moment de l'exécution.\n* L'écriture de cas de tests unitaires devient beaucoup plus facile.\n* Outils d'interface utilisateur pour différents systèmes d'exploitation.\n\n## Conséquences\n\n* L'injection de dépendances en Java masque les dépendances des classes de service qui peuvent entraîner des erreurs d'exécution qui auraient été détectées au moment de la compilation.\n* Si le modèle est idéal pour la création d'objets prédéfinis, l'ajout de nouveaux objets peut s'avérer difficile.\n* Le code devient plus compliqué qu'il ne devrait l'être car un grand nombre de nouvelles interfaces et classes sont introduites en même temps que le modèle.\n\n## Tutoriels\n\n* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java)\n\n## Utilisations connues\n\n* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)\n* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)\n* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)\n\n## Modèles apparentés ou similaire (de la même catégorie)\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n\n## Crédits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/fr/active-object/README.md",
    "content": "---\ntitle: Active Object\ncategory: Concurrency\nlanguage: fr\ntag:\n - Performance\n---\n\n\n## Intention\n\nLe patron de conception des \"active object\" actifs dissocie l'exécution et l'invocation des méthodes pour les objets qui résident chacun dans leur fil de contrôle. L'objectif est d'introduire la concurrence en utilisant l'invocation asynchrone des méthodes et un planificateur pour traiter les demandes.\n\n## Explication\n\nLa classe qui met en œuvre le patron \"active object\", contiendra un mécanisme d'auto-synchronisation sans utiliser de méthodes \"synchronisées\".\n\n**Exemple concret**\n\n> Les orques sont connus pour leur caractère sauvage et leur âme indomptable. Il semble qu'ils aient leur propre système de contrôle basé sur leur comportement antérieur.\n\nPour mettre en œuvre une créature qui possède son propre mécanisme de contrôle et qui n'expose que son API et non l'exécution elle-même, nous pouvons utiliser le patron \"active-object\".\n\n\n**Exemple de programme**\n\n```java\npublic abstract class ActiveCreature{\n  private final Logger logger = LoggerFactory.getLogger(ActiveCreature.class.getName());\n\n  private BlockingQueue<Runnable> requests;\n  \n  private String name;\n  \n  private Thread thread;\n\n  public ActiveCreature(String name) {\n    this.name = name;\n    this.requests = new LinkedBlockingQueue<Runnable>();\n    thread = new Thread(new Runnable() {\n        @Override\n        public void run() {\n          while (true) {\n            try {\n              requests.take().run();\n            } catch (InterruptedException e) { \n              logger.error(e.getMessage());\n            }\n          }\n        }\n      }\n    );\n    thread.start();\n  }\n  \n  public void eat() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} is eating!\",name());\n          logger.info(\"{} has finished eating!\",name());\n        }\n      }\n    );\n  }\n\n  public void roam() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} has started to roam the wastelands.\",name());\n        }\n      }\n    );\n  }\n  \n  public String name() {\n    return this.name;\n  }\n}\n```\n\nNous pouvons constater que toute classe qui hérite de la classe ActiveCreature aura son propre fil de contrôle pour invoquer et exécuter les méthodes.\n\nPar exemple, la classe Orc :\n\n```java\npublic class Orc extends ActiveCreature {\n\n  public Orc(String name) {\n    super(name);\n  }\n\n}\n```\n\nDésormais, nous pouvons créer plusieurs créatures telles que des orques, leur dire de manger et d'errer, et elles s'exécuteront selon leur propre fil(mechanisme) de contrôle :\n\n```java\n  public static void main(String[] args) {  \n    var app = new App();\n    app.run();\n  }\n  \n  @Override\n  public void run() {\n    ActiveCreature creature;\n    try {\n      for (int i = 0;i < creatures;i++) {\n        creature = new Orc(Orc.class.getSimpleName().toString() + i);\n        creature.eat();\n        creature.roam();\n      }\n      Thread.sleep(1000);\n    } catch (InterruptedException e) {\n      logger.error(e.getMessage());\n    }\n    Runtime.getRuntime().exit(1);\n  }\n```\n\n## Diagramme de classe\n\n![alt text](../../../active-object/etc/active-object.urm.png \"Active Object class diagram\")\n\n## Tutoriels\n\n* [Android and Java Concurrency: The Active Object Pattern](https://www.youtube.com/watch?v=Cd8t2u5Qmvc)"
  },
  {
    "path": "localization/fr/acyclic-visitore/README.md",
    "content": "---\ntitle: Acyclic Visitor\ncategory: Behavioral\nlanguage: fr\ntag:\n - Extensibility\n---\n\n## Intention\n\nPermettre l'ajout de nouvelles fonctions à des hiérarchies de classes existantes sans affecter ces hiérarchies et sans\ncréer de cycles de dépendance gênants inhérents au pqtron de conception  GoF visitor.\n\n## Explication\n\nExemple concret\n\n> Nous disposons d'une hiérarchie de classes de modems. Les modems de cette hiérarchie doivent être visités \n> par un algorithme externe basé sur des critères de filtrage (s'agit-il d'un modem compatible Unix ou DOS).\n\nEn clair\n\n> Le visiteur acyclique permet d'ajouter des fonctions à des hiérarchies de classes existantes sans modifier ces dernières.\n\n[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) dit\n\n> Le modèle du visiteur acyclique permet d'ajouter de nouvelles fonctions aux hiérarchies de classes existantes\n> sans affecter ces hiérarchies et sans créer les cycles de dépendance inhérents au patron de conception GangOfFour visitor.\n\n**Exemple de Programme**\n\nCi-dessous la hierarchie `Modem`.\n\n```java\npublic abstract class Modem {\n  public abstract void accept(ModemVisitor modemVisitor);\n}\n\npublic class Zoom extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof ZoomVisitor) {\n      ((ZoomVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only ZoomVisitor is allowed to visit Zoom modem\");\n    }\n  }\n}\n\npublic class Hayes extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof HayesVisitor) {\n      ((HayesVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only HayesVisitor is allowed to visit Hayes modem\");\n    }\n  }\n}\n```\n\nEnsuite, nous introduisons la hiérarchie `ModemVisitor`.\n\n```java\npublic interface ModemVisitor {\n}\n\npublic interface HayesVisitor extends ModemVisitor {\n  void visit(Hayes hayes);\n}\n\npublic interface ZoomVisitor extends ModemVisitor {\n  void visit(Zoom zoom);\n}\n\npublic interface AllModemVisitor extends ZoomVisitor, HayesVisitor {\n}\n\npublic class ConfigureForDosVisitor implements AllModemVisitor {\n  ...\n  @Override\n  public void visit(Hayes hayes) {\n    LOGGER.info(hayes + \" used with Dos configurator.\");\n  }\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Dos configurator.\");\n  }\n}\n\npublic class ConfigureForUnixVisitor implements ZoomVisitor {\n  ...\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Unix configurator.\");\n  }\n}\n```\n\nEnfin, voici les visitors en action.\n\n```java\n    var conUnix = new ConfigureForUnixVisitor();\n    var conDos = new ConfigureForDosVisitor();\n    var zoom = new Zoom();\n    var hayes = new Hayes();\n    hayes.accept(conDos);\n    zoom.accept(conDos);\n    hayes.accept(conUnix);\n    zoom.accept(conUnix);   \n```\n\nSortie du programme :\n\n```\n    // Hayes modem used with Dos configurator.\n    // Zoom modem used with Dos configurator.\n    // Only HayesVisitor is allowed to visit Hayes modem\n    // Zoom modem used with Unix configurator.\n```\n\n## Diagramme de classes\n\n![alt text](../../../acyclic-visitor/etc/acyclic-visitor.png \"Acyclic Visitor\")\n\n## Application\n\nCe patron de conception peut être utilisé:\n\n* Pour ajouter ne nouvelle fonction à une hiérarchie existante sans avoir à modifier ou à affecter cette hiérarchie.\n* Lorsqu'il existe des fonctions qui opèrent sur une hiérarchie, mais qui n'appartiennent pas à la hiérarchie elle-même. Par exemple, le problème ConfigureForDOS / ConfigureForUnix / ConfigureForX.\n* Lorsque vous devez éffectuer des opérations très différentes sur un objet en fonction de son type.\n* Lorsque la hiérarchie des classes visitées sera fréquemment étendue avec de nouveaux dérivés de la classe Element.\n*Lorsque la recompilation, l'interconnexion, le réessai ou la redistribution des dérivés de Element sont très coûteux.\n\n## Tutoriel\n\n* [Acyclic Visitor Pattern Example](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html)\n\n## Consequences\n\nLe bon côté:\n\n* Pas de cycles de dépendance entre les hiérarchies de classes.\n* Il n'est pas nécessaire de recompiler tous les visiteurs si un nouveau visiteur est ajouté.\n* Ne provoque pas d'échec de compilation chez les visiteurs existants si la hiérarchie des classes a un nouveau membre.\n\nLe mauvais : \n\n* viole le [principe de substitution de Liskov](https://java-design-patterns.com/principles/#liskov-substitution-principle) en montrant qu'il peut accepter tous les visiteurs alors qu'il ne s'intéresse en réalité qu'à certains d'entre eux.\n* Une hiérarchie parallèle de visiteurs doit être créée pour tous les membres de la hiérarchie des classes visitables.\n\n## Patron de conception associé\n\n* [Pqtron de conception Visitor](https://java-design-patterns.com/patterns/visitor/)\n\n## Crédits\n\n* [Acyclic Visitor by Robert C. Martin](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf)\n* [Acyclic Visitor in WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor)\n"
  },
  {
    "path": "localization/fr/adapter/README.md",
    "content": "---\ntitle: Adapter\ncategory: Structural\nlanguage: fr\ntag:\n - Gang of Four\n---\n\n## Également connu sous le nom de\nWrapper\n\n## Intention\nConvertir l'interface d'une classe en une autre interface attendue par les clients. Adapter permet à des classes de travailler ensemble\nqui ne pourraient pas fonctionner autrement en raison d'interfaces incompatibles.\n\n## Explication\n\nExemple concrêt\n\n> Supposons que vous avez des photos sur votre carte mémoire et vous devez les transférer sur votre ordinateur. Pour ce faire, vous avez besoin d'un adaptateur qui est compatible aux ports de votre ordinateur pour vous permettre de connecter votre carte memoire à l'ordinateur. dans ce cas le lecteur de carte est un adapteur.\n> Un autre exemple serait le fameux adaptateur électrique ; une fiche à trois branches ne peut pas être branchée sur une prise à deux branches, elle doit utiliser un adaptateur électrique qui la rend compatible avec les prises à deux branches.\n> Un autre exemple serait celui d'un traducteur qui traduirait les mots prononcés par une personne à une autre.\n\nEn clair\n\n> Le patron adapter permet d'envelopper un objet autrement incompatible dans un adaptateur afin de le rendre compatible avec une autre classe.\n\nWikipedia dit\n\n> En génie logiciel, le pattron de conception  adapter est un pattron de conception logicielle qui permet d'utiliser l'interface d'une classe existante comme une autre interface. Il est souvent utilisé pour faire fonctionner des classes existantes avec d'autres sans modifier leur code source.\n\n**Exemple de programme**\n\nPrenons l'exemple d'un capitaine qui ne peut utiliser que des bateaux à rames et qui ne peut pas du tout naviguer.\n\nTout d'abord, nous avons les interfaces `RowingBoat` et `FishingBoat`\n\n```java\npublic interface RowingBoat {\n  void row();\n}\n\n@Slf4j\npublic class FishingBoat {\n  public void sail() {\n    LOGGER.info(\"The fishing boat is sailing\");\n  }\n}\n```\n\nEt le capitaine s'attend à ce qu'une implémentation de l'interface `RowingBoat` soit capable de se déplacer\n\n```java\npublic class Captain {\n\n  private final RowingBoat rowingBoat;\n  // default constructor and setter for rowingBoat\n  public Captain(RowingBoat rowingBoat) {\n    this.rowingBoat = rowingBoat;\n  }\n\n  public void row() {\n    rowingBoat.row();\n  }\n}\n```\n\nSupposons maintenant que les pirates arrivent et que notre capitaine doive s'échapper, mais qu'il ne dispose que d'un bateau de pêche. Nous devons créer un adaptateur qui permette au capitaine de faire fonctionner le bateau de pêche avec ses compétences de rameur.\n\n```java\n@Slf4j\npublic class FishingBoatAdapter implements RowingBoat {\n\n  private final FishingBoat boat;\n\n  public FishingBoatAdapter() {\n    boat = new FishingBoat();\n  }\n\n  @Override\n  public void row() {\n    boat.sail();\n  }\n}\n```\n\nEt maintenant, `Captain` peut utiliser le `FishingBoat` pour échapper aux pirates.\n\n```java\nvar captain = new Captain(new FishingBoatAdapter());\ncaptain.row();\n```\n\n## Diagramme des classes\n![alt text](../../../adapter/etc/adapter.urm.png \"Adapter class diagram\")\n\n## Application\nUtiliser le pattron de conception adapter lorsque\n\n* Vous souhaitez utiliser une classe existante, mais son interface ne correspond pas à celle dont vous avez besoin\n* Vous souhaitez créer une classe réutilisable qui coopère avec des classes non liées ou imprévues, c'est-à-dire des classes qui n'ont pas nécessairement d'interfaces compatibles.\n* Vous devez utiliser plusieurs sous-classes existantes, mais il n'est pas pratique d'adapter leur interface en les sous-classant toutes. Un adaptateur d'objet peut adapter l'interface de sa classe mère.\n* La plupart des applications utilisant des bibliothèques tierces utilisent des adaptateurs comme couche intermédiaire entre l'application et la bibliothèque tierce afin de découpler l'application de la bibliothèque. Si une autre bibliothèque doit être utilisée, il suffit de créer un adaptateur pour la nouvelle bibliothèque sans avoir à modifier le code de l'application.\n\n## Tutoriels\n\n* [Dzone](https://dzone.com/articles/adapter-design-pattern-in-java)\n* [Refactoring Guru](https://refactoring.guru/design-patterns/adapter/java/example)\n* [Baeldung](https://www.baeldung.com/java-adapter-pattern)\n\n## Conséquences\nLes adaptateurs de classe et d'objet présentent différents avantages. Un adaptateur de classe :\n\n*\tAdapte l'adaptateur à la cible en s'engageant dans une classe concrète d'adaptateur. Par conséquent, un adaptateur de classe ne fonctionnera pas si nous voulons adapter une classe et toutes ses sous-classes.\n*\tPermet à l'adaptateur de surcharger certains comportements de l'adaptaté puisque l'adaptateur est une sous-classe de l'adaptaté.\n*\tN'introduit qu'un seul objet, et aucune indirection de pointeur supplémentaire n'est nécessaire pour accéder à l'adaptateur.\n\nUn adaptateur d'objet :\n\n*\tPermet à un seul adaptateur de travailler avec de nombreux adaptatés, c'est-à-dire l'adaptateur lui-même et toutes ses sous-classes (le cas échéant). L'adaptateur peut également ajouter des fonctionnalités à tous les adaptatés en même temps.\n*\tRend plus difficile la modification du comportement de l'adapté. Il faudra créer des sous classes de l'adapta et faire en sorte que l'adaptateur se réfère à la sous-classe plutôt qu'à l'adapté lui-même.\n\n\n## Utilisations connues\n\n* [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)\n* [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)\n* [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-)\n* [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-)\n\n\n## Crédits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/fr/aggregator-microservices/README.md",
    "content": "---\ntitle: Aggregator Microservices\ncategory: Architectural\nlanguage: fr\ntag:\n- Cloud distributed\n- Decoupling\n- Microservices\n---\n\n## Intention\n\nL'utilisateur fait un appel unique au service d'agrégation, et ce dernier appelle ensuite chaque microservice approprié.\n\n## Explication\n\nExemple concret\n\n> Notre marché en ligne a besoin d'informations sur les produits et leur stock actuel. Elle fait appel à un service \n> d'agrégation qui, à son tour, appelle le microservice d'information sur les produits et le microservice d'inventaire\n> des produits et renvoie les informations combinées.\n\nEn clair\n\n> Aggregator Microservice collecte des éléments de données provenant de divers microservices et renvoie un agrégat pour traitement.. \n\nStack Overflow dit\n\n> Aggregator Microservice invoque plusieurs services pour réaliser la fonctionnalité requise par l'application.\n\n**Exemple de programme**\n\nCommençons par le modèle de données. Voici notre `Product`.\n\n```java\npublic class Product {\n  private String title;\n  private int productInventories;\n  // getters and setters ->\n  ...\n}\n```\n\nEnsuite, nous pouvons présenter notre microservice `Aggregator`. Il contient les clients `ProductInformationClient` et\n`ProductInventoryClient` pour appeler les microservices respectifs.\n\n```java\n@RestController\npublic class Aggregator {\n\n  @Resource\n  private ProductInformationClient informationClient;\n\n  @Resource\n  private ProductInventoryClient inventoryClient;\n\n  @RequestMapping(path = \"/product\", method = RequestMethod.GET)\n  public Product getProduct() {\n\n    var product = new Product();\n    var productTitle = informationClient.getProductTitle();\n    var productInventory = inventoryClient.getProductInventories();\n\n    //Fallback to error message\n    product.setTitle(requireNonNullElse(productTitle, \"Error: Fetching Product Title Failed\"));\n\n    //Fallback to default error inventory\n    product.setProductInventories(requireNonNullElse(productInventory, -1));\n\n    return product;\n  }\n}\n```\n\nVoici l'essentiel de la mise en œuvre du microservice d'information. Le microservice dInventory est similaire, il renvoie simplement l'inventaire.\n\n```java\n@RestController\npublic class InformationController {\n  @RequestMapping(value = \"/information\", method = RequestMethod.GET)\n  public String getProductTitle() {\n    return \"The Product Title.\";\n  }\n}\n```\n\nL'appel à notre API REST `Aggregator` renvoie les informations sur le produit.\n\n```bash\ncurl http://localhost:50004/product\n{\"title\":\"The Product Title.\",\"productInventories\":5}\n```\n\n## Class diagram\n\n![alt text](../../../aggregator-microservices/aggregator-service/etc/aggregator-service.png \"Aggregator Microservice\")\n\n## Application\n\nUtilisez le modèle de microservices agrégateur lorsque vous avez besoin d'une API unifiée pour différents microservices, quel que soit l'appareil client.\n\n## Crédits\n\n* [Microservice Design Patterns](http://web.archive.org/web/20190705163602/http://blog.arungupta.me/microservice-design-patterns/)\n* [Microservices Patterns: With examples in Java](https://www.amazon.com/gp/product/1617294543/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617294543&linkId=8b4e570267bc5fb8b8189917b461dc60)\n* [Architectural Patterns: Uncover essential patterns in the most indispensable realm of enterprise architecture](https://www.amazon.com/gp/product/B077T7V8RC/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=B077T7V8RC&linkId=c34d204bfe1b277914b420189f09c1a4)\n"
  },
  {
    "path": "localization/fr/ambassador/README.md",
    "content": "---\ntitle: Ambassador\ncategory: Structural\nlanguage: fr\ntag:\n  - Decoupling\n  - Cloud distributed\n---\n\n## Intention\n\nFournir une instance de service d'assistance à un client et décharger une fonctionnalité commune d'une ressource partagée.\n\n## Explication\n\nExemple concret\n\n> Un service distant a de nombreux clients qui accèdent à une fonction qu'il fournit. Le service est une application\n> ancienne qu'il est impossible de mettre à jour. Le grand nombre de requêtes des utilisateurs entraîne des problèmes de\n> connectivité. De nouvelles règles relatives à la fréquence des requêtes doivent être mises en œuvre, ainsi que des \n> contrôles de latence et une journalisation côté client.\n\nEn clair\n\n>Avec le modèle Ambassador, nous pouvons mettre en œuvre des interrogations moins fréquentes de la part des clients,\n> ainsi que des contrôles de latence et une journalisation.\n\nLa documentation de Microsoft indique que\n\n> Un service ambassadeur peut être considéré comme un mandataire hors processus qui se trouve au même endroit que le client.\n> Ce pattron peut être utile pour décharger les tâches courantes de connectivité client telles que la surveillance, \n> la journalisation, le routage, la sécurité (comme TLS) et les modèles de résilience d'une manière indépendante du langage.\n> Il est souvent utilisé avec des applications anciennes ou d'autres applications difficiles à modifier, afin d'étendre \n> leurs capacités de mise en réseau. Il peut également permettre à une équipe spécialisée de mettre en œuvre ces fonctionnalités.\n\n**Exemple de programme**\n\nEn gardant en mémoire l'introduction ci-dessus, nous reproduirons cette fonctionnalité dans ce exemple. Nous avons une interface\nimplémentée par un service distant aussi bien que service ambassadeur\nWe have an interface implemented \nby the remote service as well as the ambassador service :\n\n```java\ninterface RemoteServiceInterface {\n    long doRemoteFunction(int value) throws Exception;\n}\n```\n\nUn sercive distant représenté comme un singleton.\n\n```java\n@Slf4j\npublic class RemoteService implements RemoteServiceInterface {\n    private static RemoteService service = null;\n\n    static synchronized RemoteService getRemoteService() {\n        if (service == null) {\n            service = new RemoteService();\n        }\n        return service;\n    }\n\n    private RemoteService() {}\n\n    @Override\n    public long doRemoteFunction(int value) {\n        long waitTime = (long) Math.floor(Math.random() * 1000);\n\n        try {\n            sleep(waitTime);\n        } catch (InterruptedException e) {\n            LOGGER.error(\"Thread sleep interrupted\", e);\n        }\n\n        return waitTime >= 200 ? value * 10 : -1;\n    }\n}\n```\n\nUn service ambassadeur ajoute des fonctionnalités supplémentaires à l'instar de la journalisation et des contrôles de latence\n\n```java\n@Slf4j\npublic class ServiceAmbassador implements RemoteServiceInterface {\n  private static final int RETRIES = 3;\n  private static final int DELAY_MS = 3000;\n\n  ServiceAmbassador() {\n  }\n\n  @Override\n  public long doRemoteFunction(int value) {\n    return safeCall(value);\n  }\n\n  private long checkLatency(int value) {\n    var startTime = System.currentTimeMillis();\n    var result = RemoteService.getRemoteService().doRemoteFunction(value);\n    var timeTaken = System.currentTimeMillis() - startTime;\n\n    LOGGER.info(\"Time taken (ms): \" + timeTaken);\n    return result;\n  }\n\n  private long safeCall(int value) {\n    var retries = 0;\n    var result = (long) FAILURE;\n\n    for (int i = 0; i < RETRIES; i++) {\n      if (retries >= RETRIES) {\n        return FAILURE;\n      }\n\n      if ((result = checkLatency(value)) == FAILURE) {\n        LOGGER.info(\"Failed to reach remote: (\" + (i + 1) + \")\");\n        retries++;\n        try {\n          sleep(DELAY_MS);\n        } catch (InterruptedException e) {\n          LOGGER.error(\"Thread sleep state interrupted\", e);\n        }\n      } else {\n        break;\n      }\n    }\n    return result;\n  }\n}\n```\n\nUn client dispose d'un service ambassadeur local utilisé pour interagir avec le service distant :\n\n```java\n@Slf4j\npublic class Client {\n  private final ServiceAmbassador serviceAmbassador = new ServiceAmbassador();\n\n  long useService(int value) {\n    var result = serviceAmbassador.doRemoteFunction(value);\n    LOGGER.info(\"Service result: \" + result);\n    return result;\n  }\n}\n```\n\nVoici deux clients utilisant le service.\n\n```java\npublic class App {\n  public static void main(String[] args) {\n    var host1 = new Client();\n    var host2 = new Client();\n    host1.useService(12);\n    host2.useService(73);\n  }\n}\n```\n\nCi-déssous la sortie du programme :\n\n```java\nTime taken (ms): 111\nService result: 120\nTime taken (ms): 931\nFailed to reach remote: (1)\nTime taken (ms): 665\nFailed to reach remote: (2)\nTime taken (ms): 538\nFailed to reach remote: (3)\nService result: -1\n```\n\n## Class diagram\n\n![alt text](../../../ambassador/etc/ambassador.urm.png \"Ambassador class diagram\")\n\n## Application\n\n* Le pattron ambassador s'applique lorsque l'on travaille avec un service distant existant qui ne peut pas être modifié ou\nqui serait extrêmement difficile à modifier. Les fonctions de connectivité peuvent être mises en œuvre sur le client sans\nqu'il soit nécessaire d'apporter des modifications au service distant.\n* Ambassador fournit une interface locale pour un service distant.\n* Ambassador assure la journalisation, la coupure de circuit, les tentatives et la sécurité sur le client.\n\n## Cas d'utilisation typique\n\n* Contrôler l'accès à un autre objet\n* Mise en œuvre de la journalisation\n* Mettre en œuvre d'un coupe-circuit\n* Décharger les tâches de service à distance\n* Faciliter la connexion au réseau\n\n## Utilisations connues\n\n* [Kubernetes-native API gateway for microservices](https://github.com/datawire/ambassador)\n\n## Modèles connexes\n\n* [Proxy](https://java-design-patterns.com/patterns/proxy/)\n\n## Crédits\n\n* [Ambassador pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/ambassador)\n* [Designing Distributed Systems: Patterns and Paradigms for Scalable, Reliable Services](https://www.amazon.com/s?k=designing+distributed+systems&sprefix=designing+distri%2Caps%2C156&linkCode=ll2&tag=javadesignpat-20&linkId=a12581e625462f9038557b01794e5341&language=en_US&ref_=as_li_ss_tl)\n"
  },
  {
    "path": "localization/fr/anti-corruption-layer/README.md",
    "content": "---\ntitle: \"Patron de conception Couche Anti-Corruption en Java : Assurer l'intégrité du système face aux systèmes hérités\"\nshortTitle: Couche Anti-Corruption\ndescription: \"Découvrez comment le patron de conception de la Couche Anti-Corruption (Anti-Corruption Layer Pattern) aide à découpler les sous-systèmes, à prévenir la corruption des données et à faciliter une intégration fluide dans les applications Java.\"\ncategory: Integration\nlanguage: fr\ntag:\n  - Architecture\n  - Decoupling\n  - Integration\n  - Isolation\n  - Layered architecture\n  - Migration\n  - Modernization\n  - Refactoring\n  - Wrapping\n---\n\n## Aussi connu sous le nom de\n\n* ACL\n* Couche d'interface\n* Couche de traduction\n\n## Intention du modèle de conception de la couche anti-corruption\n\nLa couche anti-corruption (ACL) est un patron de conception essentiel dans le développement Java, en particulier pour l'intégration des systèmes et le maintien de l'intégrité des données. Implémentez une couche de façade ou d'adaptateur entre différents sous-systèmes qui ne partagent pas la même sémantique. Elle traduit entre différents formats de données et systèmes, garantissant que l'intégration entre les systèmes ne conduit pas à une corruption de la logique métier ou à une perte d'intégrité des données.\n\n## Explication détaillée du patron de conception Couche Anti-Corruption avec des exemples concrets\n\nExemple concret\n\n> Cet exemple montre comment la couche anti-corruption garantit une intégration fluide entre les systèmes hérités et les plateformes modernes, essentiel pour maintenir l'intégrité de la logique métier lors de la migration du système.\n> \n> Imaginez une grande entreprise de vente au détail qui passe d'un ancien logiciel de gestion des stocks à une nouvelle plateforme moderne. Le système hérité est utilisé depuis des décennies et contient des règles métier complexes et des formats de données incompatibles avec le nouveau système. Au lieu de connecter directement le nouveau système à l'ancien, l'entreprise implémente une couche anti-corruption (ACL).\n> \n> L'ACL agit comme un médiateur, traduisant et adaptant les données entre les deux systèmes. Lorsque le nouveau système demande des données d'inventaire, l'ACL traduit la requête dans un format compréhensible par le système hérité, récupère les données, puis les traduit à nouveau dans un format adapté au nouveau système. Cette approche garantit que le nouveau système reste indépendant des complexités du système hérité, évitant ainsi la corruption des données et de la logique métier tout en facilitant une transition en douceur.\n\nEn termes simples\n\n> Le patron de conception Couche Anti-Corruption protège un système des complexités et des changements des systèmes externes en fournissant une couche de traduction intermédiaire.\n\n[La documentation de Microsoft](https://learn.microsoft.com/fr-fr/azure/architecture/patterns/anti-corruption-layer) dit\n\n> Implémentez une couche de façade ou d’adaptateur entre différents sous-systèmes qui ne partagent pas la même sémantique. Cette couche traduit les requêtes qu’un sous-système envoie à l’autre sous-système. Utilisez ce modèle pour vous assurer que la conception d’une application n’est pas limitée par les dépendances aux sous-systèmes externes. Ce modèle a d’abord été décrit par Eric Evans dans Domain-Driven Design (Conception orientée domaine).\n\n## Exemple programmatique du patron de conception de Couche Anti-Corruption en Java\n\nLe modèle ACL en Java fournit une couche intermédiaire qui traduit les formats de données, garantissant que l'intégration entre différents systèmes ne conduit pas à une corruption des données.\n\nVoici 2 systèmes de commande de magasin : `Legacy` et `Modern`.\n\nCes systèmes ont des modèles de domaine différents et doivent fonctionner simultanément. Comme ils travaillent de manière indépendante, les commandes peuvent provenir soit du système `Legacy`, soit du système `Modern`. Par conséquent, le système qui reçoit la commande `orderLegacy` doit vérifier si cette commande est valide et non présente dans l'autre système. Ensuite, il peut placer la commande `orderLegacy` dans son propre système.\n\nMais pour cela, le système doit connaître le modèle de domaine de l'autre système et pour éviter cela, la couche anti-corruption (ACL) est introduite. L'ACL est une couche qui traduit le modèle de domaine du système `Legacy` en celui du système `Modern` et inversement. De plus, elle masque toutes les autres opérations avec l'autre système, découplant les systèmes.\n\nModèle de domaine du système `Legacy` :\n\n```java\npublic class LegacyOrder {\n    private String id;\n    private String customer;\n    private String item;\n    private String qty;\n    private String price;\n}\n```\n\nModèle de domaine du système `Modern` :\n\n```java\npublic class ModernOrder {\n    private String id;\n    private Customer customer;\n\n    private Shipment shipment;\n\n    private String extra;\n}\n\npublic class Customer {\n    private String address;\n}\n\npublic class Shipment {\n    private String item;\n    private String qty;\n    private String price;\n}\n```\n\nCouche anti-corruption :\n\n```java\npublic class AntiCorruptionLayer {\n\n    @Autowired\n    private ModernShop modernShop;\n\n    @Autowired\n    private LegacyShop legacyShop;\n\n    public Optional<LegacyOrder> findOrderInModernSystem(String id) {\n        return modernShop.findOrder(id).map(o -> /* map to legacyOrder*/);\n    }\n\n    public Optional<ModernOrder> findOrderInLegacySystem(String id) {\n        return legacyShop.findOrder(id).map(o -> /* map to modernOrder*/);\n    }\n\n}\n```\n\nLa connexion entre les systèmes. Chaque fois que le système `Legacy` ou `Modern` doit communiquer avec l'autre, l'ACL doit être utilisée pour éviter de corrompre le modèle de domaine actuel. L'exemple ci-dessous montre comment le système `Legacy` passe une commande avec une validation du système `Modern`.\n\n```java\npublic class LegacyShop {\n    @Autowired\n    private AntiCorruptionLayer acl;\n\n    public void placeOrder(LegacyOrder legacyOrder) throws ShopException {\n\n        String id = legacyOrder.getId();\n\n        Optional<LegacyOrder> orderInModernSystem = acl.findOrderInModernSystem(id);\n\n        if (orderInModernSystem.isPresent()) {\n            // la commande est déjà dans le système moderne\n        } else {\n            // passer la commande dans le système actuel\n        }\n    }\n}\n```\n## Quand utiliser le patron de conception Couche Anti-Corruption en Java\n\nUtilisez ce modèle lorsque :\n\n* Une migration est prévue en plusieurs étapes, mais l'intégration entre les nouveaux et les anciens systèmes doit être maintenue\n* Deux ou plusieurs sous-systèmes ont une sémantique différentes, mais doivent tout de même communiquer\n* Lors de l'intégration avec des systèmes hérités ou des systèmes externes où une intégration directe pourrait polluer le modèle de domaine du nouveau système\n* Dans des scénarios où différents sous-systèmes au sein d'un système plus large utilisent différents formats ou structures de données\n* Lorsqu'il est nécessaire de garantir un découplage lâche entre différents sous-systèmes ou services externes pour faciliter la maintenance et la scalabilité\n\n## Tutoriels sur le patron de conception Couche Anti-Corruption en Java\n\n* [Couche Anti-Corruption](https://learn.microsoft.com/fr-fr/azure/architecture/patterns/anti-corruption-layer)\n* [Patron de conception Couche Anti-Corruption](https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/acl.html)\n\n## Applications concrètes du modèle de couche anti-corruption en Java\n\n* Architectures microservices où les services individuels doivent communiquer sans être étroitement couplés aux schémas de données des autres\n* Intégration des systèmes d'entreprise, notamment lors de l'intégration des systèmes modernes avec des systèmes hérités\n* Dans des contextes délimités au sein de la Domain-Driven Design (DDD) pour maintenir l'intégrité d'un modèle de domaine lors de l'interaction avec des systèmes ou sous-systèmes externes\n\n## Avantages et compromis du modèle de couche anti-corruption\n\nAvantages :\n\n* Protège l'intégrité du modèle de domaine en fournissant une frontière claire\n* Favorise le découplage lâche entre les systèmes, rendant le système plus résilient aux changements des systèmes externes\n* Facilite un code plus propre et plus facile à maintenir en isolant le code d'intégration de la logique métier\n\nCompromis :\n\n* Introduit une complexité supplémentaire et un potentiel de surcharge de performance en raison du processus de traduction\n* Nécessite un effort supplémentaire dans la conception et la mise en œuvre pour s'assurer que la couche est efficace sans devenir un goulet d'étranglement\n* Peut entraîner une duplication des modèles s'il n'est pas géré avec soin\n\n## Patron de conception Java associés\n\n* [Adaptateur (Adapter)](https://java-design-patterns.com/patterns/adapter/): La couche anti-corruption peut être implémentée en utilisant le modèle Adaptateur pour traduire entre différents formats ou structures de données\n* [Façade](https://java-design-patterns.com/patterns/facade/): La couche anti-corruption peut être vue comme une forme spécialisée du modèle Façade utilisée pour isoler différents sous-systèmes\n* [Passerelle (Gateway)](https://java-design-patterns.com/patterns/gateway/): La couche anti-corruption peut être utilisée comme une passerelle vers des systèmes externes pour fournir une interface unifiée\n\n## Références et Crédits\n\n* [Domain-Driven Design : Résoudre la complexité au cœur du logiciel](https://amzn.to/3vptcJz)\n* [Implémentation du Domain-Driven Design](https://amzn.to/3ISOSRA)\n* [Patterns of Enterprise Application Architecture (Modèles d'architecture des applications d'entreprise)](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "localization/fr/api-gateway/README.md",
    "content": "---\ntitle: API Gateway\ncategory: Architectural\nlanguage: fr\ntag:\n  - Cloud distributed\n  - Decoupling\n  - Microservices\n---\n\n## Intention\n\nRegrouper les appels aux microservices en un seul endroit, la passerelle API. \nL'utilisateur fait un seul appel à la passerelle API, qui appelle ensuite chaque microservice concerné.\n\n## Explication\n\nAvec les pattrons microservices, un client peut avoir besoin de données provenant de plusieurs microservices différents.\nSi le client appelait directement chaque microservice, cela pourrait contribuer à allonger les temps de chargement, \npuisque le client devrait faire une requete réseau pour chaque microservice appelé. En outre, le fait que le client appelle\nchaque microservice directement le lie à ce microservice - si les implémentations internes des microservices changent\n(par exemple, si deux microservices sont combinés) ou si l'emplacement (hôte et port) d'un microservice change, \nalors chaque client qui utilise ces microservices doit être informé de l'existence de ce microservice.\n\nL'objectif du pattron API Gateway est d'atténuer certains de ces problèmes. Dans le pattron API Gateway une entité supplémentaire\n(la passerelle API) est placée entre le client et les microservices. Le rôle de la passerelle API est d'agréger les appels aux microservices. Plutôt que le client\nappelle chaque microservice individuellement, le client appelle la passerelle API une seule fois.\nLa passerelle API appelle alors chacun des microservices dont le client a besoin.\n\nExemple concret\n\n> Nous mettons en œuvre des microservices et un pattron API Gateway pour un site de commerce en ligne.\n> Dans ce système la passerelle API fait des appels aux microservices Image et Prix.\n\nEn clair\n\n> Pour un système mis en œuvre à l'aide d'une architecture de microservices,\n> API Gateway est le point d'entrée unique qui regroupe les appels aux différents microservices.\n\nWikipedia dit\n\n> La passerelle API est un serveur qui agit comme un front-end API, reçoit les requêtes API, applique des politiques de\n> limitation et de sécurité, transmet les requêtes au service back-end et renvoie la réponse au demandeur. \n> Une passerelle comprend souvent un moteur de transformation pour orchestrer et modifier les demandes et les réponses à la volée.\n> Une passerelle peut également fournir des fonctionnalités telles que la collecte de données analytiques et la mise en cache. \n> La passerelle peut fournir des fonctionnalités pour prendre en charge l'authentification, l'autorisation, la sécurité, \n> l'audit et la conformité réglementaire.\n\n**Exemple de programme**\n\nCette mise en œuvre montre à quoi pourrait ressembler le pattron de conception API Gateway pour un site de commerce électronique.\nLa passerelle `ApiGateway` fait des appels aux microservices Image et Price en utilisant respectivement `ImageClientImpl` et `PriceClientImpl` respectivement.\nLes clients qui consultent le site sur un ordinateur de bureau peuvent voir à la fois les informations sur le prix et l'image d'un produit.\nLes clients qui consultent le site sur un ordinateur de bureau peuvent voir à la fois des informations sur le prix et l'image d'un produit,\ndonc la passerelle appelle les deux microservices et regroupe les données dans le modèle `DesktopProduct`.\nCependant, les utilisateurs mobiles ne voient que les informations sur le prix ; Ils ne voient pas l'image du produit.\nPour les utilisateurs mobiles, la passerelle `ApiGateway` ne récupère que les informations de prix, qu'elle utilise pour remplir le modèle `MobileProduct`.\n\nVoici l'implémentation du microservice Image.\n\n```java\npublic interface ImageClient {\n  String getImagePath();\n}\n\npublic class ImageClientImpl implements ImageClient {\n  @Override\n  public String getImagePath() {\n    var httpClient = HttpClient.newHttpClient();\n    var httpGet = HttpRequest.newBuilder()\n        .GET()\n        .uri(URI.create(\"http://localhost:50005/image-path\"))\n        .build();\n\n    try {\n      var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n      return httpResponse.body();\n    } catch (IOException | InterruptedException e) {\n      e.printStackTrace();\n    }\n\n    return null;\n  }\n}\n```\n\nVoici l'implémentation du microservice Price.\n\n```java\npublic interface PriceClient {\n  String getPrice();\n}\n\npublic class PriceClientImpl implements PriceClient {\n\n  @Override\n  public String getPrice() {\n    var httpClient = HttpClient.newHttpClient();\n    var httpGet = HttpRequest.newBuilder()\n        .GET()\n        .uri(URI.create(\"http://localhost:50006/price\"))\n        .build();\n\n    try {\n      var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n      return httpResponse.body();\n    } catch (IOException | InterruptedException e) {\n      e.printStackTrace();\n    }\n\n    return null;\n  }\n}\n```\n\nNous voyons ici comment API Gateway fait correspondre les demandes aux microservices.\n\n```java\npublic class ApiGateway {\n\n  @Resource\n  private ImageClient imageClient;\n\n  @Resource\n  private PriceClient priceClient;\n\n  @RequestMapping(path = \"/desktop\", method = RequestMethod.GET)\n  public DesktopProduct getProductDesktop() {\n    var desktopProduct = new DesktopProduct();\n    desktopProduct.setImagePath(imageClient.getImagePath());\n    desktopProduct.setPrice(priceClient.getPrice());\n    return desktopProduct;\n  }\n\n  @RequestMapping(path = \"/mobile\", method = RequestMethod.GET)\n  public MobileProduct getProductMobile() {\n    var mobileProduct = new MobileProduct();\n    mobileProduct.setPrice(priceClient.getPrice());\n    return mobileProduct;\n  }\n}\n```\n\n## Diagramme de clqsses\n![alt text](../../../api-gateway/etc/api-gateway.png \"API Gateway\")\n\n## Application\n\nUtilisez le pattron de passerelle API lorsque\n\n* Vous utilisez une architecture de microservices et avez besoin d'un point d'agrégation unique pour vos appels de microservices.\n\n## Tutoriels\n\n* [Exploring the New Spring Cloud Gateway](https://www.baeldung.com/spring-cloud-gateway)\n* [Spring Cloud - Gateway](https://www.tutorialspoint.com/spring_cloud/spring_cloud_gateway.htm)\n* [Getting Started With Spring Cloud Gateway](https://dzone.com/articles/getting-started-with-spring-cloud-gateway)\n\n## Crédits\n\n* [microservices.io - API Gateway](http://microservices.io/patterns/apigateway.html)\n* [NGINX - Building Microservices: Using an API Gateway](https://www.nginx.com/blog/building-microservices-using-an-api-gateway/)\n* [Microservices Patterns: With examples in Java](https://www.amazon.com/gp/product/1617294543/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617294543&linkId=ac7b6a57f866ac006a309d9086e8cfbd)\n* [Building Microservices: Designing Fine-Grained Systems](https://www.amazon.com/gp/product/1491950358/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1491950358&linkId=4c95ca9831e05e3f0dadb08841d77bf1)\n"
  },
  {
    "path": "localization/fr/arrange-act-assert/README.md",
    "content": "---\ntitle: Arrange/Act/Assert\ncategory: Idiom\nlanguage: fr\ntag:\n - Testing\n---\n\n## Aussi connu sous le nom de\n\nGiven/When/Then\n\n## Intention\n\nArrange/Act/Assert (AAA) est un pattron d'organisation des tests unitaires.\nIl décompose les tests en trois étapes claires et distinctes :\n\n1. Arrange : éffectuer la configuration et l'initialisation requises pour le test.\n2. Act : éffectuer la ou les actions requises pour le test.\n3. Assert: Vérifier le(s) résultat(s) du test.\n\n## Explication\n\nCe pattron présente plusieurs avantages importants. Il crée une séparation claire entre la mise en place d'un test d'un test,\nles opérations et les résultats. Cette structure rend le code plus facile à lire et à comprendre. \nSi vous placez les étapes dans l'ordre et que vous formatez votre code source pour les séparer, vous pouvez parcourir un test et comprendre rapidement ce qu'il fait.\n\nIl impose également un certain degré de discipline lors de l'écriture des tests. Vous devez penser clairement les trois étapes de votre test.\nIl est plus naturel d'écrire les tests en même temps, puisque vous avez déjà un plan.\n\nExemple\n\n> Pour écrire des tests unitaire clairs et compréhensibles.\n\nEn clair\n\n> Arrange/Act/Assert est un pattron de conception de tests qui organise les tests en trois étapes pour une maintenance facile.\n\nWikiWikiWeb dit\n\n> Arrange/Act/Assert est un pattron pour organiser et formater un code dans les methodes de test unitaire.\n\n**Exemple de programme**\n\nCommençons par présenter notre classe  `Cash` qui subira un test unitaire.\n\n```java\npublic class Cash {\n\n  private int amount;\n\n  Cash(int amount) {\n    this.amount = amount;\n  }\n\n  void plus(int addend) {\n    amount += addend;\n  }\n\n  boolean minus(int subtrahend) {\n    if (amount >= subtrahend) {\n      amount -= subtrahend;\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  int count() {\n    return amount;\n  }\n}\n```\n\nEnsuite, nous rédigeons nos tests unitaires suivant le pattron Arrange/Act/Assert.\nNotez les étapes clairement séparées pour chaque test unitaire.\n\n```java\nclass CashAAATest {\n\n  @Test\n  void testPlus() {\n    //Arrange\n    var cash = new Cash(3);\n    //Act\n    cash.plus(4);\n    //Assert\n    assertEquals(7, cash.count());\n  }\n\n  @Test\n  void testMinus() {\n    //Arrange\n    var cash = new Cash(8);\n    //Act\n    var result = cash.minus(5);\n    //Assert\n    assertTrue(result);\n    assertEquals(3, cash.count());\n  }\n\n  @Test\n  void testInsufficientMinus() {\n    //Arrange\n    var cash = new Cash(1);\n    //Act\n    var result = cash.minus(6);\n    //Assert\n    assertFalse(result);\n    assertEquals(1, cash.count());\n  }\n\n  @Test\n  void testUpdate() {\n    //Arrange\n    var cash = new Cash(5);\n    //Act\n    cash.plus(6);\n    var result = cash.minus(3);\n    //Assert\n    assertTrue(result);\n    assertEquals(8, cash.count());\n  }\n}\n```\n\n## Application\n\nLe pattron Arrange/Act/Assert peut être utilisé lorsque :\n\n* Vous avez besoin d'organiser vos tests unitaire pour qu'il soit facile à lire, maintenir et améliorer.\n\n## Crédits\n\n* [Arrange, Act, Assert: What is AAA Testing?](https://blog.ncrunch.net/post/arrange-act-assert-aaa-testing.aspx)\n* [Bill Wake: 3A – Arrange, Act, Assert](https://xp123.com/articles/3a-arrange-act-assert/)\n* [Martin Fowler: GivenWhenThen](https://martinfowler.com/bliki/GivenWhenThen.html)\n* [xUnit Test Patterns: Refactoring Test Code](https://www.amazon.com/gp/product/0131495054/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0131495054&linkId=99701e8f4af2f7e8dd50d720c9b63dbf)\n* [Unit Testing Principles, Practices, and Patterns](https://www.amazon.com/gp/product/1617296279/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617296279&linkId=74c75cf22a63c3e4758ae08aa0a0cc35)\n* [Test Driven Development: By Example](https://www.amazon.com/gp/product/0321146530/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0321146530&linkId=5c63a93d8c1175b84ca5087472ef0e05)\n"
  },
  {
    "path": "localization/fr/async-method-invocation/README.md",
    "content": "---\ntitle: Async Method Invocation\ncategory: Concurrency\nlanguage: fr\ntag:\n - Reactive\n---\n\n## Intention\n\nLe pattron de conception Asynchronous method invocation est un pattron dans lequel le thread appelé n'est pas bloqué en \nattendant la fin de l'exécution des tâches.\nCe pattron permet le traitement parallèle de plusieurs tâches indépendantes et récupère les résultats via les callback ou patiente jusqu'à la fin.\n\n## Explication\n\nExemple concret\n\n> Le lancement de fusées spatiales est une activité passionnante. Le commandant de la mission donne\n> l'ordre de lancement et, après un temps indéterminé, la fusée réussit son lancement ou échoue lamentablement.\n\nEn clair\n\n> Asynchronous method invocation démarre l'exécution de la tâche et retourne directement avant la fin de l'exécution de la tâche.\n> Les résultats de l'exécution des tâches sont retournés après.\n\nWikipedia dit\n\n> Dans la programmation multithread, asynchronous method invocation (AMI), également connue sous le nom de asynchronous method calls \n> ou le pattron asynchronous, est un pattron de conception dans lequel le site d'appel n'est pas bloqué en attendant que le code appelé se termine.\n> Au lieu de cela, le thread appelant est informé de l'arrivée de la réponse. L'interrogation pour une réponse est une option non souhaitée.\n\n**Exemple de programme**\n\nDans cet exemple, nous lançons des fusées spatiales et déployons des rovers lunaires.\n\nL'application démontre le pattron async method invocation. Les éléments clés de ce modèle sont `AsyncResult`\nqui est un conteneur intermédiaire pour une valeur évaluée de manière asynchrone, `AsyncCallback` qui peut être fourni\npour être exécuté à la fin de la tâche et `AsyncExecutor` qui gère l'exécution des tâches asynchrones. qui gère l'exécution des tâches asynchrones.\n\n```java\npublic interface AsyncResult<T> {\n  boolean isCompleted();\n  T getValue() throws ExecutionException;\n  void await() throws InterruptedException;\n}\n```\n\n```java\npublic interface AsyncCallback<T> {\n  void onComplete(T value, Optional<Exception> ex);\n}\n```\n\n```java\npublic interface AsyncExecutor {\n  <T> AsyncResult<T> startProcess(Callable<T> task);\n  <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback);\n  <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException;\n}\n```\n\n`ThreadAsyncExecutor` est une implémentation de `AsyncExecutor`. Certains de ses éléments clés sont décrits ci-dessous.\n\n```java\npublic class ThreadAsyncExecutor implements AsyncExecutor {\n\n  @Override\n  public <T> AsyncResult<T> startProcess(Callable<T> task) {\n    return startProcess(task, null);\n  }\n\n  @Override\n  public <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback) {\n    var result = new CompletableResult<>(callback);\n    new Thread(\n            () -> {\n              try {\n                result.setValue(task.call());\n              } catch (Exception ex) {\n                result.setException(ex);\n              }\n            },\n            \"executor-\" + idx.incrementAndGet())\n        .start();\n    return result;\n  }\n\n  @Override\n  public <T> T endProcess(AsyncResult<T> asyncResult)\n      throws ExecutionException, InterruptedException {\n    if (!asyncResult.isCompleted()) {\n      asyncResult.await();\n    }\n    return asyncResult.getValue();\n  }\n}\n```\n\nNous sommes ensuite prêts à lancer quelques fusées pour voir comment tout fonctionne ensemble.\n\n```java\npublic static void main(String[] args) throws Exception {\n  // construct a new executor that will run async tasks\n  var executor = new ThreadAsyncExecutor();\n\n  // start few async tasks with varying processing times, two last with callback handlers\n  final var asyncResult1 = executor.startProcess(lazyval(10, 500));\n  final var asyncResult2 = executor.startProcess(lazyval(\"test\", 300));\n  final var asyncResult3 = executor.startProcess(lazyval(50L, 700));\n  final var asyncResult4 = executor.startProcess(lazyval(20, 400), callback(\"Deploying lunar rover\"));\n  final var asyncResult5 =\n      executor.startProcess(lazyval(\"callback\", 600), callback(\"Deploying lunar rover\"));\n\n  // emulate processing in the current thread while async tasks are running in their own threads\n  Thread.sleep(350); // Oh boy, we are working hard here\n  log(\"Mission command is sipping coffee\");\n\n  // wait for completion of the tasks\n  final var result1 = executor.endProcess(asyncResult1);\n  final var result2 = executor.endProcess(asyncResult2);\n  final var result3 = executor.endProcess(asyncResult3);\n  asyncResult4.await();\n  asyncResult5.await();\n\n  // log the results of the tasks, callbacks log immediately when complete\n  log(\"Space rocket <\" + result1 + \"> launch complete\");\n  log(\"Space rocket <\" + result2 + \"> launch complete\");\n  log(\"Space rocket <\" + result3 + \"> launch complete\");\n}\n```\n\nVoici la sortie de la console du programme.\n\n```java\n21:47:08.227 [executor-2] INFO com.iluwatar.async.method.invocation.App - Space rocket <test> launched successfully\n21:47:08.269 [main] INFO com.iluwatar.async.method.invocation.App - Mission command is sipping coffee\n21:47:08.318 [executor-4] INFO com.iluwatar.async.method.invocation.App - Space rocket <20> launched successfully\n21:47:08.335 [executor-4] INFO com.iluwatar.async.method.invocation.App - Deploying lunar rover <20>\n21:47:08.414 [executor-1] INFO com.iluwatar.async.method.invocation.App - Space rocket <10> launched successfully\n21:47:08.519 [executor-5] INFO com.iluwatar.async.method.invocation.App - Space rocket <callback> launched successfully\n21:47:08.519 [executor-5] INFO com.iluwatar.async.method.invocation.App - Deploying lunar rover <callback>\n21:47:08.616 [executor-3] INFO com.iluwatar.async.method.invocation.App - Space rocket <50> launched successfully\n21:47:08.617 [main] INFO com.iluwatar.async.method.invocation.App - Space rocket <10> launch complete\n21:47:08.617 [main] INFO com.iluwatar.async.method.invocation.App - Space rocket <test> launch complete\n21:47:08.618 [main] INFO com.iluwatar.async.method.invocation.App - Space rocket <50> launch complete\n```\n\n# Diagramme de classes\n\n![alt text](../../../async-method-invocation/etc/async-method-invocation.png \"Async Method Invocation\")\n\n## Application\n\nUtilisez le pattron async method invocation lorsque\n\n* Vous avez plusieurs tâches indépendantes qui peuvent être exécutées en parallèle\n* Vous devez améliorer les performances d'un groupe de tâches séquentielles\n* Vous disposez d'une capacité de traitement limitée ou de tâches à long terme et l'appelant ne doit pas attendre que les tâches soient exécutées.\n\n## Application concrete\n\n* [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html)\n* [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)\n* [ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html)\n* [Task-based Asynchronous Pattern](https://msdn.microsoft.com/en-us/library/hh873175.aspx)\n"
  },
  {
    "path": "localization/fr/balking/README.md",
    "content": "---\ntitle: Balking\ncategory: Concurrency\nlanguage: fr\ntag:\n - Decoupling\n---\n\n## Intention\n\nLe pattron de conception Balking est utilisé pour empêcher un objet d'exécuter un certain code \ns'il est dans un état incomplet ou inapproprié.\n\n## Explication\n\nExemple concret\n\n> Sur une machine à laver, un bouton de démarrage permet de lancer le lavage du linge. Lorsque la machine à laver est inactive,\n> le bouton fonctionne comme prévu, mais si la machine est déjà en train de laver, le bouton ne fait rien.\n\nEn clair\n\n> En utilisant le pattron balking, un certain code ne s'exécute que si l'objet se trouve dans un état particulier.\n\nWikipedia dit\n\n> Le pattron de conception balking est un pattron de conception de logiciel qui n'exécute une action sur un objet que\n> lorsque l'objet se trouve dans un état particulier. Par exemple, si un objet lit des fichiers ZIP et qu'une méthode \n> appelante invoque une méthode get sur l'objet alors que le fichier ZIP n'est pas ouvert, l'objet rejette la demande.\n\n**Exemple de programme**\n\nDans cet exemple d'implémentation, `WashingMachine` est un objet qui peut être dans deux états : ENABLED et WASHING.\nSi la machine est ENABLED, l'état change en WASHING en utilisant une méthode thread-safe. D'autre part, si elle a déjà\nété lavée et qu'un autre thread exécute `wash()`, elle ne le fera pas et terminera sans rien faire.\n\nVoici les parties pertinentes de la classe `WashingMachine`\n\n```java\n@Slf4j\npublic class WashingMachine {\n\n  private final DelayProvider delayProvider;\n  private WashingMachineState washingMachineState;\n\n  public WashingMachine(DelayProvider delayProvider) {\n    this.delayProvider = delayProvider;\n    this.washingMachineState = WashingMachineState.ENABLED;\n  }\n\n  public WashingMachineState getWashingMachineState() {\n    return washingMachineState;\n  }\n\n  public void wash() {\n    synchronized (this) {\n      var machineState = getWashingMachineState();\n      LOGGER.info(\"{}: Actual machine state: {}\", Thread.currentThread().getName(), machineState);\n      if (this.washingMachineState == WashingMachineState.WASHING) {\n        LOGGER.error(\"Cannot wash if the machine has been already washing!\");\n        return;\n      }\n      this.washingMachineState = WashingMachineState.WASHING;\n    }\n    LOGGER.info(\"{}: Doing the washing\", Thread.currentThread().getName());\n    this.delayProvider.executeAfterDelay(50, TimeUnit.MILLISECONDS, this::endOfWashing);\n  }\n\n  public synchronized void endOfWashing() {\n    washingMachineState = WashingMachineState.ENABLED;\n    LOGGER.info(\"{}: Washing completed.\", Thread.currentThread().getId());\n  }\n}\n```\n\nVoici l'interface simple `DelayProvider` utilisée par le `WashingMachine`.\n\n```java\npublic interface DelayProvider {\n  void executeAfterDelay(long interval, TimeUnit timeUnit, Runnable task);\n}\n```\n\nNous allons maintenant présenter l'application en utilisant le `WashingMachine`.\n\n```java\n  public static void main(String... args) {\n    final var washingMachine = new WashingMachine();\n    var executorService = Executors.newFixedThreadPool(3);\n    for (int i = 0; i < 3; i++) {\n      executorService.execute(washingMachine::wash);\n    }\n    executorService.shutdown();\n    try {\n      executorService.awaitTermination(10, TimeUnit.SECONDS);\n    } catch (InterruptedException ie) {\n      LOGGER.error(\"ERROR: Waiting on executor service shutdown!\");\n      Thread.currentThread().interrupt();\n    }\n  }\n```\n\nVoici la sortie de la console du programme.\n\n```\n14:02:52.268 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Actual machine state: ENABLED\n14:02:52.272 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Doing the washing\n14:02:52.272 [pool-1-thread-3] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-3: Actual machine state: WASHING\n14:02:52.273 [pool-1-thread-3] ERROR com.iluwatar.balking.WashingMachine - Cannot wash if the machine has been already washing!\n14:02:52.273 [pool-1-thread-1] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-1: Actual machine state: WASHING\n14:02:52.273 [pool-1-thread-1] ERROR com.iluwatar.balking.WashingMachine - Cannot wash if the machine has been already washing!\n14:02:52.324 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - 14: Washing completed.\n```\n\n## Diagramme de classe\n\n![alt text](../../../balking/etc/balking.png \"Balking\")\n\n## Application\n\nUtilisé le pattron balking lorsque :\n\n* Vous souhaitez invoquer une action sur un objet uniquement lorsqu'il se trouve dans un état spécifique\n* Les objets ne sont généralement que dans un état susceptible d'évoluer temporairement, mais pour une durée inconnue.\n\n## Pattron de conception apparentés\n\n* [Guarded Suspension Pattern](https://java-design-patterns.com/patterns/guarded-suspension/)\n* [Double Checked Locking Pattern](https://java-design-patterns.com/patterns/double-checked-locking/)\n\n## Crédits\n\n* [Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML, 2nd Edition, Volume 1](https://www.amazon.com/gp/product/0471227293/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0471227293&linkId=0e39a59ffaab93fb476036fecb637b99)\n"
  },
  {
    "path": "localization/fr/bridge/README.md",
    "content": "---\ntitle: Bridge\ncategory: Structural\nlanguage: fr\ntag:\n - Gang of Four\n---\n\n## Également connu sous le nom de\n\nHandle/Body\n\n## Intention\n\nDécoupler une abstraction de son implémentation afin que les deux puissent varier indépendamment.\n\n## Explication\n\nExemple concret\n\n> Considérons que vous avez une arme avec différents enchantements, et que vous êtes censé permettre de mélanger \n> différentes armes avec différents enchantements. Que feriez-vous ? Créer plusieurs copies de chaque arme pour chacun\n> des enchantements ou simplement créer un enchantement séparé et l'appliquer à l'arme en fonction des besoins ? \n> Le pattron de concepetion Bridge pattern vous permet de faire la deuxième solution.\n\nEn clair\n\n> Bridge pattern consiste à préférer la composition à l'héritage. Les détails de la mise en œuvre(implémentation) \n> sont transférés d'une hiérarchie à un autre objet ayant une hiérarchie distincte.\n\nWikipedia dit\n\n> Bridge pattern est un patron de conception utilisé en génie logiciel qui vise à \"découpler une abstraction de sa \n> mise en œuvre(son implémention) de manière à ce que les deux puissent varier de manière indépendante\"\n\n**Exemple de programme**\n\nServons nous de notre exemple d'arme ci-dessus. Nous avons ici la hiérarchie `Weapon` :\n\n```java\npublic interface Weapon {\n  void wield();\n  void swing();\n  void unwield();\n  Enchantment getEnchantment();\n}\n\npublic class Sword implements Weapon {\n\n  private final Enchantment enchantment;\n\n  public Sword(Enchantment enchantment) {\n    this.enchantment = enchantment;\n  }\n\n  @Override\n  public void wield() {\n    LOGGER.info(\"The sword is wielded.\");\n    enchantment.onActivate();\n  }\n\n  @Override\n  public void swing() {\n    LOGGER.info(\"The sword is swinged.\");\n    enchantment.apply();\n  }\n\n  @Override\n  public void unwield() {\n    LOGGER.info(\"The sword is unwielded.\");\n    enchantment.onDeactivate();\n  }\n\n  @Override\n  public Enchantment getEnchantment() {\n    return enchantment;\n  }\n}\n\npublic class Hammer implements Weapon {\n\n  private final Enchantment enchantment;\n\n  public Hammer(Enchantment enchantment) {\n    this.enchantment = enchantment;\n  }\n\n  @Override\n  public void wield() {\n    LOGGER.info(\"The hammer is wielded.\");\n    enchantment.onActivate();\n  }\n\n  @Override\n  public void swing() {\n    LOGGER.info(\"The hammer is swinged.\");\n    enchantment.apply();\n  }\n\n  @Override\n  public void unwield() {\n    LOGGER.info(\"The hammer is unwielded.\");\n    enchantment.onDeactivate();\n  }\n\n  @Override\n  public Enchantment getEnchantment() {\n    return enchantment;\n  }\n}\n```\n\nVoici la hiérarchie des enchantements distincts :\n\n```java\npublic interface Enchantment {\n  void onActivate();\n  void apply();\n  void onDeactivate();\n}\n\npublic class FlyingEnchantment implements Enchantment {\n\n  @Override\n  public void onActivate() {\n    LOGGER.info(\"The item begins to glow faintly.\");\n  }\n\n  @Override\n  public void apply() {\n    LOGGER.info(\"The item flies and strikes the enemies finally returning to owner's hand.\");\n  }\n\n  @Override\n  public void onDeactivate() {\n    LOGGER.info(\"The item's glow fades.\");\n  }\n}\n\npublic class SoulEatingEnchantment implements Enchantment {\n\n  @Override\n  public void onActivate() {\n    LOGGER.info(\"The item spreads bloodlust.\");\n  }\n\n  @Override\n  public void apply() {\n    LOGGER.info(\"The item eats the soul of enemies.\");\n  }\n\n  @Override\n  public void onDeactivate() {\n    LOGGER.info(\"Bloodlust slowly disappears.\");\n  }\n}\n```\n\nVoici les deux hiérarchies en action :\n\n```java\nLOGGER.info(\"The knight receives an enchanted sword.\");\nvar enchantedSword = new Sword(new SoulEatingEnchantment());\nenchantedSword.wield();\nenchantedSword.swing();\nenchantedSword.unwield();\n\nLOGGER.info(\"The valkyrie receives an enchanted hammer.\");\nvar hammer = new Hammer(new FlyingEnchantment());\nhammer.wield();\nhammer.swing();\nhammer.unwield();\n```\n\nVoici la sortie de la console.\n\n```\nThe knight receives an enchanted sword.\nThe sword is wielded.\nThe item spreads bloodlust.\nThe sword is swung.\nThe item eats the soul of enemies.\nThe sword is unwielded.\nBloodlust slowly disappears.\nThe valkyrie receives an enchanted hammer.\nThe hammer is wielded.\nThe item begins to glow faintly.\nThe hammer is swung.\nThe item flies and strikes the enemies finally returning to owner's hand.\nThe hammer is unwielded.\nThe item's glow fades.\n```\n\n## Diagramme de classes\n\n![alt text](../../../bridge/etc/bridge.urm.png \"Bridge class diagram\")\n\n## Application\n\nUtilisez Bridge pattern lorsque\n\n* Vous souhaitez éviter un lien permanent entre une abstraction et son implémentation. Cela peut être le cas, par exemple, lorsque l'implémentation doit être sélectionnée ou changée au moment de l'exécution.\n* Les abstractions et leurs implémentations doivent être extensibles par des classes filles. Dans ce cas, Bridge pattern vous permet de combiner les différentes abstractions et implémentations et de les étendre indépendamment.\n* Les changements dans l'implémentation d'une abstraction ne doivent pas avoir d'impact sur les clients, c'est-à-dire que leur code ne doit pas être recompilé.\n* Vous avez une prolifération de classes. Une telle hiérarchie de classes indique la nécessité de diviser un objet en deux parties. Rumbaugh utilise le terme de \"généralisations imbriquées\" pour désigner de telles hiérarchies de classes.\n* Vous souhaitez partager une implémentation entre plusieurs objets (peut-être en utilisant le comptage de références), et ce fait doit être caché au client. Un exemple simple est la classe String de Coplien, dans laquelle plusieurs objets peuvent partager la même représentation d'une chaîne de caractères.\n\n## Tutoriel\n\n* [Bridge Pattern Tutorial](https://www.journaldev.com/1491/bridge-design-pattern-java)\n\n## Crédits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/fr/builder/README.md",
    "content": "---\ntitle: \"Patron de conception 'Builder' en Java: Créer des objets personnalisés avec clarté\"\nshortTitle: Builder\ndescription: \"Découvrez le patron de conception Builder en Java, un puissant modèle de création qui simplifie la construction d'objets. Apprenez à séparer la construction d'un objet complexe de sa représentation avec des exemples pratiques et des cas d'utilisation.\"\ncategory: Creational\nlanguage: fr\ntag:\n  - Gang of Four\n  - Instantiation\n  - Object composition\n---\n\n## Intention du Patron de conception Builder\n\nLe patron de conception Builder en Java, un modèle de création fondamental, permet de construire des objets complexes étape par étape. Il sépare la construction d'un objet complexe de sa représentation afin que le même processus de construction puisse créer différentes représentations.\n\n## Explication détaillée du patron de conception Builder avec des exemples réels\n\nExemple réel\n\n> Le patron de conception Builder en Java est particulièrement utile dans des scénarios où la création d'un objet nécessite de nombreux paramètres.\n> \n> Imaginez que vous créez un sandwich personnalisable dans un restaurant. Le patron de conception Builder dans ce contexte impliquerait un `SandwichBuilder` qui vous permet de spécifier chaque composant du sandwich, comme le type de pain, de viande, de fromage, de légumes, et de condiments. Au lieu de savoir comment assembler le sandwich de zéro, vous utilisez le `SandwichBuilder` pour ajouter chaque composant désiré étape par étape, assurant que vous obtenez exactement le sandwich que vous souhaitez. Cette séparation entre la construction et la représentation finale du produit garantit que le même processus de construction peut produire différents types de sandwiches selon les composants spécifiés.\n\nEn termes simples\n\n> Il vous permet de créer différentes versions d'un objet tout en évitant la \"pollution\" des constructeurs. Utile lorsque plusieurs variantes d'un objet sont possibles, ou lorsqu'il y a beaucoup d'étapes impliquées dans la création d'un objet.\n\nWikipedia dit\n\n> Le modèle Builder est un modèle de conception de création d'objets qui vise à trouver une solution au problème des constructeurs à paramètres multiples, aussi connu sous le nom d'antipattern du constructeur télescopique.\n\nAvec cela à l'esprit, expliquons ce qu'est l'antipattern du constructeur télescopique. À un moment donné, nous avons tous rencontré un constructeur comme celui-ci:\n\n```java\npublic Hero(Profession profession,String name,HairType hairType,HairColor hairColor,Armor armor,Weapon weapon){\n    // Assignation des valeurs\n}\n```\n\nComme vous pouvez le voir, le nombre de paramètres du constructeur peut rapidement devenir écrasant, ce qui rend difficile de comprendre leur agencement. De plus, cette liste de paramètres pourrait continuer à s'allonger si vous décidez d'ajouter plus d'options à l'avenir. Cela s'appelle l'antipattern du constructeur télescopique.\n\n## Exemple programmatique du Modèle Builder en Java\n\nDans cet exemple du patron de conception Builder en Java, nous construisons différents types d'objets `Hero` avec des attributs variés.\n\nImaginez un générateur de personnages pour un jeu de rôle. La solution la plus simple est de laisser l'ordinateur générer le personnage pour vous. Cependant, si vous préférez sélectionner manuellement les détails du personnage comme la profession, le genre, la couleur des cheveux, etc., la création de personnage devient un processus étape par étape qui se termine une fois toutes les sélections effectuées.\n\nUne approche plus logique est d'utiliser le modèle Builder. D'abord, considérons le `Hero` que nous voulons créer:\n\n```java\npublic final class Hero {\n    private final Profession profession;\n    private final String name;\n    private final HairType hairType;\n    private final HairColor hairColor;\n    private final Armor armor;\n    private final Weapon weapon;\n\n    private Hero(Builder builder) {\n        this.profession = builder.profession;\n        this.name = builder.name;\n        this.hairColor = builder.hairColor;\n        this.hairType = builder.hairType;\n        this.weapon = builder.weapon;\n        this.armor = builder.armor;\n    }\n}\n````\n\nEnsuite, nous avons le `Builder`:\n\n```java\n  public static class Builder {\n    private final Profession profession;\n    private final String name;\n    private HairType hairType;\n    private HairColor hairColor;\n    private Armor armor;\n    private Weapon weapon;\n\n    public Builder(Profession profession, String name) {\n        if (profession == null || name == null) {\n            throw new IllegalArgumentException(\"profession and name can not be null\");\n        }\n        this.profession = profession;\n        this.name = name;\n    }\n\n    public Builder withHairType(HairType hairType) {\n        this.hairType = hairType;\n        return this;\n    }\n\n    public Builder withHairColor(HairColor hairColor) {\n        this.hairColor = hairColor;\n        return this;\n    }\n\n    public Builder withArmor(Armor armor) {\n        this.armor = armor;\n        return this;\n    }\n\n    public Builder withWeapon(Weapon weapon) {\n        this.weapon = weapon;\n        return this;\n    }\n\n    public Hero build() {\n        return new Hero(this);\n    }\n}\n```\n\nEnsuite, il peut être utilisé comme suit:\n\n```java\n  public static void main(String[] args) {\n\n    var mage = new Hero.Builder(Profession.MAGE, \"Riobard\")\n            .withHairColor(HairColor.BLACK)\n            .withWeapon(Weapon.DAGGER)\n            .build();\n    LOGGER.info(mage.toString());\n\n    var warrior = new Hero.Builder(Profession.WARRIOR, \"Amberjill\")\n            .withHairColor(HairColor.BLOND)\n            .withHairType(HairType.LONG_CURLY).withArmor(Armor.CHAIN_MAIL).withWeapon(Weapon.SWORD)\n            .build();\n    LOGGER.info(warrior.toString());\n\n    var thief = new Hero.Builder(Profession.THIEF, \"Desmond\")\n            .withHairType(HairType.BALD)\n            .withWeapon(Weapon.BOW)\n            .build();\n    LOGGER.info(thief.toString());\n}\n```\n\nSortie du programme:\n\n```\n16:28:06.058 [main] INFO com.iluwatar.builder.App -- This is a mage named Riobard with black hair and wielding a dagger.\n16:28:06.060 [main] INFO com.iluwatar.builder.App -- This is a warrior named Amberjill with blond long curly hair wearing chain mail and wielding a sword.\n16:28:06.060 [main] INFO com.iluwatar.builder.App -- This is a thief named Desmond with bald head and wielding a bow.\n```\n\n## Diagramme de classe du Modèle Builder\n\n![Builder](./etc/builder.urm.png \"Diagramme de classe du patron Builder\")\n\n## Quand utiliser le patron de conception Builder en Java\n\nUtilisez le modèle Builder lorsque\n\n* Le patron de conception Builder est idéal pour les applications Java nécessitant la création d'objets complexes.\n* L'algorithme pour créer un objet complexe doit être indépendant des parties qui composent l'objet et de la façon dont elles sont assemblées.\n* Le processus de construction doit permettre différentes représentations de l'objet construit.\n* Il est particulièrement utile lorsqu'un produit nécessite beaucoup d'étapes pour être créé et lorsque ces étapes doivent être exécutées dans un ordre spécifique.\n\n## Tutoriels Java sur le Modèle Builder\n\n\n* [Patron de conception Builder (DigitalOcean)](https://www.journaldev.com/1425/builder-design-pattern-in-java)\n* [Builder (Refactoring Guru)](https://refactoring.guru/design-patterns/builder)\n* [Exploring Joshua Bloch’s Builder design pattern in Java (Java Magazine)](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java)\n\n## Applications réelles du Modèle Builder en Java\n\n* StringBuilder en Java pour construire des chaînes de caractères.\n* java.lang.StringBuffer utilisé pour créer des objets chaîne modifiables.\n* Java.nio.ByteBuffer ainsi que des tampons similaires comme FloatBuffer, IntBuffer, et d'autres.\n* javax.swing.GroupLayout.Group#addComponent()\n* Divers constructeurs d'IHM dans les IDE qui créent des composants d'interface utilisateur.\n* Toutes les implémentations de [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)\n* [Constructeurs Apache Camel](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)\n* [Apache Commons Option.Builder](https://commons.apache.org/proper/commons-cli/apidocs/org/apache/commons/cli/Option.Builder.html)\n\n## Avantages et inconvénients du Modèle Builder\n\nAvantages:\n\n* Plus de contrôle sur le processus de construction par rapport à d'autres modèles de création.\n* Permet de construire des objets étape par étape, de différer les étapes de construction ou d'exécuter des étapes de manière récursive.\n* Peut construire des objets qui nécessitent un assemblage complexe de sous-objets. Le produit final est détaché des parties qui le composent ainsi que de leur processus d'assemblage.\n* Principe de responsabilité unique. Vous pouvez isoler le code de construction complexe de la logique métier du produit.\n\nInconvénients:\n\n* La complexité générale du code peut augmenter car le modèle nécessite la création de plusieurs nouvelles classes.\n* Peut augmenter l'utilisation de la mémoire en raison de la nécessité de créer plusieurs objets builder.\n\n## Patrons de conception Java liés\n\n* [Fabrique abstraite (Abstract Factory)](https://java-design-patterns.com/patterns/abstract-factory/): Peut être utilisé en conjonction avec le patron de conception Builder pour construire des parties d'un objet complexe.\n* [Prototype](https://java-design-patterns.com/patterns/prototype/): Les builders créent souvent des objets à partir d'un prototype.\n* [Step Builder](https://java-design-patterns.com/patterns/step-builder/): Il s'agit d'une variation du modèle Builder qui génère un objet complexe en utilisant une approche étape par étape. Le modèle Step Builder est un bon choix lorsque vous avez besoin de construire un objet avec un grand nombre de paramètres optionnels, et que vous souhaitez éviter l'antipattern du constructeur télescopique.\n\n## Références et crédits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "localization/fr/business-delegate/README.md",
    "content": "---\ntitle: \"Business Delegate Pattern en Java: Simplifier l'intéraction avec les services métiers\"\nshortTitle: Business Delegate\ndescription: \"Apprenez à connaître le patron Business Delegate en Java. Ce patron ajoute une niveau d'abstraction en la couche de présentation et la couche métier, assurant un couplage faible et une intéraction simplifiée entre les sevices.\"\ncategory: Structural\nlanguage: fr\ntag:\n  - Business\n  - Decoupling\n  - Delegation\n  - Enterprise patterns\n  - Layered architecture\n---\n\n## Aussi connu sous le nom de \n\n* Service Representative\n\n## But du modèle de conception Business-Delegate\n\nLe modèle Business Delegate est un modèle de conception structurel en Java qui ajoute un niveau d'abstraction en la couche de pésentation et la couche métier. Utiliser ce modèle garanti un couplage faible entre les couches et encapsule les informations sur la localisation, la connexion et les interactions des objets métiers qui composent l'application.\n\n## Explication détaillée et exemples concrets\n\nExemple concret\n\n> Dans une application d'entreprise utilisant Java EE, le modèle Business-Delegate permet de gérer les interactions entre les différents services commerciaux.\n> \n> Imaginez un restaurant où le personnel de service sert d'intermédiaire entre les clients et la cuisine. Lorsqu'un client passe une commande, le serveur l'apporte à la cuisine, transmet toute demande spécifique et ramène ensuite le plat préparé au client. Le personnel de salle fait abstraction de la complexité des opérations de cuisine, ce qui permet aux chefs de se concentrer uniquement sur la préparation des plats, sans avoir à interagir directement avec les clients. Cette configuration permet au service à la clientèle (niveau de présentation) et à la cuisine (service commercial) de fonctionner de manière indépendante et efficace. Le personnel de service joue le rôle de délégué commercial, en gérant la communication et en garantissant des interactions harmonieuses entre les deux secteurs distincts.\n\nEn clair\n\n> Le Business-Delegate ajoute une couche d'abstraction entre le niveau de présentation et le niveau commercial.\n\nDéfinition Wikipedia : \n\n> Business Delegate est un modèle de conception Java EE. Ce modèle vise à réduire le couplage entre les services métier et le niveau de présentation connecté, et à masquer les détails de mise en œuvre des services (y compris la consultation et l'accessibilité de l'architecture EJB). Les délégués commerciaux agissent comme un adaptateur permettant d'invoquer des objets commerciaux à partir du niveau de présentation.\n\n## Example de programme\n\nLe code Java suivant montre comment mettre en œuvre le modèle de délégué commercial. Ce modèle est particulièrement utile dans les applications nécessitant un couplage lâche et une interaction efficace entre les services.\n\nUne application pour téléphone portable promet de diffuser en continu n'importe quel film existant sur votre appareil. Elle capture la chaîne de recherche de l'utilisateur et la transmet au Business Delegate. Ce dernier sélectionne le service de streaming vidéo le plus approprié et lit la vidéo à partir de là.\n\nTout d'abord, nous disposons d'une abstraction pour les services de streaming vidéo et de quelques implémentations.\n\n```java\npublic interface VideoStreamingService {\n    void doProcessing();\n}\n\n@Slf4j\npublic class NetflixService implements VideoStreamingService {\n    @Override\n    public void doProcessing() {\n        LOGGER.info(\"NetflixService is now processing\");\n    }\n}\n\n@Slf4j\npublic class YouTubeService implements VideoStreamingService {\n    @Override\n    public void doProcessing() {\n        LOGGER.info(\"YouTubeService is now processing\");\n    }\n}\n```\n\nEnsuite, nous avons un service de recherche qui décide quel service de streaming vidéo utiliser.\n\n```java\n\n@Setter\npublic class BusinessLookup {\n\n    private NetflixService netflixService;\n    private YouTubeService youTubeService;\n\n    public VideoStreamingService getBusinessService(String movie) {\n        if (movie.toLowerCase(Locale.ROOT).contains(\"die hard\")) {\n            return netflixService;\n        } else {\n            return youTubeService;\n        }\n    }\n}\n```\n\nLe Business Delegate utilise un service de recherche pour acheminer les requêtes vers le bon service de streaming.\n\n```java\n\n@Setter\npublic class BusinessDelegate {\n\n    private BusinessLookup lookupService;\n\n    public void playbackMovie(String movie) {\n        VideoStreamingService videoStreamingService = lookupService.getBusinessService(movie);\n        videoStreamingService.doProcessing();\n    }\n}\n```\n\nLe client mobile se sert du Business Delegate pour appeler la couche métier.\n\n```java\npublic class MobileClient {\n\n    private final BusinessDelegate businessDelegate;\n\n    public MobileClient(BusinessDelegate businessDelegate) {\n        this.businessDelegate = businessDelegate;\n    }\n\n    public void playbackMovie(String movie) {\n        businessDelegate.playbackMovie(movie);\n    }\n}\n```\n\nFinalement, l'exemple concret en action.\n\n```java\npublic static void main(String[] args) {\n\n    // prepare the objects\n    var businessDelegate = new BusinessDelegate();\n    var businessLookup = new BusinessLookup();\n    businessLookup.setNetflixService(new NetflixService());\n    businessLookup.setYouTubeService(new YouTubeService());\n    businessDelegate.setLookupService(businessLookup);\n\n    // create the client and use the business delegate\n    var client = new MobileClient(businessDelegate);\n    client.playbackMovie(\"Die Hard 2\");\n    client.playbackMovie(\"Maradona: The Greatest Ever\");\n}\n```\n\nVoici la sortie affichée dans la console.\n\n```\n21:15:33.790 [main] INFO com.iluwatar.business.delegate.NetflixService - NetflixService is now processing\n21:15:33.794 [main] INFO com.iluwatar.business.delegate.YouTubeService - YouTubeService is now processing\n```\n\n## Diagramme de classe \n\n![Business Delegate](./etc/business-delegate.urm.png \"Business Delegate\")\n\n## Quand utiliser ce modèle de conception \n\nUtilisez le modèle Business Delegate lorsque\n\n* Vous avez besoin d'un couplage lâche entre les niveaux de présentation et d'activité ou vous avez besoin d'abstraire les recherches de services.\n* Vous souhaitez organiser des appels à de multiples services commerciaux.\n* Vous voulez encapsuler les recherches et les appels de services.\n* Il est nécessaire d'abstraire et d'encapsuler la communication entre le niveau client et les services métier.\n\n## Tutoriels \n\n* [Design Patterns - Business Delegate Pattern (TutorialsPoint)](https://www.tutorialspoint.com/design_pattern/business_delegate_pattern.htm)\n\n## Applications concrêtes \n\n* Applications d'entreprise utilisant Java EE (Java Platform, Enterprise Edition)\n* Applications nécessitant un accès à distance aux services de l'entreprised\n\n## Avantages et inconvénients \n\nAvantages :\n\n* Découplage des niveaux de présentation et d'activité : Permet au niveau client et aux services commerciaux d'évoluer indépendamment.\n* Transparence de l'emplacement : Les clients ne sont pas affectés par les changements de localisation ou d'instanciation des services commerciaux.\n* Réutilisation et évolutivité : Les objets Business Delegate peuvent être réutilisés par plusieurs clients, et le modèle prend en charge l'équilibrage de la charge et l'évolutivité.\n\nInconvénients :\n\n* Complexity: Introduces additional layers and abstractions, which may increase complexity.\n* Performance Overhead: The additional indirection may incur a slight performance penalty.\n\n## Réferences et crédits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "localization/hi/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n\n# जावा में कार्यान्वित डिजाइन पैटर्न\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-213-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n# परिचय\n\nडिज़ाइन पैटर्न सर्वोत्तम, औपचारिक अभ्यास हैं जिनका उपयोग एक प्रोग्रामर कर सकता है\nकिसी एप्लिकेशन या सिस्टम को डिजाइन करते समय सामान्य समस्याओं को हल करें।\n\nडिज़ाइन पैटर्न परीक्षण किए गए, सिद्ध विकास प्रतिमान प्रदान करके विकास प्रक्रिया को गति दे सकते हैं।\n\nडिज़ाइन पैटर्न का पुन: उपयोग करने से सूक्ष्म मुद्दों को रोकने में मदद मिलती है जो बड़ी समस्याएं पैदा करते हैं, और यह कोडर्स और आर्किटेक्ट्स के लिए कोड पठनीयता में भी सुधार करता है जो पैटर्न से परिचित हैं।\n\n# शुरू करते है\n\nयह साइट जावा डिज़ाइन पैटर्न प्रदर्शित करती है। समाधान द्वारा विकसित किए गए हैं\nओपन-सोर्स समुदाय के अनुभवी प्रोग्रामर और आर्किटेक्ट।\nपैटर्न को उनके उच्च-स्तरीय विवरणों द्वारा या उनके को देखकर ब्राउज़ किया जा सकता है\nसोर्स कोड। स्रोत कोड के उदाहरणों पर अच्छी तरह से टिप्पणी की गई है और इसे इस प्रकार माना जा सकता है\nएक विशिष्ट पैटर्न को लागू करने के तरीके पर प्रोग्रामिंग ट्यूटोरियल। हम सबसे ज्यादा इस्तेमाल करते हैं\nलोकप्रिय युद्ध-सिद्ध ओपन-सोर्स जावा प्रौद्योगिकियां।\n\nसामग्री में गोता लगाने से पहले, आपको विभिन्न से परिचित होना चाहिए\n[सॉफ्टवेयर डिजाइन सिद्धांत](https://java-design-patterns.com/principles/).\n\nसभी डिज़ाइन यथासंभव सरल होने चाहिए। आपको KISS, YAGNI से शुरू करना चाहिए और वह सरलतम कार्य करें जो संभवतः सिद्धांतों पर कार्य कर सके। जटिलता और पैटर्न केवल तभी पेश किए जाने चाहिए जब व्यावहारिक विस्तारशीलता के लिए उनकी आवश्यकता हो।\n\nएक बार जब आप इन अवधारणाओं से परिचित हो जाते हैं तो आप नीचे की ओर ड्रिलिंग शुरू कर सकते हैं\n[उपलब्ध डिजाइन पैटर्न](https://java-design-patterns.com/patterns/) निम्नलिखित में से किसी भी दृष्टिकोण से\n\n - नाम से एक विशिष्ट पैटर्न खोजें। एक नहीं मिल रहा है? कृपया एक नए पैटर्न की रिपोर्ट करें [यहां](https://github.com/iluwatar/java-design-patterns/issues).\n - `Performance`, `Gang of Four` या `Data access` जैसे टैग का उपयोग करना।\n - पैटर्न श्रेणियों, `Creational`, `Behavioral`, और अन्य का उपयोग करना।\n\nउम्मीद है, आप इस साइट पर प्रस्तुत किए गए ऑब्जेक्ट-ओरिएंटेड समाधान अपने आर्किटेक्चर में उपयोगी पाते हैं और उन्हें सीखने में उतना ही मज़ा आता है जितना हमें उन्हें विकसित करते समय मिला था।\n\n# कैसे योगदान करें\n\nयदि आप परियोजना में योगदान करने के इच्छुक हैं तो आपको हमारे [डेवलपर विकी](https://github.com/iluwatar/java-design-patterns/wiki) में प्रासंगिक जानकारी मिल जाएगी। हम आपकी मदद करेंगे और [गिटर चैटरूम](https://gitter.im/iluwatar/java-design-patterns) में आपके सवालों के जवाब देंगे।\n\n# लाइसेंस\n\nयह परियोजना एमआईटी लाइसेंस की शर्तों के तहत लाइसेंस प्राप्त है।\n\n"
  },
  {
    "path": "localization/hi/abstract-document/README.md",
    "content": "---\ntitle: Abstract Document\ncategory: Structural\nlanguage: hi\ntag: \n - Extensibility\n---\n\n## हेतु\n\nगतिशील गुणों का उपयोग करें और टाइप-सेफ्टी रखते हुए अनटाइप्ड लैंग्वेज का लचीलापन प्राप्त करें।\n\n## व्याख्या\n\nसार दस्तावेज़ पैटर्न अतिरिक्त, गैर-स्थैतिक गुणों को संभालने में सक्षम बनाता है। यह पैटर्न\nप्रकार की सुरक्षा और विभिन्न वर्गों के अलग-अलग गुणों को सक्षम करने के लिए लक्षणों की अवधारणा का उपयोग करता है\nइंटरफेस का सेट।\nवास्तविक उदाहरण\n\n>  एक कार पर विचार करें जिसमें कई हिस्से होते हैं। हालाँकि हम नहीं जानते कि क्या विशिष्ट कार में वास्तव में सभी पुर्जे हैं, या उनमें से कुछ ही हैं। हमारी कारें गतिशील और बेहद लचीली हैं।\n\nसरल शब्दो मे\n\n> सार दस्तावेज़ पैटर्न वस्तुओं को इसके बारे में जानने के बिना गुणों को संलग्न करने की अनुमति देता है।\n\nविकिपीडिया कहता है\n\n> ढीले टाइप की-वैल्यू स्टोर्स और एक्सपोज़िंग में ऑब्जेक्ट्स को व्यवस्थित करने के लिए एक ऑब्जेक्ट-ओरिएंटेड स्ट्रक्चरल डिज़ाइन पैटर्न\nटाइप किए गए दृश्यों का उपयोग कर डेटा। पैटर्न का उद्देश्य घटकों के बीच उच्च स्तर का लचीलापन प्राप्त करना है\nएक दृढ़ता से टाइप की गई भाषा में जहां ऑब्जेक्ट-ट्री में नए गुण जोड़े जा सकते हैं, बिना खोए\nप्रकार-सुरक्षा का समर्थन। पैटर्न एक वर्ग के विभिन्न गुणों को अलग-अलग करने के लिए लक्षणों का उपयोग करता है\nइंटरफेस।\n\n**प्रोग्रामेटिक उदाहरण**\n\nआइए पहले आधार वर्ग `Document` और `AbstractDocument` को परिभाषित करें। वे मूल रूप से वस्तु को एक संपत्ति बनाते हैं\nनक्शा और बाल वस्तुओं की कोई भी राशि।\n\n```java\npublic interface Document {\n\n  Void put(String key, Object value);\n\n  Object get(String key);\n\n  <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);\n}\n\npublic abstract class AbstractDocument implements Document {\n\n  private final Map<String, Object> properties;\n\n  protected AbstractDocument(Map<String, Object> properties) {\n    Objects.requireNonNull(properties, \"properties map is required\");\n    this.properties = properties;\n  }\n\n  @Override\n  public Void put(String key, Object value) {\n    properties.put(key, value);\n    return null;\n  }\n\n  @Override\n  public Object get(String key) {\n    return properties.get(key);\n  }\n\n  @Override\n  public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {\n    return Stream.ofNullable(get(key))\n        .filter(Objects::nonNull)\n        .map(el -> (List<Map<String, Object>>) el)\n        .findAny()\n        .stream()\n        .flatMap(Collection::stream)\n        .map(constructor);\n  }\n  ...\n}\n```\nइसके बाद हम एक एनुम `Property` और प्रकार, मूल्य, मॉडल और भागों के लिए इंटरफेस का एक सेट परिभाषित करते हैं। यह हमें बनाने की अनुमति देता है\nहमारे `Car` वर्ग के लिए स्थिर दिखने वाला इंटरफ़ेस।\n\n```java\npublic enum Property {\n\n  PARTS, TYPE, PRICE, MODEL\n}\n\npublic interface HasType extends Document {\n\n  default Optional<String> getType() {\n    return Optional.ofNullable((String) get(Property.TYPE.toString()));\n  }\n}\n\npublic interface HasPrice extends Document {\n\n  default Optional<Number> getPrice() {\n    return Optional.ofNullable((Number) get(Property.PRICE.toString()));\n  }\n}\npublic interface HasModel extends Document {\n\n  default Optional<String> getModel() {\n    return Optional.ofNullable((String) get(Property.MODEL.toString()));\n  }\n}\n\npublic interface HasParts extends Document {\n\n  default Stream<Part> getParts() {\n    return children(Property.PARTS.toString(), Part::new);\n  }\n}\n```\n\nअब हम पेश करने के लिए तैयार हैं `Car`.\n\n```java\npublic class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {\n\n  public Car(Map<String, Object> properties) {\n    super(properties);\n  }\n}\n```\n\nऔर अंत में यहां बताया गया है कि कैसे हम `Car` का निर्माण और उपयोग एक पूर्ण उदाहरण में करते हैं।\n\n```java\n    LOGGER.info(\"Constructing parts and car\");\n\n    var wheelProperties = Map.of(\n        Property.TYPE.toString(), \"wheel\",\n        Property.MODEL.toString(), \"15C\",\n        Property.PRICE.toString(), 100L);\n\n    var doorProperties = Map.of(\n        Property.TYPE.toString(), \"door\",\n        Property.MODEL.toString(), \"Lambo\",\n        Property.PRICE.toString(), 300L);\n\n    var carProperties = Map.of(\n        Property.MODEL.toString(), \"300SL\",\n        Property.PRICE.toString(), 10000L,\n        Property.PARTS.toString(), List.of(wheelProperties, doorProperties));\n\n    var car = new Car(carProperties);\n\n    LOGGER.info(\"Here is our car:\");\n    LOGGER.info(\"-> model: {}\", car.getModel().orElseThrow());\n    LOGGER.info(\"-> price: {}\", car.getPrice().orElseThrow());\n    LOGGER.info(\"-> parts: \");\n    car.getParts().forEach(p -> LOGGER.info(\"\\t{}/{}/{}\",\n        p.getType().orElse(null),\n        p.getModel().orElse(null),\n        p.getPrice().orElse(null))\n    );\n\n    // Constructing parts and car\n    // Here is our car:\n    // model: 300SL\n    // price: 10000\n    // parts: \n    // wheel/15C/100\n    // door/Lambo/300\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../abstract-document/etc/abstract-document.png \"Abstract Document Traits and Domain\")\n\n## उपयोग\n\nकब सार दस्तावेज़ पैटर्न का प्रयोग करें\n\n* तत्काल नई संपत्तियों को जोड़ने की जरूरत है\n* आप डोमेन को वृक्ष जैसी संरचना में व्यवस्थित करने के लिए एक लचीला तरीका चाहते हैं\n* आप अधिक शिथिल युग्मित प्रणाली चाहते हैं\n\n## श्रेय\n\n* [Wikipedia: Abstract Document Pattern](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)\n* [Martin Fowler: Dealing with properties](http://martinfowler.com/apsupp/properties.pdf)\n* [Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4)](https://www.amazon.com/gp/product/0470059028/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0470059028&linkId=e3aacaea7017258acf184f9f3283b492)\n"
  },
  {
    "path": "localization/hi/abstract-factory/README.md",
    "content": "---\ntitle: Abstract Factory\ncategory: Creational\nlanguage: hi\ntag:\n - Gang of Four\n---\n\n## के रूप में भी जाना जाता है\n\nकिट\n\n## हेतु\n\nसंबंधित या आश्रित परिवारों को बनाने के लिए एक इंटरफ़ेस प्रदान करें\nवस्तुओं को उनके ठोस वर्गों को निर्दिष्ट किए बिना।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> एक राज्य बनाने के लिए हमें एक सामान्य विषय वाली वस्तुओं की आवश्यकता होती है। Elven किंगडम को एक Elven King, Elven Castle और Elven सेना की आवश्यकता होती है जबकि Orcish राज्य को एक Orcish King, Orcish Castle और Orcish सेना की आवश्यकता होती है। राज्य में वस्तुओं के बीच एक निर्भरता है।\n\nसरल शब्दो मे\n\n> कारखानों का एक कारखाना; एक कारखाना जो व्यक्तिगत लेकिन संबंधित/आश्रित कारखानों को उनके ठोस वर्गों को निर्दिष्ट किए बिना एक साथ समूहित करता है।\n\nविकिपीडिया कहता है\n\n> अमूर्त फ़ैक्टरी पैटर्न व्यक्तिगत फ़ैक्टरियों के एक समूह को समाहित करने का एक तरीका प्रदान करता है, जिनके ठोस वर्गों को निर्दिष्ट किए बिना एक सामान्य विषय है। \n\n**Programmatic Example**\n\nऊपर किंगडम उदाहरण का अनुवाद। सबसे पहले, हमारे पास वस्तुओं के लिए कुछ इंटरफेस और कार्यान्वयन हैं\nसाम्राज्य।\n\n```java\npublic interface Castle {\n  String getDescription();\n}\n\npublic interface King {\n  String getDescription();\n}\n\npublic interface Army {\n  String getDescription();\n}\n\n// Elven implementations ->\npublic class ElfCastle implements Castle {\n  static final String DESCRIPTION = \"This is the elven castle!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfKing implements King {\n  static final String DESCRIPTION = \"This is the elven king!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfArmy implements Army {\n  static final String DESCRIPTION = \"This is the elven Army!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\n// Orcish implementations similarly -> ...\n\n```\n\nफिर हमारे पास राज्य कारखाने के लिए अमूर्तता और कार्यान्वयन है।\n\n```java\npublic interface KingdomFactory {\n  Castle createCastle();\n  King createKing();\n  Army createArmy();\n}\n\npublic class ElfKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new ElfCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new ElfKing();\n  }\n\n  @Override\n  public Army createArmy() {\n    return new ElfArmy();\n  }\n}\n\npublic class OrcKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new OrcCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new OrcKing();\n  }\n  \n  @Override\n  public Army createArmy() {\n    return new OrcArmy();\n  }\n}\n```\n\nअब हमारे पास एब्स्ट्रैक्ट फैक्ट्री है जो हमें संबंधित वस्तुओं का एक परिवार बनाने की सुविधा देती है, जैसे कि एल्वेन किंगडम फैक्ट्री एल्वेन कैसल, राजा और सेना आदि बनाती है।\n\n```java\nvar factory = new ElfKingdomFactory();\nvar castle = factory.createCastle();\nvar king = factory.createKing();\nvar army = factory.createArmy();\n\ncastle.getDescription();\nking.getDescription();\narmy.getDescription();\n```\n\nProgram output:\n\n```java\nThis is the elven castle!\nThis is the elven king!\nThis is the elven Army!\n```\n\nअब, हम अपने विभिन्न राज्य कारखानों के लिए एक कारखाना डिजाइन कर सकते हैं। इस उदाहरण में, हमने `FactoryMaker` बनाया, जो `ElfKingdomFactory` या `OrcKingdomFactory` के उदाहरण को वापस करने के लिए ज़िम्मेदार है।\nग्राहक वांछित कंक्रीट फैक्ट्री बनाने के लिए `फैक्ट्रीमेकर` का उपयोग कर सकता है, जो बदले में, विभिन्न ठोस वस्तुओं का उत्पादन करेगा (`आर्मी`, `किंग`, `कैसल` से व्युत्पन्न)।\nइस उदाहरण में, हमने क्लाइंट द्वारा अनुरोध किए जाने वाले राज्य कारखाने के प्रकार को पैरामीटर करने के लिए एक एनम का भी उपयोग किया।\n\n```java\npublic static class FactoryMaker {\n\n    public enum KingdomType {\n        ELF, ORC\n    }\n\n    public static KingdomFactory makeFactory(KingdomType type) {\n        return switch (type) {\n            case ELF -> new ElfKingdomFactory();\n            case ORC -> new OrcKingdomFactory();\n            default -> throw new IllegalArgumentException(\"KingdomType not supported.\");\n        };\n    }\n}\n\n    public static void main(String[] args) {\n        var app = new App();\n\n        LOGGER.info(\"Elf Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));\n        LOGGER.info(app.getArmy().getDescription());\n        LOGGER.info(app.getCastle().getDescription());\n        LOGGER.info(app.getKing().getDescription());\n\n        LOGGER.info(\"Orc Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));\n        --similar use of the orc factory\n    }\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../abstract-factory/etc/abstract-factory.urm.png \"Abstract Factory class diagram\")\n\n\n## प्रयोज्यता\n\nएब्सट्रैक्ट फ़ैक्टरी पैटर्न का उपयोग कब करें\n\n* सिस्टम इस बात से स्वतंत्र होना चाहिए कि इसके उत्पाद कैसे बनाए जाते हैं, बनाए जाते हैं और प्रस्तुत किए जाते हैं\n* सिस्टम को उत्पादों के कई परिवारों में से एक के साथ कॉन्फ़िगर किया जाना चाहिए\n* संबंधित उत्पाद वस्तुओं के परिवार को एक साथ उपयोग करने के लिए डिज़ाइन किया गया है, और आपको इस बाधा को लागू करने की आवश्यकता है\n* आप उत्पादों की एक क्लास लाइब्रेरी प्रदान करना चाहते हैं, और आप केवल उनके इंटरफेस को प्रकट करना चाहते हैं, उनके कार्यान्वयन को नहीं\n* निर्भरता का जीवनकाल अवधारणात्मक रूप से उपभोक्ता के जीवनकाल से छोटा होता है।\n* किसी विशेष निर्भरता के निर्माण के लिए आपको रन-टाइम मान की आवश्यकता होती है\n* आप यह तय करना चाहते हैं कि रनटाइम के दौरान परिवार से किस उत्पाद को कॉल किया जाए।\n* आपको निर्भरता को हल करने से पहले केवल रन-टाइम पर ज्ञात एक या अधिक पैरामीटर प्रदान करने की आवश्यकता है।\n* जब आपको उत्पादों के बीच निरंतरता की आवश्यकता हो\n* प्रोग्राम में नए उत्पादों या उत्पादों के समूह को जोड़ते समय आप मौजूदा कोड को बदलना नहीं चाहते हैं।\n\nउदाहरण उपयोग के मामले\t\n\n* रनटाइम पर FileSystemAcmeService या DatabaseAcmeService या NetworkAcmeService के उपयुक्त कार्यान्वयन के लिए कॉल करने का चयन करना।\n* यूनिट टेस्ट केस लिखना बहुत आसान हो जाता है\n* विभिन्न ओएस के लिए यूआई उपकरण\n\n## नतीजे\n\n* जावा में निर्भरता इंजेक्शन सेवा वर्ग की निर्भरता को छुपाता है जो रनटाइम त्रुटियों को जन्म दे सकता है जो संकलन समय पर पकड़ा गया होता।\n* जबकि पूर्वनिर्धारित वस्तुओं को बनाते समय पैटर्न बहुत अच्छा होता है, नए को जोड़ना चुनौतीपूर्ण हो सकता है।\n* कोड अधिक जटिल हो जाता है जितना होना चाहिए क्योंकि पैटर्न के साथ बहुत सारे नए इंटरफेस और कक्षाएं पेश की जाती हैं।\n\n## ट्यूटोरियल\n\n* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java) \n\n## ज्ञात उपयोग\n\n* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)\n* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)\n* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)\n\n## संबंधित पैटर्न\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n\n## श्रेय\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/hi/active-object/README.md",
    "content": "---\ntitle: Active Object\ncategory: Concurrency\nlanguage: hi\ntag:\n - Performance\n---\n\n\n## हेतु\nसक्रिय ऑब्जेक्ट डिज़ाइन पैटर्न उन वस्तुओं के लिए विधि आमंत्रण से विधि निष्पादन को अलग करता है जो प्रत्येक अपने नियंत्रण के धागे में रहते हैं। लक्ष्य एसिंक्रोनस विधि आमंत्रण और अनुरोधों को संभालने के लिए शेड्यूलर का उपयोग करके समवर्तीता पेश करना है।\n\n## व्याख्या\n\nसक्रिय ऑब्जेक्ट पैटर्न को लागू करने वाली कक्षा में 'सिंक्रनाइज़' विधियों का उपयोग किए बिना एक स्व-सिंक्रनाइज़ेशन तंत्र होगा।\n\nवास्तविक दुनिया का उदाहरण\n\n> ओर्क्स अपने जंगलीपन और अदम्य आत्मा के लिए जाने जाते हैं। ऐसा लगता है जैसे उनके पास पिछले व्यवहार के आधार पर नियंत्रण का अपना सूत्र है।\n\nएक प्राणी को लागू करने के लिए जिसके पास नियंत्रण तंत्र का अपना धागा है और केवल अपने एपीआई का पर्दाफाश करता है न कि स्वयं निष्पादन, हम सक्रिय ऑब्जेक्ट पैटर्न का उपयोग कर सकते हैं।\n\n\n**Programmatic Example**\n\n```java\npublic abstract class ActiveCreature{\n  private final Logger logger = LoggerFactory.getLogger(ActiveCreature.class.getName());\n\n  private BlockingQueue<Runnable> requests;\n  \n  private String name;\n  \n  private Thread thread;\n\n  public ActiveCreature(String name) {\n    this.name = name;\n    this.requests = new LinkedBlockingQueue<Runnable>();\n    thread = new Thread(new Runnable() {\n        @Override\n        public void run() {\n          while (true) {\n            try {\n              requests.take().run();\n            } catch (InterruptedException e) { \n              logger.error(e.getMessage());\n            }\n          }\n        }\n      }\n    );\n    thread.start();\n  }\n  \n  public void eat() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} is eating!\",name());\n          logger.info(\"{} has finished eating!\",name());\n        }\n      }\n    );\n  }\n\n  public void roam() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} has started to roam the wastelands.\",name());\n        }\n      }\n    );\n  }\n  \n  public String name() {\n    return this.name;\n  }\n}\n```\n\nहम देख सकते हैं कि कोई भी वर्ग जो ActiveCreature वर्ग का विस्तार करेगा, उसके पास तरीकों को लागू करने और निष्पादित करने के लिए नियंत्रण का अपना धागा होगा।\n\n\nउदाहरण के लिए, Orc क्लास:\n\n```java\npublic class Orc extends ActiveCreature {\n\n  public Orc(String name) {\n    super(name);\n  }\n\n}\n```\n\nअब, हम Orcs जैसे कई जीव बना सकते हैं, उन्हें खाने और घूमने के लिए कह सकते हैं, और वे इसे अपने नियंत्रण के thread पर क्रियान्वित करेंगे:\n\n```java\n  public static void main(String[] args) {  \n    var app = new App();\n    app.run();\n  }\n  \n  @Override\n  public void run() {\n    ActiveCreature creature;\n    try {\n      for (int i = 0;i < creatures;i++) {\n        creature = new Orc(Orc.class.getSimpleName().toString() + i);\n        creature.eat();\n        creature.roam();\n      }\n      Thread.sleep(1000);\n    } catch (InterruptedException e) {\n      logger.error(e.getMessage());\n    }\n    Runtime.getRuntime().exit(1);\n  }\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../active-object/etc/active-object.urm.png \"Active Object class diagram\")\n\n## ट्यूटोरियल\n\n* [Android and Java Concurrency: The Active Object Pattern](https://www.youtube.com/watch?v=Cd8t2u5Qmvc)"
  },
  {
    "path": "localization/hi/acyclic-visitor/README.md",
    "content": "---\ntitle: Acyclic Visitor\ncategory: Behavioral\nlanguage: hi\ntag:\n - Extensibility\n---\n\n## हेतु\n\nउन पदानुक्रमों को प्रभावित किए बिना और बनाए बिना मौजूदा वर्ग पदानुक्रमों में नए कार्यों को जोड़ने की अनुमति दें\nतकलीफ़देह निर्भरता चक्र जो GoF विज़िटर पैटर्न में अंतर्निहित हैं।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n\n> हमारे पास मॉडेम कक्षाओं का एक पदानुक्रम है। इस पदानुक्रम में मोडेम को बाहरी एल्गोरिथम आधारित द्वारा देखा जाना चाहिए\n> फ़िल्टरिंग मानदंड पर (क्या यह यूनिक्स या डॉस संगत मॉडेम है)। \n\nसरल शब्दो मे\n\n> चक्रीय आगंतुक पदानुक्रम को संशोधित किए बिना कार्यों को मौजूदा वर्ग पदानुक्रम में जोड़ने की अनुमति देता है।\n\n[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) कहता है\n\n\n> एसाइक्लिक विज़िटर पैटर्न मौजूदा वर्ग पदानुक्रमों को प्रभावित किए बिना नए कार्यों को जोड़ने की अनुमति देता है\n> पदानुक्रम, और निर्भरता चक्र बनाए बिना जो GangOfFour विज़िटरपैटर्न में निहित हैं।\n\n**Programmatic Example**\n\nयहाँ `मॉडेम` पदानुक्रम है।\n\n```java\npublic abstract class Modem {\n  public abstract void accept(ModemVisitor modemVisitor);\n}\n\npublic class Zoom extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof ZoomVisitor) {\n      ((ZoomVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only ZoomVisitor is allowed to visit Zoom modem\");\n    }\n  }\n}\n\npublic class Hayes extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof HayesVisitor) {\n      ((HayesVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only HayesVisitor is allowed to visit Hayes modem\");\n    }\n  }\n}\n```\n\n\nआगे हम `मॉडेमविज़िटर` पदानुक्रम का परिचय देते हैं।\n\n```java\npublic interface ModemVisitor {\n}\n\npublic interface HayesVisitor extends ModemVisitor {\n  void visit(Hayes hayes);\n}\n\npublic interface ZoomVisitor extends ModemVisitor {\n  void visit(Zoom zoom);\n}\n\npublic interface AllModemVisitor extends ZoomVisitor, HayesVisitor {\n}\n\npublic class ConfigureForDosVisitor implements AllModemVisitor {\n  ...\n  @Override\n  public void visit(Hayes hayes) {\n    LOGGER.info(hayes + \" used with Dos configurator.\");\n  }\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Dos configurator.\");\n  }\n}\n\npublic class ConfigureForUnixVisitor implements ZoomVisitor {\n  ...\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Unix configurator.\");\n  }\n}\n```\n\nअंत में, यहां आगंतुक कार्रवाई में हैं।\n\n```java\n    var conUnix = new ConfigureForUnixVisitor();\n    var conDos = new ConfigureForDosVisitor();\n    var zoom = new Zoom();\n    var hayes = new Hayes();\n    hayes.accept(conDos);\n    zoom.accept(conDos);\n    hayes.accept(conUnix);\n    zoom.accept(conUnix);   \n```\n\nProgram output:\n\n```\n    // Hayes modem used with Dos configurator.\n    // Zoom modem used with Dos configurator.\n    // Only HayesVisitor is allowed to visit Hayes modem\n    // Zoom modem used with Unix configurator.\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../acyclic-visitor/etc/acyclic-visitor.png \"Acyclic Visitor\")\n\n## प्रयोज्यता\n\nपैटर्न का उपयोग कब करें\n\n* जब आपको उस पदानुक्रम को बदलने या प्रभावित करने की आवश्यकता के बिना किसी मौजूदा पदानुक्रम में एक नया फ़ंक्शन जोड़ने की आवश्यकता होती है।\n* जब ऐसे कार्य होते हैं जो एक पदानुक्रम पर काम करते हैं, लेकिन जो स्वयं पदानुक्रम में शामिल नहीं होते हैं। उदा. ConfigureForDOS / ConfigureForUnix / ConfigureForX समस्या।\n* जब आपको किसी वस्तु के प्रकार के आधार पर बहुत भिन्न संचालन करने की आवश्यकता होती है।\n* जब विज़िट किए गए वर्ग पदानुक्रम को तत्व वर्ग के नए डेरिवेटिव के साथ अक्सर विस्तारित किया जाएगा।\n* जब एलिमेंट के डेरिवेटिव का पुनर्संकलन, रीलिंकिंग, रीटेस्टिंग या पुनर्वितरण बहुत महंगा हो।\n\n## ट्यूटोरियल\n\n* [Acyclic Visitor Pattern Example](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html)\n\n## नतीजे\n\n\nअच्छा:\n\n* वर्ग पदानुक्रमों के बीच कोई निर्भरता चक्र नहीं।\n* यदि कोई नया जोड़ा जाता है तो सभी आगंतुकों को पुनः संकलित करने की आवश्यकता नहीं है।\n* यदि वर्ग पदानुक्रम में एक नया सदस्य है तो मौजूदा आगंतुकों में संकलन विफलता का कारण नहीं बनता है।\n\n\nखराब:\n\n* यह दिखाते हुए [लिस्कोव के प्रतिस्थापन सिद्धांत](https://java-design-patterns.com/principles/#liskov-substitution-principle) का उल्लंघन करता है कि यह सभी आगंतुकों को स्वीकार कर सकता है लेकिन वास्तव में केवल विशेष आगंतुकों में रुचि रखता है।\n* विज़िट करने योग्य वर्ग पदानुक्रम में सभी सदस्यों के लिए आगंतुकों का समानांतर पदानुक्रम बनाया जाना है।\n\n## संबंधित पैटर्न\n\n* [Visitor Pattern](https://java-design-patterns.com/patterns/visitor/)\n\n## श्रेय\n\n* [Acyclic Visitor by Robert C. Martin](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf)\n* [Acyclic Visitor in WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor)\n"
  },
  {
    "path": "localization/hi/adapter/README.md",
    "content": "---\ntitle: Adapter\ncategory: Structural\nlanguage: hi\ntag:\n - Gang of Four\n---\n\n## दूसरा नाम\nआवरण\n\n## हेतु\nकिसी क्लास के इंटरफ़ेस को क्लाइंट द्वारा अपेक्षित किसी अन्य इंटरफ़ेस में कनवर्ट करें। एडाप्टर कक्षाओं को एक साथ काम करने देता है\nअसंगत इंटरफ़ेस के कारण अन्यथा नहीं हो सका।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> विचार करें कि आपके मेमोरी कार्ड पर कुछ चित्र हैं और आपको उन्हें अपने कंप्यूटर पर स्थानांतरित करने की आवश्यकता है। उन्हें स्थानांतरित करने के लिए, आपको किसी प्रकार के एडाप्टर की आवश्यकता होती है जो आपके कंप्यूटर पोर्ट के साथ संगत हो ताकि आप अपने कंप्यूटर में मेमोरी कार्ड संलग्न कर सकें। इस मामले में कार्ड रीडर एक एडाप्टर है।\n> एक अन्य उदाहरण प्रसिद्ध पावर एडॉप्टर होगा; तीन-पैर वाले प्लग को दो-आयामी आउटलेट से नहीं जोड़ा जा सकता है, इसके लिए एक पावर एडाप्टर का उपयोग करने की आवश्यकता होती है जो इसे दो-आयामी आउटलेट के साथ संगत बनाता है।\n> एक अन्य उदाहरण एक अनुवादक का होगा जो एक व्यक्ति द्वारा दूसरे व्यक्ति द्वारा बोले गए शब्दों का अनुवाद करेगा।\n\nसरल शब्दो मे\n\n> एडेप्टर पैटर्न आपको किसी अन्यथा असंगत ऑब्जेक्ट को किसी अन्य वर्ग के साथ संगत बनाने के लिए एडॉप्टर में लपेटने की सुविधा देता है।\n\nविकिपीडिया कहता है\n\n> सॉफ्टवेयर इंजीनियरिंग में, एडॉप्टर पैटर्न एक सॉफ्टवेयर डिज़ाइन पैटर्न है जो मौजूदा क्लास के इंटरफ़ेस को दूसरे इंटरफ़ेस के रूप में उपयोग करने की अनुमति देता है। इसका उपयोग अक्सर मौजूदा कक्षाओं को उनके स्रोत कोड को संशोधित किए बिना दूसरों के साथ काम करने के लिए किया जाता है।\n\n**प्रोग्रामेटिक उदाहरण**\n\nएक ऐसे कप्तान पर विचार करें जो केवल नाव चला सकता है और बिल्कुल भी नाव नहीं चला सकता।\n\nसबसे पहले, हमारे पास इंटरफ़ेस `RowingBoat` और `FishingBoat` हैं\n\n```java\npublic interface RowingBoat {\n  void row();\n}\n\n@Slf4j\npublic class FishingBoat {\n  public void sail() {\n    LOGGER.info(\"The fishing boat is sailing\");\n  }\n}\n```\n\nऔर कैप्टन को उम्मीद है कि `RowingBoat` इंटरफ़ेस का कार्यान्वयन आगे बढ़ने में सक्षम होगा\n\n```java\npublic class Captain {\n\n  private final RowingBoat rowingBoat;\n  // default constructor and setter for rowingBoat\n  public Captain(RowingBoat rowingBoat) {\n    this.rowingBoat = rowingBoat;\n  }\n\n  public void row() {\n    rowingBoat.row();\n  }\n}\n```\n\nअब मान लीजिए कि समुद्री डाकू आ रहे हैं और हमारे कप्तान को भागने की जरूरत है लेकिन केवल मछली पकड़ने वाली नाव उपलब्ध है। हमें एक एडॉप्टर बनाने की आवश्यकता है जो कप्तान को नाव चलाने के अपने कौशल के साथ मछली पकड़ने वाली नाव को संचालित करने की अनुमति दे।\n\n```java\n@Slf4j\npublic class FishingBoatAdapter implements RowingBoat {\n\n  private final FishingBoat boat;\n\n  public FishingBoatAdapter() {\n    boat = new FishingBoat();\n  }\n\n  @Override\n  public void row() {\n    boat.sail();\n  }\n}\n```\n\nऔर अब `Captain` समुद्री डाकुओं से बचने के लिए `FishingBoat` का उपयोग कर सकता है\n\n```java\nvar captain = new Captain(new FishingBoatAdapter());\ncaptain.row();\n```\n\n## क्लास डायग्राम\n![alt text](../../../adapter/etc/adapter.urm.png \"एडाप्टर क्लास डायग्राम\")\n\n## प्रयोज्यता\nजब एडॉप्टर पैटर्न का उपयोग करें\n\n* आप किसी मौजूदा कक्षा का उपयोग करना चाहते हैं, और इसका इंटरफ़ेस आपकी ज़रूरत से मेल नहीं खाता है।\n* आप एक पुन: प्रयोज्य वर्ग बनाना चाहते हैं जो असंबद्ध या अप्रत्याशित वर्गों के साथ सहयोग करता है, अर्थात, ऐसे वर्ग जिनमें आवश्यक रूप से संगत इंटरफ़ेस नहीं है\n* आपको कई मौजूदा उपवर्गों का उपयोग करने की आवश्यकता है, लेकिन सभी को उपवर्गित करके उनके इंटरफ़ेस को अनुकूलित करना अव्यावहारिक है। एक ऑब्जेक्ट एडाप्टर अपने मूल वर्ग के इंटरफ़ेस को अनुकूलित कर सकता है।\n* तृतीय-पक्ष लाइब्रेरी का उपयोग करने वाले अधिकांश एप्लिकेशन लाइब्रेरी से एप्लिकेशन को अलग करने के लिए एप्लिकेशन और तृतीय पक्ष लाइब्रेरी के बीच मध्य परत के रूप में एडेप्टर का उपयोग करते हैं। यदि किसी अन्य लाइब्रेरी का उपयोग करना है तो एप्लिकेशन कोड को बदले बिना नई लाइब्रेरी के लिए केवल एक एडाप्टर की आवश्यकता होती है।\n\n## ट्यूटोरियल\n\n* [Dzone](https://dzone.com/articles/adapter-design-pattern-in-java)\n* [Refactoring Guru](https://refactoring.guru/design-patterns/adapter/java/example)\n* [Baeldung](https://www.baeldung.com/java-adapter-pattern)\n\n## नतीजे\nक्लास और ऑब्जेक्ट एडेप्टर के अलग-अलग ट्रेड-ऑफ़ होते हैं। एक क्लास एडॉप्टर\n\n*\tएक ठोस एडाप्टी वर्ग के लिए प्रतिबद्ध होकर एडाप्टी को लक्ष्य के अनुसार अनुकूलित करता है। परिणामस्वरूप, जब हम किसी क्लास और उसके सभी उपवर्गों को अनुकूलित करना चाहते हैं तो क्लास एडॉप्टर काम नहीं करेगा।\n*\tएडॉप्टर को एडैप्टी के कुछ व्यवहारों को ओवरराइड करने दें क्योंकि एडॉप्टर एडैप्टी का एक उपवर्ग है।\n*\tकेवल एक ऑब्जेक्ट का परिचय देता है, और एडाप्टी तक पहुंचने के लिए किसी अतिरिक्त सूचक संकेत की आवश्यकता नहीं होती है।\n\nएक ऑब्जेक्ट एडाप्टर\n\n*\tएक ही एडॉप्टर को कई एडाप्टीज़ के साथ काम करने देता है, यानी स्वयं एडाप्टी और उसके सभी उपवर्गों (यदि कोई हो) के साथ। एडॉप्टर एक साथ सभी एडेप्टीज़ में कार्यक्षमता भी जोड़ सकता है।\n*\tएडाप्टी व्यवहार को ओवरराइड करना कठिन बना देता है। इसके लिए एडाप्टी को उपवर्गित करने और एडॉप्टर को एडाप्टी के बजाय उपवर्ग को संदर्भित करने की आवश्यकता होगी।\n\n\n## वास्तविक दुनिया के उदाहरण\n\n* [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)\n* [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)\n* [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-)\n* [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-)\n\n\n## श्रेय\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)"
  },
  {
    "path": "localization/hi/aggregator-microservices/README.md",
    "content": "---\ntitle: Aggregator Microservices\ncategory: Architectural\nlanguage: hi\ntag:\n- Cloud distributed\n- Decoupling\n- Microservices\n---\n\n## हेतु\n\nउपयोगकर्ता एग्रीगेटर सेवा पर एक कॉल करता है, और एग्रीगेटर फिर प्रत्येक प्रासंगिक माइक्रोसर्विस को कॉल करता है।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> हमारे वेब बाज़ार को उत्पादों और उनकी वर्तमान सूची के बारे में जानकारी की आवश्यकता है। यह एक एग्रीगेटर को कॉल करता है\n> सेवा जो बदले में उत्पाद जानकारी माइक्रोसर्विस और उत्पाद इन्वेंट्री माइक्रोसर्विस को कॉल करती है\n> संयुक्त जानकारी.\n\nसाफ़ शब्दों में\n\n> एग्रीगेटर माइक्रोसर्विस विभिन्न माइक्रोसर्विसेज से डेटा के टुकड़े एकत्र करता है और प्रसंस्करण के लिए एक समुच्चय लौटाता है। \n\nस्टैक ओवरफ्लो कहता है\n\n> एग्रीगेटर माइक्रोसर्विस एप्लिकेशन द्वारा आवश्यक कार्यक्षमता प्राप्त करने के लिए कई सेवाओं को आमंत्रित करता है।\n\n**प्रोग्रामेटिक उदाहरण**\n\nआइए डेटा मॉडल से शुरू करें। यहाँ हमारा `Product` है।\n\n```java\npublic class Product {\n  private String title;\n  private int productInventories;\n  // getters and setters ->\n  ...\n}\n```\n\nआगे हम अपना `Aggregator` माइक्रोसर्विस पेश कर सकते हैं। इसमें क्लाइंट `ProductInformationClient` और शामिल हैं\nसंबंधित माइक्रोसर्विसेज़ को कॉल करने के लिए `ProductInventoryClient`।\n\n```java\n@RestController\npublic class Aggregator {\n\n  @Resource\n  private ProductInformationClient informationClient;\n\n  @Resource\n  private ProductInventoryClient inventoryClient;\n\n  @RequestMapping(path = \"/product\", method = RequestMethod.GET)\n  public Product getProduct() {\n\n    var product = new Product();\n    var productTitle = informationClient.getProductTitle();\n    var productInventory = inventoryClient.getProductInventories();\n\n    //Fallback to error message\n    product.setTitle(requireNonNullElse(productTitle, \"Error: Fetching Product Title Failed\"));\n\n    //Fallback to default error inventory\n    product.setProductInventories(requireNonNullElse(productInventory, -1));\n\n    return product;\n  }\n}\n```\n\nयहां सूचना माइक्रोसर्विस कार्यान्वयन का सार है। इन्वेंटरी माइक्रोसर्विस समान है, यह सिर्फ रिटर्न देता है\nइन्वेंट्री मायने रखती है।\n\n```java\n@RestController\npublic class InformationController {\n  @RequestMapping(value = \"/information\", method = RequestMethod.GET)\n  public String getProductTitle() {\n    return \"The Product Title.\";\n  }\n}\n```\n\nअब हमारे `Aggregator` REST API को कॉल करने से उत्पाद की जानकारी मिलती है।\n\n```bash\ncurl http://localhost:50004/product\n{\"title\":\"The Product Title.\",\"productInventories\":5}\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../aggregator-microservices/aggregator-service/etc/aggregator-service.png \"एग्रीगेटर माइक्रोसर्विस\")\n\n## प्रयोज्यता\n\nजब आपको क्लाइंट डिवाइस की परवाह किए बिना विभिन्न माइक्रोसर्विसेज के लिए एकीकृत एपीआई की आवश्यकता हो तो एग्रीगेटर माइक्रोसर्विसेज पैटर्न का उपयोग करें।\n\n## श्रेय\n\n* [Microservice Design Patterns](http://web.archive.org/web/20190705163602/http://blog.arungupta.me/microservice-design-patterns/)\n* [Microservices Patterns: With examples in Java](https://www.amazon.com/gp/product/1617294543/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617294543&linkId=8b4e570267bc5fb8b8189917b461dc60)\n* [Architectural Patterns: Uncover essential patterns in the most indispensable realm of enterprise architecture](https://www.amazon.com/gp/product/B077T7V8RC/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=B077T7V8RC&linkId=c34d204bfe1b277914b420189f09c1a4)\n"
  },
  {
    "path": "localization/hi/ambassador/README.md",
    "content": "---\ntitle: Ambassador\ncategory: Structural\nlanguage: hi\ntag:\n  - Decoupling\n  - Cloud distributed\n---\n\n## हेतु\n\nक्लाइंट पर एक सहायक सेवा उदाहरण प्रदान करें और साझा संसाधन से सामान्य कार्यक्षमता को दूर रखें।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> एक दूरस्थ सेवा में कई ग्राहक उसके द्वारा प्रदान किए गए फ़ंक्शन तक पहुँच प्राप्त करते हैं। यह सेवा एक विरासती एप्लिकेशन है और है\n> अद्यतन करना असंभव है. उपयोगकर्ताओं की ओर से बड़ी संख्या में अनुरोधों के कारण कनेक्टिविटी संबंधी समस्याएं उत्पन्न हो रही हैं। अनुरोध के लिए नए नियम\n> आवृत्ति को विलंबता जांच और क्लाइंट-साइड लॉगिंग के साथ लागू किया जाना चाहिए।\n\nसाफ़ शब्दों में\n\n> एंबेसेडर पैटर्न के साथ, हम विलंबता जांच के साथ-साथ ग्राहकों से कम-बार-बार मतदान लागू कर सकते हैं\n> लॉगिंग.\n\nमाइक्रोसॉफ्ट दस्तावेज़ बताता है\n\n> एक राजदूत सेवा को एक आउट-ऑफ-प्रोसेस प्रॉक्सी के रूप में सोचा जा सकता है जो क्लाइंट के साथ सह-स्थित होती है। यह पैटर्न\n> मॉनिटरिंग, लॉगिंग, रूटिंग जैसे सामान्य क्लाइंट कनेक्टिविटी कार्यों को ऑफ़लोड करने के लिए उपयोगी हो सकता है।\n> सुरक्षा (जैसे टीएलएस), और भाषा अज्ञेयवादी तरीके से लचीलापन पैटर्न। इसका उपयोग अक्सर पुराने अनुप्रयोगों के साथ किया जाता है,\n> या अन्य एप्लिकेशन जिन्हें अपनी नेटवर्किंग क्षमताओं को बढ़ाने के लिए संशोधित करना मुश्किल है। यह भी हो सकता है\n> उन सुविधाओं को लागू करने के लिए एक विशेष टीम को सक्षम करें।\n\n**प्रोग्रामेटिक उदाहरण**\n\nउपरोक्त परिचय को ध्यान में रखते हुए हम इस उदाहरण में कार्यक्षमता का अनुकरण करेंगे। हमने एक इंटरफ़ेस लागू किया है\nदूरस्थ सेवा के साथ-साथ राजदूत सेवा द्वारा:\n\n```java\ninterface RemoteServiceInterface {\n    long doRemoteFunction(int value) throws Exception;\n}\n```\n\nएक दूरस्थ सेवा को सिंगलटन के रूप में दर्शाया गया है।\n\n```java\n@Slf4j\npublic class RemoteService implements RemoteServiceInterface {\n    private static RemoteService service = null;\n\n    static synchronized RemoteService getRemoteService() {\n        if (service == null) {\n            service = new RemoteService();\n        }\n        return service;\n    }\n\n    private RemoteService() {}\n\n    @Override\n    public long doRemoteFunction(int value) {\n        long waitTime = (long) Math.floor(Math.random() * 1000);\n\n        try {\n            sleep(waitTime);\n        } catch (InterruptedException e) {\n            LOGGER.error(\"Thread sleep interrupted\", e);\n        }\n\n        return waitTime >= 200 ? value * 10 : -1;\n    }\n}\n```\n\nएक सेवा राजदूत लॉगिंग, विलंबता जांच जैसी अतिरिक्त सुविधाएं जोड़ रहा है\n\n```java\n@Slf4j\npublic class ServiceAmbassador implements RemoteServiceInterface {\n  private static final int RETRIES = 3;\n  private static final int DELAY_MS = 3000;\n\n  ServiceAmbassador() {\n  }\n\n  @Override\n  public long doRemoteFunction(int value) {\n    return safeCall(value);\n  }\n\n  private long checkLatency(int value) {\n    var startTime = System.currentTimeMillis();\n    var result = RemoteService.getRemoteService().doRemoteFunction(value);\n    var timeTaken = System.currentTimeMillis() - startTime;\n\n    LOGGER.info(\"Time taken (ms): \" + timeTaken);\n    return result;\n  }\n\n  private long safeCall(int value) {\n    var retries = 0;\n    var result = (long) FAILURE;\n\n    for (int i = 0; i < RETRIES; i++) {\n      if (retries >= RETRIES) {\n        return FAILURE;\n      }\n\n      if ((result = checkLatency(value)) == FAILURE) {\n        LOGGER.info(\"Failed to reach remote: (\" + (i + 1) + \")\");\n        retries++;\n        try {\n          sleep(DELAY_MS);\n        } catch (InterruptedException e) {\n          LOGGER.error(\"Thread sleep state interrupted\", e);\n        }\n      } else {\n        break;\n      }\n    }\n    return result;\n  }\n}\n```\n\nएक ग्राहक के पास एक स्थानीय सेवा राजदूत होता है जिसका उपयोग दूरस्थ सेवा के साथ बातचीत करने के लिए किया जाता है:\n\n```java\n@Slf4j\npublic class Client {\n  private final ServiceAmbassador serviceAmbassador = new ServiceAmbassador();\n\n  long useService(int value) {\n    var result = serviceAmbassador.doRemoteFunction(value);\n    LOGGER.info(\"Service result: \" + result);\n    return result;\n  }\n}\n```\n\nयहां दो ग्राहक सेवा का उपयोग कर रहे हैं।\n\n```java\npublic class App {\n  public static void main(String[] args) {\n    var host1 = new Client();\n    var host2 = new Client();\n    host1.useService(12);\n    host2.useService(73);\n  }\n}\n```\n\nउदाहरण चलाने के लिए आउटपुट यहां दिया गया है:\n\n```java\nTime taken (ms): 111\nService result: 120\nTime taken (ms): 931\nFailed to reach remote: (1)\nTime taken (ms): 665\nFailed to reach remote: (2)\nTime taken (ms): 538\nFailed to reach remote: (3)\nService result: -1\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../ambassador/etc/ambassador.urm.png \"Ambassador class diagram\")\n\n## प्रयोज्यता\n\nएंबेसडर एक विरासती दूरस्थ सेवा के साथ काम करते समय लागू होता है जिसे संशोधित नहीं किया जा सकता है या अत्यधिक होगा\nसंशोधित करना कठिन. रिमोट पर बदलाव की आवश्यकता से बचते हुए क्लाइंट पर कनेक्टिविटी सुविधाएँ लागू की जा सकती हैं\nसेवा।\n\n* राजदूत दूरस्थ सेवा के लिए एक स्थानीय इंटरफ़ेस प्रदान करता है।\n* एंबेसडर क्लाइंट को लॉगिंग, सर्किट ब्रेकिंग, रिट्रीज़ और सुरक्षा प्रदान करता है।\n\n## विशिष्ट उपयोग का मामला\n\n* किसी अन्य वस्तु तक पहुंच को नियंत्रित करें\n* लॉगिंग लागू करें\n* सर्किट ब्रेकिंग लागू करें\n* दूरस्थ सेवा कार्यों को ऑफलोड करें\n* नेटवर्क कनेक्शन की सुविधा\n\n## ज्ञात उपयोग\n\n* [Kubernetes-native API gateway for microservices](https://github.com/datawire/ambassador)\n\n## संबंधित पैटर्न\n\n* [Proxy](https://java-design-patterns.com/patterns/proxy/)\n\n## श्रेय\n\n* [Ambassador pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/ambassador)\n* [Designing Distributed Systems: Patterns and Paradigms for Scalable, Reliable Services](https://www.amazon.com/s?k=designing+distributed+systems&sprefix=designing+distri%2Caps%2C156&linkCode=ll2&tag=javadesignpat-20&linkId=a12581e625462f9038557b01794e5341&language=en_US&ref_=as_li_ss_tl)\n"
  },
  {
    "path": "localization/hi/api-gateway/README.md",
    "content": "---\ntitle: API Gateway\ncategory: Architectural\nlanguage: hi\ntag:\n  - Cloud distributed\n  - Decoupling\n  - Microservices\n---\n\n## हेतु\n\nएक ही स्थान, एपीआई गेटवे पर माइक्रोसर्विसेज के लिए एकत्रित कॉल। उपयोगकर्ता एक ही कॉल करता है\nएपीआई गेटवे पर, और एपीआई गेटवे फिर प्रत्येक प्रासंगिक माइक्रोसर्विस को कॉल करता है।\n\n## व्याख्या\n\nमाइक्रोसर्विसेज पैटर्न के साथ, एक क्लाइंट को कई अलग-अलग माइक्रोसर्विसेज से डेटा की आवश्यकता हो सकती है। यदि\nक्लाइंट ने प्रत्येक माइक्रोसर्विस को सीधे कॉल किया, जो लंबे समय तक लोड करने में योगदान दे सकता है\nक्लाइंट को कॉल की गई प्रत्येक माइक्रोसर्विस के लिए नेटवर्क अनुरोध करना होगा। इसके अलावा, होने\nक्लाइंट कॉल प्रत्येक माइक्रोसर्विस क्लाइंट को सीधे उस माइक्रोसर्विस से जोड़ती है - यदि आंतरिक है\nमाइक्रोसर्विसेज का कार्यान्वयन बदल जाता है (उदाहरण के लिए, यदि दो माइक्रोसर्विसेज को कभी-कभी संयोजित किया जाता है\nभविष्य में) या यदि किसी माइक्रोसर्विस का स्थान (होस्ट और पोर्ट) बदलता है, तो प्रत्येक ग्राहक\nउन माइक्रोसर्विसेज का उपयोग अद्यतन किया जाना चाहिए।\n\nएपीआई गेटवे पैटर्न का इरादा इनमें से कुछ मुद्दों को कम करना है। एपीआई गेटवे में\nपैटर्न, एक अतिरिक्त इकाई (एपीआई गेटवे) क्लाइंट और माइक्रोसर्विसेज के बीच रखी गई है।\nएपीआई गेटवे का काम माइक्रोसर्विसेज पर कॉल को एकत्रित करना है। ग्राहक के बजाय\nप्रत्येक माइक्रोसर्विस को व्यक्तिगत रूप से कॉल करने पर, क्लाइंट एपीआई गेटवे को एक बार कॉल करता है। एपीआई\nगेटवे फिर प्रत्येक माइक्रोसर्विसेज को कॉल करता है जिनकी ग्राहक को आवश्यकता होती है।\n\nवास्तविक दुनिया का उदाहरण\n\n> हम एक ई-कॉमर्स साइट के लिए माइक्रोसर्विसेज और एपीआई गेटवे पैटर्न लागू कर रहे हैं। इस व्यवस्था में\n> एपीआई गेटवे इमेज और प्राइस माइक्रोसर्विसेज को कॉल करता है।\n\nसाफ़ शब्दों में\n\n> माइक्रोसर्विसेज आर्किटेक्चर का उपयोग करके कार्यान्वित सिस्टम के लिए, एपीआई गेटवे एकल प्रवेश बिंदु है\n> जो व्यक्तिगत माइक्रोसर्विसेज के लिए कॉलों को एकत्रित करता है।\n\nविकिपीडिया कहता है\n\n> एपीआई गेटवे एक सर्वर है जो एपीआई फ्रंट-एंड के रूप में कार्य करता है, एपीआई अनुरोध प्राप्त करता है, थ्रॉटलिंग लागू करता है\n> और सुरक्षा नीतियां, अनुरोधों को बैक-एंड सेवा तक भेजती हैं और फिर प्रतिक्रिया को वापस भेजती हैं\n> अनुरोधकर्ता को. एक गेटवे में अक्सर व्यवस्थित करने और संशोधित करने के लिए एक परिवर्तन इंजन शामिल होता है\n> तुरंत अनुरोध और प्रतिक्रियाएँ। एक गेटवे संग्रहण जैसी कार्यक्षमता भी प्रदान कर सकता है\n> एनालिटिक्स डेटा और कैशिंग प्रदान करना। गेटवे समर्थन के लिए कार्यक्षमता प्रदान कर सकता है\n> प्रमाणीकरण, प्राधिकरण, सुरक्षा, ऑडिट और नियामक अनुपालन।\n\n**प्रोग्रामेटिक उदाहरण**\n\nयह कार्यान्वयन दिखाता है कि ई-कॉमर्स साइट के लिए एपीआई गेटवे पैटर्न कैसा दिख सकता है।\n`ApiGateway` `ImageClientImpl` का उपयोग करके इमेज और प्राइस माइक्रोसर्विसेज को कॉल करता है और\nक्रमशः `PriceClientImpl`। डेस्कटॉप डिवाइस पर साइट देखने वाले ग्राहक दोनों कीमतें देख सकते हैं\nजानकारी और उत्पाद की एक छवि, इसलिए `ApiGateway` दोनों माइक्रोसर्विसेज को कॉल करता है\nडेटा को `DesktopProduct` मॉडल में एकत्रित करता है। हालाँकि, मोबाइल उपयोगकर्ता केवल कीमत की जानकारी देखते हैं;\nउन्हें उत्पाद की छवि नहीं दिखती. मोबाइल उपयोगकर्ताओं के लिए, `ApiGateway` केवल मूल्य प्राप्त करता है\nजानकारी, जिसका उपयोग यह `MobileProduct` को पॉप्युलेट करने के लिए करता है।\n\nयहां इमेज माइक्रोसर्विस कार्यान्वयन है।\n\n```java\npublic interface ImageClient {\n  String getImagePath();\n}\n\npublic class ImageClientImpl implements ImageClient {\n  @Override\n  public String getImagePath() {\n    var httpClient = HttpClient.newHttpClient();\n    var httpGet = HttpRequest.newBuilder()\n        .GET()\n        .uri(URI.create(\"http://localhost:50005/image-path\"))\n        .build();\n\n    try {\n      var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n      return httpResponse.body();\n    } catch (IOException | InterruptedException e) {\n      e.printStackTrace();\n    }\n\n    return null;\n  }\n}\n```\n\nयहां प्राइस माइक्रोसर्विस कार्यान्वयन है।\n\n```java\npublic interface PriceClient {\n  String getPrice();\n}\n\npublic class PriceClientImpl implements PriceClient {\n\n  @Override\n  public String getPrice() {\n    var httpClient = HttpClient.newHttpClient();\n    var httpGet = HttpRequest.newBuilder()\n        .GET()\n        .uri(URI.create(\"http://localhost:50006/price\"))\n        .build();\n\n    try {\n      var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n      return httpResponse.body();\n    } catch (IOException | InterruptedException e) {\n      e.printStackTrace();\n    }\n\n    return null;\n  }\n}\n```\n\nयहां हम देख सकते हैं कि एपीआई गेटवे माइक्रोसर्विसेज के अनुरोधों को कैसे मैप करता है।\n\n```java\npublic class ApiGateway {\n\n  @Resource\n  private ImageClient imageClient;\n\n  @Resource\n  private PriceClient priceClient;\n\n  @RequestMapping(path = \"/desktop\", method = RequestMethod.GET)\n  public DesktopProduct getProductDesktop() {\n    var desktopProduct = new DesktopProduct();\n    desktopProduct.setImagePath(imageClient.getImagePath());\n    desktopProduct.setPrice(priceClient.getPrice());\n    return desktopProduct;\n  }\n\n  @RequestMapping(path = \"/mobile\", method = RequestMethod.GET)\n  public MobileProduct getProductMobile() {\n    var mobileProduct = new MobileProduct();\n    mobileProduct.setPrice(priceClient.getPrice());\n    return mobileProduct;\n  }\n}\n```\n\n## क्लास डायग्राम\n![alt text](../../../api-gateway/etc/api-gateway.png \"API Gateway\")\n\n## प्रयोज्यता\n\n एपीआई गेटवे पैटर्न का उपयोग करें जब\n\n* आप माइक्रोसर्विसेज आर्किटेक्चर का उपयोग कर रहे हैं और आपको अपने माइक्रोसर्विसेज कॉल के लिए एकत्रीकरण के एक बिंदु की आवश्यकता है।\n\n## ट्यूटोरियल\n\n* [Exploring the New Spring Cloud Gateway](https://www.baeldung.com/spring-cloud-gateway)\n* [Spring Cloud - Gateway](https://www.tutorialspoint.com/spring_cloud/spring_cloud_gateway.htm)\n* [Getting Started With Spring Cloud Gateway](https://dzone.com/articles/getting-started-with-spring-cloud-gateway)\n\n## श्रेय\n\n* [microservices.io - API Gateway](http://microservices.io/patterns/apigateway.html)\n* [NGINX - Building Microservices: Using an API Gateway](https://www.nginx.com/blog/building-microservices-using-an-api-gateway/)\n* [Microservices Patterns: With examples in Java](https://www.amazon.com/gp/product/1617294543/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617294543&linkId=ac7b6a57f866ac006a309d9086e8cfbd)\n* [Building Microservices: Designing Fine-Grained Systems](https://www.amazon.com/gp/product/1491950358/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1491950358&linkId=4c95ca9831e05e3f0dadb08841d77bf1)\n"
  },
  {
    "path": "localization/hi/arrange-act-assert/README.md",
    "content": "---\ntitle: Arrange/Act/Assert\ncategory: Idiom\nlanguage: hi\ntag:\n - Testing\n---\n\n## दूसरा नाम\n\nदिया/कब/तब\n\n## हेतु\n\nअरेंज/एक्ट/एसर्ट (एएए) यूनिट परीक्षणों के आयोजन के लिए एक पैटर्न है।\nयह परीक्षणों को तीन स्पष्ट और विशिष्ट चरणों में विभाजित करता है:\n\n1. व्यवस्थित करें: परीक्षण के लिए आवश्यक सेटअप और आरंभीकरण करें।\n2. अधिनियम: परीक्षण के लिए आवश्यक कार्रवाई करें।\n3. दावा: परीक्षण के परिणाम सत्यापित करें।\n\n## व्याख्या\n\nइस पैटर्न के कई महत्वपूर्ण लाभ हैं. यह एक परीक्षण के बीच स्पष्ट अलगाव पैदा करता है\nसेटअप, संचालन और परिणाम। यह संरचना कोड को पढ़ने और समझने में आसान बनाती है। अगर\nआप चरणों को क्रम में रखते हैं और उन्हें अलग करने के लिए अपना कोड प्रारूपित करते हैं, आप एक परीक्षण स्कैन कर सकते हैं और\nजल्दी से समझें कि यह क्या करता है।\n\nजब आप अपनी परीक्षाएँ लिखते हैं तो यह कुछ हद तक अनुशासन भी लागू करता है। आपको सोचना होगा\nआपके परीक्षण द्वारा निष्पादित किए जाने वाले तीन चरणों के बारे में स्पष्ट रूप से बताएं। यह परीक्षणों को लिखने के लिए अधिक स्वाभाविक बनाता है\nउसी समय, चूँकि आपके पास पहले से ही एक रूपरेखा है।\n\nवास्तविक दुनिया का उदाहरण\n\n> हमें एक कक्षा के लिए व्यापक और स्पष्ट यूनिट टेस्ट सूट लिखने की जरूरत है।\n\nसाफ़ शब्दों में\n\n> अरेंज/एक्ट/एसर्ट एक परीक्षण पैटर्न है जो परीक्षणों को आसान बनाने के लिए तीन स्पष्ट चरणों में व्यवस्थित करता है\n> रखरखाव।\n\nविकीविकीवेब कहता है\n\n> अरेंज/एक्ट/एसर्ट यूनिटटेस्ट विधियों में कोड को व्यवस्थित करने और फ़ॉर्मेट करने का एक पैटर्न है।\n\n**प्रोग्रामेटिक उदाहरण**\n\nआइए सबसे पहले इकाई परीक्षण के लिए अपने `Cash` वर्ग का परिचय दें।\n\n```java\npublic class Cash {\n\n  private int amount;\n\n  Cash(int amount) {\n    this.amount = amount;\n  }\n\n  void plus(int addend) {\n    amount += addend;\n  }\n\n  boolean minus(int subtrahend) {\n    if (amount >= subtrahend) {\n      amount -= subtrahend;\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  int count() {\n    return amount;\n  }\n}\n```\n\nफिर हम अपने यूनिट परीक्षण को अरेंज/एक्ट/एसर्ट पैटर्न के अनुसार लिखते हैं। स्पष्ट रूप से ध्यान दें\nप्रत्येक इकाई परीक्षण के लिए अलग-अलग चरण।\n\n```java\nclass CashAAATest {\n\n  @Test\n  void testPlus() {\n    //Arrange\n    var cash = new Cash(3);\n    //Act\n    cash.plus(4);\n    //Assert\n    assertEquals(7, cash.count());\n  }\n\n  @Test\n  void testMinus() {\n    //Arrange\n    var cash = new Cash(8);\n    //Act\n    var result = cash.minus(5);\n    //Assert\n    assertTrue(result);\n    assertEquals(3, cash.count());\n  }\n\n  @Test\n  void testInsufficientMinus() {\n    //Arrange\n    var cash = new Cash(1);\n    //Act\n    var result = cash.minus(6);\n    //Assert\n    assertFalse(result);\n    assertEquals(1, cash.count());\n  }\n\n  @Test\n  void testUpdate() {\n    //Arrange\n    var cash = new Cash(5);\n    //Act\n    cash.plus(6);\n    var result = cash.minus(3);\n    //Assert\n    assertTrue(result);\n    assertEquals(8, cash.count());\n  }\n}\n```\n\n## प्रयोज्यता\n\nजब अरेंज/एक्ट/एसर्ट पैटर्न का उपयोग करें\n\n* आपको अपने यूनिट परीक्षणों की संरचना करने की आवश्यकता है ताकि उन्हें पढ़ना, बनाए रखना और बढ़ाना आसान हो।\n\n## श्रेय\n\n* [Arrange, Act, Assert: What is AAA Testing?](https://blog.ncrunch.net/post/arrange-act-assert-aaa-testing.aspx)\n* [Bill Wake: 3A – Arrange, Act, Assert](https://xp123.com/articles/3a-arrange-act-assert/)\n* [Martin Fowler: GivenWhenThen](https://martinfowler.com/bliki/GivenWhenThen.html)\n* [xUnit Test Patterns: Refactoring Test Code](https://www.amazon.com/gp/product/0131495054/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0131495054&linkId=99701e8f4af2f7e8dd50d720c9b63dbf)\n* [Unit Testing Principles, Practices, and Patterns](https://www.amazon.com/gp/product/1617296279/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617296279&linkId=74c75cf22a63c3e4758ae08aa0a0cc35)\n* [Test Driven Development: By Example](https://www.amazon.com/gp/product/0321146530/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0321146530&linkId=5c63a93d8c1175b84ca5087472ef0e05)\n"
  },
  {
    "path": "localization/hi/async-method-invocation/README.md",
    "content": "---\ntitle: Async Method Invocation\ncategory: Concurrency\nlanguage: hi\ntag:\n - Reactive\n---\n\n## हेतु\n\nएसिंक्रोनस विधि मंगलाचरण एक पैटर्न है जहां कॉलिंग थ्रेड होता है\nकार्यों के परिणाम की प्रतीक्षा करते समय अवरुद्ध नहीं किया जाता है। पैटर्न समानांतर प्रदान करता है\nअनेक स्वतंत्र कार्यों को संसाधित करना और इनके माध्यम से परिणाम प्राप्त करना\nकॉलबैक या सब कुछ पूरा होने तक प्रतीक्षा करना। \n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n>अंतरिक्ष रॉकेट लॉन्च करना एक रोमांचक व्यवसाय है। मिशन कमांड लॉन्च करने का आदेश देता है और\n> कुछ अनिश्चित समय के बाद, रॉकेट या तो सफलतापूर्वक लॉन्च होता है या बुरी तरह विफल हो जाता है।\n\nसाफ़ शब्दों में\n\n> एसिंक्रोनस विधि मंगलाचरण कार्य प्रसंस्करण शुरू करता है और कार्य पूरा होने से तुरंत पहले वापस आ जाता है\n> तैयार. कार्य प्रसंस्करण के परिणाम बाद में कॉल करने वाले को लौटा दिए जाते हैं।\n\nविकिपीडिया कहता है\n\n> मल्टीथ्रेडेड कंप्यूटर प्रोग्रामिंग में, एसिंक्रोनस मेथड इनवोकेशन (एएमआई) के रूप में भी जाना जाता है\n> एसिंक्रोनस विधि कॉल या एसिंक्रोनस पैटर्न एक डिज़ाइन पैटर्न है जिसमें कॉल साइट\n> कॉल किए गए कोड के समाप्त होने की प्रतीक्षा करते समय अवरुद्ध नहीं होता है। इसके बजाय, कॉलिंग थ्रेड है\n> उत्तर आने पर सूचित किया जाएगा। उत्तर के लिए मतदान एक अवांछित विकल्प है।\n\n**प्रोग्रामेटिक उदाहरण**\n\nइस उदाहरण में, हम अंतरिक्ष रॉकेट लॉन्च कर रहे हैं और चंद्र रोवर्स तैनात कर रहे हैं।\n\nएप्लिकेशन एसिंक विधि मंगलाचरण पैटर्न प्रदर्शित करता है। पैटर्न के प्रमुख भाग हैं\n`AsyncResult` जो अतुल्यकालिक रूप से मूल्यांकन किए गए मान के लिए एक मध्यवर्ती कंटेनर है,\n`AsyncCallback` जिसे कार्य पूरा होने पर निष्पादित करने के लिए प्रदान किया जा सकता है और `AsyncExecutor`\nasync कार्यों के निष्पादन का प्रबंधन करता है।\n\n```java\npublic interface AsyncResult<T> {\n  boolean isCompleted();\n  T getValue() throws ExecutionException;\n  void await() throws InterruptedException;\n}\n```\n\n```java\npublic interface AsyncCallback<T> {\n  void onComplete(T value, Optional<Exception> ex);\n}\n```\n\n```java\npublic interface AsyncExecutor {\n  <T> AsyncResult<T> startProcess(Callable<T> task);\n  <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback);\n  <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException;\n}\n```\n\n`ThreadAsyncExecutor` is an implementation of `AsyncExecutor`. Some of its key parts are highlighted \nnext.\n\n```java\npublic class ThreadAsyncExecutor implements AsyncExecutor {\n\n  @Override\n  public <T> AsyncResult<T> startProcess(Callable<T> task) {\n    return startProcess(task, null);\n  }\n\n  @Override\n  public <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback) {\n    var result = new CompletableResult<>(callback);\n    new Thread(\n            () -> {\n              try {\n                result.setValue(task.call());\n              } catch (Exception ex) {\n                result.setException(ex);\n              }\n            },\n            \"executor-\" + idx.incrementAndGet())\n        .start();\n    return result;\n  }\n\n  @Override\n  public <T> T endProcess(AsyncResult<T> asyncResult)\n      throws ExecutionException, InterruptedException {\n    if (!asyncResult.isCompleted()) {\n      asyncResult.await();\n    }\n    return asyncResult.getValue();\n  }\n}\n```\n\nफिर हम यह देखने के लिए कुछ रॉकेट लॉन्च करने के लिए तैयार हैं कि सब कुछ एक साथ कैसे काम करता है।\n\n```java\npublic static void main(String[] args) throws Exception {\n  // construct a new executor that will run async tasks\n  var executor = new ThreadAsyncExecutor();\n\n  // start few async tasks with varying processing times, two last with callback handlers\n  final var asyncResult1 = executor.startProcess(lazyval(10, 500));\n  final var asyncResult2 = executor.startProcess(lazyval(\"test\", 300));\n  final var asyncResult3 = executor.startProcess(lazyval(50L, 700));\n  final var asyncResult4 = executor.startProcess(lazyval(20, 400), callback(\"Deploying lunar rover\"));\n  final var asyncResult5 =\n      executor.startProcess(lazyval(\"callback\", 600), callback(\"Deploying lunar rover\"));\n\n  // emulate processing in the current thread while async tasks are running in their own threads\n  Thread.sleep(350); // Oh boy, we are working hard here\n  log(\"Mission command is sipping coffee\");\n\n  // wait for completion of the tasks\n  final var result1 = executor.endProcess(asyncResult1);\n  final var result2 = executor.endProcess(asyncResult2);\n  final var result3 = executor.endProcess(asyncResult3);\n  asyncResult4.await();\n  asyncResult5.await();\n\n  // log the results of the tasks, callbacks log immediately when complete\n  log(\"Space rocket <\" + result1 + \"> launch complete\");\n  log(\"Space rocket <\" + result2 + \"> launch complete\");\n  log(\"Space rocket <\" + result3 + \"> launch complete\");\n}\n```\n\nयहां प्रोग्राम कंसोल आउटपुट है।\n\n```java\n21:47:08.227 [executor-2] INFO com.iluwatar.async.method.invocation.App - Space rocket <test> launched successfully\n21:47:08.269 [main] INFO com.iluwatar.async.method.invocation.App - Mission command is sipping coffee\n21:47:08.318 [executor-4] INFO com.iluwatar.async.method.invocation.App - Space rocket <20> launched successfully\n21:47:08.335 [executor-4] INFO com.iluwatar.async.method.invocation.App - Deploying lunar rover <20>\n21:47:08.414 [executor-1] INFO com.iluwatar.async.method.invocation.App - Space rocket <10> launched successfully\n21:47:08.519 [executor-5] INFO com.iluwatar.async.method.invocation.App - Space rocket <callback> launched successfully\n21:47:08.519 [executor-5] INFO com.iluwatar.async.method.invocation.App - Deploying lunar rover <callback>\n21:47:08.616 [executor-3] INFO com.iluwatar.async.method.invocation.App - Space rocket <50> launched successfully\n21:47:08.617 [main] INFO com.iluwatar.async.method.invocation.App - Space rocket <10> launch complete\n21:47:08.617 [main] INFO com.iluwatar.async.method.invocation.App - Space rocket <test> launch complete\n21:47:08.618 [main] INFO com.iluwatar.async.method.invocation.App - Space rocket <50> launch complete\n```\n\n# क्लास डायग्राम\n\n![alt text](../../../async-method-invocation/etc/async-method-invocation.png \"Async Method Invocation\")\n\n## प्रयोज्यता\n\nजब async विधि मंगलाचरण पैटर्न का उपयोग करें\n\n* आपके पास कई स्वतंत्र कार्य हैं जो समानांतर में चल सकते हैं\n* आपको अनुक्रमिक कार्यों के समूह के प्रदर्शन में सुधार करने की आवश्यकता है\n* आपके पास सीमित मात्रा में प्रसंस्करण क्षमता या लंबे समय तक चलने वाले कार्य हैं और कॉल करने वाले को कार्यों के तैयार होने का इंतजार नहीं करना चाहिए\n\n## वास्तविक दुनिया के उदाहरण\n\n* [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html)\n* [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)\n* [ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html)\n* [Task-based Asynchronous Pattern](https://msdn.microsoft.com/en-us/library/hh873175.aspx)\n"
  },
  {
    "path": "localization/hi/balking/README.md",
    "content": "---\ntitle: Balking\ncategory: Concurrency\nlanguage: hi\ntag:\n - Decoupling\n---\n\n## हेतु\n\nबाल्किंग पैटर्न का उपयोग किसी ऑब्जेक्ट को किसी निश्चित कोड को निष्पादित करने से रोकने के लिए किया जाता है यदि वह अधूरा है\nया अनुचित स्थिति.\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> कपड़े धोने की मशीन में कपड़े धोने की शुरुआत करने के लिए एक स्टार्ट-बटन होता है। धोते समय\n> मशीन निष्क्रिय है तो बटन अपेक्षानुसार काम करता है, लेकिन यदि वह पहले से ही धुलाई कर रहा है तो बटन काम करता है\n> कुछ नहीं.\n\nसाफ़ शब्दों में\n\n> बैल्किंग पैटर्न का उपयोग करते हुए, एक निश्चित कोड केवल तभी निष्पादित होता है जब ऑब्जेक्ट विशेष स्थिति में हो।\n\nविकिपीडिया कहता है\n\n> बैल्किंग पैटर्न एक सॉफ्टवेयर डिज़ाइन पैटर्न है जो किसी ऑब्जेक्ट पर केवल तभी क्रिया निष्पादित करता है\n> वस्तु एक विशेष अवस्था में है। उदाहरण के लिए, यदि कोई ऑब्जेक्ट ज़िप फ़ाइलें और कॉलिंग पढ़ता है\n> विधि ऑब्जेक्ट पर एक गेट विधि को लागू करती है जब ज़िप फ़ाइल खुली नहीं होती है, तो ऑब्जेक्ट \"बाल्क\" हो जाएगा\n> अनुरोध पर.\n\n**प्रोग्रामेटिक उदाहरण**\n\nइस उदाहरण के कार्यान्वयन में, `WashingMachine` एक ऑब्जेक्ट है जिसमें दो स्थितियाँ हैं जिनमें यह हो सकता है\nहोना: सक्षम और धुलाई। यदि मशीन सक्षम है, तो थ्रेड-सेफ का उपयोग करके स्थिति वॉशिंग में बदल जाती है\nतरीका। दूसरी ओर, यदि यह पहले से ही धुलाई कर रहा है और कोई अन्य थ्रेड `wash()` निष्पादित करता है\nयह ऐसा नहीं करेगा और बिना कुछ किए वापस लौट आएगा।\n\nयहां `WashingMachine` वर्ग के प्रासंगिक भाग दिए गए हैं।\n\n```java\n@Slf4j\npublic class WashingMachine {\n\n  private final DelayProvider delayProvider;\n  private WashingMachineState washingMachineState;\n\n  public WashingMachine(DelayProvider delayProvider) {\n    this.delayProvider = delayProvider;\n    this.washingMachineState = WashingMachineState.ENABLED;\n  }\n\n  public WashingMachineState getWashingMachineState() {\n    return washingMachineState;\n  }\n\n  public void wash() {\n    synchronized (this) {\n      var machineState = getWashingMachineState();\n      LOGGER.info(\"{}: Actual machine state: {}\", Thread.currentThread().getName(), machineState);\n      if (this.washingMachineState == WashingMachineState.WASHING) {\n        LOGGER.error(\"Cannot wash if the machine has been already washing!\");\n        return;\n      }\n      this.washingMachineState = WashingMachineState.WASHING;\n    }\n    LOGGER.info(\"{}: Doing the washing\", Thread.currentThread().getName());\n    this.delayProvider.executeAfterDelay(50, TimeUnit.MILLISECONDS, this::endOfWashing);\n  }\n\n  public synchronized void endOfWashing() {\n    washingMachineState = WashingMachineState.ENABLED;\n    LOGGER.info(\"{}: Washing completed.\", Thread.currentThread().getId());\n  }\n}\n```\n\nयहां `WashingMachine` द्वारा उपयोग किया जाने वाला सरल `DelayProvider` इंटरफ़ेस है।\n\n```java\npublic interface DelayProvider {\n  void executeAfterDelay(long interval, TimeUnit timeUnit, Runnable task);\n}\n```\n\nअब हम `WashingMachine` का उपयोग करके एप्लिकेशन का परिचय देते हैं।\n\n```java\n  public static void main(String... args) {\n    final var washingMachine = new WashingMachine();\n    var executorService = Executors.newFixedThreadPool(3);\n    for (int i = 0; i < 3; i++) {\n      executorService.execute(washingMachine::wash);\n    }\n    executorService.shutdown();\n    try {\n      executorService.awaitTermination(10, TimeUnit.SECONDS);\n    } catch (InterruptedException ie) {\n      LOGGER.error(\"ERROR: Waiting on executor service shutdown!\");\n      Thread.currentThread().interrupt();\n    }\n  }\n```\n\nयहां प्रोग्राम का कंसोल आउटपुट है।\n\n```\n14:02:52.268 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Actual machine state: ENABLED\n14:02:52.272 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Doing the washing\n14:02:52.272 [pool-1-thread-3] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-3: Actual machine state: WASHING\n14:02:52.273 [pool-1-thread-3] ERROR com.iluwatar.balking.WashingMachine - Cannot wash if the machine has been already washing!\n14:02:52.273 [pool-1-thread-1] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-1: Actual machine state: WASHING\n14:02:52.273 [pool-1-thread-1] ERROR com.iluwatar.balking.WashingMachine - Cannot wash if the machine has been already washing!\n14:02:52.324 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - 14: Washing completed.\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../balking/etc/balking.png \"Balking\")\n\n## प्रयोज्यता\n\nजब बाल्किंग पैटर्न का प्रयोग करें\n\n* आप किसी वस्तु पर तभी कोई कार्रवाई करना चाहते हैं जब वह किसी विशेष स्थिति में हो\n* वस्तुएँ आम तौर पर केवल ऐसी स्थिति में होती हैं जो अस्थायी रूप से लेकिन किसी अज्ञात के लिए झुकने की संभावना होती है\n  लगने वाला समय\n\n## संबंधित पैटर्न\n\n* [Guarded Suspension Pattern](https://java-design-patterns.com/patterns/guarded-suspension/)\n* [Double Checked Locking Pattern](https://java-design-patterns.com/patterns/double-checked-locking/)\n\n## श्रेय\n\n* [Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML, 2nd Edition, Volume 1](https://www.amazon.com/gp/product/0471227293/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0471227293&linkId=0e39a59ffaab93fb476036fecb637b99)\n"
  },
  {
    "path": "localization/hi/bridge/README.md",
    "content": "---\ntitle: Bridge\ncategory: Structural\nlanguage: hi\ntag:\n - Gang of Four\n---\n\n## दूसरा नाम\n\nहैंडल/बॉडी\n\n## हेतु\n\nइसके कार्यान्वयन से एक अमूर्त को अलग करें ताकि दोनों स्वतंत्र रूप से भिन्न हो सकें।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> विचार करें कि आपके पास विभिन्न जादूओं वाला एक हथियार है, और आपको मिश्रण की अनुमति देनी चाहिए\n> अलग-अलग जादू वाले अलग-अलग हथियार। आप क्या करेंगे? प्रत्येक की एकाधिक प्रतिलिपियाँ बनाएँ\n> प्रत्येक जादू के लिए हथियारों का या आप बस अलग-अलग जादू और सेट बनाएंगे\n> क्या यह आवश्यकतानुसार हथियार के लिए है? ब्रिज पैटर्न आपको दूसरा करने की अनुमति देता है।\n\nसादे शब्दों में\n\n> ब्रिज पैटर्न वंशानुक्रम पर संरचना को प्राथमिकता देने के बारे में है। कार्यान्वयन विवरण आगे बढ़ाए गए हैं\n> एक पदानुक्रम से दूसरे ऑब्जेक्ट पर एक अलग पदानुक्रम के साथ।\n\nविकिपीडिया कहता है\n\n> ब्रिज पैटर्न सॉफ्टवेयर इंजीनियरिंग में उपयोग किया जाने वाला एक डिज़ाइन पैटर्न है जिसका अर्थ है \"इसके कार्यान्वयन से एक अमूर्तता को अलग करना ताकि दोनों स्वतंत्र रूप से भिन्न हो सकें\"\n\n**प्रोग्रामेटिक उदाहरण**\n\nऊपर से हमारे हथियार उदाहरण का अनुवाद। यहां हमारे पास `Weapon` पदानुक्रम है:\n\n```java\npublic interface Weapon {\n  void wield();\n  void swing();\n  void unwield();\n  Enchantment getEnchantment();\n}\n\npublic class Sword implements Weapon {\n\n  private final Enchantment enchantment;\n\n  public Sword(Enchantment enchantment) {\n    this.enchantment = enchantment;\n  }\n\n  @Override\n  public void wield() {\n    LOGGER.info(\"The sword is wielded.\");\n    enchantment.onActivate();\n  }\n\n  @Override\n  public void swing() {\n    LOGGER.info(\"The sword is swinged.\");\n    enchantment.apply();\n  }\n\n  @Override\n  public void unwield() {\n    LOGGER.info(\"The sword is unwielded.\");\n    enchantment.onDeactivate();\n  }\n\n  @Override\n  public Enchantment getEnchantment() {\n    return enchantment;\n  }\n}\n\npublic class Hammer implements Weapon {\n\n  private final Enchantment enchantment;\n\n  public Hammer(Enchantment enchantment) {\n    this.enchantment = enchantment;\n  }\n\n  @Override\n  public void wield() {\n    LOGGER.info(\"The hammer is wielded.\");\n    enchantment.onActivate();\n  }\n\n  @Override\n  public void swing() {\n    LOGGER.info(\"The hammer is swinged.\");\n    enchantment.apply();\n  }\n\n  @Override\n  public void unwield() {\n    LOGGER.info(\"The hammer is unwielded.\");\n    enchantment.onDeactivate();\n  }\n\n  @Override\n  public Enchantment getEnchantment() {\n    return enchantment;\n  }\n}\n```\n\nयहां अलग मंत्रमुग्धता पदानुक्रम है:\n\n```java\npublic interface Enchantment {\n  void onActivate();\n  void apply();\n  void onDeactivate();\n}\n\npublic class FlyingEnchantment implements Enchantment {\n\n  @Override\n  public void onActivate() {\n    LOGGER.info(\"The item begins to glow faintly.\");\n  }\n\n  @Override\n  public void apply() {\n    LOGGER.info(\"The item flies and strikes the enemies finally returning to owner's hand.\");\n  }\n\n  @Override\n  public void onDeactivate() {\n    LOGGER.info(\"The item's glow fades.\");\n  }\n}\n\npublic class SoulEatingEnchantment implements Enchantment {\n\n  @Override\n  public void onActivate() {\n    LOGGER.info(\"The item spreads bloodlust.\");\n  }\n\n  @Override\n  public void apply() {\n    LOGGER.info(\"The item eats the soul of enemies.\");\n  }\n\n  @Override\n  public void onDeactivate() {\n    LOGGER.info(\"Bloodlust slowly disappears.\");\n  }\n}\n```\n\nयहां दोनों पदानुक्रम क्रियान्वित हैं:\n\n```java\nLOGGER.info(\"The knight receives an enchanted sword.\");\nvar enchantedSword = new Sword(new SoulEatingEnchantment());\nenchantedSword.wield();\nenchantedSword.swing();\nenchantedSword.unwield();\n\nLOGGER.info(\"The valkyrie receives an enchanted hammer.\");\nvar hammer = new Hammer(new FlyingEnchantment());\nhammer.wield();\nhammer.swing();\nhammer.unwield();\n```\n\nयहाँ कंसोल आउटपुट है.\n\n```\nThe knight receives an enchanted sword.\nThe sword is wielded.\nThe item spreads bloodlust.\nThe sword is swung.\nThe item eats the soul of enemies.\nThe sword is unwielded.\nBloodlust slowly disappears.\nThe valkyrie receives an enchanted hammer.\nThe hammer is wielded.\nThe item begins to glow faintly.\nThe hammer is swung.\nThe item flies and strikes the enemies finally returning to owner's hand.\nThe hammer is unwielded.\nThe item's glow fades.\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../bridge/etc/bridge.urm.png \"Bridge class diagram\")\n\n## प्रयोज्यता\n\nजब ब्रिज पैटर्न का प्रयोग करें\n\n* आप किसी अमूर्तता और उसके कार्यान्वयन के बीच स्थायी बंधन से बचना चाहते हैं। यह मामला हो सकता है, उदाहरण के लिए, जब कार्यान्वयन को रन-टाइम पर चुना या स्विच किया जाना चाहिए।\n* अमूर्तीकरण और उनके कार्यान्वयन दोनों को उपवर्गीकरण द्वारा विस्तार योग्य होना चाहिए। इस मामले में, ब्रिज पैटर्न आपको विभिन्न अमूर्तताओं और कार्यान्वयनों को संयोजित करने और उन्हें स्वतंत्र रूप से विस्तारित करने की सुविधा देता है।\n* किसी अमूर्त के कार्यान्वयन में परिवर्तन का ग्राहकों पर कोई प्रभाव नहीं पड़ना चाहिए; अर्थात्, उनके कोड को पुनः संकलित नहीं करना पड़ेगा।\n* आपके पास वर्गों का प्रसार है। ऐसा वर्ग पदानुक्रम किसी वस्तु को दो भागों में विभाजित करने की आवश्यकता को इंगित करता है। रुंबॉघ ऐसे वर्ग पदानुक्रमों को संदर्भित करने के लिए \"नेस्टेड सामान्यीकरण\" शब्द का उपयोग करता है।\n* आप एक कार्यान्वयन को कई ऑब्जेक्ट्स के बीच साझा करना चाहते हैं (शायद संदर्भ गणना का उपयोग करके), और यह तथ्य क्लाइंट से छिपा होना चाहिए। एक सरल उदाहरण कोप्लियन का स्ट्रिंग क्लास है, जिसमें कई ऑब्जेक्ट एक ही स्ट्रिंग प्रतिनिधित्व साझा कर सकते हैं।\n\n## ट्यूटोरियल\n\n* [Bridge Pattern Tutorial](https://www.journaldev.com/1491/bridge-design-pattern-java)\n\n## श्रेय\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/hi/builder/README.md",
    "content": "---\ntitle: Builder\ncategory: Creational\nlanguage: hi\ntag:\n - Gang of Four\n---\n\n## हेतु\n\nकिसी जटिल वस्तु के निर्माण को उसके प्रतिनिधित्व से अलग करें ताकि निर्माण समान हो\nप्रक्रिया विभिन्न अभ्यावेदन बना सकती है।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> रोल-प्लेइंग गेम के लिए एक चरित्र जनरेटर की कल्पना करें। सबसे आसान विकल्प कंप्यूटर को चालू करना है\n> अपने लिए चरित्र बनाएं. यदि आप मैन्युअल रूप से चरित्र विवरण का चयन करना चाहते हैं जैसे\n> पेशा, लिंग, बालों का रंग आदि, चरित्र निर्माण एक चरण-दर-चरण प्रक्रिया बन जाती है\n> सभी चयन तैयार होने पर पूरा होता है।\n\nसाफ़ शब्दों में\n\n> कंस्ट्रक्टर प्रदूषण से बचते हुए आपको किसी वस्तु के विभिन्न स्वाद बनाने की अनुमति देता है। उपयोगी\n>जब किसी वस्तु के कई स्वाद हो सकते हैं। या जब इसमें बहुत सारे चरण शामिल हों\n> किसी वस्तु का निर्माण।\n\nविकिपीडिया कहता है\n\n> बिल्डर पैटर्न खोजने के इरादे से एक ऑब्जेक्ट निर्माण सॉफ़्टवेयर डिज़ाइन पैटर्न है\n> टेलिस्कोपिंग कंस्ट्रक्टर एंटी-पैटर्न का समाधान।\n\nयह कहने के बाद, मैं इस बारे में थोड़ा जोड़ना चाहूंगा कि टेलीस्कोपिंग कंस्ट्रक्टर एंटी-पैटर्न क्या है। एक बिंदु पर\nया अन्य, हम सभी ने नीचे जैसा एक कंस्ट्रक्टर देखा है:\n\n```java\npublic Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) {\n}\n```\n\nजैसा कि आप देख सकते हैं, कंस्ट्रक्टर मापदंडों की संख्या जल्दी से नियंत्रण से बाहर हो सकती है, और यह बन सकती है\nमापदंडों की व्यवस्था को समझना कठिन है। साथ ही यह पैरामीटर सूची चालू रह सकती है\nयदि आप भविष्य में और विकल्प जोड़ना चाहेंगे तो बढ़ रहा हूँ। इसे टेलिस्कोपिंग कंस्ट्रक्टर कहा जाता है\nविरोधी पैटर्न.\n\n**प्रोग्रामेटिक उदाहरण**\n\nबिल्डर पैटर्न का उपयोग करना समझदारी भरा विकल्प है। सबसे पहले, हमारे पास अपना हीरो है जिसे हम चाहते हैं\nबनाएं:\n\n```java\npublic final class Hero {\n  private final Profession profession;\n  private final String name;\n  private final HairType hairType;\n  private final HairColor hairColor;\n  private final Armor armor;\n  private final Weapon weapon;\n\n  private Hero(Builder builder) {\n    this.profession = builder.profession;\n    this.name = builder.name;\n    this.hairColor = builder.hairColor;\n    this.hairType = builder.hairType;\n    this.weapon = builder.weapon;\n    this.armor = builder.armor;\n  }\n}\n```\n\nफिर हमारे पास बिल्डर है:\n\n```java\n  public static class Builder {\n    private final Profession profession;\n    private final String name;\n    private HairType hairType;\n    private HairColor hairColor;\n    private Armor armor;\n    private Weapon weapon;\n\n    public Builder(Profession profession, String name) {\n      if (profession == null || name == null) {\n        throw new IllegalArgumentException(\"profession and name can not be null\");\n      }\n      this.profession = profession;\n      this.name = name;\n    }\n\n    public Builder withHairType(HairType hairType) {\n      this.hairType = hairType;\n      return this;\n    }\n\n    public Builder withHairColor(HairColor hairColor) {\n      this.hairColor = hairColor;\n      return this;\n    }\n\n    public Builder withArmor(Armor armor) {\n      this.armor = armor;\n      return this;\n    }\n\n    public Builder withWeapon(Weapon weapon) {\n      this.weapon = weapon;\n      return this;\n    }\n\n    public Hero build() {\n      return new Hero(this);\n    }\n  }\n```\n\nतब इसका उपयोग इस प्रकार किया जा सकता है:\n\n```java\nvar mage = new Hero.Builder(Profession.MAGE, \"Riobard\").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../builder/etc/builder.urm.png \"Builder class diagram\")\n\n## प्रयोज्यता\n\nजब बिल्डर पैटर्न का उपयोग करें\n\n* एक जटिल वस्तु बनाने के लिए एल्गोरिदम उन हिस्सों से स्वतंत्र होना चाहिए जो वस्तु बनाते हैं और उन्हें कैसे इकट्ठा किया जाता है\n* निर्माण प्रक्रिया में निर्मित वस्तु के लिए अलग-अलग प्रतिनिधित्व की अनुमति होनी चाहिए\n\n## ट्यूटोरियल\n\n* [Refactoring Guru](https://refactoring.guru/design-patterns/builder)\n* [Oracle Blog](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java)\n* [Journal Dev](https://www.journaldev.com/1425/builder-design-pattern-in-java)\n\n## ज्ञात उपयोग\n\n* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)\n* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) साथ ही समान बफ़र्स जैसे फ़्लोटबफ़र, इंटबफ़र इत्यादि।\n* [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-)\n* के सभी कार्यान्वयन [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)\n* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)\n* [Apache Commons Option.Builder](https://commons.apache.org/proper/commons-cli/apidocs/org/apache/commons/cli/Option.Builder.html)\n\n## श्रेय\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/hi/business-delegate/README.md",
    "content": "---\ntitle: Business Delegate\ncategory: Structural\nlanguage: hi\ntag:\n - Decoupling\n---\n\n## हेतु\n\nबिजनेस डेलीगेट पैटर्न बीच में एक अमूर्त परत जोड़ता है\nप्रस्तुतिकरण और व्यावसायिक स्तर। पैटर्न का उपयोग करके हम ढीला युग्मन प्राप्त करते हैं\nस्तरों के बीच और पता लगाने, कनेक्ट करने के तरीके के बारे में ज्ञान को समाहित करें,\nऔर एप्लिकेशन बनाने वाली व्यावसायिक वस्तुओं के साथ इंटरैक्ट करें।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> एक मोबाइल फोन एप्लिकेशन आपके फोन पर मौजूदा किसी भी फिल्म को स्ट्रीम करने का वादा करता है। यह पकड़ लेता है\n> उपयोगकर्ता की खोज स्ट्रिंग और इसे व्यवसाय प्रतिनिधि को भेजता है। व्यापार प्रतिनिधि\n> सबसे उपयुक्त वीडियो स्ट्रीमिंग सेवा का चयन करता है और वहां से वीडियो चलाता है।\n\nसादे शब्दों में\n\n> व्यावसायिक प्रतिनिधि प्रस्तुतिकरण और व्यावसायिक स्तरों के बीच एक अमूर्त परत जोड़ता है।\n\nविकिपीडिया कहता है\n\n> बिजनेस डेलिगेट एक जावा ईई डिज़ाइन पैटर्न है। यह पैटर्न युग्मन को कम करने का निर्देश दे रहा है\n> व्यावसायिक सेवाओं और कनेक्टेड प्रेजेंटेशन स्तर के बीच, और कार्यान्वयन को छिपाने के लिए\n> सेवाओं का विवरण (ईजेबी आर्किटेक्चर की खोज और पहुंच सहित)। व्यापार प्रतिनिधि\n> प्रेजेंटेशन स्तर से व्यावसायिक वस्तुओं को आमंत्रित करने के लिए एक एडाप्टर के रूप में कार्य करता है।\n\n**प्रोग्रामेटिक उदाहरण**\n\nसबसे पहले, हमारे पास वीडियो स्ट्रीमिंग सेवाओं और कुछ कार्यान्वयन के लिए एक सार है।\n\n```java\npublic interface VideoStreamingService {\n  void doProcessing();\n}\n\n@Slf4j\npublic class NetflixService implements VideoStreamingService {\n  @Override\n  public void doProcessing() {\n    LOGGER.info(\"NetflixService is now processing\");\n  }\n}\n\n@Slf4j\npublic class YouTubeService implements VideoStreamingService {\n  @Override\n  public void doProcessing() {\n    LOGGER.info(\"YouTubeService is now processing\");\n  }\n}\n```\n\nफिर हमारे पास एक लुकअप सेवा है जो यह तय करती है कि कौन सी वीडियो स्ट्रीमिंग सेवा का उपयोग किया जाए।\n\n```java\n@Setter\npublic class BusinessLookup {\n\n  private NetflixService netflixService;\n  private YouTubeService youTubeService;\n\n  public VideoStreamingService getBusinessService(String movie) {\n    if (movie.toLowerCase(Locale.ROOT).contains(\"die hard\")) {\n      return netflixService;\n    } else {\n      return youTubeService;\n    }\n  }\n}\n```\n\nव्यवसाय प्रतिनिधि मूवी प्लेबैक अनुरोधों को उपयुक्त स्थान पर रूट करने के लिए व्यवसाय लुकअप का उपयोग करता है\nवीडियो स्ट्रीमिंग सेवा.\n\n```java\n@Setter\npublic class BusinessDelegate {\n\n  private BusinessLookup lookupService;\n\n  public void playbackMovie(String movie) {\n    VideoStreamingService videoStreamingService = lookupService.getBusinessService(movie);\n    videoStreamingService.doProcessing();\n  }\n}\n```\n\nमोबाइल क्लाइंट व्यवसाय स्तर पर कॉल करने के लिए व्यवसाय प्रतिनिधि का उपयोग करता है।\n\n```java\npublic class MobileClient {\n\n  private final BusinessDelegate businessDelegate;\n\n  public MobileClient(BusinessDelegate businessDelegate) {\n    this.businessDelegate = businessDelegate;\n  }\n\n  public void playbackMovie(String movie) {\n    businessDelegate.playbackMovie(movie);\n  }\n}\n```\n\nअंत में, हम कार्रवाई में पूरा उदाहरण दिखा सकते हैं।\n\n```java\n  public static void main(String[] args) {\n\n    // prepare the objects\n    var businessDelegate = new BusinessDelegate();\n    var businessLookup = new BusinessLookup();\n    businessLookup.setNetflixService(new NetflixService());\n    businessLookup.setYouTubeService(new YouTubeService());\n    businessDelegate.setLookupService(businessLookup);\n\n    // create the client and use the business delegate\n    var client = new MobileClient(businessDelegate);\n    client.playbackMovie(\"Die Hard 2\");\n    client.playbackMovie(\"Maradona: The Greatest Ever\");\n  }\n```\n\nयहाँ कंसोल आउटपुट है.\n\n```\n21:15:33.790 [main] INFO com.iluwatar.business.delegate.NetflixService - NetflixService is now processing\n21:15:33.794 [main] INFO com.iluwatar.business.delegate.YouTubeService - YouTubeService is now processing\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../business-delegate/etc/business-delegate.urm.png \"Business Delegate\")\n\n## संबंधित पैटर्न\n\n* [Service locator pattern](https://java-design-patterns.com/patterns/service-locator/)\n\n## प्रयोज्यता\n\nबिजनेस डेलीगेट पैटर्न का उपयोग कब करें\n\n* आप प्रस्तुतिकरण और व्यावसायिक स्तरों के बीच ढीला युग्मन चाहते हैं\n* आप एकाधिक व्यावसायिक सेवाओं के लिए कॉल व्यवस्थित करना चाहते हैं\n* आप सेवा लुकअप और सेवा कॉल को समाहित करना चाहते हैं\n\n## ट्यूटोरियल\n\n* [Business Delegate Pattern at TutorialsPoint](https://www.tutorialspoint.com/design_pattern/business_delegate_pattern.htm)\n\n## Credits\n\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://www.amazon.com/gp/product/0130648841/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0130648841&linkId=a0100de2b28c71ede8db1757fb2b5947)\n"
  },
  {
    "path": "localization/hi/bytecode/README.md",
    "content": "---\ntitle: Bytecode\ncategory: Behavioral\nlanguage: hi\ntag:\n - Game programming\n---\n\n## हेतु\n\nवर्चुअल मशीन के लिए निर्देशों के रूप में एन्कोडिंग व्यवहार की अनुमति देता है।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> एक टीम एक नए गेम पर काम कर रही है जहां जादूगर एक-दूसरे के खिलाफ लड़ते हैं। जादूगर का व्यवहार\n> प्लेटेस्टिंग के माध्यम से सैकड़ों बार सावधानीपूर्वक समायोजित और पुनरावृत्त करने की आवश्यकता है। यह\n> हर बार जब गेम डिजाइनर बदलाव करना चाहता है तो प्रोग्रामर से बदलाव करने के लिए कहना सबसे अच्छा है\n> व्यवहार, इसलिए विज़ार्ड व्यवहार को डेटा-संचालित वर्चुअल मशीन के रूप में कार्यान्वित किया जाता है।\n\nसाफ़ शब्दों में\n\n> बाइटकोड पैटर्न कोड के बजाय डेटा द्वारा संचालित व्यवहार को सक्षम बनाता है।\n\n[Gameprogrammingpatterns.com](https://gameprogrammingpatterns.com/bytecode.html) प्रलेखन\nबताता है:\n\n> एक निर्देश सेट निम्न-स्तरीय संचालन को परिभाषित करता है जिन्हें निष्पादित किया जा सकता है। की एक श्रृंखला\n> निर्देश बाइट्स के अनुक्रम के रूप में एन्कोड किया गया है। एक वर्चुअल मशीन इन निर्देशों को एक-एक करके क्रियान्वित करती है\n> एक समय में, मध्यवर्ती मानों के लिए स्टैक का उपयोग करना। अनुदेशों के संयोजन से, जटिल उच्च-स्तरीय\n> व्यवहार को परिभाषित किया जा सकता है।\n\n**प्रोग्रामेटिक उदाहरण**\n\nसबसे महत्वपूर्ण गेम ऑब्जेक्ट में से एक `Wizard` वर्ग है।\n\n```java\n@AllArgsConstructor\n@Setter\n@Getter\n@Slf4j\npublic class Wizard {\n\n  private int health;\n  private int agility;\n  private int wisdom;\n  private int numberOfPlayedSounds;\n  private int numberOfSpawnedParticles;\n\n  public void playSound() {\n    LOGGER.info(\"Playing sound\");\n    numberOfPlayedSounds++;\n  }\n\n  public void spawnParticles() {\n    LOGGER.info(\"Spawning particles\");\n    numberOfSpawnedParticles++;\n  }\n}\n```\n\nइसके बाद, हम अपनी वर्चुअल मशीन के लिए उपलब्ध निर्देश दिखाते हैं। प्रत्येक निर्देश का अपना है\nयह स्टैक डेटा के साथ कैसे संचालित होता है, इसका अपना शब्दार्थ। उदाहरण के लिए, ADD निर्देश शीर्ष पर है\nस्टैक से दो आइटम, उन्हें एक साथ जोड़ता है और परिणाम को स्टैक पर भेजता है।\n\n```java\n@AllArgsConstructor\n@Getter\npublic enum Instruction {\n\n  LITERAL(1),         // e.g. \"LITERAL 0\", push 0 to stack\n  SET_HEALTH(2),      // e.g. \"SET_HEALTH\", pop health and wizard number, call set health\n  SET_WISDOM(3),      // e.g. \"SET_WISDOM\", pop wisdom and wizard number, call set wisdom\n  SET_AGILITY(4),     // e.g. \"SET_AGILITY\", pop agility and wizard number, call set agility\n  PLAY_SOUND(5),      // e.g. \"PLAY_SOUND\", pop value as wizard number, call play sound\n  SPAWN_PARTICLES(6), // e.g. \"SPAWN_PARTICLES\", pop value as wizard number, call spawn particles\n  GET_HEALTH(7),      // e.g. \"GET_HEALTH\", pop value as wizard number, push wizard's health\n  GET_AGILITY(8),     // e.g. \"GET_AGILITY\", pop value as wizard number, push wizard's agility\n  GET_WISDOM(9),      // e.g. \"GET_WISDOM\", pop value as wizard number, push wizard's wisdom\n  ADD(10),            // e.g. \"ADD\", pop 2 values, push their sum\n  DIVIDE(11);         // e.g. \"DIVIDE\", pop 2 values, push their division\n  // ...\n}\n```\n\nहमारे उदाहरण के केंद्र में `VirtualMachine` वर्ग है। यह निर्देशों को इनपुट के रूप में लेता है और\nगेम ऑब्जेक्ट व्यवहार प्रदान करने के लिए उन्हें निष्पादित करता है।\n\n```java\n@Getter\n@Slf4j\npublic class VirtualMachine {\n\n  private final Stack<Integer> stack = new Stack<>();\n\n  private final Wizard[] wizards = new Wizard[2];\n\n  public VirtualMachine() {\n    wizards[0] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),\n        0, 0);\n    wizards[1] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),\n        0, 0);\n  }\n\n  public VirtualMachine(Wizard wizard1, Wizard wizard2) {\n    wizards[0] = wizard1;\n    wizards[1] = wizard2;\n  }\n\n  public void execute(int[] bytecode) {\n    for (var i = 0; i < bytecode.length; i++) {\n      Instruction instruction = Instruction.getInstruction(bytecode[i]);\n      switch (instruction) {\n        case LITERAL:\n          // Read the next byte from the bytecode.\n          int value = bytecode[++i];\n          // Push the next value to stack\n          stack.push(value);\n          break;\n        case SET_AGILITY:\n          var amount = stack.pop();\n          var wizard = stack.pop();\n          setAgility(wizard, amount);\n          break;\n        case SET_WISDOM:\n          amount = stack.pop();\n          wizard = stack.pop();\n          setWisdom(wizard, amount);\n          break;\n        case SET_HEALTH:\n          amount = stack.pop();\n          wizard = stack.pop();\n          setHealth(wizard, amount);\n          break;\n        case GET_HEALTH:\n          wizard = stack.pop();\n          stack.push(getHealth(wizard));\n          break;\n        case GET_AGILITY:\n          wizard = stack.pop();\n          stack.push(getAgility(wizard));\n          break;\n        case GET_WISDOM:\n          wizard = stack.pop();\n          stack.push(getWisdom(wizard));\n          break;\n        case ADD:\n          var a = stack.pop();\n          var b = stack.pop();\n          stack.push(a + b);\n          break;\n        case DIVIDE:\n          a = stack.pop();\n          b = stack.pop();\n          stack.push(b / a);\n          break;\n        case PLAY_SOUND:\n          wizard = stack.pop();\n          getWizards()[wizard].playSound();\n          break;\n        case SPAWN_PARTICLES:\n          wizard = stack.pop();\n          getWizards()[wizard].spawnParticles();\n          break;\n        default:\n          throw new IllegalArgumentException(\"Invalid instruction value\");\n      }\n      LOGGER.info(\"Executed \" + instruction.name() + \", Stack contains \" + getStack());\n    }\n  }\n\n  public void setHealth(int wizard, int amount) {\n    wizards[wizard].setHealth(amount);\n  }\n  // other setters ->\n  // ...\n}\n```\n\nअब हम वर्चुअल मशीन का उपयोग करके पूरा उदाहरण दिखा सकते हैं।\n\n```java\n  public static void main(String[] args) {\n\n    var vm = new VirtualMachine(\n        new Wizard(45, 7, 11, 0, 0),\n        new Wizard(36, 18, 8, 0, 0));\n\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"GET_HEALTH\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"GET_AGILITY\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"GET_WISDOM\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"ADD\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 2\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"DIVIDE\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"ADD\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"SET_HEALTH\"));\n  }\n```\n\nयहाँ कंसोल आउटपुट है.\n\n```\n16:20:10.193 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0]\n16:20:10.196 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_HEALTH, Stack contains [0, 45]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_AGILITY, Stack contains [0, 45, 7]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 7, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_WISDOM, Stack contains [0, 45, 7, 11]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 45, 18]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 18, 2]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed DIVIDE, Stack contains [0, 45, 9]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 54]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed SET_HEALTH, Stack contains []\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../bytecode/etc/bytecode.urm.png \"Bytecode class diagram\")\n\n## प्रयोज्यता\n\nजब आपके पास बहुत सारे व्यवहार हों जिन्हें आपको परिभाषित करने की आवश्यकता हो तो बाइटकोड पैटर्न का उपयोग करें\nगेम की कार्यान्वयन भाषा उपयुक्त नहीं है क्योंकि:\n\n* यह बहुत निम्न स्तर का है, जिससे इसे प्रोग्राम करना कठिन या त्रुटि-प्रवण हो जाता है।\n* धीमे संकलन समय या अन्य टूलींग समस्याओं के कारण इस पर पुनरावृत्ति करने में बहुत अधिक समय लगता है।\n* इस पर बहुत ज्यादा भरोसा है. यदि आप यह सुनिश्चित करना चाहते हैं कि परिभाषित किया जा रहा व्यवहार गेम को तोड़ न सके, तो आपको इसे शेष कोडबेस से सैंडबॉक्स करना होगा।\n\n## संबंधित पैटर्न\n\n* [Interpreter](https://java-design-patterns.com/patterns/interpreter/)\n\n## श्रेय\n\n* [Game programming patterns](http://gameprogrammingpatterns.com/bytecode.html)\n"
  },
  {
    "path": "localization/hi/caching/README.md",
    "content": "---\ntitle: Caching\ncategory: Behavioral\nlanguage: hi\ntag:\n  - Performance\n  - Cloud distributed\n---\n\n## हेतु\n\nकैशिंग पैटर्न संसाधनों को तुरंत जारी न करके उनके महंगे पुन: अधिग्रहण से बचाता है\nउपयोग के बाद। संसाधन अपनी पहचान बनाए रखते हैं, कुछ तेज़-पहुँच वाले भंडारण में रखे जाते हैं, और हैं\nउन्हें दोबारा प्राप्त करने से बचने के लिए पुन: उपयोग किया जाता है।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> एक टीम एक ऐसी वेबसाइट पर काम कर रही है जो परित्यक्त बिल्लियों के लिए नए घर उपलब्ध कराती है। लोग अपनी पोस्ट कर सकते हैं\n> पंजीकरण के बाद वेबसाइट पर बिल्लियाँ, लेकिन सभी नए पोस्ट के लिए इनमें से किसी एक से अनुमोदन की आवश्यकता होती है\n> साइट मॉडरेटर. साइट मॉडरेटर के उपयोगकर्ता खातों में एक विशिष्ट ध्वज और डेटा होता है\n> MongoDB डेटाबेस में संग्रहीत है। हर बार पोस्ट देखे जाने पर मॉडरेटर फ़्लैग की जाँच करना\n> महंगा हो जाता है और यहां कैशिंग का उपयोग करना एक अच्छा विचार है।\n\nसाफ़ शब्दों में\n\n> कैशिंग पैटर्न प्रदर्शन को बेहतर बनाने के लिए अक्सर आवश्यक डेटा को फास्ट-एक्सेस स्टोरेज में रखता है।\n\nविकिपीडिया कहता है:\n\n> कंप्यूटिंग में, कैश एक हार्डवेयर या सॉफ़्टवेयर घटक है जो भविष्य में डेटा संग्रहीत करता है\n> उस डेटा के लिए अनुरोध तेजी से प्रस्तुत किए जा सकते हैं; कैश में संग्रहीत डेटा का परिणाम हो सकता है\n> पहले की गणना या अन्यत्र संग्रहीत डेटा की एक प्रति। अनुरोध किए जाने पर कैश हिट होता है\n> डेटा कैश में पाया जा सकता है, जबकि कैश मिस तब होता है जब ऐसा नहीं हो पाता। कैश हिट द्वारा परोसे जाते हैं\n> कैश से डेटा पढ़ना, जो किसी परिणाम की पुन: गणना करने या धीमी गति से पढ़ने की तुलना में तेज़ है\n> डेटा स्टोर; इस प्रकार, कैश से जितने अधिक अनुरोध दिए जा सकेंगे, सिस्टम उतना ही तेज़ होगा\n> प्रदर्शन करता है.\n\n**प्रोग्रामेटिक उदाहरण**\n\nआइए सबसे पहले हमारे एप्लिकेशन के डेटा स्तर को देखें। दिलचस्प कक्षाएं `UserAccount` हैं\nजो एक सरल जावा ऑब्जेक्ट है जिसमें उपयोगकर्ता खाता विवरण और `DbManager` इंटरफ़ेस शामिल है जो संभालता है\nडेटाबेस से/इन ऑब्जेक्ट को पढ़ना और लिखना।\n\n```java\n@Data\n@AllArgsConstructor\n@ToString\n@EqualsAndHashCode\npublic class UserAccount {\n  private String userId;\n  private String userName;\n  private String additionalInfo;\n}\n\npublic interface DbManager {\n\n  void connect();\n  void disconnect();\n  \n  UserAccount readFromDb(String userId);\n  UserAccount writeToDb(UserAccount userAccount);\n  UserAccount updateDb(UserAccount userAccount);\n  UserAccount upsertDb(UserAccount userAccount);\n}\n```\n\nउदाहरण में, हम विभिन्न कैशिंग नीतियों का प्रदर्शन कर रहे हैं\n\n* राइट-थ्रू एक ही लेनदेन में कैश और डीबी में डेटा लिखता है\n* राइट-अराउंड डेटा को कैश के बजाय तुरंत डीबी में लिखता है\n* राइट-बैक शुरू में डेटा को कैश में लिखता है जबकि डेटा केवल डीबी में लिखा जाता है\n  जब कैश भर जाए\n* कैश-साइड दोनों डेटा स्रोतों में डेटा को सिंक्रनाइज़ रखने की ज़िम्मेदारी को आगे बढ़ाता है\n  आवेदन ही\n* उपरोक्त रणनीतियों में रीड-थ्रू रणनीति भी शामिल है और यह डेटा लौटाती है\n  यदि यह मौजूद है तो कॉल करने वाले को कैश, अन्यथा डीबी से क्वेरी करता है और इसे कैश में संग्रहीत करता है\n  भविष्य के काम।\n\n`LruCache` में कैश कार्यान्वयन एक डबल के साथ एक हैश तालिका है\nलिंक्ड सूची। लिंक्ड-लिस्ट कैश में एलआरयू डेटा को कैप्चर करने और बनाए रखने में मदद करती है। कब\nडेटा को क्वेरी किया जाता है (कैश से), जोड़ा जाता है (कैश में), या अपडेट किया जाता है, डेटा को सामने ले जाया जाता है\nसूची में खुद को सबसे हाल ही में उपयोग किए गए डेटा के रूप में दर्शाया गया है। एलआरयू डेटा हमेशा अंत में होता है\nसूची।\n\n```java\n@Slf4j\npublic class LruCache {\n\n  static class Node {\n    String userId;\n    UserAccount userAccount;\n    Node previous;\n    Node next;\n\n    public Node(String userId, UserAccount userAccount) {\n      this.userId = userId;\n      this.userAccount = userAccount;\n    }\n  }\n  \n  /* ... omitted details ... */\n\n  public LruCache(int capacity) {\n    this.capacity = capacity;\n  }\n\n  public UserAccount get(String userId) {\n    if (cache.containsKey(userId)) {\n      var node = cache.get(userId);\n      remove(node);\n      setHead(node);\n      return node.userAccount;\n    }\n    return null;\n  }\n\n  public void set(String userId, UserAccount userAccount) {\n    if (cache.containsKey(userId)) {\n      var old = cache.get(userId);\n      old.userAccount = userAccount;\n      remove(old);\n      setHead(old);\n    } else {\n      var newNode = new Node(userId, userAccount);\n      if (cache.size() >= capacity) {\n        LOGGER.info(\"# Cache is FULL! Removing {} from cache...\", end.userId);\n        cache.remove(end.userId); // remove LRU data from cache.\n        remove(end);\n        setHead(newNode);\n      } else {\n        setHead(newNode);\n      }\n      cache.put(userId, newNode);\n    }\n  }\n\n  public boolean contains(String userId) {\n    return cache.containsKey(userId);\n  }\n  \n  public void remove(Node node) { /* ... */ }\n  public void setHead(Node node) { /* ... */ }\n  public void invalidate(String userId) { /* ... */ }\n  public boolean isFull() { /* ... */ }\n  public UserAccount getLruData() { /* ... */ }\n  public void clear() { /* ... */ }\n  public List<UserAccount> getCacheDataInListForm() { /* ... */ }\n  public void setCapacity(int newCapacity) { /* ... */ }\n}\n```\n\nअगली परत जिसे हम देखने जा रहे हैं वह `CacheStore` है जो विभिन्न कैशिंग को लागू करती है\nरणनीतियाँ।\n\n```java\n@Slf4j\npublic class CacheStore {\n\n  private static final int CAPACITY = 3;\n  private static LruCache cache;\n  private final DbManager dbManager;\n\n  /* ... details omitted ... */\n\n  public UserAccount readThrough(final String userId) {\n    if (cache.contains(userId)) {\n      LOGGER.info(\"# Found in Cache!\");\n      return cache.get(userId);\n    }\n    LOGGER.info(\"# Not found in cache! Go to DB!!\");\n    UserAccount userAccount = dbManager.readFromDb(userId);\n    cache.set(userId, userAccount);\n    return userAccount;\n  }\n\n  public void writeThrough(final UserAccount userAccount) {\n    if (cache.contains(userAccount.getUserId())) {\n      dbManager.updateDb(userAccount);\n    } else {\n      dbManager.writeToDb(userAccount);\n    }\n    cache.set(userAccount.getUserId(), userAccount);\n  }\n\n  public void writeAround(final UserAccount userAccount) {\n    if (cache.contains(userAccount.getUserId())) {\n      dbManager.updateDb(userAccount);\n      // Cache data has been updated -- remove older\n      cache.invalidate(userAccount.getUserId());\n      // version from cache.\n    } else {\n      dbManager.writeToDb(userAccount);\n    }\n  }\n\n  public static void clearCache() {\n    if (cache != null) {\n      cache.clear();\n    }\n  }\n\n  public static void flushCache() {\n    LOGGER.info(\"# flushCache...\");\n    Optional.ofNullable(cache)\n        .map(LruCache::getCacheDataInListForm)\n        .orElse(List.of())\n        .forEach(DbManager::updateDb);\n  }\n\n  /* ... omitted the implementation of other caching strategies ... */\n\n}\n```\n\n`AppManager` मुख्य वर्ग और एप्लिकेशन के बीच संचार में अंतर को पाटने में मदद करता है\nपिछला भाग। इस वर्ग के माध्यम से DB कनेक्शन प्रारंभ किया जाता है। चुनी गई कैशिंग रणनीति/नीति है\nयहाँ भी आरंभ किया गया। कैश का उपयोग करने से पहले, कैश का आकार सेट करना होगा। निर्भर करता है\nचुनी गई कैशिंग नीति पर, `AppManager` `CacheStore` में उपयुक्त फ़ंक्शन को कॉल करेगा\nकक्षा।\n\n```java\n@Slf4j\npublic final class AppManager {\n\n  private static CachingPolicy cachingPolicy;\n  private final DbManager dbManager;\n  private final CacheStore cacheStore;\n\n  private AppManager() {\n  }\n\n  public void initDb() { /* ... */ }\n\n  public static void initCachingPolicy(CachingPolicy policy) { /* ... */ }\n\n  public static void initCacheCapacity(int capacity) { /* ... */ }\n\n  public UserAccount find(final String userId) {\n    LOGGER.info(\"Trying to find {} in cache\", userId);\n    if (cachingPolicy == CachingPolicy.THROUGH\n            || cachingPolicy == CachingPolicy.AROUND) {\n      return cacheStore.readThrough(userId);\n    } else if (cachingPolicy == CachingPolicy.BEHIND) {\n      return cacheStore.readThroughWithWriteBackPolicy(userId);\n    } else if (cachingPolicy == CachingPolicy.ASIDE) {\n      return findAside(userId);\n    }\n    return null;\n  }\n\n  public void save(final UserAccount userAccount) {\n    LOGGER.info(\"Save record!\");\n    if (cachingPolicy == CachingPolicy.THROUGH) {\n      cacheStore.writeThrough(userAccount);\n    } else if (cachingPolicy == CachingPolicy.AROUND) {\n      cacheStore.writeAround(userAccount);\n    } else if (cachingPolicy == CachingPolicy.BEHIND) {\n      cacheStore.writeBehind(userAccount);\n    } else if (cachingPolicy == CachingPolicy.ASIDE) {\n      saveAside(userAccount);\n    }\n  }\n\n  public static String printCacheContent() {\n    return CacheStore.print();\n  }\n\n  /* ... details omitted ... */\n}\n```\n\nएप्लिकेशन के मुख्य वर्ग में हम यही करते हैं।\n\n```java\n@Slf4j\npublic class App {\n\n  public static void main(final String[] args) {\n    boolean isDbMongo = isDbMongo(args);\n    if(isDbMongo){\n      LOGGER.info(\"Using the Mongo database engine to run the application.\");\n    } else {\n      LOGGER.info(\"Using the 'in Memory' database to run the application.\");\n    }\n    App app = new App(isDbMongo);\n    app.useReadAndWriteThroughStrategy();\n    String splitLine = \"==============================================\";\n    LOGGER.info(splitLine);\n    app.useReadThroughAndWriteAroundStrategy();\n    LOGGER.info(splitLine);\n    app.useReadThroughAndWriteBehindStrategy();\n    LOGGER.info(splitLine);\n    app.useCacheAsideStategy();\n    LOGGER.info(splitLine);\n  }\n\n  public void useReadAndWriteThroughStrategy() {\n    LOGGER.info(\"# CachingPolicy.THROUGH\");\n    appManager.initCachingPolicy(CachingPolicy.THROUGH);\n\n    var userAccount1 = new UserAccount(\"001\", \"John\", \"He is a boy.\");\n\n    appManager.save(userAccount1);\n    LOGGER.info(appManager.printCacheContent());\n    appManager.find(\"001\");\n    appManager.find(\"001\");\n  }\n\n  public void useReadThroughAndWriteAroundStrategy() { /* ... */ }\n\n  public void useReadThroughAndWriteBehindStrategy() { /* ... */ }\n\n  public void useCacheAsideStategy() { /* ... */ }\n}\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../caching/etc/caching.png \"Caching\")\n\n## प्रयोज्यता\n\nजब कैशिंग पैटर्न का उपयोग करें\n\n* एक ही संसाधन का बार-बार अधिग्रहण, आरंभीकरण और जारी करना अनावश्यक कारण बनता है\n  प्रदर्शन उपरि.\n\n## संबंधित पैटर्न\n\n* [Proxy](https://java-design-patterns.com/patterns/proxy/)\n\n## श्रेय\n\n* [Write-through, write-around, write-back: Cache explained](http://www.computerweekly.com/feature/Write-through-write-around-write-back-Cache-explained)\n* [Read-Through, Write-Through, Write-Behind, and Refresh-Ahead Caching](https://docs.oracle.com/cd/E15357_01/coh.360/e15723/cache_rtwtwbra.htm#COHDG5177)\n* [Cache-Aside pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/cache-aside)\n* [Java EE 8 High Performance: Master techniques such as memory optimization, caching, concurrency, and multithreading to achieve maximum performance from your enterprise applications](https://www.amazon.com/gp/product/178847306X/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=178847306X&linkId=e948720055599f248cdac47da9125ff4)\n* [Java Performance: In-Depth Advice for Tuning and Programming Java 8, 11, and Beyond](https://www.amazon.com/gp/product/1492056111/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1492056111&linkId=7e553581559b9ec04221259e52004b08)\n* [Effective Java](https://www.amazon.com/gp/product/B078H61SCH/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=B078H61SCH&linkId=f06607a0b48c76541ef19c5b8b9e7882)\n* [Java Performance: The Definitive Guide: Getting the Most Out of Your Code](https://www.amazon.com/gp/product/1449358454/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1449358454&linkId=475c18363e350630cc0b39ab681b2687)\n"
  },
  {
    "path": "localization/hi/callback/README.md",
    "content": "---\ntitle: Callback\ncategory: Idiom\nlanguage: hi\ntag:\n - Reactive\n---\n\n## हेतु\n\nकॉलबैक निष्पादन योग्य कोड का एक टुकड़ा है जिसे अन्य कोड के तर्क के रूप में पारित किया जाता है\nकिसी सुविधाजनक समय पर तर्क को वापस बुलाने (निष्पादित) करने की अपेक्षा की जाती है।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n>कार्य निष्पादन समाप्त होने के बाद हमें सूचित किया जाना आवश्यक है। हम इसके लिए कॉलबैक विधि पास करते हैं\n> निष्पादक और उसके हमें वापस बुलाने की प्रतीक्षा करें।\n\nसाफ़ शब्दों में\n\n> कॉलबैक निष्पादक को दी गई एक विधि है जिसे निर्धारित समय पर कॉल किया जाएगा।\n\nविकिपीडिया कहता है\n\n> कंप्यूटर प्रोग्रामिंग में, कॉलबैक, जिसे \"कॉल-आफ्टर\" फ़ंक्शन के रूप में भी जाना जाता है, कोई भी निष्पादन योग्य है\n> वह कोड जो अन्य कोड के तर्क के रूप में पारित किया जाता है; उस अन्य कोड को कॉल करने की उम्मीद है\n> किसी निश्चित समय पर तर्क को वापस (निष्पादित) करें।\n\n**प्रोग्रामेटिक उदाहरण**\n\nकॉलबैक एकल विधि वाला एक सरल इंटरफ़ेस है।\n\n```java\npublic interface Callback {\n\n  void call();\n}\n```\n\nआगे हम एक कार्य को परिभाषित करते हैं जो कार्य निष्पादन समाप्त होने के बाद कॉलबैक निष्पादित करेगा।\n\n```java\npublic abstract class Task {\n\n  final void executeWith(Callback callback) {\n    execute();\n    Optional.ofNullable(callback).ifPresent(Callback::call);\n  }\n\n  public abstract void execute();\n}\n\n@Slf4j\npublic final class SimpleTask extends Task {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"Perform some important activity and after call the callback method.\");\n  }\n}\n```\n\nअंत में, यहां बताया गया है कि हम किसी कार्य को कैसे निष्पादित करते हैं और उसके समाप्त होने पर कॉलबैक प्राप्त करते हैं।\n\n```java\n    var task = new SimpleTask();\n    task.executeWith(() -> LOGGER.info(\"I'm done now.\"));\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../callback/etc/callback.png \"Callback\")\n\n## प्रयोज्यता\n\nजब कॉलबैक पैटर्न का उपयोग करें\n\n* जब कुछ परिभाषित गतिविधि के निष्पादन के बाद कुछ मनमाना सिंक्रोनस या एसिंक्रोनस क्रिया निष्पादित की जानी चाहिए।\n\n## वास्तविक दुनिया के उदाहरण\n\n* [CyclicBarrier](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29) कंस्ट्रक्टर एक कॉलबैक स्वीकार कर सकता है जो हर बार बैरियर ट्रिप होने पर ट्रिगर हो जाएगा।\n"
  },
  {
    "path": "localization/hi/chain-of-responsibility/README.md",
    "content": "---\ntitle: Chain of responsibility\ncategory: Behavioral\nlanguage: hi\ntag:\n - Gang of Four\n---\n\n## हेतु\n\nएक से अधिक ऑब्जेक्ट को मौका देकर अनुरोध भेजने वाले को उसके प्राप्तकर्ता से जोड़ने से बचें\nअनुरोध संभालें. प्राप्त वस्तुओं को श्रृंखलाबद्ध करें और किसी वस्तु तक श्रृंखला के साथ अनुरोध को पास करें\nइसे संभालता है.\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> ऑर्क किंग अपनी सेना को ऊंचे स्वर में आदेश देता है। फिर, प्रतिक्रिया देने वाला सबसे करीबी व्यक्ति कमांडर होता है\n> एक अधिकारी, और फिर एक सैनिक। कमांडर, अधिकारी और सैनिक जिम्मेदारी की एक श्रृंखला बनाते हैं।\n\nसाफ़ शब्दों में\n\n> यह वस्तुओं की श्रृंखला बनाने में मदद करता है। एक अनुरोध एक छोर से प्रवेश करता है और एक वस्तु से जाता रहता है\n> दूसरे को तब तक भेजें जब तक उसे कोई उपयुक्त हैंडलर न मिल जाए।\n\nविकिपीडिया कहता है\n\n> ऑब्जेक्ट-ओरिएंटेड डिज़ाइन में, श्रृंखला-की-जिम्मेदारी पैटर्न एक डिज़ाइन पैटर्न है जिसमें शामिल है\n> कमांड ऑब्जेक्ट का एक स्रोत और प्रोसेसिंग ऑब्जेक्ट की एक श्रृंखला। प्रत्येक प्रोसेसिंग ऑब्जेक्ट में शामिल है\n> तर्क जो कमांड ऑब्जेक्ट के प्रकार को परिभाषित करता है जिसे वह संभाल सकता है; बाकी को पास कर दिया गया है\n> श्रृंखला में अगली प्रसंस्करण वस्तु।\n\n**प्रोग्रामेटिक उदाहरण**\n\nऊपर से ओर्क्स के साथ हमारे उदाहरण का अनुवाद करना। सबसे पहले, हमारे पास `Request` वर्ग है:\n\n```java\npublic class Request {\n\n  private final RequestType requestType;\n  private final String requestDescription;\n  private boolean handled;\n\n  public Request(final RequestType requestType, final String requestDescription) {\n    this.requestType = Objects.requireNonNull(requestType);\n    this.requestDescription = Objects.requireNonNull(requestDescription);\n  }\n\n  public String getRequestDescription() { return requestDescription; }\n\n  public RequestType getRequestType() { return requestType; }\n\n  public void markHandled() { this.handled = true; }\n\n  public boolean isHandled() { return this.handled; }\n\n  @Override\n  public String toString() { return getRequestDescription(); }\n}\n\npublic enum RequestType {\n  DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX\n}\n```\n\nइसके बाद, हम अनुरोध हैंडलर पदानुक्रम दिखाते हैं।\n\n```java\npublic interface RequestHandler {\n\n    boolean canHandleRequest(Request req);\n\n    int getPriority();\n\n    void handle(Request req);\n\n    String name();\n}\n\n@Slf4j\npublic class OrcCommander implements RequestHandler {\n    @Override\n    public boolean canHandleRequest(Request req) {\n        return req.getRequestType() == RequestType.DEFEND_CASTLE;\n    }\n\n    @Override\n    public int getPriority() {\n        return 2;\n    }\n\n    @Override\n    public void handle(Request req) {\n        req.markHandled();\n        LOGGER.info(\"{} handling request \\\"{}\\\"\", name(), req);\n    }\n\n    @Override\n    public String name() {\n        return \"Orc commander\";\n    }\n}\n\n// OrcOfficer and OrcSoldier are defined similarly as OrcCommander\n\n```\n\nऑर्क किंग आदेश देता है और श्रृंखला बनाता है।\n\n```java\npublic class OrcKing {\n\n  private List<RequestHandler> handlers;\n\n  public OrcKing() {\n    buildChain();\n  }\n\n  private void buildChain() {\n    handlers = Arrays.asList(new OrcCommander(), new OrcOfficer(), new OrcSoldier());\n  }\n\n  public void makeRequest(Request req) {\n    handlers\n        .stream()\n        .sorted(Comparator.comparing(RequestHandler::getPriority))\n        .filter(handler -> handler.canHandleRequest(req))\n        .findFirst()\n        .ifPresent(handler -> handler.handle(req));\n  }\n}\n```\n\nकार्रवाई में जिम्मेदारी की श्रृंखला.\n\n```java\nvar king = new OrcKing();\nking.makeRequest(new Request(RequestType.DEFEND_CASTLE, \"defend castle\"));\nking.makeRequest(new Request(RequestType.TORTURE_PRISONER, \"torture prisoner\"));\nking.makeRequest(new Request(RequestType.COLLECT_TAX, \"collect tax\"));\n```\n\nकंसोल आउटपुट.\n\n```\nOrc commander handling request \"defend castle\"\nOrc officer handling request \"torture prisoner\"\nOrc soldier handling request \"collect tax\"\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../chain-of-responsibility/etc/chain-of-responsibility.urm.png \"Chain of Responsibility class diagram\")\n\n## प्रयोज्यता\n\nजिम्मेदारी की श्रृंखला का प्रयोग कब करें\n\n* एक से अधिक ऑब्जेक्ट एक अनुरोध को संभाल सकते हैं, और हैंडलर को पहले से ज्ञात नहीं है। हैंडलर का स्वचालित रूप से पता लगाया जाना चाहिए।\n* आप रिसीवर को स्पष्ट रूप से निर्दिष्ट किए बिना कई ऑब्जेक्ट में से एक के लिए अनुरोध जारी करना चाहते हैं।\n* ऑब्जेक्ट का सेट जो अनुरोध को संभाल सकता है उसे गतिशील रूप से निर्दिष्ट किया जाना चाहिए।\n\n## ज्ञात उपयोग\n\n* [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29)\n* [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html)\n* [javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-)\n\n## श्रेय\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/hi/circuit-breaker/README.md",
    "content": "---\ntitle: Circuit Breaker\ncategory: Behavioral\nlanguage: hi\ntag:\n  - Performance\n  - Decoupling\n  - Cloud distributed\n---\n\n## हेतु\n\nमहँगी दूरस्थ सेवा कॉलों को इस प्रकार संभालें कि किसी एक सेवा/घटक की विफलता हो\nसंपूर्ण एप्लिकेशन को नीचे नहीं लाया जा सकता है, और हम यथाशीघ्र सेवा से पुनः कनेक्ट कर सकते हैं।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> एक ऐसे वेब एप्लिकेशन की कल्पना करें जिसमें स्थानीय फ़ाइलें/छवियां और दूरस्थ सेवाएं दोनों हैं जिनका उपयोग किया जाता है\n> डेटा लाया जा रहा है। ये दूरस्थ सेवाएँ कभी-कभी स्वस्थ और उत्तरदायी हो सकती हैं, या बन सकती हैं\n> विभिन्न कारणों से किसी समय धीमी और अनुत्तरदायी। तो अगर रिमोट में से एक\n> सेवाएँ धीमी हैं या सफलतापूर्वक प्रतिक्रिया नहीं दे रही हैं, हमारा एप्लिकेशन प्रतिक्रिया प्राप्त करने का प्रयास करेगा\n> कई थ्रेड्स/प्रक्रियाओं का उपयोग करने वाली दूरस्थ सेवा, जल्द ही वे सभी हैंग हो जाएंगी (जिन्हें भी कहा जाता है)।\n> [Thread starvation](https://en.wikipedia.org/wiki/Starvation_(computer_science)) जिसके कारण हमारा संपूर्ण वेब एप्लिकेशन क्रैश हो गया है। हमें पता लगाने में सक्षम होना चाहिए\n> यह स्थिति और उपयोगकर्ता को एक उपयुक्त संदेश दिखाएं ताकि वह इसके अन्य हिस्सों का पता लगा सके\n> ऐप दूरस्थ सेवा विफलता से अप्रभावित है। इस बीच, अन्य सेवाएँ जो काम कर रही हैं\n> सामान्यतः, इस विफलता से अप्रभावित रहकर कार्य करते रहना चाहिए।\n\nसाफ़ शब्दों में\n\n> सर्किट ब्रेकर विफल दूरस्थ सेवाओं को शानदार ढंग से संभालने की अनुमति देता है। यह विशेष रूप से तब उपयोगी होता है जब\n> हमारे एप्लिकेशन के सभी हिस्से एक-दूसरे से अत्यधिक अलग हैं, और एक घटक विफल हो गया है\n> इसका मतलब यह नहीं है कि अन्य हिस्से काम करना बंद कर देंगे।\n\nविकिपीडिया कहता है\n\n> सर्किट ब्रेकर आधुनिक सॉफ्टवेयर विकास में उपयोग किया जाने वाला एक डिज़ाइन पैटर्न है। इसका उपयोग पता लगाने के लिए किया जाता है\n> विफलताएं और विफलता को लगातार दोहराए जाने से रोकने के तर्क को समाहित करती है\n> रखरखाव, अस्थायी बाहरी सिस्टम विफलता या अप्रत्याशित सिस्टम कठिनाइयाँ।\n\n## प्रोग्रामेटिक उदाहरण\n\nतो, यह सब एक साथ कैसे आता है? उपरोक्त उदाहरण को ध्यान में रखते हुए हम इसका अनुकरण करेंगे\nएक सरल उदाहरण में कार्यक्षमता. एक निगरानी सेवा वेब ऐप की नकल करती है और स्थानीय और दोनों बनाती है\nदूरस्थ कॉल.\n\nसेवा वास्तुकला इस प्रकार है:\n\n![alt text](../../../circuit-breaker/etc/ServiceDiagram.png \"Service Diagram\")\n\nकोड के संदर्भ में, अंतिम उपयोगकर्ता एप्लिकेशन है:\n\n```java\n@Slf4j\npublic class App {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var serverStartTime = System.nanoTime();\n\n    var delayedService = new DelayedRemoteService(serverStartTime, 5);\n    var delayedServiceCircuitBreaker = new DefaultCircuitBreaker(delayedService, 3000, 2,\n        2000 * 1000 * 1000);\n\n    var quickService = new QuickRemoteService();\n    var quickServiceCircuitBreaker = new DefaultCircuitBreaker(quickService, 3000, 2,\n        2000 * 1000 * 1000);\n\n    //Create an object of monitoring service which makes both local and remote calls\n    var monitoringService = new MonitoringService(delayedServiceCircuitBreaker,\n        quickServiceCircuitBreaker);\n\n    //Fetch response from local resource\n    LOGGER.info(monitoringService.localResourceResponse());\n\n    //Fetch response from delayed service 2 times, to meet the failure threshold\n    LOGGER.info(monitoringService.delayedServiceResponse());\n    LOGGER.info(monitoringService.delayedServiceResponse());\n\n    //Fetch current state of delayed service circuit breaker after crossing failure threshold limit\n    //which is OPEN now\n    LOGGER.info(delayedServiceCircuitBreaker.getState());\n\n    //Meanwhile, the delayed service is down, fetch response from the healthy quick service\n    LOGGER.info(monitoringService.quickServiceResponse());\n    LOGGER.info(quickServiceCircuitBreaker.getState());\n\n    //Wait for the delayed service to become responsive\n    try {\n      LOGGER.info(\"Waiting for delayed service to become responsive\");\n      Thread.sleep(5000);\n    } catch (InterruptedException e) {\n      e.printStackTrace();\n    }\n    //Check the state of delayed circuit breaker, should be HALF_OPEN\n    LOGGER.info(delayedServiceCircuitBreaker.getState());\n\n    //Fetch response from delayed service, which should be healthy by now\n    LOGGER.info(monitoringService.delayedServiceResponse());\n    //As successful response is fetched, it should be CLOSED again.\n    LOGGER.info(delayedServiceCircuitBreaker.getState());\n  }\n}\n```\n\nनिगरानी सेवा:\n\n```java\npublic class MonitoringService {\n\n  private final CircuitBreaker delayedService;\n\n  private final CircuitBreaker quickService;\n\n  public MonitoringService(CircuitBreaker delayedService, CircuitBreaker quickService) {\n    this.delayedService = delayedService;\n    this.quickService = quickService;\n  }\n\n  //Assumption: Local service won't fail, no need to wrap it in a circuit breaker logic\n  public String localResourceResponse() {\n    return \"Local Service is working\";\n  }\n\n  /**\n   * Fetch response from the delayed service (with some simulated startup time).\n   *\n   * @return response string\n   */\n  public String delayedServiceResponse() {\n    try {\n      return this.delayedService.attemptRequest();\n    } catch (RemoteServiceException e) {\n      return e.getMessage();\n    }\n  }\n\n  /**\n   * Fetches response from a healthy service without any failure.\n   *\n   * @return response string\n   */\n  public String quickServiceResponse() {\n    try {\n      return this.quickService.attemptRequest();\n    } catch (RemoteServiceException e) {\n      return e.getMessage();\n    }\n  }\n}\n```\nजैसा कि देखा जा सकता है, यह स्थानीय संसाधनों को सीधे प्राप्त करने के लिए कॉल करता है, लेकिन यह कॉल को लपेट देता है\nसर्किट ब्रेकर ऑब्जेक्ट में रिमोट (महंगी) सेवा, जो निम्नानुसार दोषों को रोकती है:\n\n```java\npublic class DefaultCircuitBreaker implements CircuitBreaker {\n\n    private final long timeout;\n    private final long retryTimePeriod;\n    private final RemoteService service;\n    long lastFailureTime;\n    private String lastFailureResponse;\n    int failureCount;\n    private final int failureThreshold;\n    private State state;\n    private final long futureTime = 1000 * 1000 * 1000 * 1000;\n\n    /**\n     * Constructor to create an instance of Circuit Breaker.\n     *\n     * @param timeout          Timeout for the API request. Not necessary for this simple example\n     * @param failureThreshold Number of failures we receive from the depended service before changing\n     *                         state to 'OPEN'\n     * @param retryTimePeriod  Time period after which a new request is made to remote service for\n     *                         status check.\n     */\n    DefaultCircuitBreaker(RemoteService serviceToCall, long timeout, int failureThreshold,\n                          long retryTimePeriod) {\n        this.service = serviceToCall;\n        // We start in a closed state hoping that everything is fine\n        this.state = State.CLOSED;\n        this.failureThreshold = failureThreshold;\n        // Timeout for the API request.\n        // Used to break the calls made to remote resource if it exceeds the limit\n        this.timeout = timeout;\n        this.retryTimePeriod = retryTimePeriod;\n        //An absurd amount of time in future which basically indicates the last failure never happened\n        this.lastFailureTime = System.nanoTime() + futureTime;\n        this.failureCount = 0;\n    }\n\n    // Reset everything to defaults\n    @Override\n    public void recordSuccess() {\n        this.failureCount = 0;\n        this.lastFailureTime = System.nanoTime() + futureTime;\n        this.state = State.CLOSED;\n    }\n\n    @Override\n    public void recordFailure(String response) {\n        failureCount = failureCount + 1;\n        this.lastFailureTime = System.nanoTime();\n        // Cache the failure response for returning on open state\n        this.lastFailureResponse = response;\n    }\n\n    // Evaluate the current state based on failureThreshold, failureCount and lastFailureTime.\n    protected void evaluateState() {\n        if (failureCount >= failureThreshold) { //Then something is wrong with remote service\n            if ((System.nanoTime() - lastFailureTime) > retryTimePeriod) {\n                //We have waited long enough and should try checking if service is up\n                state = State.HALF_OPEN;\n            } else {\n                //Service would still probably be down\n                state = State.OPEN;\n            }\n        } else {\n            //Everything is working fine\n            state = State.CLOSED;\n        }\n    }\n\n    @Override\n    public String getState() {\n        evaluateState();\n        return state.name();\n    }\n\n    /**\n     * Break the circuit beforehand if it is known service is down Or connect the circuit manually if\n     * service comes online before expected.\n     *\n     * @param state State at which circuit is in\n     */\n    @Override\n    public void setState(State state) {\n        this.state = state;\n        switch (state) {\n            case OPEN -> {\n                this.failureCount = failureThreshold;\n                this.lastFailureTime = System.nanoTime();\n            }\n            case HALF_OPEN -> {\n                this.failureCount = failureThreshold;\n                this.lastFailureTime = System.nanoTime() - retryTimePeriod;\n            }\n            default -> this.failureCount = 0;\n        }\n    }\n\n    /**\n     * Executes service call.\n     *\n     * @return Value from the remote resource, stale response or a custom exception\n     */\n    @Override\n    public String attemptRequest() throws RemoteServiceException {\n        evaluateState();\n        if (state == State.OPEN) {\n            // return cached response if the circuit is in OPEN state\n            return this.lastFailureResponse;\n        } else {\n            // Make the API request if the circuit is not OPEN\n            try {\n                //In a real application, this would be run in a thread and the timeout\n                //parameter of the circuit breaker would be utilized to know if service\n                //is working. Here, we simulate that based on server response itself\n                var response = service.call();\n                // Yay!! the API responded fine. Let's reset everything.\n                recordSuccess();\n                return response;\n            } catch (RemoteServiceException ex) {\n                recordFailure(ex.getMessage());\n                throw ex;\n            }\n        }\n    }\n}\n```\n\nउपरोक्त पैटर्न विफलताओं को कैसे रोकता है? आइए इस परिमित राज्य मशीन के माध्यम से समझें\nइसके द्वारा कार्यान्वित किया गया।\n\n![alt text](../../../circuit-breaker/etc/StateDiagram.png \"State Diagram\")\n\n- हम सर्किट ब्रेकर ऑब्जेक्ट को कुछ मापदंडों के साथ आरंभ करते हैं: `timeout`, `failureThreshold` और `retryTimePeriod` जो यह निर्धारित करने में मदद करते हैं कि एपीआई कितना लचीला है।\n- प्रारंभ में, हम `closed` स्थिति में हैं और एपीआई पर कोई दूरस्थ कॉल नहीं हुई है।\n- हर बार जब कॉल सफल हो जाती है, तो हम स्थिति को उसी स्थिति में रीसेट कर देते हैं जैसी वह शुरुआत में थी।\n- यदि विफलताओं की संख्या एक निश्चित सीमा को पार कर जाती है, तो हम `open` स्थिति में चले जाते हैं, जो एक ओपन सर्किट की तरह कार्य करता है और दूरस्थ सेवा कॉल को करने से रोकता है, इस प्रकार संसाधनों की बचत होती है। (यहां, हम ```stale response from API``` नामक प्रतिक्रिया लौटाते हैं)\n- एक बार जब हम पुन: प्रयास की समय-सीमा पार कर लेते हैं, तो हम `half-open` स्थिति में चले जाते हैं और यह जांचने के लिए दूरस्थ सेवा पर दोबारा कॉल करते हैं कि सेवा काम कर रही है या नहीं ताकि हम ताजा सामग्री पेश कर सकें। एक विफलता इसे वापस `open` स्थिति में सेट कर देती है और दूसरा प्रयास पुनः प्रयास की समयावधि के बाद किया जाता है, जबकि एक सफलता इसे `closed` स्थिति में सेट कर देती है ताकि सब कुछ फिर से सामान्य रूप से काम करना शुरू कर दे।\n\n## क्लास डायग्राम\n\n![alt text](../../../circuit-breaker/etc/circuit-breaker.urm.png \"Circuit Breaker class diagram\")\n\n## प्रयोज्यता\n\nजब सर्किट ब्रेकर पैटर्न का उपयोग करें\n\n- एक दोष-सहिष्णु एप्लिकेशन का निर्माण जहां कुछ सेवाओं की विफलता से संपूर्ण एप्लिकेशन बंद नहीं होना चाहिए।\n- लगातार चलने वाले (हमेशा चालू रहने वाले) एप्लिकेशन का निर्माण करना, ताकि इसके घटकों को पूरी तरह से बंद किए बिना अपग्रेड किया जा सके।\n\n## संबंधित पैटर्न\n\n- [Retry Pattern](https://github.com/iluwatar/java-design-patterns/tree/master/retry)\n\n## वास्तविक दुनिया के उदाहरण\n\n* [Spring Circuit Breaker module](https://spring.io/guides/gs/circuit-breaker)\n* [Netflix Hystrix API](https://github.com/Netflix/Hystrix)\n\n## श्रेय\n\n* [Understanding Circuit Breaker Pattern](https://itnext.io/understand-circuitbreaker-design-pattern-with-simple-practical-example-92a752615b42)\n* [Martin Fowler on Circuit Breaker](https://martinfowler.com/bliki/CircuitBreaker.html)\n* [Fault tolerance in a high volume, distributed system](https://medium.com/netflix-techblog/fault-tolerance-in-a-high-volume-distributed-system-91ab4faae74a)\n* [Circuit Breaker pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker)\n"
  },
  {
    "path": "localization/hi/client-session/README.md",
    "content": "---\ntitle: Client Session Pattern\ncategory: Architectural\nlanguage: hi\ntags:\n- Decoupling\n---\n\n## नाम\n\n[Client Session pattern](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-client)\n\n## हेतु\n\n- स्टेटलेस सर्वर बनाएं जो क्लस्टरिंग की समस्या को दूर करता है, क्योंकि उपयोगकर्ता सर्वर के बीच निर्बाध रूप से स्विच कर सकते हैं।\n- सर्वर फेल-ओवर की स्थिति में डेटा को अधिक लचीला बनाता है।\n- छोटे डेटा आकार के साथ अच्छा काम करता है।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> आप एक डेटा प्रबंधन ऐप बनाना चाह रहे हैं जो उपयोगकर्ताओं को सर्वर पर अनुरोध भेजने की अनुमति दे\n> अपने उपकरणों पर संग्रहीत डेटा को संशोधित और परिवर्तित करें। ये अनुरोध आकार में छोटे हैं और\n> बड़े पैमाने पर डेटाबेस कार्यान्वयन की आवश्यकता को नकारते हुए, डेटा प्रत्येक उपयोगकर्ता के लिए अलग-अलग होता है।\n> क्लाइंट सत्र पैटर्न का उपयोग करके, आप एकाधिक समवर्ती अनुरोधों, लोड को संभालने में सक्षम हैं\n> सर्वर के स्टेटलेस रहने के कारण विभिन्न सर्वरों पर क्लाइंट को आसानी से संतुलित करना। आप भी ना\n> क्लाइंट द्वारा सभी सुविधाएं प्रदान करने के कारण सर्वर साइड पर सत्र आईडी संग्रहीत करने की आवश्यकता को हटा दें\n> वह जानकारी जो सर्वर को अपनी प्रक्रिया निष्पादित करने के लिए आवश्यक होती है।\n\nसाफ़ शब्दों में\n\n> मौजूदा क्लाइंट और उस पर एक्सेस की जा रही जानकारी के बारे में जानकारी संग्रहीत करने के बजाय\n> सर्वर, इसे केवल क्लाइंट साइड में ही बनाए रखा जाता है। क्लाइंट को प्रत्येक अनुरोध के साथ सत्र डेटा भेजना होगा\n> सर्वर को क्लाइंट को एक अद्यतन स्थिति वापस भेजनी होती है, जो क्लाइंट पर संग्रहीत होती है\n> मशीन. सर्वर को क्लाइंट जानकारी संग्रहीत करने की आवश्यकता नहीं है।\n> ([ref](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-client))\n\n**प्रोग्रामेटिक उदाहरण**\n\nक्लाइंट-सत्र पैटर्न का वर्णन करने के लिए नमूना कोड यहां दिया गया है। नीचे दिए गए कोड में हम पहले हैं\nसर्वर का एक उदाहरण बनाना। इस सर्वर इंस्टेंस का उपयोग सत्र ऑब्जेक्ट प्राप्त करने के लिए किया जाएगा\nदो ग्राहकों के लिए. जैसा कि आप नीचे दिए गए कोड से देख सकते हैं, सेशन ऑब्जेक्ट का उपयोग किसी भी चीज़ को स्टोर करने के लिए किया जा सकता है\nप्रासंगिक जानकारी जो क्लाइंट अनुरोध को संसाधित करने के लिए सर्वर द्वारा आवश्यक है। ये सत्र\nफिर प्रत्येक अनुरोध के साथ ऑब्जेक्ट को सर्वर पर भेज दिया जाएगा। अनुरोध में सत्र होगा\nऑब्जेक्ट जो प्रसंस्करण के लिए आवश्यक डेटा के साथ प्रासंगिक ग्राहक विवरण संग्रहीत करता है\nअनुरोध। प्रत्येक अनुरोध में सत्र की जानकारी सर्वर को क्लाइंट और प्रक्रिया की पहचान करने में मदद करती है\nतदनुसार अनुरोध.\n\n```java\npublic class App {\n\n  public static void main(String[] args) {\n    var server = new Server(\"localhost\", 8080);\n    var session1 = server.getSession(\"Session1\");\n    var session2 = server.getSession(\"Session2\");\n    var request1 = new Request(\"Data1\", session1);\n    var request2 = new Request(\"Data2\", session2);\n    server.process(request1);\n    server.process(request2);\n  }\n}\n\n@Data\n@AllArgsConstructor\npublic class Session {\n\n  /**\n   * Session id.\n   */\n  private String id;\n\n  /**\n   * Client name.\n   */\n  private String clientName;\n\n}\n\n@Data\n@AllArgsConstructor\npublic class Request {\n\n  private String data;\n\n  private Session session;\n\n}\n```\n\n## वास्तुकला आरेख\n\n![alt text](../../../client-session/etc/session_state_pattern.png \"Session State Pattern\")\n\n## प्रयोज्यता\n\nक्लाइंट स्थिति पैटर्न का उपयोग तब करें जब:\n\n- बड़े अनुरोधों और प्रतिक्रिया आकारों को रोकने के लिए छोटी मात्रा में डेटा संसाधित करना।\n- क्लाइंट स्थिति को सहेजने के लिए सर्वर की आवश्यकता को हटा दें। ऐसा करने से सत्र आईडी संग्रहीत करने की आवश्यकता भी समाप्त हो जाती है।\n- क्लस्टरिंग एक मुद्दा है और इससे बचा जाना चाहिए। स्टेटलेस सर्वर क्लाइंट को सर्वर पर आसानी से वितरित करने की अनुमति देते हैं।\n- सर्वर विफलता के कारण डेटा हानि से लचीलापन बनाता है।\n\n## नतीजे\n\n- सर्वर स्टेटलेस है. कोई भी कंप्यूट एपीआई कोई डेटा संग्रहीत नहीं करेगा।\n- बड़ी मात्रा में डेटा से निपटने के लिए संघर्ष करना पड़ता है। प्रबंधित करने के लिए सत्र डेटा की बड़ी मात्रा के कारण भेजने और प्राप्त करने में अधिक समय लगता है।\n- सुरक्षा। सारा डेटा क्लाइंट की मशीन पर संग्रहीत होता है। इसका मतलब यह है कि क्लाइंट की ओर से कोई भी भेद्यता सर्वर द्वारा भेजे और प्राप्त किए जा रहे सभी डेटा को उजागर कर सकती है।\n\n\n## श्रेय\n\n- [Dzone - Practical PHP patterns](https://dzone.com/articles/practical-php-patterns/practical-php-patterns-client)\n- [Client Session State Design Pattern - Ram N Java](https://www.youtube.com/watch?v=ycOSj9g41pc)\n"
  },
  {
    "path": "localization/hi/collecting-parameter/README.md",
    "content": "---\ntitle: Collecting Parameter \ncategory: Idiom\nlanguage: hi\ntag:\n- Generic\n---\n\n## नाम\nपैरामीटर एकत्रित करना\n\n## हेतु\nएक संग्रह के भीतर अनेक विधियों के सहयोगात्मक परिणाम को संग्रहीत करना।\n\n## व्याख्या\n### वास्तविक दुनिया का उदाहरण\nएक बड़े कॉर्पोरेट भवन के भीतर, एक वैश्विक प्रिंटर कतार मौजूद है जो सभी मुद्रण कार्यों का एक संग्रह है\nजो फिलहाल लंबित हैं। विभिन्न मंजिलों पर प्रिंटर के अलग-अलग मॉडल होते हैं, प्रत्येक की अलग-अलग प्रिंटिंग होती है\nनीति। हमें एक ऐसे प्रोग्राम का निर्माण करना चाहिए जो किसी संग्रह में लगातार उपयुक्त मुद्रण कार्य जोड़ सके, जिसे *कलेक्टिंग पैरामीटर* कहा जाता है।\n\n### साफ़ शब्दों में\nएक विशाल विधि के बजाय जिसमें एक चर में जानकारी एकत्र करने के लिए कई नीतियां शामिल हैं, हम ऐसा कर सकते हैं\nकई छोटे फ़ंक्शन बनाएं जो प्रत्येक पैरामीटर लें, और नई जानकारी जोड़ें। हम पैरामीटर को पास कर सकते हैं\nये सभी छोटे कार्य और अंत तक, हमें वही मिलेगा जो हम मूल रूप से चाहते थे। इस बार, कोड साफ़ है\nऔर समझने में आसान है. क्योंकि बड़े फ़ंक्शन को तोड़ दिया गया है, परिवर्तन के रूप में कोड को संशोधित करना भी आसान है\nछोटे कार्यों के लिए स्थानीयकृत हैं।\n\n### विकिपीडिया कहता है\nकलेक्टिंग पैरामीटर मुहावरे में एक संग्रह (सूची, मानचित्र, आदि) को एक विधि के पैरामीटर के रूप में बार-बार पारित किया जाता है जो संग्रह में आइटम जोड़ता है।\n\n### प्रोग्रामेटिक उदाहरण\nऊपर से हमारे उदाहरण को कोड करते हुए, हम संग्रह `result` को एक संग्रहण पैरामीटर के रूप में उपयोग कर सकते हैं। निम्नलिखित प्रतिबंध\nकार्यान्वित हैं:\n- यदि A4 कागज रंगीन है, तो वह भी एक तरफा होना चाहिए। अन्य सभी गैर-रंगीन कागज स्वीकार किए जाते हैं\n- A3 कागज़ गैर-रंगीन और एक तरफा होने चाहिए\n- A2 पेपर एकल-पृष्ठ, एकल-पक्षीय और गैर-रंगीन होने चाहिए\n\n```java\npackage com.iluwatar.collectingparameter;\nimport java.util.LinkedList;\nimport java.util.Queue;\npublic class App {\n  static PrinterQueue printerQueue = PrinterQueue.getInstance();\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    /*\n      Initialising the printer queue with jobs\n    */\n    printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A4, 5, false, false));\n    printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A3, 2, false, false));\n    printerQueue.addPrinterItem(new PrinterItem(PaperSizes.A2, 5, false, false));\n\n    /*\n      This variable is the collecting parameter.\n    */    \n    var result = new LinkedList<PrinterItem>();\n\n    /* \n     * Using numerous sub-methods to collaboratively add information to the result collecting parameter\n     */\n    addA4Papers(result);\n    addA3Papers(result);\n    addA2Papers(result);\n  }\n}\n```\nहम `result` संग्रहण पैरामीटर को पॉप्युलेट करने के लिए `addA4Paper`, `addA3Paper`, और `addA2Paper` विधियों का उपयोग करते हैं\nपहले वर्णित नीति के अनुसार उपयुक्त मुद्रण कार्य। तीन नीतियां नीचे एन्कोड की गई हैं,\n\n```java\npublic class App {\n  static PrinterQueue printerQueue = PrinterQueue.getInstance();\n  /**\n   * Adds A4 document jobs to the collecting parameter according to some policy that can be whatever the client\n   * (the print center) wants.\n   *\n   * @param printerItemsCollection the collecting parameter\n   */\n  public static void addA4Papers(Queue<PrinterItem> printerItemsCollection) {\n    /*\n      Iterate through the printer queue, and add A4 papers according to the correct policy to the collecting parameter,\n      which is 'printerItemsCollection' in this case.\n     */\n    for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n      if (nextItem.paperSize.equals(PaperSizes.A4)) {\n        var isColouredAndSingleSided = nextItem.isColour && !nextItem.isDoubleSided;\n        if (isColouredAndSingleSided) {\n          printerItemsCollection.add(nextItem);\n        } else if (!nextItem.isColour) {\n          printerItemsCollection.add(nextItem);\n        }\n      }\n    }\n  }\n\n  /**\n   * Adds A3 document jobs to the collecting parameter according to some policy that can be whatever the client\n   * (the print center) wants. The code is similar to the 'addA4Papers' method. The code can be changed to accommodate\n   * the wants of the client.\n   *\n   * @param printerItemsCollection the collecting parameter\n   */\n  public static void addA3Papers(Queue<PrinterItem> printerItemsCollection) {\n    for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n      if (nextItem.paperSize.equals(PaperSizes.A3)) {\n\n        // Encoding the policy into a Boolean: the A3 paper cannot be coloured and double-sided at the same time\n        var isNotColouredAndSingleSided = !nextItem.isColour && !nextItem.isDoubleSided;\n        if (isNotColouredAndSingleSided) {\n          printerItemsCollection.add(nextItem);\n        }\n      }\n    }\n  }\n\n  /**\n   * Adds A2 document jobs to the collecting parameter according to some policy that can be whatever the client\n   * (the print center) wants. The code is similar to the 'addA4Papers' method. The code can be changed to accommodate\n   * the wants of the client.\n   *\n   * @param printerItemsCollection the collecting parameter\n   */\n  public static void addA2Papers(Queue<PrinterItem> printerItemsCollection) {\n    for (PrinterItem nextItem : printerQueue.getPrinterQueue()) {\n      if (nextItem.paperSize.equals(PaperSizes.A2)) {\n\n        // Encoding the policy into a Boolean: the A2 paper must be single page, single-sided, and non-coloured.\n        var isNotColouredSingleSidedAndOnePage = nextItem.pageCount == 1 && !nextItem.isDoubleSided\n                && !nextItem.isColour;\n        if (isNotColouredSingleSidedAndOnePage) {\n          printerItemsCollection.add(nextItem);\n        }\n      }\n    }\n  }\n}\n```\n\nप्रत्येक विधि एक संग्रह पैरामीटर को तर्क के रूप में लेती है। इसके बाद यह वैश्विक चर से लिए गए तत्वों को जोड़ता है,\nयदि प्रत्येक तत्व किसी दिए गए मानदंड को पूरा करता है तो इस संग्रहण पैरामीटर पर। इन विधियों में ग्राहक की इच्छानुसार कोई भी नीति हो सकती है।\n\nइस प्रोग्रामेटिक उदाहरण में, तीन प्रिंट कार्य कतार में जोड़े गए हैं। केवल पहले दो प्रिंट कार्य ही जोड़े जाने चाहिए\nनीति के अनुसार संग्रहण पैरामीटर। निष्पादन के बाद `result` चर के तत्व हैं,\n\n| paperSize | pageCount | isDoubleSided | isColour |\n|-----------|-----------|---------------|----------|\n| A4        | 5         | false         | false    |\n| A3        | 2         | false         | false    |\n\nजिसकी हमें अपेक्षा थी।\n\n## क्लास डायग्राम\n![alt text](../../../collecting-parameter/etc/collecting-parameter.urm.png \"Collecting Parameter\")\n\n## प्रयोज्यता\nजब कलेक्टिंग पैरामीटर डिज़ाइन पैटर्न का उपयोग करें\n- आप एक संग्रह या ऑब्जेक्ट वापस करना चाहते हैं जो कई विधियों का सहयोगात्मक परिणाम है\n- आप एक ऐसी विधि को सरल बनाना चाहते हैं जो डेटा जमा करती है क्योंकि मूल विधि बहुत जटिल है\n\n## ट्यूटोरियल\nइस विधि के लिए ट्यूटोरियल यहां पाए जाते हैं:\n- [रिफैक्टरिंग टू पैटर्न्स](http://www.tarrani.net/RefactoringToPatterns.pdf) जोशुआ केरिवस्की द्वारा\n- [स्मॉलटॉक सर्वोत्तम अभ्यास पैटर्न] (https://ptgmedia.pearsoncmg.com/images/9780134769042/samplepages/013476904X.pdf) केंट बेक द्वारा\n\n## ज्ञात उपयोग\nजोशुआ केरिव्स्की ने अपनी पुस्तक 'रिफैक्टरिंग टू पैटर्न्स' में वास्तविक दुनिया का उदाहरण दिया है। वह इसका उपयोग करने का एक उदाहरण देता है\nXML ट्री के लिए `toString()` विधि बनाने के लिए पैरामीटर डिज़ाइन पैटर्न एकत्रित करना। इस डिज़ाइन पैटर्न का उपयोग किए बिना,\nइसके लिए सशर्त और संयोजन के साथ एक भारी फ़ंक्शन की आवश्यकता होगी जो कोड पठनीयता को खराब कर देगा। ऐसी विधि\nइसे छोटी-छोटी विधियों में विभाजित किया जा सकता है, जिनमें से प्रत्येक जानकारी के अपने स्वयं के सेट को संग्रहण पैरामीटर में जोड़ता है।\n\nइसे [रिफैक्टरिंग टू पैटर्न](http://www.tarrani.net/RefactoringToPatterns.pdf) में देखें।\n\n## नतीजे\nपेशेवर:\n- कोड को अधिक पठनीय बनाता है\n- 'लिंकेज' से बचें, जहां कई विधियां एक ही वैश्विक चर का संदर्भ देती हैं\n- बड़े कार्यों को विघटित करके रखरखाव बढ़ाता है\n\nदोष:\n- कोड की लंबाई बढ़ सकती है\n- तरीकों की 'परतें' जोड़ता है\n\n## संबंधित पैटर्न\n- [Compose Methods](https://www.geeksforgeeks.org/composite-design-pattern/)\n\n## श्रेय\nनिम्नलिखित पुस्तकों का उपयोग किया गया:\n- [Refactoring To Patterns](http://www.tarrani.net/RefactoringToPatterns.pdf) जोशुआ केरिवस्की द्वारा\n- [Smalltalk Best Practice Patterns](https://ptgmedia.pearsoncmg.com/images/9780134769042/samplepages/013476904X.pdf) केंट बेक द्वारा\n  साइटें:\n- [Wiki](https://wiki.c2.com/?CollectingParameter)\n"
  },
  {
    "path": "localization/hi/collection-pipeline/README.md",
    "content": "---\ntitle: Collection Pipeline\ncategory: Functional\nlanguage: hi\ntag:\n - Reactive\n---\n\n## हेतु\nकलेक्शन पाइपलाइन फ़ंक्शन कंपोज़िशन और कलेक्शन पाइपलाइन पेश करती है, दो कार्यात्मक-शैली पैटर्न जिन्हें आप अपने कोड में संग्रहों को पुनरावृत्त करने के लिए जोड़ सकते हैं।\nकार्यात्मक प्रोग्रामिंग में, छोटे मॉड्यूलर कार्यों या संचालन की एक श्रृंखला के माध्यम से जटिल संचालन को अनुक्रमित करना आम बात है। श्रृंखला को फ़ंक्शंस की संरचना, या फ़ंक्शंस संरचना कहा जाता है। जब डेटा का संग्रह किसी फ़ंक्शन संरचना के माध्यम से प्रवाहित होता है, तो यह एक संग्रह पाइपलाइन बन जाता है। फ़ंक्शन संरचना और संग्रह पाइपलाइन दो डिज़ाइन पैटर्न हैं जिनका उपयोग अक्सर कार्यात्मक-शैली प्रोग्रामिंग में किया जाता है।\n\n## क्लास डायग्राम\n![alt text](../../../collection-pipeline/etc/collection-pipeline.png \"Collection Pipeline\")\n\n## प्रयोज्यता\nजब संग्रह पाइपलाइन पैटर्न का उपयोग करें\n\n* जब आप ऑपरेशनों का एक क्रम निष्पादित करना चाहते हैं जहां एक ऑपरेशन का एकत्रित आउटपुट अगले में फीड किया जाता है\n* जब आप अपने कोड में बहुत सारे स्टेटमेंट का उपयोग करते हैं\n* जब आप अपने कोड में बहुत सारे लूप का उपयोग करते हैं\n\n## श्रेय\n\n* [Function composition and the Collection Pipeline pattern](https://www.ibm.com/developerworks/library/j-java8idioms2/index.html)\n* [Martin Fowler](https://martinfowler.com/articles/collection-pipeline/)\n* [Java8 Streams](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html)\n"
  },
  {
    "path": "localization/hi/combinator/README.md",
    "content": "---\ntitle: Combinator\ncategory: Idiom\nlanguage: hi\ntag:\n - Reactive\n---\n\n## दूसरा नाम\n\nसंयोजन पैटर्न\n\n## हेतु\n\nकार्यों के संयोजन के विचार पर केंद्रित पुस्तकालयों को व्यवस्थित करने की शैली का प्रतिनिधित्व करने वाला कार्यात्मक पैटर्न।\nइसे सीधे शब्दों में कहें तो, कुछ प्रकार टी हैं, प्रकार टी के \"आदिम\" मूल्यों के निर्माण के लिए कुछ कार्य हैं, और कुछ \"कॉम्बिनेटर\" हैं जो प्रकार टी के अधिक जटिल मूल्यों को बनाने के लिए विभिन्न तरीकों से प्रकार टी के मूल्यों को जोड़ सकते हैं।\n\n## व्याख्या\n\nवास्तविक दुनिया का उदाहरण\n\n> कंप्यूटर विज्ञान में, कॉम्बिनेटरी लॉजिक का उपयोग गणना के सरलीकृत मॉडल के रूप में किया जाता है, जिसका उपयोग कंप्यूटेबिलिटी सिद्धांत और प्रूफ सिद्धांत में किया जाता है। अपनी सरलता के बावजूद, संयोजनात्मक तर्क गणना की कई आवश्यक विशेषताओं को पकड़ लेता है।\n>\n\nसाफ़ शब्दों में\n\n> कॉम्बिनेटर आपको पहले से परिभाषित \"things\" से नई \"things\" बनाने की अनुमति देता है।\n>\n\nविकिपीडिया कहता है\n\n> कॉम्बिनेटर एक उच्च-क्रम वाला फ़ंक्शन है जो अपने तर्कों से परिणाम को परिभाषित करने के लिए केवल फ़ंक्शन एप्लिकेशन और पहले से परिभाषित कॉम्बिनेटर का उपयोग करता है।\n>\n\n**प्रोग्रामेटिक उदाहरण**\n\nउपरोक्त कॉम्बिनेटर उदाहरण का अनुवाद करना। सबसे पहले, हमारे पास एक इंटरफ़ेस है जिसमें कई विधियाँ `contains`, `not`, `or`, `and` शामिल हैं।\n\n```java\n// Functional interface to find lines in text.\npublic interface Finder {\n\n\t// The function to find lines in text.\n\tList<String> find(String text);\n\n\t// Simple implementation of function {@link #find(String)}.\n\tstatic Finder contains(String word) {\n    \t\treturn txt -> Stream.of(txt.split(\"\\n\"))\n        \t\t.filter(line -> line.toLowerCase().contains(word.toLowerCase()))\n        \t\t.collect(Collectors.toList());\n  \t}\n\n\t// combinator not.\n\tdefault Finder not(Finder notFinder) {\n    \t\treturn txt -> {\n      \t\t\tList<String> res = this.find(txt);\n      \t\t\tres.removeAll(notFinder.find(txt));\n      \t\t\treturn res;\n    \t\t\t};\n  \t}\n\n\t// combinator or.\n\tdefault Finder or(Finder orFinder) {\n    \t\treturn txt -> {\n      \t\t\tList<String> res = this.find(txt);\n      \t\t\tres.addAll(orFinder.find(txt));\n      \t\t\treturn res;\n    \t\t\t};\n\t}\n\n\t// combinator and.\n\tdefault Finder and(Finder andFinder) {\n    \t\treturn\n        \ttxt -> this\n            \t\t.find(txt)\n            \t\t.stream()\n            \t\t.flatMap(line -> andFinder.find(line).stream())\n            \t\t.collect(Collectors.toList());\n  \t}\n\t...\n}\n```\n\nफिर हमारे पास कुछ जटिल खोजकों `advancedFinder`, `filteredFinder`, `specializedFinder` and `expandedFinder` के लिए एक और कॉम्बिनेटर भी है।\n\n```java\n// Complex finders consisting of simple finder.\npublic class Finders {\n\n\tprivate Finders() {\n  \t}\n\n\t// Finder to find a complex query.\n\tpublic static Finder advancedFinder(String query, String orQuery, String notQuery) {\n    \t\treturn\n        \t\tFinder.contains(query)\n            \t\t\t.or(Finder.contains(orQuery))\n            \t\t\t.not(Finder.contains(notQuery));\n\t}\n\n\t// Filtered finder looking a query with excluded queries as well.\n\tpublic static Finder filteredFinder(String query, String... excludeQueries) {\n\t\tvar finder = Finder.contains(query);\n\n    \t\tfor (String q : excludeQueries) {\n      \t\t\tfinder = finder.not(Finder.contains(q));\n    \t\t}\n    \t\treturn finder;\n\t}\n\n\t// Specialized query. Every next query is looked in previous result.\n\tpublic static Finder specializedFinder(String... queries) {\n    \t\tvar finder = identMult();\n\n\t\tfor (String query : queries) {\n      \t\t\tfinder = finder.and(Finder.contains(query));\n    \t\t}\n    \t\treturn finder;\n  \t}\n\n\t// Expanded query. Looking for alternatives.\n\tpublic static Finder expandedFinder(String... queries) {\n    \t\tvar finder = identSum();\n\n    \t\tfor (String query : queries) {\n      \t\t\tfinder = finder.or(Finder.contains(query));\n    \t\t}\n   \t\treturn finder;\n  \t}\n\t...\n}\n```\n\nअब हमने कॉम्बिनेटरों के लिए इंटरफ़ेस और विधियाँ बना ली हैं। अब हमारे पास इन कॉम्बिनेटरों पर काम करने वाला एक एप्लिकेशन है।\n\n```java\nvar queriesOr = new String[]{\"many\", \"Annabel\"};\nvar finder = Finders.expandedFinder(queriesOr);\nvar res = finder.find(text());\nLOGGER.info(\"the result of expanded(or) query[{}] is {}\", queriesOr, res);\n\nvar queriesAnd = new String[]{\"Annabel\", \"my\"};\nfinder = Finders.specializedFinder(queriesAnd);\nres = finder.find(text());\nLOGGER.info(\"the result of specialized(and) query[{}] is {}\", queriesAnd, res);\n\nfinder = Finders.advancedFinder(\"it was\", \"kingdom\", \"sea\");\nres = finder.find(text());\nLOGGER.info(\"the result of advanced query is {}\", res);\n\nres = Finders.filteredFinder(\" was \", \"many\", \"child\").find(text());\nLOGGER.info(\"the result of filtered query is {}\", res);\n\nprivate static String text() {\n    return\n        \"It was many and many a year ago,\\n\"\n            + \"In a kingdom by the sea,\\n\"\n            + \"That a maiden there lived whom you may know\\n\"\n            + \"By the name of ANNABEL LEE;\\n\"\n            + \"And this maiden she lived with no other thought\\n\"\n            + \"Than to love and be loved by me.\\n\"\n            + \"I was a child and she was a child,\\n\"\n            + \"In this kingdom by the sea;\\n\"\n            + \"But we loved with a love that was more than love-\\n\"\n            + \"I and my Annabel Lee;\\n\"\n            + \"With a love that the winged seraphs of heaven\\n\"\n            + \"Coveted her and me.\";\n  }\n```\n\n**प्रोग्राम आउटपुट:**\n\n```java\nthe result of expanded(or) query[[many, Annabel]] is [It was many and many a year ago,, By the name of ANNABEL LEE;, I and my Annabel Lee;]\nthe result of specialized(and) query[[Annabel, my]] is [I and my Annabel Lee;]\nthe result of advanced query is [It was many and many a year ago,]\nthe result of filtered query is [But we loved with a love that was more than love-]\n```\n\nअब हम अपने ऐप को `expandedFinder`, `specializedFinder`, `advancedFinder`, `filteredFinder` खोजने वाले प्रश्नों के साथ डिज़ाइन कर सकते हैं, जो सभी `contains`, `or`, `not`, `and` से प्राप्त होते हैं।\n\n\n## क्लास डायग्राम\n![alt text](../../../combinator/etc/combinator.urm.png \"Combinator class diagram\")\n\n## प्रयोज्यता\nकॉम्बिनेटर पैटर्न का उपयोग तब करें जब:\n\n- आप अधिक सादे मानों से अधिक जटिल मान बनाने में सक्षम हैं, लेकिन उनका प्रकार समान है (उनका संयोजन)\n\n## फ़ायदे\n\n- डेवलपर्स के नजरिए से एपीआई डोमेन के शब्दों से बना है।\n- संयोजन और अनुप्रयोग चरण के बीच स्पष्ट अंतर है।\n- पहले एक इंस्टेंस बनाता है और फिर उसे निष्पादित करता है।\n- यह पैटर्न को समानांतर वातावरण में लागू बनाता है।\n\n\n## वास्तविक दुनिया के उदाहरण\n\n- java.util.function.Function#compose\n- java.util.function.Function#andThen\n\n## श्रेय\n\n- [Example for java](https://gtrefs.github.io/code/combinator-pattern/)\n- [Combinator pattern](https://wiki.haskell.org/Combinator_pattern)\n- [Combinatory logic](https://wiki.haskell.org/Combinatory_logic)\n"
  },
  {
    "path": "localization/hi/command/README.md",
    "content": "---\ntitle: Command\ncategory: Behavioral\nlanguage: hi\ntag:\n - Gang of Four\n---\n\n## दूसरा नाम\n\nक्रिया, लेन-देन\n\n## हेतु\n\nएक अनुरोध को एक ऑब्जेक्ट के रूप में इनकैप्सुलेट करें, जिससे आपको क्लाइंट को अलग-अलग पैरामीटराइज़ करने की सुविधा मिलती है\nअनुरोध, कतार या लॉग अनुरोध, और पूर्ववत संचालन का समर्थन करते हैं।\n\n## व्याख्या\nवास्तविक दुनिया का उदाहरण\n\n> एक जादूगर भूत पर जादू कर रहा है। मंत्रों को एक-एक करके भूत पर क्रियान्वित किया जाता है।\n> पहला जादू भूत को सिकोड़ देता है और दूसरा उसे अदृश्य बना देता है। फिर विज़ार्ड उलट जाता है\n> मंत्र एक-एक करके। यहां प्रत्येक मंत्र एक कमांड ऑब्जेक्ट है जिसे पूर्ववत किया जा सकता है।\n\nसाफ़ शब्दों में\n\n> अनुरोधों को कमांड ऑब्जेक्ट के रूप में संग्रहीत करने से कोई कार्रवाई करने या बाद में उसे पूर्ववत करने की अनुमति मिलती है।\n\nविकिपीडिया कहता है\n\n> ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में, कमांड पैटर्न एक व्यवहारिक डिज़ाइन पैटर्न है जिसमें a\n> ऑब्जेक्ट का उपयोग किसी क्रिया को करने या किसी ईवेंट को ट्रिगर करने के लिए आवश्यक सभी जानकारी को समाहित करने के लिए किया जाता है\n> बाद में।\n\n**प्रोग्रामेटिक उदाहरण**\n\nयहां विज़ार्ड और गॉब्लिन के साथ नमूना कोड दिया गया है। आइए `Wizard` वर्ग से शुरू करें।\n\n```java\n@Slf4j\npublic class Wizard {\n\n  private final Deque<Runnable> undoStack = new LinkedList<>();\n  private final Deque<Runnable> redoStack = new LinkedList<>();\n\n  public Wizard() {}\n\n  public void castSpell(Runnable runnable) {\n    runnable.run();\n    undoStack.offerLast(runnable);\n  }\n\n  public void undoLastSpell() {\n    if (!undoStack.isEmpty()) {\n      var previousSpell = undoStack.pollLast();\n      redoStack.offerLast(previousSpell);\n      previousSpell.run();\n    }\n  }\n\n  public void redoLastSpell() {\n    if (!redoStack.isEmpty()) {\n      var previousSpell = redoStack.pollLast();\n      undoStack.offerLast(previousSpell);\n      previousSpell.run();\n    }\n  }\n\n  @Override\n  public String toString() {\n    return \"Wizard\";\n  }\n}\n```\n\nइसके बाद, हमारे पास वह भूत है जो मंत्रों का लक्ष्य है।\n\n```java\n@Slf4j\npublic abstract class Target {\n\n  private Size size;\n\n  private Visibility visibility;\n\n  public Size getSize() {\n    return size;\n  }\n\n  public void setSize(Size size) {\n    this.size = size;\n  }\n\n  public Visibility getVisibility() {\n    return visibility;\n  }\n\n  public void setVisibility(Visibility visibility) {\n    this.visibility = visibility;\n  }\n\n  @Override\n  public abstract String toString();\n\n  public void printStatus() {\n    LOGGER.info(\"{}, [size={}] [visibility={}]\", this, getSize(), getVisibility());\n  }\n}\n\npublic class Goblin extends Target {\n\n  public Goblin() {\n    setSize(Size.NORMAL);\n    setVisibility(Visibility.VISIBLE);\n  }\n\n  @Override\n  public String toString() {\n    return \"Goblin\";\n  }\n\n  public void changeSize() {\n    var oldSize = getSize() == Size.NORMAL ? Size.SMALL : Size.NORMAL;\n    setSize(oldSize);\n  }\n\n  public void changeVisibility() {\n    var visible = getVisibility() == Visibility.INVISIBLE\n          ? Visibility.VISIBLE : Visibility.INVISIBLE;\n    setVisibility(visible);\n  }\n}\n```\n\nअंत में, हमारे पास मुख्य फ़ंक्शन कास्टिंग मंत्र में विज़ार्ड है।\n\n```java\npublic static void main(String[] args) {\n  var wizard = new Wizard();\n  var goblin = new Goblin();\n\n  // casts shrink/unshrink spell\n  wizard.castSpell(goblin::changeSize);\n\n  // casts visible/invisible spell\n  wizard.castSpell(goblin::changeVisibility);\n\n  // undo and redo casts\n   wizard.undoLastSpell();\n   wizard.redoLastSpell();\n```\n\nयहाँ कार्रवाई में पूरा उदाहरण है।\n\n```java\nvar wizard = new Wizard();\nvar goblin = new Goblin();\n\ngoblin.printStatus();\nwizard.castSpell(goblin::changeSize);\ngoblin.printStatus();\n\nwizard.castSpell(goblin::changeVisibility);\ngoblin.printStatus();\n\nwizard.undoLastSpell();\ngoblin.printStatus();\n\nwizard.undoLastSpell();\ngoblin.printStatus();\n\nwizard.redoLastSpell();\ngoblin.printStatus();\n\nwizard.redoLastSpell();\ngoblin.printStatus();\n```\n\nयहाँ प्रोग्राम आउटपुट है:\n\n```java\nGoblin, [size=normal] [visibility=visible]\nGoblin, [size=small] [visibility=visible]\nGoblin, [size=small] [visibility=invisible]\nGoblin, [size=small] [visibility=visible]\nGoblin, [size=normal] [visibility=visible]\nGoblin, [size=small] [visibility=visible]\nGoblin, [size=small] [visibility=invisible]\n```\n\n## क्लास डायग्राम\n\n![alt text](../../../command/etc/command.png \"Command\")\n\n## प्रयोज्यता\n\nजब आप चाहें तो कमांड पैटर्न का उपयोग करें:\n\n* निष्पादित की जाने वाली क्रिया द्वारा वस्तुओं का मापन करें। आप ऐसे मानकीकरण को a में व्यक्त कर सकते हैं\n  कॉलबैक फ़ंक्शन के साथ प्रक्रियात्मक भाषा, यानी, एक फ़ंक्शन जो कहीं पंजीकृत है\n  बाद में बुलाया गया। कमांड कॉलबैक के लिए ऑब्जेक्ट-ओरिएंटेड प्रतिस्थापन हैं।\n* अलग-अलग समय पर अनुरोध निर्दिष्ट करें, कतारबद्ध करें और निष्पादित करें। एक कमांड ऑब्जेक्ट में जीवन हो सकता है\n  मूल अनुरोध से स्वतंत्र. यदि किसी अनुरोध के प्राप्तकर्ता को किसी पते में दर्शाया जा सकता है\n  अंतरिक्ष-स्वतंत्र तरीके से, फिर आप अनुरोध के लिए एक कमांड ऑब्जेक्ट को एक अलग प्रक्रिया में स्थानांतरित कर सकते हैं\n  और वहां अनुरोध पूरा करें।\n* समर्थन पूर्ववत करें। कमांड का निष्पादन ऑपरेशन इसके प्रभावों को उलटने के लिए स्थिति को संग्रहीत कर सकता है\n  स्वयं आदेश दें. कमांड इंटरफ़ेस में एक अतिरिक्त अन-एक्ज़िक्यूट ऑपरेशन होना चाहिए जो उलट देता है\n  निष्पादित करने के लिए पिछली कॉल के प्रभाव। निष्पादित आदेश इतिहास सूची में संग्रहीत होते हैं।\n  इस सूची को आगे और पीछे घुमाकर असीमित स्तर की पूर्ववत और पुनः करें कार्यक्षमता प्राप्त की जाती है\n  क्रमशः अन-एक्ज़ीक्यूट और एक्ज़िक्यूट को कॉल करना।\n* लॉगिंग परिवर्तनों का समर्थन करें ताकि सिस्टम क्रैश होने की स्थिति में उन्हें फिर से लागू किया जा सके। को बढ़ाकर\n  लोड और स्टोर संचालन के साथ कमांड इंटरफ़ेस, आप परिवर्तनों का लगातार लॉग रख सकते हैं।\n  क्रैश से उबरने में डिस्क से लॉग किए गए कमांड को फिर से लोड करना और उन्हें फिर से निष्पादित करना शामिल है\n  निष्पादित ऑपरेशन.\n* उच्च-स्तरीय संचालन के आसपास एक प्रणाली की संरचना करें जो आदिम संचालन पर आधारित हो। ऐसी संरचना है\n  लेनदेन का समर्थन करने वाली सूचना प्रणालियों में आम है। एक लेन-देन डेटा के एक सेट को समाहित करता है\n  परिवर्तन। कमांड पैटर्न लेनदेन को मॉडल करने का एक तरीका प्रदान करता है। कमांड का एक सामान्य इंटरफ़ेस होता है,\n  आपको सभी लेन-देन एक ही तरीके से शुरू करने देता है। यह पैटर्न विस्तार करना भी आसान बनाता है\n  नए लेनदेन के साथ प्रणाली.\n* अनुरोधों का इतिहास रखें।\n* कॉलबैक कार्यक्षमता लागू करें।\n* पूर्ववत कार्यक्षमता लागू करें।\n\n## ज्ञात उपयोग\n\n* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)\n* [org.junit.runners.model.Statement](https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/runners/model/Statement.java)\n* [Netflix Hystrix](https://github.com/Netflix/Hystrix/wiki)\n* [javax.swing.Action](http://docs.oracle.com/javase/8/docs/api/javax/swing/Action.html)\n\n## श्रेय\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n"
  },
  {
    "path": "localization/hi/factory-method/README.md",
    "content": "---\ntitle: Factory Method\ncategory: Creational\nlanguage: hi\ntag:\n  - Extensibility \n  - Gang Of Four\n---\n\n## वर्चुअल कन्स्ट्रक्टर के रूप में भी जाना जाता \n\n## हेतु\n\nएक इंटरफ़ेस को परिभाषित करें जो एक ऑब्जेक्ट बनाने की अनुमति देता है, लेकिन उपवर्गों को यह तय करने देता है कि किस वर्ग को तत्काल बनाया जाए।\nफ़ैक्टरी मेथड एक वर्ग को उपवर्गों में तत्कालिकता स्थगित करने देता है।\n\n## स्पष्टीकरण\n\nवास्तविक दुनिया का उदाहरण\n\nलोहार हथियार बनाता है। कल्पित बौनों को एल्विश हथियारों की आवश्यकता होती है और orcs को Orcish हथियारों की आवश्यकता होती है।\nग्राहक के हाथ पर निर्भर करता है कि सही प्रकार के लोहार को बुलाया जाता है।\n\nसाधारण शब्दों में\n\nयह चाइल्ड क्लासेस को इंस्टेंटिएशन लॉजिक को डेलिगेट करने का एक तरीका प्रदान करता है।\n\nविकिपीडिया का कहना है कि\n\nक्लास-आधारित प्रोग्रामिंग में, फैक्ट्री मेथड पैटर्न एक क्रिएशनल पैटर्न है जो फैक्ट्री मेथड का उपयोग उस ऑब्जेक्ट को बनाने की समस्या से निपटने के लिए करता है जो उस ऑब्जेक्ट के सटीक वर्ग को निर्दिष्ट किए बिना बनाया जाएगा। यह एक फैक्ट्री मेथड को कॉल करके ऑब्जेक्ट बनाकर किया जाता है - या तो एक इंटरफ़ेस में निर्दिष्ट और चाइल्ड कक्षाओं द्वारा कार्यान्वित किया जाता है, या एक बेस क्लास में कार्यान्वित किया जाता है और वैकल्पिक रूप से व्युत्पन्न कक्षाओं द्वारा ओवरराइड किया जाता है - बजाय कंस्ट्रक्टर को कॉल करने के।\n\nप्रोग्रामेटिक उदाहरण\n\nहमारे ब्लैकस्मिथ उदाहरण को ऊपर लेते हुए, पहले हमारे पास एक 'ब्लैकस्मिथ' इंटरफेस होता है और इसके लिए कुछ अंगीकरण होते हैं:\n\n```java\npublic interface Blacksmith {\n  Weapon manufactureWeapon(WeaponType weaponType);\n}\n\npublic class ElfBlacksmith implements Blacksmith {\n  public Weapon manufactureWeapon(WeaponType weaponType) {\n    return ELFARSENAL.get(weaponType);\n  }\n}\n\npublic class OrcBlacksmith implements Blacksmith {\n  public Weapon manufactureWeapon(WeaponType weaponType) {\n    return ORCARSENAL.get(weaponType);\n  }\n}\n```\nजब ग्राहक आते हैं, तो सही प्रकार के ब्लैकस्मिथ को बुलाया जाता है और अनुरोधित हथियार निर्मित किए जाते हैं  \n\n```java\nBlacksmith blacksmith = new OrcBlacksmith();\nWeapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);\nLOGGER.info(\"{} manufactured {}\", blacksmith, weapon);\nweapon = blacksmith.manufactureWeapon(WeaponType.AXE);\nLOGGER.info(\"{} manufactured {}\", blacksmith, weapon);\n\nblacksmith = new ElfBlacksmith();\nweapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);\nLOGGER.info(\"{} manufactured {}\", blacksmith, weapon);\nweapon = blacksmith.manufactureWeapon(WeaponType.AXE);\nLOGGER.info(\"{} manufactured {}\", blacksmith, weapon);\n\n``` \nप्रोग्राम का आउटपुट :\n```text\nThe orc blacksmith manufactured an orcish spear\nThe orc blacksmith manufactured an orcish axe\nThe elf blacksmith manufactured an elven spear\nThe elf blacksmith manufactured an elven axe\n\n```\n## क्लास डायग्राम\n\n![alt text](./etc/factory-method.urm.png \"Factory Method pattern class diagram\")\n\n## प्रयोज्यता\n\nनिम्नलिखित स्थितियों में फैक्टरी मेथड पैटर्न का उपयोग करें:\n\n* क्लास उन ऑब्जेक्ट्स के वर्ग का अनुमान नहीं लगा सकता है जिन्हें उसे बनाना चाहिए।\n* क्लास चाहता है कि उसके उपवर्ग उन ऑब्जेक्ट्स को निर्दिष्ट करें जो वह बनाता है।\n* कक्षाएं कई सहायक उपवर्गों में से एक को जिम्मेदारी सौंपती हैं, और आप यह जानना चाहते हैं कि कौन सा सहायक उपवर्ग प्रतिनिधि है।\n\n## ज्ञात उपयोग\n\n* [java.util.Calendar](http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)\n* [java.util.ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)\n* [java.text.NumberFormat](http://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)\n* [java.nio.charset.Charset](http://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)\n* [java.net.URLStreamHandlerFactory](http://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html#createURLStreamHandler-java.lang.String-)\n* [java.util.EnumSet](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of-E-)\n* [javax.xml.bind.JAXBContext](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--)\n\n## श्रेय\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/hi/module/README.md",
    "content": "---\ntitle: Module\ncategory: Structural\nlanguage: hi\ntag:\n  - Decoupling\n  - Cloud distributed\n---\n\n## हेतु\n\nमॉड्यूल पैटर्न का उपयोग सॉफ़्टवेयर मॉड्यूल की अवधारणा को लागू करने के लिए किया जाता है, जिसे मॉड्यूलर प्रोग्रामिंग द्वारा परिभाषित किया जाता है, एक प्रोग्रामिंग भाषा में जो अवधारणा के लिए अपूर्ण प्रत्यक्ष समर्थन प्रदान करती है।\n\n## क्लास डायग्राम\n\n\n![alt text](../../../module/etc/module.png \"Module class diagram\")\n\n## प्रयोज्यता\n\nमॉड्यूल पैटर्न को एक क्रिएशनल पैटर्न और एक स्ट्रक्चरल पैटर्न माना जा सकता है। यह अन्य तत्वों के निर्माण और संगठन को प्रबंधित करता है, और उन्हें स्ट्रक्चरल पैटर्न की तरह समूहों में विभाजित करता है।\n\nइस पैटर्न को लागू करने वाली कोई वस्तु एक नामस्थान के समकक्ष प्रदान कर सकती है, जो एक स्थैतिक वर्ग या स्थैतिक सदस्यों वाले वर्ग के आरंभीकरण और अंतिमकरण प्रक्रिया को क्लीनर, अधिक संक्षिप्त वाक्यविन्यास और अर्थशास्त्र के साथ प्रदान करती है।\n\n## श्रेय\n\n* [Module](https://en.wikipedia.org/wiki/Module_pattern)\n"
  },
  {
    "path": "localization/id/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n\n# Implementasi design patterns pada Java\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-176-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n<br/>\n\nBaca dalam bahasa lain : [**zh**](localization/zh/README.md), [**ko**](localization/ko/README.md), [**fr**](localization/fr/README.md), [**tr**](localization/tr/README.md), [**ar**](localization/ar/README.md), [**es**](localization/es/README.md), [**pt**](localization/pt/README.md), [**id**](localization/id/README.md)\n\n<br/>\n\n# Pengenalan\n\nDesign patterns adalah best practice yang dapat digunakan programmer untuk memecahkan masalah umum saat merancang aplikasi atau sistem.\n\nDesign patterns dapat mempercepat proses pengembangan dengan menyediakan kode yang teruji, terbukti paradigma pengembangan.\n\nMenggunakan kembali design patterns membantu mencegah masalah-masalah kecil yang dapat menyebabkan masalah yang lebih besar, dan juga meningkatkan keterbacaan kode untuk programmer dan arsitek yang\nfamiliar dengan pola.\n\n\n# Mulai\n\nSitus ini menampilkan Design Patterns pada Java. Solusi-solusi yang terdapat pada situs ini telah dikembangkan oleh programmer dan arsitek  yang berpengalaman dari komunitas open source. Pola-polanya dapat dilihat pada deskripsi atau dengan melihat source code mereka. Contoh-contoh source code memiliki komentar yang baik dan dapat dianggap sebagai tutorial pemrograman tentang cara menerapkan pola tertentu. Kami menggunakan teknologi Java open source yang populer dan telah terbukti.\n\nSebelum anda masuk kedalam materinya, anda harus familiar dengan macam-macam [Software Design Principles](https://java-design-patterns.com/principles/).\n\nSemua desain seharusnya sesimpel mungkin. Anda harus mulai dengan KISS, YAGNI, dan prinsip Do The Simples Thing That Could Possibly Work. hanya boleh diperkenalkan ketika dibutuhkan untuk praktik\nkemungkinan diperpanjang.\n\nSetelah Anda terbiasa dengan konsep-konsep ini, Anda dapat mulai belajar\n[design patterns yang tersedia](https://java-design-patterns.com/patterns/) menggunakan cara-cara berikut\n\n - Cari spesifik pattern berdasarkan namanya. Apabila tidak menemukannya tolong lapor pattern baru [disini](https://github.com/iluwatar/java-design-patterns/issues).\n - Gunakan tag-tag seperti `Performance`, `Gang of Four` atau `Data access`.\n - Gunakan kategori dari pattern, `Creational`, `Behavioral`, dan sebagainya.\n\nSemoga Anda menemukan solusi Object-Oriented yang bermanfaat untuk arsitektur Anda dari yang disajikan di situs ini dan mempelajarinya dengan senang seperti kami mengembangkannya.\n\n# Cara berkontribusi\n\nJika anda memiliki keinginan untuk berkontribusi pada proyek ini anda akan menemukan informasi yang revelan pada halaman [developer wiki](https://github.com/iluwatar/java-design-patterns/wiki). Kami akan membantu anda dan menjawab pertanyaan anda pada [Gitter chatroom](https://gitter.im/iluwatar/java-design-patterns).\n\n# License\n\nProyek ini dilisensikan di bawah ketentuan lisensi MIT.\n\n"
  },
  {
    "path": "localization/id/decorator/README.md",
    "content": "---\ntitle: Decorator\ncategory: Structural\nlanguage: id\ntag:\n - Gang of Four\n - Extensibility\n---\n\n## Juga dikenal sebagai\n\nPembungkus\n\n## Tujuan\n\nMenyematkan tanggung jawab tambahan ke suatu objek secara dinamis. Dekorator memberikan alternatif yang fleksibel terhadap subkelas untuk memperluas fungsionalitas.\n\n## Penjelasan\n\nContoh dunia nyata\n\n> Ada troll pemarah yang tinggal di perbukitan terdekat. Biasanya ia pergi dengan tangan kosong, tetapi terkadang ia\n> punya senjata. Untuk mempersenjatai troll, Anda tidak perlu membuat troll baru, melainkan mendekorasinya\n> secara dinamis dengan senjata yang sesuai.\n\nDengan kata sederhana\n\n> Pola dekorator memungkinkan Anda mengubah perilaku objek secara dinamis saat run time dengan membungkus\n> mereka dalam objek kelas dekorator.\n\nWikipedia(en) mengatakan\n\n> Dalam pemrograman berorientasi objek, pola dekorator adalah pola desain yang memungkinkan perilaku \n> ditambahkan ke objek individual, baik secara statis maupun dinamis, tanpa memengaruhi perilaku \n> objek lain dari kelas yang sama. Pola dekorator sering kali berguna untuk mematuhi Prinsip Tanggung \n> Jawab Tunggal, karena memungkinkan fungsionalitas dibagi antara kelas-kelas dengan area perhatian yang \n> unik serta Prinsip Terbuka-Tertutup, dengan memungkinkan fungsionalitas suatu kelas diperluas tanpa diubah.\n\n**Contoh Program**\n\nMari kita ambil contoh troll. Pertama-tama kita memiliki `SimpleTroll` yang mengimplementasikan antarmuka\n`Troll`:\n\n```java\npublic interface Troll {\n  void attack();\n  int getAttackPower();\n  void fleeBattle();\n}\n\n@Slf4j\npublic class SimpleTroll implements Troll {\n\n  @Override\n  public void attack() {\n    LOGGER.info(\"Troll itu mencoba menangkapmu!\");\n  }\n\n  @Override\n  public int getAttackPower() {\n    return 10;\n  }\n\n  @Override\n  public void fleeBattle() {\n    LOGGER.info(\"Troll itu menjerit ketakutan dan melarikan diri!\");\n  }\n}\n```\n\nKemudian kita ingin menambahkan gada untuk troll tersebut. Kita dapat melakukannya secara dinamis dengan menggunakan dekorator:\n\n```java\n@Slf4j\npublic class ClubbedTroll implements Troll {\n\n  private final Troll decorated;\n\n  public ClubbedTroll(Troll decorated) {\n    this.decorated = decorated;\n  }\n\n  @Override\n  public void attack() {\n    decorated.attack();\n    LOGGER.info(\"Troll itu mengayunkan gada ke arahmu!\");\n  }\n\n  @Override\n  public int getAttackPower() {\n    return decorated.getAttackPower() + 10;\n  }\n\n  @Override\n  public void fleeBattle() {\n    decorated.fleeBattle();\n  }\n}\n```\n\nBerikut aksi troll tersebut:\n\n```java\n// simple troll\nLOGGER.info(\"Troll biasa mendekat.\");\nvar troll = new SimpleTroll();\ntroll.attack();\ntroll.fleeBattle();\nLOGGER.info(\"Kekuatan troll sederhana: {}.\\n\", troll.getAttackPower());\n\n// change the behavior of the simple troll by adding a decorator\nLOGGER.info(\"Troll dengan gada besar mengejutkanmu.\");\nvar clubbedTroll = new ClubbedTroll(troll);\nclubbedTroll.attack();\nclubbedTroll.fleeBattle();\nLOGGER.info(\"Kekuatan troll dengan gada: {}.\\n\", clubbedTroll.getAttackPower());\n```\n\nOutput program:\n\n```java\nTroll biasa mendekat.\nTroll itu mencoba menangkapmu!\nTroll itu menjerit ketakutan dan melarikan diri!\nKekuatan troll sederhana: 10.\n\nTroll dengan gada besar mengejutkanmu.\nTroll itu mencoba menangkapmu!\nTroll itu mengayunkan gada ke arahmu!\nTroll itu menjerit ketakutan dan melarikan diri!\nKekuatan troll dengan gada: 20.\n```\n\n## Diagram kelas\n\n![alt text](./etc/decorator.urm.png \"Diagram kelas pola dekorator\")\n\n## Penerapan\n\nDekorator digunakan untuk:\n\n* Tambahkan tanggung jawab ke objek individual secara dinamis dan transparan, tanpa\nmemengaruhi objek lain.\n* Untuk tanggung jawab yang dapat ditarik/dihapus.\n* Dimana ekstensi dengan subkelas tidak praktis; Ketika sejumlah besar ekstensi independen\nmungkin dilakukan dan akan menghasilkan ledakan subkelas untuk mendukung setiap kombinasi, atau definisi \nkelas mungkin tersembunyi dan/atau tidak tersedia untuk subkelas.\n\n## Tutorial\n\n* [Tutorial Pola Dekorator](https://www.journaldev.com/1540/decorator-design-pattern-in-java-example)\n\n## Kegunaan yang diketahui\n\n * [java.io.InputStream](http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html), [java.io.OutputStream](http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html),\n [java.io.Reader](http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html) dan [java.io.Writer](http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html)\n * [java.util.Collections#synchronizedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedCollection-java.util.Collection-)\n * [java.util.Collections#unmodifiableXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableCollection-java.util.Collection-)\n * [java.util.Collections#checkedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedCollection-java.util.Collection-java.lang.Class-)\n\n\n## Kredit\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n"
  },
  {
    "path": "localization/it/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n\n# Modelli di progettazione in Java\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-233-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n<br/>\n\nLeggi in lingue diverse: [**it**](localization/it/README.md), [**zh**](localization/zh/README.md), [**ko**](localization/ko/README.md), [**fr**](localization/fr/README.md), [**tr**](localization/tr/README.md), [**ar**](localization/ar/README.md), [**es**](localization/es/README.md), [**pt**](localization/pt/README.md), [**id**](localization/id/README.md), [**ru**](localization/ru/README.md), [**de**](localization/de/README.md), [**ja**](localization/ja/README.md), [**vi**](localization/vi/README.md), [**bn**](localization/bn/README.md), [**np**](localization/np/README.md)\n<br/>\n\n# Introduzione\n\nI design patterns sono le migliori pratiche di programmazione che uno sviluppatore puó usare per\nrisolvere problemi durante il design di un'applicazione o di un sistema.\n\nI design patterns possono velocizzare lo sviluppo fornendo paradigmi di \nsviluppo testati e approvati.\n\nRiutilizzare i design patterns aiuta a prevenire problematiche che possono causare maggiori problemi, inoltre migliorano la leggibilità del codice per gli sviluppatori e ingegneri che hanno familiarità con questi patterns.\n\n# Come iniziare\n\nIl sito mostra i design patterns sviluppati utilizzando il linguaggio Java. Le soluzioni sono state \nsviluppate da programmatori e ingegneri esperti provenienti dalla community open-source. Questi patterns possono essere compresi attraverso descrizioni dettagliate o guardando\nil codice sorgente. Gli esempi di codice sono ben commentati e possono essere\nvisti come dei tutorial di programmazione su come implementare uno specifico pattern. Per fare ciò utiliziamo le migliori tecnologie open-source di Java.\n\nPrima di cimentarti nel materiale proposto, dovresti prima familiarizzare con i vari\n[Principi di Software Design](https://java-design-patterns.com/principles/).\n\nTutti i patterns dovrebbero essere i più semplici possibili. Ti consigliamo di cominiciare \ncon i principi KISS, YAGNI e Do The Simplest Thing That Could Possibly Work. Complessità\ne patterns dovrebbero essere introdotti solamente quando sono necessari per motivi pratici.\n\nQuando hai familiarizzato con questi concetti puoi cominciare a immergerti nei\n[design patterns disponibili](https://java-design-patterns.com/patterns/) utilizzando\nuno dei seguenti approcci:\n\n - Cercando uno specifico pattern tramite il nome. Non riesci a trovarlo? Allora comunicacelo [qui](https://github.com/iluwatar/java-design-patterns/issues).\n - Usando tags come `Performance`, `Gang of four` o `Data access`.\n - Usando categorie appartenenti ai patterns come `Creational`, `Behavioral`, etc.\n\nSperiamo che le soluzioni object-oriented mostrate ti siano utili per i tuoi progetti e che tu \nti diverta a impararle come abbiamo fatto noi nell' implementarle.\n\n# Come contribuire \n\nSe desideri contribuire al progetto puoi trovare le informazioni necessarie nella nostra pagina \n[wiki](https://github.com/iluwatar/java-design-patterns/wiki). Ti aiuteremo a rispondere a\nogni tua domanda nella [chatroom Gitter](https://gitter.im/iluwatar/java-design-patterns).\n\n# Licenza\n\nQuesto progetto è licanziato nei termini della licenza MIT.\n"
  },
  {
    "path": "localization/it/abstract-document/README.md",
    "content": "---\ntitle: Abstract Document\ncategory: Structural\nlanguage: it\ntag: \n - Extensibility\n---\n\n## Intento\n\nIl design pattern \"Abstract Document\" è un design pattern strutturale che mira a fornire un modo coerente per gestire strutture dati gerarchiche e ad albero, definendo un'interfaccia comune per vari tipi di documenti.\n\n## Spiegazione\n\nIl pattern Abstract Document consente di gestire proprietà aggiuntive e non statiche. Questo pattern utilizza il concetto di trait per consentire la sicurezza dei tipi e separare le proprietà delle diverse classi in un insieme di interfacce.\n\nEsempio del mondo reale\n\n>  Prendiamo ad esempio un'auto composta da diverse parti. Tuttavia, non sappiamo se l'auto ha tutte le parti o solo alcune di esse. Le nostre auto sono dinamiche ed estremamente flessibili.\n\nIn parole semplici\n\n> Il pattern Abstract Document permette di associare proprietà agli oggetti senza che gli oggetti ne siano a conoscenza.\n\nWikipedia dice\n\n> Un design pattern strutturale orientato agli oggetti per organizzare gli oggetti in archivi chiave-valore con\n> tipizzazione debole ed esporre i dati utilizzando viste tipizzate. Lo scopo del pattern è ottenere un alto grado di\n> flessibilità tra i componenti in un linguaggio fortemente tipizzato in cui nuove proprietà possono essere aggiunte\n> all'albero degli oggetti al volo, senza perdere il supporto della sicurezza dei tipi. Il pattern fa uso di trait per\n> separare diverse proprietà di una classe in diverse interfacce. Il termine \"documento\" è ispirato dai database\n> orientati ai documenti. _(Testo tradotto dalla voce Abstract Document Pattern da Wikipedia in lingua inglese)._\n\n**Esempio di codice**\n\nPer prima cosa definiamo le classi di base `Document` e `AbstractDocument`. Essenzialmente, queste classi fanno sì che l'oggetto contenga una mappa di proprietà e una qualunque quantità di oggetti figlio.\n\n```java\npublic interface Document {\n\n  Void put(String key, Object value);\n\n  Object get(String key);\n\n  <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);\n}\n\npublic abstract class AbstractDocument implements Document {\n\n  private final Map<String, Object> properties;\n\n  protected AbstractDocument(Map<String, Object> properties) {\n    Objects.requireNonNull(properties, \"properties map is required\");\n    this.properties = properties;\n  }\n\n  @Override\n  public Void put(String key, Object value) {\n    properties.put(key, value);\n    return null;\n  }\n\n  @Override\n  public Object get(String key) {\n    return properties.get(key);\n  }\n\n  @Override\n  public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {\n    return Stream.ofNullable(get(key))\n        .filter(Objects::nonNull)\n        .map(el -> (List<Map<String, Object>>) el)\n        .findAny()\n        .stream()\n        .flatMap(Collection::stream)\n        .map(constructor);\n  }\n  ...\n}\n```\nSuccessivamente definiamo un enum `Property` e un insieme di interfacce per tipo, prezzo, modello e parti. Questo ci permette di creare interfacce dall'aspetto statico per la nostra classe `Car`.\n\n```java\npublic enum Property {\n\n  PARTS, TYPE, PRICE, MODEL\n}\n\npublic interface HasType extends Document {\n\n  default Optional<String> getType() {\n    return Optional.ofNullable((String) get(Property.TYPE.toString()));\n  }\n}\n\npublic interface HasPrice extends Document {\n\n  default Optional<Number> getPrice() {\n    return Optional.ofNullable((Number) get(Property.PRICE.toString()));\n  }\n}\npublic interface HasModel extends Document {\n\n  default Optional<String> getModel() {\n    return Optional.ofNullable((String) get(Property.MODEL.toString()));\n  }\n}\n\npublic interface HasParts extends Document {\n\n  default Stream<Part> getParts() {\n    return children(Property.PARTS.toString(), Part::new);\n  }\n}\n```\n\nOra siamo pronti per introdurre la classe `Car`.\n\n```java\npublic class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {\n\n  public Car(Map<String, Object> properties) {\n    super(properties);\n  }\n}\n```\n\nE infine, costruiamo e usiamo la classe `Car` in un esempio completo.\n\n```java\n    LOGGER.info(\"Constructing parts and car\");\n\n    var wheelProperties = Map.of(\n        Property.TYPE.toString(), \"wheel\",\n        Property.MODEL.toString(), \"15C\",\n        Property.PRICE.toString(), 100L);\n\n    var doorProperties = Map.of(\n        Property.TYPE.toString(), \"door\",\n        Property.MODEL.toString(), \"Lambo\",\n        Property.PRICE.toString(), 300L);\n\n    var carProperties = Map.of(\n        Property.MODEL.toString(), \"300SL\",\n        Property.PRICE.toString(), 10000L,\n        Property.PARTS.toString(), List.of(wheelProperties, doorProperties));\n\n    var car = new Car(carProperties);\n\n    LOGGER.info(\"Here is our car:\");\n    LOGGER.info(\"-> model: {}\", car.getModel().orElseThrow());\n    LOGGER.info(\"-> price: {}\", car.getPrice().orElseThrow());\n    LOGGER.info(\"-> parts: \");\n    car.getParts().forEach(p -> LOGGER.info(\"\\t{}/{}/{}\",\n        p.getType().orElse(null),\n        p.getModel().orElse(null),\n        p.getPrice().orElse(null))\n    );\n\n    // Constructing parts and car\n    // Here is our car:\n    // model: 300SL\n    // price: 10000\n    // parts: \n    // wheel/15C/100\n    // door/Lambo/300\n```\n\n## Diagramma delle classi\n\n![alt text](../../../abstract-document/etc/abstract-document.png \"Abstract Document Traits and Domain\")\n\n## Applicabilità\n\nQuesto pattern è particolarmente utile in scenari in cui si hanno diversi tipi di documenti che condividono alcune proprietà o comportamenti comuni, ma hanno anche proprietà o comportamenti unici specifici per i rispettivi tipi. Ecco alcuni scenari in cui il pattern Abstract Document può essere applicabile:\n\n* Sistemi di Gestione dei Contenuti (CMS): In un CMS, potresti avere vari tipi di contenuti, come articoli, immagini, video, ecc. Ogni tipo di contenuto potrebbe condividere attributi comuni come la data di creazione, l'autore e i tag, ma potrebbe anche avere attributi specifici come le dimensioni dell'immagine per le immagini o la durata del video per i video.\n\n* File System: Se stai progettando un file system in cui è necessario gestire diversi tipi di file, come documenti, immagini, file audio e directory, il pattern Abstract Document può aiutare a fornire un modo coerente per accedere agli attributi come la dimensione del file, la data di creazione, ecc., consentendo allo stesso tempo attributi specifici come la risoluzione dell'immagine o la durata dell'audio.\n\n* Sistemi di E-commerce: Una piattaforma di e-commerce potrebbe avere diversi tipi di prodotti, come prodotti fisici, download digitali e abbonamenti. Ogni tipo potrebbe condividere attributi comuni come il nome, il prezzo e la descrizione, ma avere attributi unici come il peso di spedizione per i prodotti fisici o il link di download per i prodotti digitali.\n\n* Sistemi di Gestione delle Cartelle Cliniche: Nel settore sanitario, le cartelle cliniche dei pazienti potrebbero includere vari tipi di dati come dati demografici, storia clinica, risultati dei test e prescrizioni. Il pattern Abstract Document può aiutare a gestire attributi condivisi come l'ID del paziente e la data di nascita, consentendo allo stesso tempo di gestire attributi specializzati come i risultati dei test o le prescrizioni.\n\n* Gestione delle Configurazioni: Quando si tratta di impostazioni di configurazione per applicazioni software, possono esserci diversi tipi di elementi di configurazione, ciascuno con il proprio insieme di attributi. Il pattern Abstract Document può essere utilizzato per gestire questi elementi di configurazione, garantendo un modo coerente per accedere e manipolare i loro attributi.\n\n* Piattaforme Educative: I sistemi educativi potrebbero avere vari tipi di materiali didattici come contenuti basati su testo, video, quiz e compiti. Attributi comuni come il titolo, l'autore e la data di pubblicazione possono essere condivisi, mentre attributi unici come la durata del video o le scadenze degli esercizi possono essere specifici per ciascun tipo.\n\n* Strumenti di Gestione dei Progetti: Nelle applicazioni di gestione dei progetti, potresti avere diversi tipi di attività come attività specifiche, fasi e problemi. Il pattern Abstract Document potrebbe essere utilizzato per gestire attributi generali come il nome dell'attività specifica e l'assegnatario, consentendo allo stesso tempo attributi specifici come la data della fase o la priorità del problema.\n\nL'idea chiave alla base del design pattern Abstract Document è fornire un modo flessibile ed estensibile per gestire diversi tipi di documenti o entità con attributi comuni e distinti. Definendo un'interfaccia comune e implementandola in vari tipi di documenti, è possibile ottenere un approccio più organizzato e coerente alla gestione di strutture dati complesse.\n\n## Collegamenti esterni\n\n* [Wikipedia: Abstract Document Pattern](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)\n* [Martin Fowler: Dealing with properties](http://martinfowler.com/apsupp/properties.pdf)\n* [Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4)](https://www.amazon.com/gp/product/0470059028/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0470059028&linkId=e3aacaea7017258acf184f9f3283b492)"
  },
  {
    "path": "localization/it/abstract-factory/README.md",
    "content": "---\ntitle: Abstract Factory\ncategory: Creational\nlanguage: it\ntag:\n - Gang of Four\n---\n\n## Anche conosciuto come\n\nKit\n\n## Intento\n\nFornire un'interfaccia per la creazione di famiglie di oggetti correlati o dipendenti senza specificarne le classi concrete.\n\n## Spiegazione\n\nEsempio del mondo reale\n\n> Per creare un regno, abbiamo bisogno di oggetti con un tema comune. Il regno elfico ha bisogno di un re elfico, di un castello elfico e di un esercito elfico, mentre il regno degli orchi ha bisogno di un re degli orchi, di un castello degli orchi e di un esercito degli orchi. Esiste una dipendenza tra gli oggetti all'interno del regno.\n\nIn parole semplici\n\n> Una fabbrica di fabbriche; una fabbrica che raggruppa le singole fabbriche correlate o dipendenti senza specificare le loro classi concrete.\n\nWikipedia dice\n\n> L'Abstract Factory fornisce un'interfaccia per creare famiglie di oggetti connessi o dipendenti tra loro, in modo che non ci sia necessità da parte dei client di specificare i nomi delle classi concrete all'interno del proprio codice.\n\n**Esempio di codice**\n\nTraducendo l'esempio del regno sopra. Prima di tutto, abbiamo alcune interfacce e implementazioni per gli oggetti all'interno del regno.\n\n```java\npublic interface Castle {\n  String getDescription();\n}\n\npublic interface King {\n  String getDescription();\n}\n\npublic interface Army {\n  String getDescription();\n}\n\n// Elven implementations ->\npublic class ElfCastle implements Castle {\n  static final String DESCRIPTION = \"This is the elven castle!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfKing implements King {\n  static final String DESCRIPTION = \"This is the elven king!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfArmy implements Army {\n  static final String DESCRIPTION = \"This is the elven Army!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\n// Orcish implementations similarly -> ...\n\n```\n\nSuccessivamente, abbiamo l'astrazione e le implementazioni per la fabbrica del regno.\n\n```java\npublic interface KingdomFactory {\n  Castle createCastle();\n  King createKing();\n  Army createArmy();\n}\n\npublic class ElfKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new ElfCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new ElfKing();\n  }\n\n  @Override\n  public Army createArmy() {\n    return new ElfArmy();\n  }\n}\n\npublic class OrcKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new OrcCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new OrcKing();\n  }\n  \n  @Override\n  public Army createArmy() {\n    return new OrcArmy();\n  }\n}\n```\n\nOra abbiamo la fabbrica astratta che ci consente di creare una famiglia di oggetti correlati, ad esempio la fabbrica del regno elfico crea il castello elfico, il re elfico e l'esercito elfico, ecc.\n\n```java\nvar factory = new ElfKingdomFactory();\nvar castle = factory.createCastle();\nvar king = factory.createKing();\nvar army = factory.createArmy();\n\ncastle.getDescription();\nking.getDescription();\narmy.getDescription();\n```\n\nOutput del programma:\n\n```java\nThis is the elven castle!\nThis is the elven king!\nThis is the elven Army!\n```\n\nOra possiamo progettare una fabbrica per le nostre diverse fabbriche di regni. In questo esempio, abbiamo creato `FactoryMaker`, responsabile di restituire un'istanza di `ElfKingdomFactory` o `OrcKingdomFactory`.  \nIl client può utilizzare `FactoryMaker` per creare la fabbrica concreta desiderata, che a sua volta produrrà diversi oggetti concreti (derivati da `Army`, `King`, `Castle`).  \nIn questo esempio, abbiamo anche utilizzato un enum per parametrizzare il tipo di fabbrica di regno richiesto dal client.\n\n```java\npublic static class FactoryMaker {\n\n    public enum KingdomType {\n        ELF, ORC\n    }\n\n    public static KingdomFactory makeFactory(KingdomType type) {\n        return switch (type) {\n            case ELF -> new ElfKingdomFactory();\n            case ORC -> new OrcKingdomFactory();\n            default -> throw new IllegalArgumentException(\"KingdomType not supported.\");\n        };\n    }\n}\n\n    public static void main(String[] args) {\n        var app = new App();\n\n        LOGGER.info(\"Elf Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));\n        LOGGER.info(app.getArmy().getDescription());\n        LOGGER.info(app.getCastle().getDescription());\n        LOGGER.info(app.getKing().getDescription());\n\n        LOGGER.info(\"Orc Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));\n        --similar use of the orc factory\n    }\n```\n\n## Diagramma delle classi\n\n![alt text](../../../abstract-factory/etc/abstract-factory.urm.png \"Abstract Factory class diagram\")\n\n\n## Applicabilità\n\nUtilizza il pattern Abstract Factory quando\n\n* Il sistema deve essere indipendente dal modo in cui i suoi prodotti vengono creati, composti e rappresentati.\n* Il sistema deve essere configurato con una delle molteplici famiglie di prodotti.\n* La famiglia di oggetti di prodotto correlati è progettata per essere utilizzata interamente, e hai bisogno di imporre questo presupposto.\n* Vuoi fornire una libreria di classi di prodotto e vuoi esporre solo le loro interfacce, non le loro implementazioni.\n* Il tempo di vita della dipendenza è concettualmente più breve di quella del consumer.\n* Hai bisogno di un valore di runtime per costruire una particolare dipendenza.\n* Vuoi decidere quale prodotto chiamare da una famiglia a runtime.\n* Devi fornire uno o più parametri conosciuti solo a runtime prima di poter risolvere una dipendenza.\n* Hai bisogno di coerenza tra i prodotti.\n* Non vuoi modificare il codice esistente quando aggiungi nuovi prodotti o famiglie di prodotti al programma.\n\nEsempi di casi d'uso\t\n\n* Selezionare la chiamata all'implementazione appropriata di FileSystemAcmeService o DatabaseAcmeService o NetworkAcmeService in fase di esecuzione. \n* La scrittura di casi di unit test diventa molto più semplice. \n* Strumenti UI per diversi sistemi operativi.\n\n## Conseguenze\n\n* La dependency injection in Java nasconde le dipendenze delle classi di servizio, il che può portare a errori a runtime che sarebbero stati rilevati in fase di compilazione. \n* Se da un lato il pattern è ottimo per la creazione di oggetti predefiniti, l'aggiunta di nuovi oggetti potrebbe essere complicato. \n* Il codice diventa più complesso di quanto dovrebbe essere, poiché vengono introdotte molte nuove interfacce e classi insieme al pattern.\n\n## Tutorial\n\n* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java) \n\n## Usi noti\n\n* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)\n* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)\n* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)\n\n## Pattern correlati\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n\n## Collegamenti esterni\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/it/active-object/README.md",
    "content": "---\ntitle: Active Object\ncategory: Concurrency\nlanguage: it\ntag:\n - Performance\n---\n\n\n## Intento\nIl design pattern active object disaccoppia l'esecuzione del metodo dall'invocazione del metodo per gli oggetti che risiedono ciascuno nel proprio thread di controllo. L'obiettivo è introdurre la concorrenza utilizzando l'invocazione asincrona dei metodi e uno scheduler per gestire le richieste.\n\n## Spiegazione\n\nLa classe che implementa il pattern active object conterrà un meccanismo di autosincronizzazione senza utilizzare metodi 'synchronized'.\n\nEsempio del mondo reale\n\n>Gli Orchi sono noti per la loro natura selvaggia e la loro anima indomabile. Sembra che abbiano il loro proprio thread di controllo basato su comportamenti precedenti.\n\nPer implementare una creatura che ha il suo meccanismo di thread di controllo e che esponga solo la sua API e non l'esecuzione stessa, possiamo utilizzare il pattern Active Object.\n\n\n**Esempio di codice**\n\n```java\npublic abstract class ActiveCreature{\n  private final Logger logger = LoggerFactory.getLogger(ActiveCreature.class.getName());\n\n  private BlockingQueue<Runnable> requests;\n  \n  private String name;\n  \n  private Thread thread;\n\n  public ActiveCreature(String name) {\n    this.name = name;\n    this.requests = new LinkedBlockingQueue<Runnable>();\n    thread = new Thread(new Runnable() {\n        @Override\n        public void run() {\n          while (true) {\n            try {\n              requests.take().run();\n            } catch (InterruptedException e) { \n              logger.error(e.getMessage());\n            }\n          }\n        }\n      }\n    );\n    thread.start();\n  }\n  \n  public void eat() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} is eating!\",name());\n          logger.info(\"{} has finished eating!\",name());\n        }\n      }\n    );\n  }\n\n  public void roam() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} has started to roam the wastelands.\",name());\n        }\n      }\n    );\n  }\n  \n  public String name() {\n    return this.name;\n  }\n}\n```\n\nPossiamo vedere che qualsiasi classe che estenderà la classe ActiveCreature avrà il proprio thread di controllo per invocare ed eseguire i metodi.\n\nAd esempio, la classe Orc:\n\n```java\npublic class Orc extends ActiveCreature {\n\n  public Orc(String name) {\n    super(name);\n  }\n\n}\n```\n\nOra possiamo creare diverse creature come gli Orchi, dir loro di mangiare e vagabondare, e loro eseguiranno queste azioni nel proprio thread di controllo:\n\n```java\n  public static void main(String[] args) {  \n    var app = new App();\n    app.run();\n  }\n  \n  @Override\n  public void run() {\n    ActiveCreature creature;\n    try {\n      for (int i = 0;i < creatures;i++) {\n        creature = new Orc(Orc.class.getSimpleName().toString() + i);\n        creature.eat();\n        creature.roam();\n      }\n      Thread.sleep(1000);\n    } catch (InterruptedException e) {\n      logger.error(e.getMessage());\n    }\n    Runtime.getRuntime().exit(1);\n  }\n```\n\n## Diagramma delle classi\n\n![alt text](../../../active-object/etc/active-object.urm.png \"Active Object class diagram\")\n\n## Tutorial\n\n* [Android and Java Concurrency: The Active Object Pattern](https://www.youtube.com/watch?v=Cd8t2u5Qmvc)"
  },
  {
    "path": "localization/it/acyclic-visitor/README.md",
    "content": "---\ntitle: Acyclic Visitor\ncategory: Behavioral\nlanguage: it\ntag:\n - Extensibility\n---\n\n## Intento\n\nPermette di aggiungere nuove funzioni alle gerarchie di classi esistenti senza influire su tali gerarchie e senza creare i cicli di dipendenza problematici che sono intrinseci al pattern Visitor dei GoF.\n\n## Spiegazione\n\nEsempio del mondo reale\n\n> Abbiamo una gerarchia di classi di modem. I modem in questa gerarchia devono essere visitati da un algoritmo esterno basato su criteri di filtraggio (ad esempio, se si tratta di un modem compatibile con Unix o DOS).\n\nIn parole semplici\n\n> L'Acyclic Visitor consente di aggiungere funzioni alle gerarchie di classi esistenti senza modificarle.\n\n[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) dice\n\n>Il pattern Acyclic Visitor consente di aggiungere nuove funzioni alle gerarchie di classi esistenti senza influire su tali gerarchie e senza creare i cicli di dipendenza che sono intrinseci al pattern Visitor dei Gang of Four. _(Testo tradotto dalla voce Acyclic Visitor da WikiWikiWeb in lingua inglese)._\n\n**Esempio di codice**\n\nEcco la gerarchia delle classi `Modem`.\n\n```java\npublic abstract class Modem {\n  public abstract void accept(ModemVisitor modemVisitor);\n}\n\npublic class Zoom extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof ZoomVisitor) {\n      ((ZoomVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only ZoomVisitor is allowed to visit Zoom modem\");\n    }\n  }\n}\n\npublic class Hayes extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof HayesVisitor) {\n      ((HayesVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only HayesVisitor is allowed to visit Hayes modem\");\n    }\n  }\n}\n```\n\n\nSuccessivamente introduciamo la gerarchia delle classi `ModemVisitor`.\n\n```java\npublic interface ModemVisitor {\n}\n\npublic interface HayesVisitor extends ModemVisitor {\n  void visit(Hayes hayes);\n}\n\npublic interface ZoomVisitor extends ModemVisitor {\n  void visit(Zoom zoom);\n}\n\npublic interface AllModemVisitor extends ZoomVisitor, HayesVisitor {\n}\n\npublic class ConfigureForDosVisitor implements AllModemVisitor {\n  ...\n  @Override\n  public void visit(Hayes hayes) {\n    LOGGER.info(hayes + \" used with Dos configurator.\");\n  }\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Dos configurator.\");\n  }\n}\n\npublic class ConfigureForUnixVisitor implements ZoomVisitor {\n  ...\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Unix configurator.\");\n  }\n}\n```\n\nInfine, ecco i visitatori in azione.\n\n```java\n    var conUnix = new ConfigureForUnixVisitor();\n    var conDos = new ConfigureForDosVisitor();\n    var zoom = new Zoom();\n    var hayes = new Hayes();\n    hayes.accept(conDos);\n    zoom.accept(conDos);\n    hayes.accept(conUnix);\n    zoom.accept(conUnix);   \n```\n\nOutput del programma:\n\n```\n    // Hayes modem used with Dos configurator.\n    // Zoom modem used with Dos configurator.\n    // Only HayesVisitor is allowed to visit Hayes modem\n    // Zoom modem used with Unix configurator.\n```\n\n## Diagramma delle classi\n\n![alt text](../../../acyclic-visitor/etc/acyclic-visitor.png \"Acyclic Visitor\")\n\n## Applicabilità\n\nQuesto pattern può essere utilizzato nei seguenti casi:\n\n* Quando è necessario aggiungere una nuova funzione a una gerarchia esistente senza la necessità di modificarla o influenzarla. \n* Quando ci sono funzioni che operano su una gerarchia, ma che non appartengono alla gerarchia stessa, ad esempio, il problema di ConfigureForDOS / ConfigureForUnix / ConfigureForX. \n* Quando è necessario eseguire operazioni molto diverse su un oggetto a seconda del suo tipo.\n* Quando la gerarchia delle classi visitate sarà frequentemente estesa con nuovi derivati dalla classe Element.\n* Quando la ricompilazione, il relinking, il ritestare o la ridistribuzione dei derivati da Element è molto costoso.\n\n## Tutorial\n\n* [Acyclic Visitor Pattern Example](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html)\n\n## Conseguenze\n\nAspetti positivi:\n\n* Assenza di cicli di dipendenza tra le gerarchie di classi.\n* Non è necessario ricompilare tutti i visitatori se se ne aggiunge uno nuovo.\n* Non causa errori di compilazione nei visitatori esistenti se la gerarchia delle classi ha un nuovo membro.\n\nAspetti negativi:\n\n* Viola il [Principio di sostituzione di Liskov](https://java-design-patterns.com/principles/#liskov-substitution-principle) mostrando di poter accettare tutti i visitatori ma essendo solo interessato a visitatori specifici.\n* Deve essere creata una gerarchia parallela di visitatori per tutti i membri della gerarchia di classi visitabili.\n\n## Pattern correlati\n\n* [Visitor Pattern](https://java-design-patterns.com/patterns/visitor/)\n\n## Collegamenti esterni\n\n* [Acyclic Visitor by Robert C. Martin](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf)\n* [Acyclic Visitor in WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor)\n"
  },
  {
    "path": "localization/it/adapter/README.md",
    "content": "---\ntitle: Adapter\ncategory: Structural\nlanguage: it\ntag:\n - Gang of Four\n---\n\n## Anche conosciuto come\nWrapper\n\n## Intento\nConvertire l'interfaccia di una classe in un'altra interfaccia attesa dal cliente. Il pattern Adapter consente a classi di collaborare con altre classi con cui altrimenti non potrebbero farlo a causa di problemi di compatibilità.\n\n## Spiegazione\n\nEsempio del mondo reale\n\n> Immagina di avere delle immagini su una scheda di memoria e desideri trasferirle sul tuo computer. Per effettuare il trasferimento, hai bisogno di un tipo di adattatore compatibile con le porte del tuo computer, in modo da poter inserire la tua scheda. In questo caso, il lettore di schede è un adattatore (adapter).\n> Un altro esempio potrebbe essere l'ampiamente noto adattatore di corrente; una spina con tre pin non può essere collegata a una presa con due fori, è necessario un adattatore per renderla compatibile con la presa di corrente.\n> Un altro esempio sarebbe un traduttore simultaneo che traduce le parole pronunciate da una persona a un'altra.\n\nIn parole semplici\n\n> Il pattern Adapter permette di incapsulare un oggetto in un adattatore per renderlo compatibile con una classe con cui sarebbe altrimenti incompatibile.\n\nWikipedia dice\n\n> In ingegneria del software, il pattern Adapter è un design pattern del software che consente all'interfaccia di una classe esistente di essere utilizzata come un'altra interfaccia. Spesso viene utilizzato per far sì che classi esistenti possano collaborare con altre senza dover modificare il loro codice sorgente. _(Testo tradotto dalla voce Adapter Pattern da Wikipedia in lingua inglese)._\n\n**Esempio di codice**\n\nImmagina un capitano che sa utilizzare solo barche a remi e non sa navigare affatto.\n\nInnanzitutto, abbiamo le interfacce `RowingBoat` e `FishingBoat`\n\n```java\npublic interface RowingBoat {\n  void row();\n}\n\n@Slf4j\npublic class FishingBoat {\n  public void sail() {\n    LOGGER.info(\"The fishing boat is sailing\");\n  }\n}\n```\n\nE il capitano si aspetta che ci sia un'implementazione dell'interfaccia `RowingBoat` per potersi muovere.\n\n```java\npublic class Captain {\n\n  private final RowingBoat rowingBoat;\n  // default constructor and setter for rowingBoat\n  public Captain(RowingBoat rowingBoat) {\n    this.rowingBoat = rowingBoat;\n  }\n\n  public void row() {\n    rowingBoat.row();\n  }\n}\n```\n\nOra immaginiamo che i pirati stiano arrivando e il nostro capitano debba scappare, ma è disponibile solo una barca da pesca. Dobbiamo creare un adattatore che consenta al capitano di navigare con la barca da pesca con le sue abilità di saper utilizzare le barche a remi.\n```java\n@Slf4j\npublic class FishingBoatAdapter implements RowingBoat {\n\n  private final FishingBoat boat;\n\n  public FishingBoatAdapter() {\n    boat = new FishingBoat();\n  }\n\n  @Override\n  public void row() {\n    boat.sail();\n  }\n}\n```\n\nE ora il `Captain` può usare la `FishingBoat` per sfuggire ai pirati.\n\n```java\nvar captain = new Captain(new FishingBoatAdapter());\ncaptain.row();\n```\n\n## Diagramma delle classi\n![alt text](../../../adapter/etc/adapter.urm.png \"Adapter class diagram\")\n\n## Applicabilità\nUtilizza il pattern Adapter quando\n\n* Vuoi utilizzare una classe esistente, ma la sua interfaccia non corrisponde a quella di cui hai bisogno\n* Desideri creare una classe riutilizzabile che collabori con classi non correlate o non previste, ovvero classi che non necessariamente hanno interfacce compatibili.\n* Hai bisogno di utilizzare diverse sottoclassi esistenti, ma sarebbe impraticabile adattare la loro interfaccia mediante la creazione di sottoclassi per ognuna di esse. Un adapter può adattare l'interfaccia della sua classe padre.\n* Nella maggior parte delle applicazioni che utilizzano librerie di terze parti, si utilizzano adapter come strato intermedio tra l'applicazione e la libreria di terze parti per disaccoppiare l'applicazione dalla libreria stessa. Se è necessario utilizzare un'altra libreria, è sufficiente creare un nuovo adapter per la nuova libreria senza dover modificare il codice dell'applicazione.\n\n## Tutorial\n\n* [Dzone](https://dzone.com/articles/adapter-design-pattern-in-java)\n* [Refactoring Guru](https://refactoring.guru/design-patterns/adapter/java/example)\n* [Baeldung](https://www.baeldung.com/java-adapter-pattern)\n* [GeeksforGeeks](https://www.geeksforgeeks.org/adapter-pattern/)\n\n\n## Conseguenze\nGli adapter di classe e oggetti comportano scelte diverse. Un adapter di classe\n\n*   Effettua l'adattamento rimanendo legato a una classe adattata specifica. Di conseguenza, un adapter di classe non funzionerà quando desideriamo adattare una classe e le sue sottoclassi.\n*   Permette all'Adapater di modificare il comportamento della classe adattata perché l'adpater è una sottoclasse della classe adattata.  \n*   Utilizza un solo oggetto e non richiede l'uso di puntatori aggiuntivi per fare riferimento alla classe adattata.\n\nUn adapter di oggetto\t\n\n*   Permette a un singolo Adapter di lavorare con diverse classi adattate, ovvero con la classe adattata e tutte le sue sottoclassi (se ne ha). L'Adapter può anche aggiungere funzionalità a tutte le classi adattate contemporaneamente.\n*   Rende più complicata la modifica del comportamento della classe adattata. Sarebbe necessario creare una sottoclasse della classe da adattare e far sì che l'Adapter faccia riferimento alla sottoclasse anziché alla classe da adattare.\n\n## Esempi del mondo reale\n\n* [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)\n* [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)\n* [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-)\n* [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-)\n\n\n## Collegamenti esterni\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/it/iterator/README.md",
    "content": "---\ntitle: Iterator\ncategory: Behavioral\nlanguage: it\ntag:\n - Gang of Four\n---\n\n## Anche conosciuto come\n\nCursor\n\n## Intento\nFornire un modo per accedere agli elementi di un oggetto aggregato in modo sequenziale senza esporre la sua rappresentazione sottostante.\n\n## Spiegazione\n\nEsempio del mondo reale\n\n> Lo scrigno del tesoro contiene una serie di oggetti magici. Ci sono diversi tipi di oggetti, come anelli,\n> pozioni e armi. Gli oggetti possono essere esaminati per tipo utilizzando un iteratore fornito dalla cassa\n> del tesoro.\n\nIn parole semplici\n\n> I contenitori possono fornire un'interfaccia di iterazione agnostica alla rappresentazione per consentire l'accesso agli\n> elementi.\n\nWikipedia dice\n\n> Nella programmazione orientata agli oggetti, il pattern iterator è un design pattern in cui un iteratore viene\n> utilizzato per attraversare un contenitore e accedere agli elementi del contenitore stesso. _(Testo tradotto dalla voce Iterator Pattern da Wikipedia in lingua inglese)._\n\n**Esempio di codice**\n\nLa classe principale nel nostro esempio è `TreasureChest`, che contiene gli oggetti.\n\n```java\npublic class TreasureChest {\n\n  private final List<Item> items;\n\n  public TreasureChest() {\n    items = List.of(\n        new Item(ItemType.POTION, \"Potion of courage\"),\n        new Item(ItemType.RING, \"Ring of shadows\"),\n        new Item(ItemType.POTION, \"Potion of wisdom\"),\n        new Item(ItemType.POTION, \"Potion of blood\"),\n        new Item(ItemType.WEAPON, \"Sword of silver +1\"),\n        new Item(ItemType.POTION, \"Potion of rust\"),\n        new Item(ItemType.POTION, \"Potion of healing\"),\n        new Item(ItemType.RING, \"Ring of armor\"),\n        new Item(ItemType.WEAPON, \"Steel halberd\"),\n        new Item(ItemType.WEAPON, \"Dagger of poison\"));\n  }\n\n  public Iterator<Item> iterator(ItemType itemType) {\n    return new TreasureChestItemIterator(this, itemType);\n  }\n\n  public List<Item> getItems() {\n    return new ArrayList<>(items);\n  }\n}\n```\n\nEcco la classe `Item`:\n\n```java\npublic class Item {\n\n  private ItemType type;\n  private final String name;\n\n  public Item(ItemType type, String name) {\n    this.setType(type);\n    this.name = name;\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n\n  public ItemType getType() {\n    return type;\n  }\n\n  public final void setType(ItemType type) {\n    this.type = type;\n  }\n}\n\npublic enum ItemType {\n\n  ANY, WEAPON, RING, POTION\n\n}\n```\n\nL'interfaccia `Iterator` è estremamente semplice.\n\n```java\npublic interface Iterator<T> {\n\n  boolean hasNext();\n\n  T next();\n}\n```\n\nNell'esempio seguente, si iterano gli oggetti di tipo anello che si trovano nel forziere.\n\n```java\nvar itemIterator = TREASURE_CHEST.iterator(ItemType.RING);\nwhile (itemIterator.hasNext()) {\n  LOGGER.info(itemIterator.next().toString());\n}\n```\n\nOutput del programma:\n\n```java\nRing of shadows\nRing of armor\n```\n\n## Diagramma delle classi\n\n![alt text](../../../iterator/etc/iterator_1.png \"Iterator\")\n\n## Applicabilità\n\nUsa il pattern Iterator\n\n* Per accedere ai contenuti di un oggetto aggregato senza esporre la sua rappresentazione interna.\n* Per supportare più attraversamenti di oggetti aggregati.\n* Per fornire un'interfaccia uniforme per l'attraversamento di diverse strutture aggregate.\n\n## Tutorial\n\n* [How to Use Iterator?](http://www.tutorialspoint.com/java/java_using_iterator.htm)\n\n## Usi noti\n\n* [java.util.Iterator](http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html)\n* [java.util.Enumeration](http://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html)\n\n## Collegamenti esterni\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/it/observer/README.md",
    "content": "---\ntitle: Observer\ncategory: Behavioral\nlanguage: it\ntag:\n - Gang Of Four\n - Reactive\n---\n\n## Anche conosciuto come\n\nDependents, Publish-Subscribe\n\n## Intento\n\nStabilire una dipendenza uno-a-molti tra gli oggetti in modo che quando un oggetto cambia stato, tutti i suoi dipendenti vengano avvisati e aggiornati automaticamente.\n\n## Spiegazione\n\nEsempio del mondo reale\n\n> In una terra lontana vivono le razze degli hobbit e degli orchi. Entrambi trascorrono la maggior parte del tempo all'aperto, quindi\n> seguono attentamente i cambiamenti del tempo. Si potrebbe dire che osservano costantemente le\n> condizioni meteorologiche.\n\nIn parole semplici\n\n> Registrarsi come osservatore per ricevere notifiche di cambiamenti di stato nell'oggetto.\n\nWikipedia dice\n\n> Il pattern observer è un design pattern in cui un oggetto, chiamato soggetto,\n> mantiene una lista dei suoi dipendenti, chiamati osservatori, e li avvisa automaticamente di eventuali cambiamenti di stato,\n> di solito chiamando uno dei loro metodi. _(Testo tradotto dalla voce Observer Pattern da Wikipedia in lingua inglese)._\n\n**Esempio di codice**\n\nIniziamo introducendo l'interfaccia `WeatherObserver` e le nostre razze, `Orcs` e `Hobbits`.\n\n```java\npublic interface WeatherObserver {\n\n  void update(WeatherType currentWeather);\n}\n\n@Slf4j\npublic class Orcs implements WeatherObserver {\n\n  @Override\n  public void update(WeatherType currentWeather) {\n    LOGGER.info(\"The orcs are facing \" + currentWeather.getDescription() + \" weather now\");\n  }\n}\n\n@Slf4j\npublic class Hobbits implements WeatherObserver {\n\n  @Override\n  public void update(WeatherType currentWeather) {\n    switch (currentWeather) {\n      LOGGER.info(\"The hobbits are facing \" + currentWeather.getDescription() + \" weather now\");\n    }\n  }\n}\n```\n\nPoi c'è il `Weather` che cambia continuamente.\n\n```java\n@Slf4j\npublic class Weather {\n\n  private WeatherType currentWeather;\n  private final List<WeatherObserver> observers;\n\n  public Weather() {\n    observers = new ArrayList<>();\n    currentWeather = WeatherType.SUNNY;\n  }\n\n  public void addObserver(WeatherObserver obs) {\n    observers.add(obs);\n  }\n\n  public void removeObserver(WeatherObserver obs) {\n    observers.remove(obs);\n  }\n\n  /**\n   * Makes time pass for weather.\n   */\n  public void timePasses() {\n    var enumValues = WeatherType.values();\n    currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length];\n    LOGGER.info(\"The weather changed to {}.\", currentWeather);\n    notifyObservers();\n  }\n\n  private void notifyObservers() {\n    for (var obs : observers) {\n      obs.update(currentWeather);\n    }\n  }\n}\n```\n\nEcco l'esempio completo in azione.\n\n```java\n    var weather = new Weather();\n    weather.addObserver(new Orcs());\n    weather.addObserver(new Hobbits());\n    weather.timePasses();\n    weather.timePasses();\n    weather.timePasses();\n    weather.timePasses();\n```\n\nOutput del programma:\n\n```\nThe weather changed to rainy.\nThe orcs are facing rainy weather now\nThe hobbits are facing rainy weather now\nThe weather changed to windy.\nThe orcs are facing windy weather now\nThe hobbits are facing windy weather now\nThe weather changed to cold.\nThe orcs are facing cold weather now\nThe hobbits are facing cold weather now\nThe weather changed to sunny.\nThe orcs are facing sunny weather now\nThe hobbits are facing sunny weather now\n```\n\n## Diagramma delle classi\n\n![alt text](../../../observer/etc/observer.png \"Observer\")\n\n## Applicabilità\n\nUsa il pattern Observer in una qualsiasi delle seguenti situazioni:\n\n* Quando un'astrazione ha due aspetti, uno dipendente dall'altro. L'incapsulamento di questi aspetti in oggetti separati ti permette di variarli e riutilizzarli in modo indipendente.\n* Quando una modifica a un oggetto richiede la modifica di altri oggetti, e non sai quanti oggetti devono essere modificati.\n* Quando un oggetto dovrebbe essere in grado di avvisare altri oggetti senza fare presupposizioni su chi siano questi oggetti. In altre parole, non desideri che questi oggetti siano strettamente accoppiati.\n\n## Usi noti\n\n* [java.util.Observer](http://docs.oracle.com/javase/8/docs/api/java/util/Observer.html)\n* [java.util.EventListener](http://docs.oracle.com/javase/8/docs/api/java/util/EventListener.html)\n* [javax.servlet.http.HttpSessionBindingListener](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionBindingListener.html)\n* [RxJava](https://github.com/ReactiveX/RxJava)\n\n## Collegamenti esterni\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Java Generics and Collections](https://www.amazon.com/gp/product/0596527756/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596527756&linkCode=as2&tag=javadesignpat-20&linkId=246e5e2c26fe1c3ada6a70b15afcb195)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/ja/README.md",
    "content": "# Java で実装されたデザインパターン\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n\n[![All Contributors](https://img.shields.io/badge/all_contributors-185-orange.svg?style=flat-square)](#contributors-)\n\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n# はじめに\n\nデザインパターンとは、アプリケーションやシステムを設計する際によくある問題を解決するために、プログラマーが使用できる形式化された最良の手法です。\n\nデザインパターンは、テストされ、証明された開発パラダイムを提供することで、開発プロセスを高速化することができます。\n\nデザインパターンを再利用することで、大きな問題を引き起こす微妙な問題を防ぐことができます。\nまた、デザインパターンを熟知したコーダーやアーキテクトにとっても、コードの読みやすさが向上します。\n\n# はじめる\n\nこのサイトでは、Java のデザインパターンを紹介しています。\nこれらのソリューションは、オープンソースコミュニティの経験豊富なプログラマーやアーキテクトによって開発されています。\n\nパターンは、ハイレベルの説明またはソースコードを確認することで参照できます。\n\nソースコードの例はよくコメントされていて、特定のパターンをどのように実装するかを説明するプログラミングチュートリアルのようなものです。\n\n私たちは、最も一般的で実績のあるオープンソースの Java 技術を使用しています。\n\n資料に飛び込む前に、さまざまな[ソフトウェア設計の原則](https://java-design-patterns.com/principles/)に精通している必要があります。\n\nすべてのデザインは、可能な限りシンプルであるべきです。\n\nKISS(シンプルにしておけ!この間抜け)、YAGNI(機能は実際に必要となるまでは追加しないのがよい)、そして Do The Simplest Thing That Could Possibly Work(機能する可能性のある中で最もシンプルなことをする)の原則に基づいて設計を始めるべきです。\n\n複雑さやパターンは、実用的な拡張性が必要な場合にのみ導入すべきです。\n\nこれらの概念を理解した上で、以下のような方法で[デザインパターン](https://java-design-patterns.com/patterns/) を掘り下げていくことができます。\n\n- 特定のパターンを、パターン名で検索することができます。見つかない場合は、新しいパターンを[ここ](https://github.com/iluwatar/java-design-patterns/issues)で報告してください\n- `Performance`, `Gang of Four` もしくは`Data access`などのタグを使用。\n- `Creational`, `Behavioral`などのパターンカテゴリーを使用。\n\nこのサイトで紹介されているオブジェクト指向のソリューションが、あなたのアーキテクチャに役立ち、私たちが開発したように楽しく学ぶことができますように。\n\n# コントリビュート方法\n\nプロジェクトに貢献したいとお考えの方は、[開発者 wiki](https://github.com/iluwatar/java-design-patterns/wiki)に関連情報が掲載されています。\n\n私たちは、[Gitter チャットルーム](https://gitter.im/iluwatar/java-design-patterns)であなたの質問にお答えします。\n\n# ライセンス\n\nこのプロジェクトは、MIT ライセンスの条件の下でライセンスされています。\n\n"
  },
  {
    "path": "localization/ja/decorator/README.md",
    "content": "---\ntitle: Decorator\ncategory: Structural\nlanguage: ja\ntag:\n - Gang of Four\n - Extensibility\n---\n\n## 別名\n\nWrapper\n\n## 目的\n\nオブジェクトに責任を動的に追加する。\nDecorator パターンは、サブクラス化よりも柔軟な機能拡張方法を提供する。\n\n## 説明\n\n実世界の例\n\n> 近くの丘に住む怒ったトロールがいる。大抵は素手だが、たまに武器を持っている。トロールに武器を持たせるためには、新しいトロールを作る必要はなく、適切な武器を動的に装飾すればいい。\n\n分かりやすい説明\n\n> Decorator パターンを用いると、decorator クラスのオブジェクトにラップすることで、オブジェクトの振る舞いを実行時間で動的に変更することができる。\n\nWikipedia の説明\n\n> オブジェクト指向プログラミングにおいて、Decorator パターンは、同じクラスの別のオブジェクトの振る舞いに影響を与えることなく、静的もしくは動的に、個別のオブジェクトに振る舞いを加えることができるデザインパターンである。Decorator パターンは、単一責任の原則を遵守するためにしばしば便利である。なぜなら、クラスの機能性を変更せずに拡張することで、開放/閉鎖原則などの関心事の特異な分野を元に、クラスの間で機能性を分割することができるためである。\n\n**サンプルコード**\n\nトロールを例として使用する。まず、Troll のインターフェイスを実装する SimpleTroll クラスを作る。\n\n```java\npublic interface Troll {\n  void attack();\n  int getAttackPower();\n  void fleeBattle();\n}\n\n@Slf4j\npublic class SimpleTroll implements Troll {\n\n  @Override\n  public void attack() {\n    LOGGER.info(\"The troll tries to grab you!\");\n  }\n\n  @Override\n  public int getAttackPower() {\n    return 10;\n  }\n\n  @Override\n  public void fleeBattle() {\n    LOGGER.info(\"The troll shrieks in horror and runs away!\");\n  }\n}\n```\n\n次に、トロールに対してこん棒を追加する。decorator を使い、動的に追加することが可能である。\n\n```java\n@Slf4j\npublic class ClubbedTroll implements Troll {\n\n  private final Troll decorated;\n\n  public ClubbedTroll(Troll decorated) {\n    this.decorated = decorated;\n  }\n\n  @Override\n  public void attack() {\n    decorated.attack();\n    LOGGER.info(\"The troll swings at you with a club!\");\n  }\n\n  @Override\n  public int getAttackPower() {\n    return decorated.getAttackPower() + 10;\n  }\n\n  @Override\n  public void fleeBattle() {\n    decorated.fleeBattle();\n  }\n}\n```\n\n以下がトロールの動き。\n\n```java\n// simple troll\nLOGGER.info(\"A simple looking troll approaches.\");\nvar troll = new SimpleTroll();\ntroll.attack();\ntroll.fleeBattle();\nLOGGER.info(\"Simple troll power: {}.\\n\", troll.getAttackPower());\n\n// change the behavior of the simple troll by adding a decorator\nLOGGER.info(\"A troll with huge club surprises you.\");\nvar clubbedTroll = new ClubbedTroll(troll);\nclubbedTroll.attack();\nclubbedTroll.fleeBattle();\nLOGGER.info(\"Clubbed troll power: {}.\\n\", clubbedTroll.getAttackPower());\n```\n\nアウトプット\n\n```java\nA simple looking troll approaches.\nThe troll tries to grab you!\nThe troll shrieks in horror and runs away!\nSimple troll power: 10.\n\nA troll with huge club surprises you.\nThe troll tries to grab you!\nThe troll swings at you with a club!\nThe troll shrieks in horror and runs away!\nClubbed troll power: 20.\n```\n\n## クラス図\n\n![alt text](./etc/decorator.urm.png \"Decorator pattern class diagram\")\n\n## 適用可能性\n\n次のような場合に Decorator パターンを利用する。\n\n* 個々のオブジェクトに責任を動的、かつ透明に(すなわち、他のオブジェクトに影響を与えないように)追加する場合。\n* 責任を取りはずすことができるようにする場合。\n* サブクラス化による拡張が非現実的な場合。非常に多くの独立した拡張が起こり得ることがある。このような場合、サブクラス化により全ての組み合わせの拡張に対応しようとすると、莫大な数のサブクラスが必要になるだろう。また、クラス定義が隠蔽されている場合や入手できない場合にも、このパターンを利用できる。\n\n## チュートリアル\n\n* [Decorator Pattern Tutorial](https://www.journaldev.com/1540/decorator-design-pattern-in-java-example)\n\n## 使用例\n\n * [java.io.InputStream](http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html), [java.io.OutputStream](http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html),\n [java.io.Reader](http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html) and [java.io.Writer](http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html)\n * [java.util.Collections#synchronizedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedCollection-java.util.Collection-)\n * [java.util.Collections#unmodifiableXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableCollection-java.util.Collection-)\n * [java.util.Collections#checkedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedCollection-java.util.Collection-java.lang.Class-)\n\n\n## クレジット\n\n* [オブジェクト指向における再利用のためのデザインパターン](https://www.amazon.co.jp/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E5%86%8D%E5%88%A9%E7%94%A8%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3-%E3%82%A8%E3%83%AA%E3%83%83%E3%82%AF-%E3%82%AC%E3%83%B3%E3%83%9E/dp/4797311126)\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n"
  },
  {
    "path": "localization/ko/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n\n# 자바로 구현된 디자인 패턴\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-270-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n<br/>\n\n다른 언어로 읽기 : [**zh**](localization/zh/README.md), [**fr**](localization/fr/README.md), [**tr**](localization/tr/README.md), [**ar**](localization/ar/README.md), [**es**](localization/es/README.md), [**pt**](localization/pt/README.md), [**id**](localization/id/README.md), [**ru**](localization/ru/README.md), [**de**](localization/de/README.md), [**ja**](localization/ja/README.md), [**vi**](localization/vi/README.md), [**bn**](localization/bn/README.md), [**np**](localization/ne/README.md), [**it**](localization/it/README.md), [**da**](localization/da/README.md)\n\n<br />\n\n# 소개\n\n디자인 패턴은 개발자가 응용 프로그램이나 시스템을 디자인할 때 일반적인 문제를 해결하는 데 사용할 수 있는 가장 정석적인 방법입니다.\n\n디자인 패턴은 테스트되고 입증된 개발 패러다임을 제공하여 개발 프로세스 속도를 높일 수 있습니다.\n\n디자인 패턴을 사용하면 주요 문제를 유발하는 미묘한 이슈들을 방지하는 데 도움이 되며 또한 패턴에 익숙한 개발자와 아키텍트의 코드 가독성을 향상시킵니다.\n\n# 시작하기\n\n이 사이트는 Java 디자인 패턴을 설명합니다. 이 솔루션은 오픈 소스 커뮤니티의 경험이 많은 개발자와 설계자가 개발했습니다. 패턴이 높은 수준의 설명이나 소스 코드를 통해 찾아볼 수 있습니다. 소스 코드 예제는 잘 설명되어 있으며 특정 패턴을 구현하는 방법을 알려주는 프로그래밍 튜토리얼로 사용할 수 있습니다. 우리는 가장 널리 알려지고 실무에서 입증된 오픈 소스 Java 기술을 사용합니다.\n\n자료를 살펴보기 전에 다양한 [소프트웨어 설계 원칙](https://java-design-patterns.com/principles/)을 숙지해야 합니다.\n\n모든 디자인 패턴은 가능한 한 심플해야 합니다. 소프트웨어 개발의 KISS, YAGNI 원칙을 지켜야 하며, 문제를 해결할 수 있는 가장 심플한 일을 해야 합니다. 복잡한 디자인 패턴은 실용적이고 확장성을 위해 필요할 때만 도입되어야 합니다.\n\n이러한 개념에 익숙해지면 아래와 같은 방법으로 [사용 가능한 디자인 패턴](https://java-design-patterns.com/patterns/) 중 하나를 선택하여 문제를 해결할 수 있습니다.\n\n- 이름으로 특정 패턴을 검색합니다. 찾는 패턴이 없다면 [여기](https://github.com/iluwatar/java-design-patterns/issues)에서 새 패턴을 요청하세요.\n- `Performance`, `Gang of Four` 또는 `Data access` 등의 태그로 검색하세요.\n- `Creational`, `Behavioral` 등의 패턴 카테고리로 검색하세요.\n\n이 사이트에서 제공하는 객체 지향 솔루션이 여러분의 아키텍처에 유용하고 사용되고 우리가 개발 한 것만큼 재미있게 배우기를 바랍니다.\n\n# 기여하는 방법\n\n프로젝트에 기여할 의향이 있다면 [developer wiki](https://github.com/iluwatar/java-design-patterns/wiki)에서 관련 정보를 찾을 수 있습니다. [Gitter chatroom](https://gitter.im/iluwatar/java-design-patterns)에서 귀하를 돕고 질문에 답변해 드리겠습니다.\n\n# 특허\n\n이 프로젝트는 MIT 라이센스 조건에 따라 라이센스가 적용됩니다.\n\n"
  },
  {
    "path": "localization/ko/adapter/README.md",
    "content": "---\ntitle: Adapter\nshortTitle: Adapter\ncategory: Structural\nlanguage: ko\ntag:\n- Gang of Four\n---\n\n## 또한 ~으로 알려진\n\nWrapper\n\n## 의도\n\n클래스의 인터페이스를 클라이언트가 기대하는 다른 인터페이스로 변환합니다. adapter를 사용하면 호환되지 않는 인터페이스로 인해 같이 쓸 수 없는 클래스를 함께 작동 할 수 있습니다.\n\n## 설명\n\n예시\n\n> 메모리 카드에 몇 장의 사진이 있고 컴퓨터로 전송해야한다고 생각하십시오. 이들을 전송하려면 컴퓨터에 메모리 카드를 연결할 수 있도록 컴퓨터 포트와 호환되는 어댑터가 필요합니다. 이 경우 카드 리더는 어댑터입니다. 또 다른 예는 유명한 전원 어댑터입니다. 세 갈래 플러그는 두 갈래 콘센트에 연결할 수 없습니다. 두 갈래 콘센트와 호환되는 전원 어댑터를 사용해야합니다. 또 다른 예는 한 사람이 말한 단어를 다른 사람에게 번역하는 번역가입니다.\n\n평범하게 말하자면\n\n> adapter 패턴을 사용하면 호환되지 않는 개체를 adapter에 연결하여 다른 클래스와 호환되도록 할 수 있습니다.\n\nWikipedia 말에 의하면\n\n> 소프트웨어 엔지니어링에서 adapter 패턴은 기존 클래스의 인터페이스를 다른 인터페이스로 사용할 수 있도록 하는 소프트웨어 디자인 패턴입니다. 소스 코드를 수정하지 않고 기존 클래스가 다른 클래스와 함께 작동하도록 만드는 데 자주 사용됩니다.\n\n**프로그램 코드 예제**\n\n조정 보트만 사용할 수 있고 전혀 항해할 수 없는 선장을 생각해보십시오.\n\n먼저 `RowingBoat` 및 `FishingBoat` 인터페이스가 있습니다.\n\n```java\npublic interface RowingBoat {\n  void row();\n}\n\npublic class FishingBoat {\n  private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoat.class);\n  public void sail() {\n    LOGGER.info(\"The fishing boat is sailing\");\n  }\n}\n```\n\n그리고 선장은 `RowingBoat` 인터페이스를 이동할 수 있게 구현했습니다.\n\n```java\npublic class Captain {\n\n  private final RowingBoat rowingBoat;\n  // default constructor and setter for rowingBoat\n  public Captain(RowingBoat rowingBoat) {\n    this.rowingBoat = rowingBoat;\n  }\n\n  public void row() {\n    rowingBoat.row();\n  }\n}\n```\n\n이제 해적이오고 있고 우리 선장이 탈출해야하는데 어선만 있습니다. 선장이 조정 보트 기술로 어선을 조작 할 수있는 adapter를 만들어야합니다.\n\n```java\npublic class FishingBoatAdapter implements RowingBoat {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(FishingBoatAdapter.class);\n\n  private final FishingBoat boat;\n\n  public FishingBoatAdapter() {\n    boat = new FishingBoat();\n  }\n\n  @Override\n  public void row() {\n    boat.sail();\n  }\n}\n```\n\n이제 `Captain` 은 `FishingBoat` 를 사용하여 해적을 탈출 할 수 있습니다.\n\n```java\nvar captain = new Captain(new FishingBoatAdapter());\ncaptain.row();\n```\n\n## 클레스 다이어그램\n\n![alt text](./etc/adapter.urm.png)\n\n## 적용 가능성\n\n다음과 같은 경우 adapter 패턴을 사용합니다.\n\n- 기존 클래스를 사용 하려는데 해당 인터페이스가 필요한 클래스와 일치하지 않습니다.\n- 관련이 없거나 예상치 못한 클래스, 즉 호환되는 인터페이스가 반드시 필요하지 않은 클래스와 협력하는 재사용 가능한 클래스를 만들고 싶습니다.\n- 기존의 여러 하위 클래스를 사용해야하지만 모든 하위 클래스를 하위 클래스로 지정하여 인터페이스를 조정하는 것은 비현실적입니다. 개체 adapter는 부모 클래스의 인터페이스를 조정할 수 있습니다.\n- 타사 라이브러리를 사용하는 대부분의 응용 프로그램은 adapter를 응용 프로그램과 타사 라이브러리 사이의 중간 계층으로 사용하여 라이브러리에서 응용 프로그램을 분리합니다. 다른 라이브러리를 사용해야하는 경우 애플리케이션 코드를 변경할 필요없이 새 라이브러리 용 adapter만 필요합니다.\n\n## 결과 :\n\n클래스 및 개체 adapter에는 서로 다른 장단점이 있습니다. <br>클래스 adapter\n\n- 구체적인 Adaptee 클래스를 커밋하여 Adaptee를 Target에 적용합니다. 결과적으로 클래스와 모든 하위 클래스를 조정하려는 경우 클래스 adapter가 작동하지 않습니다.\n- adapter는 Adaptee의 하위 클래스이기 때문에 Adaptee의 일부 동작을 오버라이드합니다.\n- 하나의 객체만 생성하고 adaptee를 얻기위해 위해 추가 포인터 간접 지정이 필요하지 않습니다.\n\n개체 adapter\n\n- 하나의 adapter가 많은 Adaptees, 즉 Adaptee 자체와 모든 하위 클래스 (있는 경우)와 함께 작동하도록합시다. adapter는 한 번에 모든 어댑터에 기능을 추가 할 수도 있습니다.\n- Adaptee 동작을 오버라이드하기가 더 어렵습니다. Adaptee를 서브 클래싱하고 어댑터가 Adaptee 자체가 아닌 서브 클래스를 참조하도록 해야합니다.\n\n## 실제 사례\n\n- [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)\n- [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)\n- [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-)\n- [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-)\n\n## 크레딧\n\n- [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n- [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n- [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n- [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/ko/builder/README.md",
    "content": "---\ntitle: Builder\nshortTitle: Builder\ncategory: Creational\nlanguage: ko\ntag:\n- Gang of Four\n---\n\n## 의도 \n\n동일한 구성 프로세스가 다른 표현을 생성할 수 있도록 복잡한 객체의 구성을 해당 표현과 분리합니다.\n\n## 설명\n\n실제 예제\n\n> 롤플레잉 게임의 캐릭터 생성기를 상상해 보세요. 가장 쉬운 옵션은 컴퓨터가 사용자를 위해 문자를 만들도록 하는 것입니다. 직업, 성별, 머리색 등 캐릭터 세부 정보를 수동으로 선택하려면 캐릭터 생성은 모든 선택이 준비되었을 때 완료되는 단계별 프로세스가 됩니다.\n\n쉽게 말하자면\n\n> 생성자의 오염을 방지하면서 객체의 다른 맛들을 만들 수 있습니다. 여러 가지 맛의 객체가 있을 때 유용합니다. 또는 개체를 만드는 데 많은 단계가 수반될 때 유용합니다.\n\nWikipedia에 의하면\n\n> 빌더 패턴은 점층적 생성자 안티-패턴(telescoping constructor anti-pattern)에 대한 해결책을 찾기 위한 목적을 가진 객체 생성 소프트웨어 디자인 패턴이다.\n\n그렇긴 하지만, 점층적 생성자 안티-패턴(telescoping constructor anti-pattern)이 무엇인지 조금 더 설명하겠습니다. 어느 시점에서, 우리는 모두 다음과 같은 생성자를 보았습니다.\n\n```java\npublic Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) {\n}\n```\n\n보시다시피 생성자 매개 변수의 수는 빠르게 감당할 수 없게 되고 매개 변수의 배치를 이해하는 것이 어려워질 수 있습니다. 또한 이 매개 변수 목록은 나중에 더 많은 옵션을 추가하려는 경우 계속 증가할 수 있습니다. 이를 점층적 생성자 안티-패턴(telescoping constructor anti-pattern)이라고 합니다.\n\n**코드 예제**\n\n올바른 대안은 빌더 패턴을 사용하는 것입니다. 우선, 우리는 우리가 창조하고 싶은 영웅을 가지고 있습니다. :\n\n\n```java\npublic final class Hero {\n  private final Profession profession;\n  private final String name;\n  private final HairType hairType;\n  private final HairColor hairColor;\n  private final Armor armor;\n  private final Weapon weapon;\n\n  private Hero(Builder builder) {\n    this.profession = builder.profession;\n    this.name = builder.name;\n    this.hairColor = builder.hairColor;\n    this.hairType = builder.hairType;\n    this.weapon = builder.weapon;\n    this.armor = builder.armor;\n  }\n}\n```\n\n그리고 우리는 빌더를 가지고 있습니다. :\n\n```java\n  public static class Builder {\n    private final Profession profession;\n    private final String name;\n    private HairType hairType;\n    private HairColor hairColor;\n    private Armor armor;\n    private Weapon weapon;\n\n    public Builder(Profession profession, String name) {\n      if (profession == null || name == null) {\n        throw new IllegalArgumentException(\"profession and name can not be null\");\n      }\n      this.profession = profession;\n      this.name = name;\n    }\n\n    public Builder withHairType(HairType hairType) {\n      this.hairType = hairType;\n      return this;\n    }\n\n    public Builder withHairColor(HairColor hairColor) {\n      this.hairColor = hairColor;\n      return this;\n    }\n\n    public Builder withArmor(Armor armor) {\n      this.armor = armor;\n      return this;\n    }\n\n    public Builder withWeapon(Weapon weapon) {\n      this.weapon = weapon;\n      return this;\n    }\n\n    public Hero build() {\n      return new Hero(this);\n    }\n  }\n```\n\n그런 다음, 다음과 같이 사용할 수 있습니다.\n\n\n```java\nvar mage = new Hero.Builder(Profession.MAGE, \"Riobard\").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();\n```\n\n## 클래스 다이어그램\n\n![alt text](./etc/builder.urm.png \"Builder class diagram\")\n\n## 적용 가능성\n\n다음과 같은 경우 빌더 패턴을 사용합니다.\n\n* 복잡한 객체를 만드는 알고리즘은 객체를 구성하는 부품과 이들이 조립되는 방법에 독립적이어야 한다.\n* 구축 프로세스는 구성된 객체에 대해 서로 다른 표현을 허용해야 합니다.\n\n## 튜토리얼\n\n* [Refactoring Guru](https://refactoring.guru/design-patterns/builder)\n* [Oracle Blog](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java)\n* [Journal Dev](https://www.journaldev.com/1425/builder-design-pattern-in-java)\n\n## 실제 사례\n\n* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)\n* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) as well as similar buffers such as FloatBuffer, IntBuffer and so on.\n* [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-)\n* All implementations of [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)\n* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)\n* [Apache Commons Option.Builder](https://commons.apache.org/proper/commons-cli/apidocs/org/apache/commons/cli/Option.Builder.html)\n\n## 크레딧\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/ko/callback/README.md",
    "content": "---  \ntitle: Callback  \nshortTitle: Callback  \ncategory: Idiom  \nlanguage: ko  \ntag:\n- Reactive\n---  \n\n## 의도\n\n콜백은 다른 코드에 인자로 넘어가는 실행 가능한 코드의 일부로, 인자는 적절한 시점에 다시 호출 (실행) 된다.\n\n## 설명\n\n실제 예제\n\n> 실행 항목이 완료되었다는 사실을 고지받아야 할 때, 콜백 함수를 실행 항목을 담당하는 함수에게 넘겨주고 다시 호출할 때까지 기다린다.\n\n명확하게는\n\n> 콜백은 실행 함수에 넘겨져서 정의된 순간에 호출되는 함수이다.\n\n위키피디아의 정의는\n\n> 컴퓨터 프로그래밍에서, \"사후-호출\" 함수로도 알려진 콜백은, 다른 코드에 인자로 넘겨지는 실행 가능한 코드를 말한다;  \n> 다른 코드는 정해진 시간에 인자를 다시 호출 (실행) 할 것으로 기대되어진다.\n\n**코드 예제**\n\n콜백은 하나의 메서드를 가지고 있는 단순한 인터페이스이다.\n\n```java  \npublic interface Callback {  \n  \n  void call();}  \n```  \n\n다음으로 작업의 실행이 끝나고 나서 콜백을 실행시킬 Task 클래스를 정의한다.\n\n```java  \npublic abstract class Task {  \n  \n  final void executeWith(Callback callback) {    execute();    Optional.ofNullable(callback).ifPresent(Callback::call);  }  \n  public abstract void execute();}  \n  \n@Slf4j  \npublic final class SimpleTask extends Task {  \n  \n  @Override  public void execute() {    LOGGER.info(\"우선순위의 작업을 마친 이후 콜백 메서드를 호출한다.\");  \n  }}  \n```  \n\n마지막으로, 다음은 작업을 실행한 후 마쳤을 때 콜백을 받는 방법의 예시이다.\n\n```java  \n    var task = new SimpleTask();    task.executeWith(() -> LOGGER.info(\"완료되었음.\"));  \n```  \n\n## 클래스 다이어그램\n\n![alt text](./etc/callback.png \"callback\")\n\n## 적용\n\n콜백 패턴을 사용할 수 있을 때는\n\n* 동기 또는 비동기적인 임의의 행위가 정의된 어떠한 행위의 실행 이후에 수행되어야 할 때이다.\n\n## 실질적인 예시들\n\n* [CyclicBarrier](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29) 생성자는 장벽이 넘어질 때마다 발동되는 콜백을 인자로 받을 수 있다."
  },
  {
    "path": "localization/ko/decorater/README.md",
    "content": "---\ntitle: Decorator\nshortTitle: Decorator\ncategory: Structural\nlanguage: en\ntag:\n - Gang of Four\n - Extensibility\n---\n\n## ~로 알려져 있는\n\nWrapper\n\n## 의도\n\n객체에 동적으로 추가적인 책임을 부여합니다. 데코레이터(Decorater)는 기능 확장을 위한 서브 클래스를 만드는 것의\n유연한 대안을 제공합니다.\n\n## 설명\n\n실제 예제\n\n> 근처 언덕에 성난 트롤이 살고 있습니다. 보통은 맨손으로 다니지만 가끔씩은 무기를 가지고 있습니다.\n> 트롤을 무장시키기 위해 새로운 트롤을 만들 필요 없이 적절한 무기로 트롤을 장식(decorate)하면 됩니다.\n\n쉽게 설명하면\n\n> 데코레이터(Decorator) 패턴은 객체를 데코레이터(Decorater) 클래스의 객체로 감싸 런타임 시, \n> 객체의 동작을 동적으로 변경할 수 있도록 합니다.\n\nWikipedia에 의하면\n\n> 객체 지향 프로그래밍에서, 데코레이터(Decorater)은 다음과 같은 동작을 허용하는 디자인 패턴입니다.\n> 정적, 동적 상관없이 개별 객체에 동작을 추가할 수 있는 디자인 패턴입니다.\n> 동작에 영향을 주지 않고 개별 객체에 동작을 추가할 수 있는 디자인 패턴입니다.\n> 데코레이터(Decorater) 패턴은 종종 단일 책임 원칙(SRP)을 준수하는데 유용합니다.\n> 고유한 관심 영역을 가진 클래스 간에 기능을 나눌 수 있기 때문에 개방 폐쇄 원칙(OCP)를 준수하는데 유용합니다.\n> 클래스의 기능을 수정하지 않고 확장할 수 있기 때문입니다.\n\n**프로그램 코드 예제**\n\n트롤을 예로 들어보겠습니다. 먼저, 'Troll' 인터페이스를 구현하는 'SimpleTroll'이 있습니다.\n\n```java\npublic interface Troll {\n  void attack();\n  int getAttackPower();\n  void fleeBattle();\n}\n\n@Slf4j\npublic class SimpleTroll implements Troll {\n\n  @Override\n  public void attack() {\n    LOGGER.info(\"The troll tries to grab you!\");\n  }\n\n  @Override\n  public int getAttackPower() {\n    return 10;\n  }\n\n  @Override\n  public void fleeBattle() {\n    LOGGER.info(\"The troll shrieks in horror and runs away!\");\n  }\n}\n```\n\n다음으로, 트롤을 위한 곤봉을 추가하겠습니다. 데코레이터(Decorater)를 사용해 동적으로 추가할 수 있습니다.\n\n```java\n@Slf4j\npublic class ClubbedTroll implements Troll {\n\n  private final Troll decorated;\n\n  public ClubbedTroll(Troll decorated) {\n    this.decorated = decorated;\n  }\n\n  @Override\n  public void attack() {\n    decorated.attack();\n    LOGGER.info(\"The troll swings at you with a club!\");\n  }\n\n  @Override\n  public int getAttackPower() {\n    return decorated.getAttackPower() + 10;\n  }\n\n  @Override\n  public void fleeBattle() {\n    decorated.fleeBattle();\n  }\n}\n```\n\n트롤이 실제로 동작하는 모습입니다.\n\n```java\n// simple troll\nLOGGER.info(\"A simple looking troll approaches.\");\nvar troll = new SimpleTroll();\ntroll.attack();\ntroll.fleeBattle();\nLOGGER.info(\"Simple troll power: {}.\\n\", troll.getAttackPower());\n\n// change the behavior of the simple troll by adding a decorator\nLOGGER.info(\"A troll with huge club surprises you.\");\nvar clubbedTroll = new ClubbedTroll(troll);\nclubbedTroll.attack();\nclubbedTroll.fleeBattle();\nLOGGER.info(\"Clubbed troll power: {}.\\n\", clubbedTroll.getAttackPower());\n```\n\n프로그램 실행 결과:\n\n```java\nA simple looking troll approaches.\nThe troll tries to grab you!\nThe troll shrieks in horror and runs away!\nSimple troll power: 10.\n\nA troll with huge club surprises you.\nThe troll tries to grab you!\nThe troll swings at you with a club!\nThe troll shrieks in horror and runs away!\nClubbed troll power: 20.\n```\n\n## 클래스 다이어그램\n\n![alt text](./etc/decorator.urm.png \"Decorator pattern class diagram\")\n\n## 적용 가능성\n\n다음과 같은 경우 데코레이터(Decorator) 패턴을 사용합니다.:\n\n* 다른 객체에 영향을 주지 않으면서 개별 객체에 동적으로 투명하게 책임을 추가할 수 있습니다.\n* 철회될 수 있는 책임들의 경우에 사용합니다.\n* 서브클래스를 통한 확장이 실용적이지 않을 경우에 사용합니다. 때로 많은 수의 독립적인 확장은 모든 조합을 지원하기 위해 서브클래스가 폭발적으로 늘어날 수 있습니다.\n  또는 클래스 정의가 숨겨져 있거나 서브클래스 생성이 불가능한 경우에 사용합니다.\n\n## 튜토리얼\n\n* [Decorator Pattern Tutorial](https://www.journaldev.com/1540/decorator-design-pattern-in-java-example)\n\n## 실제 사례\n\n * [java.io.InputStream](http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html), [java.io.OutputStream](http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html),\n [java.io.Reader](http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html), [java.io.Writer](http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html)\n * [java.util.Collections#synchronizedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedCollection-java.util.Collection-)\n * [java.util.Collections#unmodifiableXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableCollection-java.util.Collection-)\n * [java.util.Collections#checkedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedCollection-java.util.Collection-java.lang.Class-)\n\n\n## 크레딧\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n"
  },
  {
    "path": "localization/ko/event-driven-architecture/README.md",
    "content": "---\ntitle: Event Driven Architecture\nshortTitle: Event Driven Architecture\ncategory: Architectural\nlanguage: ko\ntag:\n- Reactive\n---\n\n## 의도\n이벤트 드리븐 아키텍처를 사용하는 다른 어플리케이션에 특정 객체의 상태 변화를 알리고 관련 이벤트를 발송할 수 있습니다.\n\n## 클래스 다이어그램\n![alt text](./etc/eda.png \"Event Driven Architecture\")\n\n## 적용 가능성\n아래와 같은 상황에서 이벤트 드리븐 아키텍처를 사용할 수 있습니다.\n\n* 느슨하게 연결된 시스템을 구축하고자 하는 경우\n* 반응형 시스템을 구축하고자 하는 경우\n* 확장성을 갖춘 시스템을 구축하고자 하는 경우\n\n## 실제 적용 사례\n\n* Chargify라는 결제 API에서는 다양한 이벤트를 통해 결제 활동을 드러냅니다. (https://docs.chargify.com/api-events)\n* Amazon의 AWS Lambda에서는 Amazon S3 버킷에서의 변경, Amazon DynamoDB 테이블에서의 수정이나 어플리케이션 및 기기에서 발생한 커스텀 이벤트에 대응하여 코드를 실행할 수 있습니다. (https://aws.amazon.com/lambda)\n* MySQL은 데이터베이스 테이블에서 발생하는 삽입이나 수정 이벤트를 기반으로 트리거를 실행합니다.\n\n## 크레딧\n\n* [이벤트 드리븐 아키텍처 - 위키피디아](https://en.wikipedia.org/wiki/Event-driven_architecture)\n* [이벤트 드리븐 아키텍처는 무엇인가?](https://aws.amazon.com/event-driven-architecture/)\n* [실제 적용 사례/이벤트 드리븐 아키텍처](https://wiki.haskell.org/Real_World_Applications/Event_Driven_Applications)\n* [이벤트 드리븐 아키텍처의 정의](http://searchsoa.techtarget.com/definition/event-driven-architecture)\n"
  },
  {
    "path": "localization/ko/event-sourcing/README.md",
    "content": "---\ntitle: Event Sourcing\nshortTitle: Event Sourcing\ncategory: Architectural\nlanguage: ko\ntag:\n- Performance\n- Cloud distributed\n\n---\n\n## 의도\n\n데이터의 현재 상태만 도메인에 저장하는 대신, 추가 전용 저장소를 사용하여 해당 데이터에 수행된 전체 작업을 기록하십시오. 저장소는 기록 시스템으로서의 역할을 하며 도메인 객체를 구체화하는데 사용할 수 있습니다. 따라서 데이터 모델과 비지니스 도메인을 동기화할 필요가 없고 성능, 확장성 및 응답성이 향상되어 복잡한 도메인에서의 작업을 단순화할 수 있습니다.\n또한, 트랜잭션 데이터에 대한 일관성을 제공하고, 보상 작업을 수행할 수 있는 전체 감사용 기록과 히스토리를 유지 관리할 수 있습니다.\n\n## 클래스 다이어그램\n\n![alt text](./etc/event-sourcing.png \"Event Sourcing\")\n\n## 적용 가능성\n아래와 같은 상황에서 이벤트 소싱 패턴을 사용할 수 있습니다.\n\n* 관계형 데이터 구조가 복잡한 어플리케이션 상태를 유지하기 위해 매우 높은 성능이 필요한 경우\n* 어플리케이션 상태의 변경 사항과 특정 시점의 상태를 복원할 수 있는 기능에 대한 로그가 필요한 경우\n* 과거에 발생한 이벤트를 다시 적용하여 프로덕션 문제를 디버깅하는 경우\n\n## 실제 적용 사례\n\n* [Lmax 아키텍처](https://martinfowler.com/articles/lmax.html)\n\n## 크레딧\n\n* [마틴 파울러 - 이벤트 소싱](https://martinfowler.com/eaaDev/EventSourcing.html)\n* [이벤트 소싱에 대한 마이크로소프트의 문서](https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing)\n* [레퍼런스 3: 이벤트 소싱에 대한 소개](https://msdn.microsoft.com/en-us/library/jj591559.aspx)\n* [이벤트 소싱 패턴](https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing)\n"
  },
  {
    "path": "localization/ko/facade/README.md",
    "content": "---\ntitle: Facade\nshortTitle: Facade\ncategory: Structural\nlanguage: ko\ntag:\n - Gang Of Four\n - Decoupling\n---\n\n## 의도\n\n하위 시스템의 인터페이스 집합에 통합 인터페이스를 제공합니다. 퍼싸드(Facade)는 상위 레벨을 정의합니다.\n하위시스템을 보다 쉽게 사용할 수 있는 인터페이스.\n\n## 설명\n\n실제 예제\n\n> 금광은 어떻게 운영되나요? \"광부들이 저 아래로 내려가서 금을 캐죠\" 라고 당신은 말합니다.\n> 당신은 금광이 외부에 제공하는 간단한 인터페이스를 사용하고 있기 때문에 그렇게 믿습니다.\n> 그러나 내부적으로는 많은 작업을 수행해야 합니다. 복잡한 하위 시스템에 대한 이 간단한 인터페이스는\n> 퍼싸드(Facade)입니다.\n\n쉽게 말하자면\n\n> 퍼싸드(Facade) 패턴은 복잡한 하위 시스템에 대한 간소화된 인터페이스를 제공합니다.\n\nWikipedia에 의하면\n\n> 퍼싸드(Facade)는 클래스 라이브러리와 같은 더 큰 코드 본운에 간단한 인터페이스를 제공하는 객체입니다.\n\n**코드 예제**\n\n위의 금광을 예로 들어 보겠습니다. 여기에는 드워프 광산 작업자 계층 구조가 있습니다.\n먼저, 베이스 클래스 `DwarvenMineWorker`가 있습니다.:\n\n```java\n\n@Slf4j\npublic abstract class DwarvenMineWorker {\n\n    public void goToSleep() {\n        LOGGER.info(\"{} goes to sleep.\", name());\n    }\n\n    public void wakeUp() {\n        LOGGER.info(\"{} wakes up.\", name());\n    }\n\n    public void goHome() {\n        LOGGER.info(\"{} goes home.\", name());\n    }\n\n    public void goToMine() {\n        LOGGER.info(\"{} goes to the mine.\", name());\n    }\n\n    private void action(Action action) {\n        switch (action) {\n            case GO_TO_SLEEP -> goToSleep();\n            case WAKE_UP -> wakeUp();\n            case GO_HOME -> goHome();\n            case GO_TO_MINE -> goToMine();\n            case WORK -> work();\n            default -> LOGGER.info(\"Undefined action\");\n        }\n    }\n\n    public void action(Action... actions) {\n        Arrays.stream(actions).forEach(this::action);\n    }\n\n    public abstract void work();\n\n    public abstract String name();\n\n    enum Action {\n        GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK\n    }\n}\n```\n\n그 다음 구체적인 드워프 클래스인  `DwarvenTunnelDigger`, `DwarvenGoldDigger` 와\n`DwarvenCartOperator` 입니다:\n\n```java\n@Slf4j\npublic class DwarvenTunnelDigger extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} creates another promising tunnel.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarven tunnel digger\";\n  }\n}\n\n@Slf4j\npublic class DwarvenGoldDigger extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} digs for gold.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarf gold digger\";\n  }\n}\n\n@Slf4j\npublic class DwarvenCartOperator extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} moves gold chunks out of the mine.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarf cart operator\";\n  }\n}\n\n```\n\n이 모든 금광의 일꾼들을 운영하기 위해 `DwarvenGoldmineFacade` 가 있습니다.:\n\n```java\npublic class DwarvenGoldmineFacade {\n\n  private final List<DwarvenMineWorker> workers;\n\n  public DwarvenGoldmineFacade() {\n      workers = List.of(\n            new DwarvenGoldDigger(),\n            new DwarvenCartOperator(),\n            new DwarvenTunnelDigger());\n  }\n\n  public void startNewDay() {\n    makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE);\n  }\n\n  public void digOutGold() {\n    makeActions(workers, DwarvenMineWorker.Action.WORK);\n  }\n\n  public void endDay() {\n    makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);\n  }\n\n  private static void makeActions(Collection<DwarvenMineWorker> workers,\n      DwarvenMineWorker.Action... actions) {\n    workers.forEach(worker -> worker.action(actions));\n  }\n}\n```\n\n이제 퍼싸드(facade) 패턴을 사용해 봅시다:\n\n```java\nvar facade = new DwarvenGoldmineFacade();\nfacade.startNewDay();\nfacade.digOutGold();\nfacade.endDay();\n```\n\n프로그램 실행 결과:\n\n```java\n// Dwarf gold digger wakes up.\n// Dwarf gold digger goes to the mine.\n// Dwarf cart operator wakes up.\n// Dwarf cart operator goes to the mine.\n// Dwarven tunnel digger wakes up.\n// Dwarven tunnel digger goes to the mine.\n// Dwarf gold digger digs for gold.\n// Dwarf cart operator moves gold chunks out of the mine.\n// Dwarven tunnel digger creates another promising tunnel.\n// Dwarf gold digger goes home.\n// Dwarf gold digger goes to sleep.\n// Dwarf cart operator goes home.\n// Dwarf cart operator goes to sleep.\n// Dwarven tunnel digger goes home.\n// Dwarven tunnel digger goes to sleep.\n```\n\n## 클래스 다이어그램\n\n![alt text](./etc/facade.urm.png \"Facade pattern class diagram\")\n\n## 적용 가능성\n\n다음과 같은 경우 파사드 패턴을 사용합니다.\n\n* 복잡한 하위시스템에 간단한 인터페이스를 제공하려는 경우, 하위시스템은 점점 더 복잡해지는 경우가 많습니다. 대부분의 패턴들은 적용되었을 때,\n  클래스가 점점 더 작아집니다. 이것은 하위 시스템의 재사용성을 늘리고 커스터마이징을 쉽게 해주지만, 커스터마이징이 필요없는 클라이언트는 사용하기\n  어려워집니다. 퍼싸드(Facade)는 하위시스템의 간단한 보기를 제공할 수 있습니다. 오직 커스터마이징이 필요한 클라이언트들만 퍼싸드(Facade) 너머를\n  살펴볼 필요가 있습니다.\n* 클라이언트와 추상화의 구현 클래스 사이에는 많은 종속성이 있습니다. 퍼싸드(Facade)를 도입해 하위 시스템을 클라이언트 및 다른 하위 시스템으로부터\n  분리하면 다음과 같은 이점이 있습니다.\n  하위 시스템의 독립성과 이식성을 촉진합니다.\n* 하위 시스템을 계층화하려고 합니다. 퍼싸드(Facade)를 이용해 각 하위 시스템 계층에 대한 진입점을 정희합니다.\n  하위 시스템이 종속적인 경우 하위 시스템 간의 종속성을 단순화할 수 있습니다.\n  퍼싸드(Facade)를 통해서만 서로 통신할 수 있습니다.\n\n## 튜토리얼\n\n*[DigitalOcean](https://www.digitalocean.com/community/tutorials/facade-design-pattern-in-java)\n* [Refactoring Guru](https://refactoring.guru/design-patterns/facade)\n* [GeekforGeeks](https://www.geeksforgeeks.org/facade-design-pattern-introduction/)\n* [Tutorialspoint](https://www.tutorialspoint.com/design_pattern/facade_pattern.htm)\n\n\n\n## 크레딧\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/ko/factory/README.md",
    "content": "---\ntitle: Factory\nshortTitle: Factory\ncategory: Creational\nlanguage: ko\ntag:\n- Gang of Four\n---\n\n## 또한 ~으로 알려진\n\n- Simple Factory\n- Static Factory Method\n\n## 의도\n\n구현 논리를 숨기고 클라이언트 코드가 새 객체를 초기화하는 대신 사용에 집중하도록하기 위해 factory라는 클래스에 캡슐화 된 정적 메서드를 제공합니다.\n\n## 설명\n\n예시\n\n> SQLServer에 연결된 웹 응용 프로그램이 있지만 이제 Oracle로 전환하려고 합니다. 기존 소스 코드를 수정하지 않고 이를 수행하려면 주어진 데이터베이스에 대한 연결을 생성하기 위해 정적 메서드를 호출 할 수 있는 Simple Factory 패턴을 구현해야합니다.\n\nWikipedia 말에 의하면\n\n> factory는 다른 객체를 생성하기위한 객체입니다. 공식적으로 factory는 다양한 프로토 타입 또는 클래스의 객체를 반환하는 함수 또는 메서드입니다.\n\n**프로그램 코드 예제**\n\n우리는 인터페이스 `Car` 와 두 가지 구현 `Ford` 와 `Ferrari`을 가지고 있습니다.\n\n```java\npublic interface Car {\n  String getDescription();\n}\n\npublic class Ford implements Car {\n\n  static final String DESCRIPTION = \"This is Ford.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\npublic class Ferrari implements Car {\n   \n  static final String DESCRIPTION = \"This is Ferrari.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n```\n\n열거형은 우리가 지원하는 자동차 유형을 나타냅니다 ( `Ford` 및 `Ferrari` ).\n\n```java\npublic enum CarType {\n  \n  FORD(Ford::new),\n  FERRARI(Ferrari::new);\n  \n  private final Supplier<Car> constructor;\n  \n  CarType(Supplier<Car> constructor) {\n    this.constructor = constructor;\n  }\n  \n  public Supplier<Car> getConstructor() {\n    return this.constructor;\n  }\n}\n```\n\n그런 다음 factory 클래스 `CarsFactory` 캡슐화 된 자동차 객체를 만드는 정적 메서드 `getCar` 가 있습니다.\n\n```java\npublic class CarsFactory {\n  \n  public static Car getCar(CarType type) {\n    return type.getConstructor().get();\n  }\n}\n```\n\n이제 클라이언트 코드에서 factory 클래스를 사용하여 다양한 유형의 자동차를 만들 수 있습니다.\n\n```java\nvar car1 = CarsFactory.getCar(CarType.FORD);\nvar car2 = CarsFactory.getCar(CarType.FERRARI);\nLOGGER.info(car1.getDescription());\nLOGGER.info(car2.getDescription());;\n```\n\n프로그램 출력 :\n\n```java\nThis is Ford.\nThis Ferrari.\n```\n\n## 클래스 다이어그램\n\n![alt text](./etc/factory.urm.png)\n\n## 적용 가능성\n\n객체 생성 및 관리 방법이 아닌 객체 생성에만 관심이있을 때 Simple Factory 패턴을 사용합니다.\n\n장점\n\n- 모든 객체 생성을 한곳에 유지하고 코드베이스에 '새'키 값이 확산되는 것을 방지합니다.\n- 느슨하게 결합 된 코드를 작성할 수 있습니다. 주요 장점 중 일부는 더 나은 테스트 가능성, 이해하기 쉬운 코드, 교체 가능한 구성 요소, 확장성 및 격리된 기능을 포함합니다.\n\n단점\n\n- 코드는 생각보다 복잡해집니다.\n\n## 관련 패턴\n\n- [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n- [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n- [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/)\n"
  },
  {
    "path": "localization/ko/factory-method/README.md",
    "content": "---\ntitle: \"Factory Method\"\nshortTitle: Factory Method\ncategory: Creational\nlanguage: ko\ntag:\n  - Gang of Four\n---\n\n## 또한 ~으로 알려진\n\n* Virtual Constructor\n\n## 의도\n\n팩토리 메소드 패턴을 사용하여 객체를 생성하기 위한 인터페이스를 정의하고, 어떤 클래스를 인스턴스화할지는 하위 클래스가 결정하도록 합니다. 이 생성 설계 패턴은 클래스가 인스턴스 생성을 하위 클래스로 위임하여 코드 유연성과 유지보수성을 향상시킬 수 있습니다.\n\n## 설명\n\n예시\n\n> 한 물류 회사가 다양한 유형의 패키지를 배송해야 한다고 가정해 봅시다. 일반, 급송, 그리고 대형 배송 패키지가 있습니다. 이 회사는 중앙 시스템을 통해 배송 요청을 처리하지만, 각 패키지 유형이 어떻게 처리되는지에 대한 구체적인 사항은 알지 못합니다. 이를 관리하기 위해 이 회사는 팩토리 메소드 패턴을 사용합니다.\n>\n> 이 구조에서 중앙 클래스인 `DeliveryRequest`에는 `createPackage()`라는 메서드가 있습니다. 이 메서드는 `StandardDelivery`, `ExpressDelivery`, `OversizedDelivery`와 같은 하위 클래스에서 오버라이딩되며, 각 하위 클래스는 해당 패키지 유형을 생성하고 관리하는 방법을 알고 있습니다. 이렇게 함으로써 중앙 시스템은 각 패키지 유형이 어떻게 생성되고 처리되는지에 대한 세부 사항을 알 필요 없이 배송 요청을 처리할 수 있어, 유연하고 쉽게 유지보수가 가능합니다.\n\n평범하게 말하자면,\n\n> 이 패턴은 인스턴스 생성 로직을 자식 클래스에 위임하는 방법을 제공합니다.\n\nWikipedia 말에 의하면\n\n> 클래스 기반 프로그래밍에서, 팩토리 메소드 패턴은 생성 패턴 중 하나로, 생성할 객체의 구체적인 클래스를 명시하지 않고 객체를 생성하는 문제를 해결합니다. 이를 위해 생성자는 직접 호출하지 않고, 팩토리 메소드를 호출하여 객체를 생성하는 방식을 사용합니다. 팩토리 메소드는 인터페이스에 명시되어 자식 클래스가 구현하거나, 기본 클래스에 구현되어 파생 클래스에서 필요에 따라 오버라이딩할 수 있습니다.\n\n## 프로그램 코드 예제\n\n팩토리 메소드 접근 방식은 다음 예제에서 볼 수 있듯이 유연하고 유지 관리 가능한 코드를 달성하기 위한 자바 디자인 패턴에서 중추적인 역할을 합니다.\n\n대장장이가 무기를 제작합니다. 엘프는 엘프족 무기를, 오크는 오크족 무기를 필요로 합니다. 고객에 따라 적합한 유형의 대장장이가 소환됩니다.\n\n우선, `Blacksmith` 인터페이스와 이를 구현한 몇 가지 클래스들이 있습니다.\n\n```java\npublic interface Blacksmith {\n  Weapon manufactureWeapon(WeaponType weaponType);\n}\n\npublic class ElfBlacksmith implements Blacksmith {\n  public Weapon manufactureWeapon(WeaponType weaponType) {\n    return ELFARSENAL.get(weaponType);\n  }\n}\n\npublic class OrcBlacksmith implements Blacksmith {\n  public Weapon manufactureWeapon(WeaponType weaponType) {\n    return ORCARSENAL.get(weaponType);\n  }\n}\n```\n\n고객이 오면, 올바른 유형의 대장장이가 소환되어 요청된 무기를 제작합니다.\n\n```java\npublic static void main(String[] args) {\n\n    Blacksmith blacksmith = new OrcBlacksmith();\n    Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);\n    LOGGER.info(MANUFACTURED, blacksmith, weapon);\n    weapon = blacksmith.manufactureWeapon(WeaponType.AXE);\n    LOGGER.info(MANUFACTURED, blacksmith, weapon);\n\n    blacksmith = new ElfBlacksmith();\n    weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);\n    LOGGER.info(MANUFACTURED, blacksmith, weapon);\n    weapon = blacksmith.manufactureWeapon(WeaponType.AXE);\n    LOGGER.info(MANUFACTURED, blacksmith, weapon);\n}\n```\n\n프로그램 실행 결과\n```\n06:40:07.269 [main] INFO com.iluwatar.factory.method.App -- The orc blacksmith manufactured an orcish spear\n06:40:07.271 [main] INFO com.iluwatar.factory.method.App -- The orc blacksmith manufactured an orcish axe\n06:40:07.272 [main] INFO com.iluwatar.factory.method.App -- The elf blacksmith manufactured an elven spear\n06:40:07.272 [main] INFO com.iluwatar.factory.method.App -- The elf blacksmith manufactured an elven axe\n```\n\n## 클래스 다이어그램\n\n![alt text](./etc/factory-method.urm.png \"Factory Method Class Diagram\")\n\n## 적용 가능성\n\n자바에서 팩토리 메소드 패턴을 사용하는 경우:\n\n* 클래스가 생성해야 할 객체의 클래스를 예측할 수 없을 때\n* 클래스가 생성할 객체를 자식 클래스가 지정하도록 하고 싶을 때\n* 여러 보조 자식 클래스 중 하나에 책임을 위임하고, 어느 자식 클래스가 해당 작업을 담당하는지에 대한 정보를 국지화하고 싶을 때\n\n## 실제 사례\n\n* [java.util.Calendar](http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)\n* [java.util.ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)\n* [java.text.NumberFormat](http://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)\n* [java.nio.charset.Charset](http://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)\n* [java.net.URLStreamHandlerFactory](http://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html#createURLStreamHandler-java.lang.String-)\n* [java.util.EnumSet](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of-E-)\n* [javax.xml.bind.JAXBContext](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--)\n* Frameworks that run application components, configured dynamically at runtime.\n\n## 장단점\n\n장점:\n\n* 팩토리 메소드 패턴은 하위 클래스에 대한 후크(hooks)를 제공하여 코드의 유연성과 유지보수성을 높입니다.\n* 병렬적인 클래스 계층 구조를 연결합니다.\n* 애플리케이션 특화 클래스를 코드에 직접 포함할 필요가 없어집니다. 코드가 제품 인터페이스와만 상호작용하므로, 사용자 정의 구체 클래스와 쉽게 연동할 수 있습니다.\n\n단점:\n\n* 확장된 팩토리 메소드를 구현하기 위해 새로운 하위 클래스를 추가해야 하므로 코드가 복잡해질 수 있습니다.\n\n## 관련 패턴\n\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): 팩토리 메소드는 종종 추상 팩토리 패턴 내에서 호출됩니다.\n* [Prototype](https://java-design-patterns.com/patterns/prototype/): 프로토타입 클래스를 복제한 새 인스턴스를 반환하는 팩토리 메소드.\n\n## 크레딧\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0Rk5y)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/3UpTLrG)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/4b2ZxoM)\n"
  },
  {
    "path": "localization/ko/iterator/README.md",
    "content": "---\ntitle: Iterator\nshortTitle: Iterator\ncategories: Behavioral\nlanguage: ko\ntag:\n- Gang of Four\n---\n\n## 또한 ~으로 알려진\n\n커서(Cursor) 패턴\n\n## 의도\n기반이되는 표현을 노출하지 않고 Aggregate 객체의 요소에 순차적으로 접근할 수 있는 방법을 제공합니다.\n\n## 설명\n\n실제 예제\n\n> 보물상자에는 마법의 아이템이 들어 있습니다. 반지, 물약, 무기와 같은 다양한 종류의 물건들이 있습니다. 보물상자가 제공하는 반복기(iterator)를 사용하여 아이템은 유형별로 검색될 수 있을 것입니다.\n\n쉽게 말하자면\n\n> 컨테이너는 요소에 대한 접근을 제공하기 위해 표현에 구애받지 않는 반복기(iterator) 인터페이스를 제공할 수 있습니다.\n\nWikipedia에 의하면\n\n> 반복자 패턴(iterator pattern)은 객체 지향 프로그래밍에서 반복자를 사용하여 컨테이너를 가로지르며 컨테이너의 요소들에 접근하는 디자인 패턴입니다.\n\n**코드 예제**\n\n예제의 메인 클래스는 아이템들을 담고있는 `보물상자(TreasureChest)` 입니다.\n\n```java\npublic class TreasureChest {\n\n  private final List<Item> items;\n\n  public TreasureChest() {\n    items = List.of(\n        new Item(ItemType.POTION, \"Potion of courage\"),\n        new Item(ItemType.RING, \"Ring of shadows\"),\n        new Item(ItemType.POTION, \"Potion of wisdom\"),\n        new Item(ItemType.POTION, \"Potion of blood\"),\n        new Item(ItemType.WEAPON, \"Sword of silver +1\"),\n        new Item(ItemType.POTION, \"Potion of rust\"),\n        new Item(ItemType.POTION, \"Potion of healing\"),\n        new Item(ItemType.RING, \"Ring of armor\"),\n        new Item(ItemType.WEAPON, \"Steel halberd\"),\n        new Item(ItemType.WEAPON, \"Dagger of poison\"));\n  }\n\n  public Iterator<Item> iterator(ItemType itemType) {\n    return new TreasureChestItemIterator(this, itemType);\n  }\n\n  public List<Item> getItems() {\n    return new ArrayList<>(items);\n  }\n}\n```\n\n다음은 `아이템(item)` 클래스입니다. :\n\n```java\npublic class Item {\n\n  private ItemType type;\n  private final String name;\n\n  public Item(ItemType type, String name) {\n    this.setType(type);\n    this.name = name;\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n\n  public ItemType getType() {\n    return type;\n  }\n\n  public final void setType(ItemType type) {\n    this.type = type;\n  }\n}\n\npublic enum ItemType {\n\n  ANY, WEAPON, RING, POTION\n\n}\n```\n\n`반복자(Iterator)` 인터페이스는 아주 단순합니다.\n\n```java\npublic interface Iterator<T> {\n\n  boolean hasNext();\n\n  T next();\n}\n```\n\n다음 예제에서는 보물상자에서 발견되는 고리형 항목을 반복한다.\n\n```java\nvar itemIterator = TREASURE_CHEST.iterator(ItemType.RING);\nwhile (itemIterator.hasNext()) {\n  LOGGER.info(itemIterator.next().toString());\n}\n```\n\n프로그램 실행결과:\n\n```java\nRing of shadows\nRing of armor\n```\n\n## 클래스 다이어그램\n\n![alt text](./etc/iterator_1.png \"Iterator\")\n\n## 적용 가능성\n\n템플릿 메소드는 사용되어야합니다.\n\n* 내부 표현을 드러내지않고 aggregate 객체의 컨텐츠에 접근하기 위해서\n\n* aggregate 오브젝트들의 여러 번의 횡단을 지원하기 위해서\n\n* 서로 다른 aggregate 구조들의 횡단을 위한  획일적인 인터페이스를 제공하기 위해서\n\n## 튜토리얼\n\n* [How to Use Iterator?](http://www.tutorialspoint.com/java/java_using_iterator.htm)\n\n## 실제 사례\n\n* [java.util.Iterator](http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html)\n* [java.util.Enumeration](http://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html)\n\n## 크레딧\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/ko/observer/README.md",
    "content": "---\ntitle: Observer\nshortTitle: Observer\ncategory: Behavioral\nlanguage: ko\ntag:\n- Gang Of Four\n- Reactive\n---\n\n## 또한 ~으로 알려진\n\nDependents, Publish-Subscribe\n\n## 의도\n\n하나의 개체가 상태를 변경하면 모든 종속 항목에 알림이 전송되고 자동으로 업데이트 되도록 개체간의 일대 다 종속성을 정의합니다.\n\n## 설명\n\n예시\n\n> 멀리 떨어진 땅에는 호빗과 오크 종족이 살고 있습니다. 둘 다 대부분 야외에 있으므로 날씨 변화를 면밀히 따릅니다. 끊임없이 날씨를 관찰하고 있다고 말할 수 있습니다.\n\n평범하게 말하자면\n\n> observer로 등록하여 개체의 상태 변경을 수신합니다.\n\nWikipedia 말에 의하면\n\n> observer 패턴은 주제라고하는 객체가 observer라고 하는 종속 항목 목록을 유지하고 일반적으로 메서드 중 하나를 호출하여 상태 변경을 자동으로 알리는 소프트웨어 디자인 패턴입니다.\n\n**프로그램 코드 예제**\n\n먼저 `WeatherObserver` 인터페이스와 우리의 종족 `Orcs` 와 `Hobbits` 소개하겠습니다.\n\n```java\npublic interface WeatherObserver {\n\n  void update(WeatherType currentWeather);\n}\n\npublic class Orcs implements WeatherObserver {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(Orcs.class);\n\n  @Override\n  public void update(WeatherType currentWeather) {\n    LOGGER.info(\"The orcs are facing \" + currentWeather.getDescription() + \" weather now\");\n  }\n}\n\npublic class Hobbits implements WeatherObserver {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(Hobbits.class);\n\n  @Override\n  public void update(WeatherType currentWeather) {\n    switch (currentWeather) {\n      LOGGER.info(\"The hobbits are facing \" + currentWeather.getDescription() + \" weather now\");\n    }\n  }\n}\n```\n\n그리고 끊임없이 변화하는 `Weather` 가 있습니다.\n\n```java\npublic class Weather {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(Weather.class);\n\n  private WeatherType currentWeather;\n  private final List<WeatherObserver> observers;\n\n  public Weather() {\n    observers = new ArrayList<>();\n    currentWeather = WeatherType.SUNNY;\n  }\n\n  public void addObserver(WeatherObserver obs) {\n    observers.add(obs);\n  }\n\n  public void removeObserver(WeatherObserver obs) {\n    observers.remove(obs);\n  }\n\n  /**\n   * Makes time pass for weather.\n   */\n  public void timePasses() {\n    var enumValues = WeatherType.values();\n    currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length];\n    LOGGER.info(\"The weather changed to {}.\", currentWeather);\n    notifyObservers();\n  }\n\n  private void notifyObservers() {\n    for (var obs : observers) {\n      obs.update(currentWeather);\n    }\n  }\n}\n```\n\n여기에 전체 예제가 있습니다.\n\n```java\n    var weather = new Weather();\n    weather.addObserver(new Orcs());\n    weather.addObserver(new Hobbits());\n    weather.timePasses();\n    weather.timePasses();\n    weather.timePasses();\n    weather.timePasses();\n```\n\n프로그램 출력 :\n\n```\nThe weather changed to rainy.\nThe orcs are facing rainy weather now\nThe hobbits are facing rainy weather now\nThe weather changed to windy.\nThe orcs are facing windy weather now\nThe hobbits are facing windy weather now\nThe weather changed to cold.\nThe orcs are facing cold weather now\nThe hobbits are facing cold weather now\nThe weather changed to sunny.\nThe orcs are facing sunny weather now\nThe hobbits are facing sunny weather now\n```\n\n## 클래스 다이어그램\n\n![alt text](./etc/observer.png)\n\n## 적용 가능성\n\n다음 상황에서 관찰자 패턴을 사용하십시오.\n\n- 추상화에 두 가지 측면이 있을 때 하나는 다른 하나에 종속됩니다. 이러한 측면을 별도의 개체에 캡슐화하면 독립적으로 변경하고 재사용 할 수 있습니다.\n- 한 개체를 변경하려면 얼마나 다른 개체를 변경해야 하는지 알 수 없는 경우입니다.\n- 개체가 다른 개체가 누구인지 가정하지 않고 알릴 수 있어야하는 경우. 즉, 개체가 단단히 결합되는 것을 원하지 않습니다.\n\n## 일반적인 사용 사례\n\n- 한 개체를 변경하면 다른 개체도 변경됩니다.\n\n## 실제 사례\n\n- [java.util.Observer](http://docs.oracle.com/javase/8/docs/api/java/util/Observer.html)\n- [java.util.EventListener](http://docs.oracle.com/javase/8/docs/api/java/util/EventListener.html)\n- [javax.servlet.http.HttpSessionBindingListener](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionBindingListener.html)\n- [RxJava](https://github.com/ReactiveX/RxJava)\n\n## 크레딧\n\n- [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n- [Java Generics and Collections](https://www.amazon.com/gp/product/0596527756/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596527756&linkCode=as2&tag=javadesignpat-20&linkId=246e5e2c26fe1c3ada6a70b15afcb195)\n- [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n- [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/ko/prototype/README.md",
    "content": "---\ntitle: Prototype\nshortTitle: Prototype\ncategory: Creational\nlanguage: ko\ntag:\n- Gang Of Four\n- Instantiation\n---\n\n## 의도\n\nprototype 인스턴스를 사용하여 만들 개체의 종류를 지정하고  prototype을 복사하여 새 개체를 만듭니다.\n\n## 설명\n\n먼저 성능 이점을 얻기 위해 prototype 패턴이 사용되지 않는다는 점에 유의해야합니다. 오직 prototype 인스턴스에서 새 개체를 만드는 데만 사용됩니다.\n\n예시\n\n> 복제된 양인 돌리에 대해 기억나십니까? 자세한 내용은 다루지 않겠습니다만 여기서 핵심은 복제에 관한 것입니다.\n\n평범한 말하자면\n\n> 복제를 통해 기존 개체를 기반으로 개체를 만듭니다.\n\nWikipedia 말에 의하면\n\n> prototype 패턴은 소프트웨어 개발에서 생성 디자인 패턴입니다. 생성 할 개체의 유형이 새 개체를 생성하기 위해 복제되는 prototype 인스턴스에 의해 결정될 때 사용됩니다.\n\n간단히 말해, 객체를 처음부터 만들고 설정하는 문제를 겪는 대신 기존 객체의 복사본을 만들어 필요에 맞게 수정할 수 있습니다.\n\n**프로그램 코드 예제**\n\nJava에서는 `Cloneable` 을 구현하고 `Object` 에서 `clone` 을 오버라이딩하여 쉽게 수행 할 수 있습니다.\n\n```java\nclass Sheep implements Cloneable {\n  private String name;\n  public Sheep(String name) { this.name = name; }\n  public void setName(String name) { this.name = name; }\n  public String getName() { return name; }\n  @Override\n  public Sheep clone() {\n    try {\n      return (Sheep)super.clone();\n    } catch(CloneNotSuportedException) {\n      throw new InternalError();\n    }\n  }\n}\n```\n\n그런 다음 아래와 같이 복제할 수 있습니다.\n\n```java\nvar original = new Sheep(\"Jolly\");\nSystem.out.println(original.getName()); // Jolly\n\n// Clone and modify what is required\nvar cloned = original.clone();\ncloned.setName(\"Dolly\");\nSystem.out.println(cloned.getName()); // Dolly\n```\n\n## 클래스 다이어그램\n\n![alt text](./etc/prototype.urm.png)\n\n## 적용 가능성\n\n시스템이 제품의 생성, 구성, 표현 및 표현 방식에 독립적이어야 할 때 prototype 패턴을 사용\n\n- 인스턴스화할 클래스가 런타임에 지정되는 경우 (예 : 동적 로딩)\n- 제품의 클래스 계층 구조와 유사한 팩토리의 클래스 계층 구조 구축을 방지해야할 경우\n- 클래스의 인스턴스가 몇 가지 다른 상태 조합 중 하나만 가질 수 있는 경우. 적절한 상태로 매번 클래스를 수동으로 인스턴스화하는 것보다 해당하는 수의 prototype을 설치하고 복제하는 것이 더 편리 할 수 있습니다.\n- 복제에 비해 개체 생성 비용이 많이 드는 경우.\n\n## 실제 사례\n\n- [java.lang.Object#clone()](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#clone%28%29)\n\n## 크레딧\n\n- [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n- [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/ko/proxy/README.md",
    "content": "---\ntitle: Proxy\nshortTitle: Proxy\ncategory: Structural\nlanguage: ko\ntag:\n- Gang Of Four\n- Decoupling\n---\n\n## 또한 ~으로 알려진\n\nSurrogate\n\n## 의도 \n\n다른 객체에 대한 접근을 제어할 수 있는 대리인 또는 자리 표시자(placeholder)를 제공합니다.\n\n## 설명\n\n실제 예제\n\n> 지역 마법사들이 주문을 공부하러 가는 탑을 상상해 보세요. 상아탑은 프록시를 통해서만 접근할 수 있으며, 프록시는 처음 세 명의 마법사만 들어갈 수 있도록 합니다. 여기서 프록시는 타워의 기능을 나타내며 액세스 제어를 추가합니다.\n\n쉽게 말하자면\n\n> 프록시 패턴을 사용하여, 클래스는 다른 클래스의 기능을 나타냅니다.\n\nWikipedia에 의하면\n\n> 프록시는 가장 일반적인 형태로 다른 것에 대한 인터페이스로서 기능하는 클래스이다. 프록시는 클라이언트가 백그라운드에서 실제 서비스 객체에 액세스하기 위해 호출하는 래퍼 또는 에이전트 객체입니다. 프록시의 사용은 단순히 실제 객체로 포워딩하거나 추가적인 논리를 제공할 수 있습니다. 프록시에서 실제 객체에 대한 작업이 리소스 집약적일 때, 캐싱하거나 실제 객체에 대한 작업이 호출되기 전에 사전 조건을 확인하는 등의 추가 기능이 제공될 수 있습니다.\n\n**코드 예제**\n\n위로부터 마법사 타워를 예로 들어보겠습니다. 먼저 `WiszrdTower` 인터페이스와 이를 구현한\n`IvoryTower` 클래스가 있습니다.\n\n```java\npublic interface WizardTower {\n\n  void enter(Wizard wizard);\n}\n\n@Slf4j\npublic class IvoryTower implements WizardTower {\n\n  public void enter(Wizard wizard) {\n    LOGGER.info(\"{} enters the tower.\", wizard);\n  }\n\n}\n```\n\n그리고 간단한 `Wizard` 클래스입니다.\n\n\n```java\npublic class Wizard {\n\n  private final String name;\n\n  public Wizard(String name) {\n    this.name = name;\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n}\n```\n\n그리고 `WizardTower`에 대한 엑세스 통제를 추가하기 위해 `WizardTowerProxy`를 가집니다.\n\n```java\n@Slf4j\npublic class WizardTowerProxy implements WizardTower {\n\n  private static final int NUM_WIZARDS_ALLOWED = 3;\n\n  private int numWizards;\n\n  private final WizardTower tower;\n\n  public WizardTowerProxy(WizardTower tower) {\n    this.tower = tower;\n  }\n\n  @Override\n  public void enter(Wizard wizard) {\n    if (numWizards < NUM_WIZARDS_ALLOWED) {\n      tower.enter(wizard);\n      numWizards++;\n    } else {\n      LOGGER.info(\"{} is not allowed to enter!\", wizard);\n    }\n  }\n}\n```\n\n그리고 다음은 타워에 입장하는 시나리오입니다.\n\n```java\nvar proxy = new WizardTowerProxy(new IvoryTower());\nproxy.enter(new Wizard(\"Red wizard\"));\nproxy.enter(new Wizard(\"White wizard\"));\nproxy.enter(new Wizard(\"Black wizard\"));\nproxy.enter(new Wizard(\"Green wizard\"));\nproxy.enter(new Wizard(\"Brown wizard\"));\n```\n\n프로그램 실행 결과:\n\n```\nRed wizard enters the tower.\nWhite wizard enters the tower.\nBlack wizard enters the tower.\nGreen wizard is not allowed to enter!\nBrown wizard is not allowed to enter!\n```\n\n## 클래스 다이어그램\n\n![alt text](./etc/proxy.urm.png \"Proxy pattern class diagram\")\n\n## 적용 가능성\n\n프록시는 단순한 포인터보다 더 다재다능하거나 정교한 오브젝트 참조가 필요할 때마다 적용할 수 있습니다. 다음은 프록시 패턴을 적용할 수 있는 몇 가지 일반적인 상황입니다.\n\n\n* 원격 프록시는 다른 주소 공간에 있는 체의 로컬 대리자를 제공합니다.\n* 가상 프록시는 요청 시 값비싼 개체를 생성합니다.\n* 보호 프록시는 원래 객체에 대한 액세스를 제어합니다. 보호 프록시는 객체가 서로 다른 액세스 권한을 가져야 할 때 유용합니다.\n\n일반적으로 프록시 패턴은 다음과 같이 사용됩니다.\n\n* 다른 객체에 대한 액세스 제어\n* 지연 초기화\n* 로깅(logging) 구현\n* 네트워크 연결 촉진\n* 객체에 대한 참조 카운팅\n\n## 튜토리얼\n\n* [Controlling Access With Proxy Pattern](http://java-design-patterns.com/blog/controlling-access-with-proxy-pattern/)\n\n## 실제 사례\n\n* [java.lang.reflect.Proxy](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html)\n* [Apache Commons Proxy](https://commons.apache.org/proper/commons-proxy/)\n* Mocking frameworks [Mockito](https://site.mockito.org/),\n  [Powermock](https://powermock.github.io/), [EasyMock](https://easymock.org/)\n\n## 관련 패턴\n\n* [Ambassador](https://java-design-patterns.com/patterns/ambassador/)\n\n## 크레딧\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/ko/singleton/README.md",
    "content": "---\ntitle: Singleton\nshortTitle: Singleton\ncategory: Creational\nlanguage: ko\ntag:\n- Gang of Four\n---\n\n## 의도\n\n클래스에 인스턴스가 하나만 있는지 확인하고 이에 대한 전역 access point을 제공합니다.\n\n## 설명\n\n예시\n\n> 마법사들이 마법을 연구하는 상아탑은 단 하나뿐입니다. 마법사는 항상 동일한 마법의 상아탑을 사용합니다. 여기서 상아탑은 singleton입니다.\n\n평범하게 말하자면\n\n> 특정 클래스의 개체가 하나만 생성되도록합니다.\n\nWikipedia 말에 의하면\n\n> 소프트웨어 엔지니어링에서 singleton 패턴은 클래스의 인스턴스화를 하나의 객체로 제한하는 소프트웨어 디자인 패턴입니다. 이는 시스템 전체에서 작업을 조정하는 데 정확히 하나의 개체가 필요할 때 유용합니다.\n\n**프로그램 코드 예제**\n\nJoshua Bloch, Effective Java 2nd Edition p.18\n\n> 단일 요소 열거형은 singleton을 구현하는 가장 좋은 방법입니다.\n\n```java\npublic enum EnumIvoryTower {\n  INSTANCE\n}\n```\n\n그런 다음 사용하려면 :\n\n```java\nvar enumIvoryTower1 = EnumIvoryTower.INSTANCE;\nvar enumIvoryTower2 = EnumIvoryTower.INSTANCE;\nassertEquals(enumIvoryTower1, enumIvoryTower2); // true\n```\n\n## 클래스 다이어그램\n\n![alt text](./etc/singleton.urm.png)\n\n## 적용 가능성\n\n다음과 같은 경우 Singleton 패턴을 사용합니다.\n\n- 정확히 하나의 클래스 인스턴스가 있어야하며 잘 알려진 access point에서 클라이언트에 접근할 수 있어야합니다.\n- 단일 인스턴스가 서브 클래싱으로 확장 가능해야하고 클라이언트가 코드를 수정하지 않고 확장 인스턴스를 사용할 수 있어야 하는 경우\n\n## 일반적인 사용 사례\n\n- 로깅 클래스\n- 데이터베이스에 대한 연결 관리\n- 파일 관리자\n\n## 실제 사례\n\n- [java.lang.Runtime#getRuntime()](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime%28%29)\n- [java.awt.Desktop#getDesktop()](http://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#getDesktop--)\n- [java.lang.System#getSecurityManager()](http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getSecurityManager--)\n\n## 결과\n\n- 자체 생성 및 수명주기를 제어하여 SRP (Single Responsibility Principle)를 위반합니다.\n- 이 개체가 사용하는 개체와 리소스가 할당 해제되는 것을 방지하는 전역 공유 인스턴스를 사용하도록 권장합니다.\n- 밀접하게 연결된 코드를 만듭니다. Singleton의 클라이언트는 테스트하기가 어려워집니다.\n- Singleton의 하위 클래스를 만드는 것이 거의 불가능합니다.\n\n## 크레딧\n\n- [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n- [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n- [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n- [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/ko/strategy/README.md",
    "content": "---\ntitle: Strategy\nshortTitle: Strategy\ncategory: Behavioral\nlanguage: ko\ntag:\n - Gang of Four\n---\n\n## 동의어\n\n정책(Policy) 패턴\n\n## 의도\n\n알고리즘군을 정의하고 각 알고리즘을 캡슐화하고 상호 변경 가능하게 만듭니다. 전략(Strategy) 패턴을 사용하면 알고리즘이 이를 사용하는 클라이언트와 독립적일 수 있습니다.\n\n## 설명\n\n실제 예제\n\n> 드래곤을 사냥하는 것은 위험한 일입니다. 경험이 쌓이면 쉬워집니다. 베테랑 사냥꾼들은 서로 다른 유형의 드래곤에 대해 서로 다른 전투 전략을 개발했습니다.\n\n평범한 말로는\n\n> 전략(Strategy) 패턴을 사용하면 런타임에 가장 적합한 알고리즘을 선택할 수 있습니다.   \n\nWikipedia는\n\n> 컴퓨터 프로그래밍에서 전략 패턴(정책 패턴이라고도 함)은 런타임에 알고리즘을 선택할 수 있는 행동 소프트웨어 디자인 패턴입니다.\n\n**프로그래밍 예**\n\n먼저 드래곤 사냥 전략 인터페이스와 그 구현을 살펴봅니다.\n\n```java\n@FunctionalInterface\npublic interface DragonSlayingStrategy {\n\n  void execute();\n}\n\n@Slf4j\npublic class MeleeStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"With your Excalibur you sever the dragon's head!\");\n  }\n}\n\n@Slf4j\npublic class ProjectileStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"You shoot the dragon with the magical crossbow and it falls dead on the ground!\");\n  }\n}\n\n@Slf4j\npublic class SpellStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\");\n  }\n}\n```\n\n그리고 여기 상대하는 드래곤에 따라 자신의 전투 전략을 선택할 수 있는 강력한 드래곤 슬레이어가 있습니다.\n\n```java\npublic class DragonSlayer {\n\n  private DragonSlayingStrategy strategy;\n\n  public DragonSlayer(DragonSlayingStrategy strategy) {\n    this.strategy = strategy;\n  }\n\n  public void changeStrategy(DragonSlayingStrategy strategy) {\n    this.strategy = strategy;\n  }\n\n  public void goToBattle() {\n    strategy.execute();\n  }\n}\n```\n\n마지막으로 여기 드래곤 슬레이어가 행동합니다.\n\n```java\n    LOGGER.info(\"Green dragon spotted ahead!\");\n    var dragonSlayer = new DragonSlayer(new MeleeStrategy());\n    dragonSlayer.goToBattle();\n    LOGGER.info(\"Red dragon emerges.\");\n    dragonSlayer.changeStrategy(new ProjectileStrategy());\n    dragonSlayer.goToBattle();\n    LOGGER.info(\"Black dragon lands before you.\");\n    dragonSlayer.changeStrategy(new SpellStrategy());\n    dragonSlayer.goToBattle();\n```\n\n프로그램 출력:\n\n```\n    Green dragon spotted ahead!\n    With your Excalibur you sever the dragon's head!\n    Red dragon emerges.\n    You shoot the dragon with the magical crossbow and it falls dead on the ground!\n    Black dragon lands before you.\n    You cast the spell of disintegration and the dragon vaporizes in a pile of dust!    \n```\n\n또한 Java 8의 새로운 기능인 Lambda Expressions은 구현을 위한 또 다른 접근 방식을 제공합니다:\n\n```java\npublic class LambdaStrategy {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(LambdaStrategy.class);\n\n  public enum Strategy implements DragonSlayingStrategy {\n    MeleeStrategy(() -> LOGGER.info(\n        \"With your Excalibur you sever the dragon's head!\")),\n    ProjectileStrategy(() -> LOGGER.info(\n        \"You shoot the dragon with the magical crossbow and it falls dead on the ground!\")),\n    SpellStrategy(() -> LOGGER.info(\n        \"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\"));\n\n    private final DragonSlayingStrategy dragonSlayingStrategy;\n\n    Strategy(DragonSlayingStrategy dragonSlayingStrategy) {\n      this.dragonSlayingStrategy = dragonSlayingStrategy;\n    }\n\n    @Override\n    public void execute() {\n      dragonSlayingStrategy.execute();\n    }\n  }\n}\n```\n\n그리고 여기 드래곤 슬레이어가 행동합니다.\n\n```java\n    LOGGER.info(\"Green dragon spotted ahead!\");\n    dragonSlayer.changeStrategy(LambdaStrategy.Strategy.MeleeStrategy);\n    dragonSlayer.goToBattle();\n    LOGGER.info(\"Red dragon emerges.\");\n    dragonSlayer.changeStrategy(LambdaStrategy.Strategy.ProjectileStrategy);\n    dragonSlayer.goToBattle();\n    LOGGER.info(\"Black dragon lands before you.\");\n    dragonSlayer.changeStrategy(LambdaStrategy.Strategy.SpellStrategy);\n    dragonSlayer.goToBattle();\n```\n\n프로그램 출력은 위와 동일합니다.\n\n## 클래스 다이어그램\n\n![alt text](./etc/strategy_urm.png \"Strategy\")\n\n## 적용 가능성\n\n다음과 같은 경우 전략(Strategy) 패턴을 사용합니다.\n\n* 비슷한 클래스들이 동작 만 다른 경우가 많이 있습니다. 전략 패턴은 여러 동작 중 하나를 클래스로 구성하는 방법을 제공합니다.\n* 알고리즘의 다양한 변형이 필요합니다. 예를 들어 다양한 공간 / 시간 절충을 반영하는 알고리즘을 정의할 수 있습니다. 이러한 변형이 알고리즘의 클래스 계층 구조로 구현될 때 전략 패턴을 사용할 수 있습니다.\n* 알고리즘은 클라이언트가 알 필요 없는 데이터를 사용합니다. 전략 패턴을 사용하여 복잡한 알고리즘 별 데이터 구조가 노출되지 않도록 합니다.\n* 클래스는 많은 동작을 정의하며 이러한 동작은 작업에서 여러 조건문으로 나타납니다. 많은 조건부 대신 관련 조건부 분기를 자체 전략 클래스로 이동하세요.\n\n## 튜토리얼 \n\n* [전략 패턴 튜토리얼](https://www.journaldev.com/1754/strategy-design-pattern-in-java-example-tutorial)\n\n## 크레딧\n\n* [디자인 패턴: 재사용 가능한 객체 지향 소프트웨어의 요소](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [자바의 함수형 프로그래밍: Java 8 Lambda 표현식의 강력한 기능 활용](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b)\n* [헤드 퍼스트 디자인 패턴: 두뇌 친화적인 가이드](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [패턴으로 리팩토링](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/ko/template-method/README.md",
    "content": "---\ntitle: Template Method\nshortTitle: Template Method\ncategory: Behavioral\nlanguage: ko\ntag:\n- Gang of Four\n---\n\n## 의도\n\n동작 상의 알고리즘의 뼈대를 정의하고 일부 단계들을 하위 클래스에게 미룹니다. 템플릿 메소드는 알고리즘 구조의 변경없이 하위 클래스들이 알고리즘의 특정 단계들을 재정의할 수 있게 합니다.\n\n## 설명\n\n실제 예제\n\n> 일반적으로 물건을 훔치는 절차는 동일합니다. 첫번째 단계로 대상을 고릅니다. 다음 단계로 대상을 어느정도 혼란스럽게 만듭니다. 마지막 단계로 물건을 훔칩니다. 하지만, 이 단계를 실행하는 구체적인 방법에는 여러가지가 있습니다.\n\n쉽게 말하자면\n\n> 템플릿 메소드 패턴은 일반적인 단계의 아웃라인을 부모 클래스에 제시합니다. 그리고 구체적인 자식 클래스의 구현으로 디테일한 사항들을 정의합니다.\n\nWikipedia에 의하면\n\n> 객체지향 프로그래밍에서, 템플릿 메소드는 디자인 패턴 책에서 감마를 포함한 책의 저자들이 확인한 행동 디자인 패턴 중 하나입니다. 템플릿 메소드는 보통 추상 수퍼클래스인 수퍼클래스에서의 메소드이며 수많은 high-level 단계들의 관점에서 동작의 뼈대를 정의합니다. 이러한 절차들은 템플릿 메소드와 동일한 클래스의 추가적인 헬퍼 메소드들에 의해 구현됩니다.\n\n**코드 예제**\n\n먼저 구체적인 구현과 함께 템플릿 방법 클래스를 소개합니다. 하위클래스들이 템플릿 메소드를 재정의하지 않는 것을 확실히 하기위해 템플릿 메소드(예제에서는 메소드명`steal`)는 `final`로 선언해야 합니다. 그렇지 않으면 기본 클래스에 정의된 뼈대는 하위 클래스에서 재정의될 수 있습니다.\n\n\n```java\n@Slf4j\npublic abstract class StealingMethod {\n\n  protected abstract String pickTarget();\n\n  protected abstract void confuseTarget(String target);\n\n  protected abstract void stealTheItem(String target);\n\n  public final void steal() {\n    var target = pickTarget();\n    LOGGER.info(\"The target has been chosen as {}.\", target);\n    confuseTarget(target);\n    stealTheItem(target);\n  }\n}\n\n@Slf4j\npublic class SubtleMethod extends StealingMethod {\n\n  @Override\n  protected String pickTarget() {\n    return \"shop keeper\";\n  }\n\n  @Override\n  protected void confuseTarget(String target) {\n    LOGGER.info(\"Approach the {} with tears running and hug him!\", target);\n  }\n\n  @Override\n  protected void stealTheItem(String target) {\n    LOGGER.info(\"While in close contact grab the {}'s wallet.\", target);\n  }\n}\n\n@Slf4j\npublic class HitAndRunMethod extends StealingMethod {\n\n  @Override\n  protected String pickTarget() {\n    return \"old goblin woman\";\n  }\n\n  @Override\n  protected void confuseTarget(String target) {\n    LOGGER.info(\"Approach the {} from behind.\", target);\n  }\n\n  @Override\n  protected void stealTheItem(String target) {\n    LOGGER.info(\"Grab the handbag and run away fast!\");\n  }\n}\n```\n\n템플릿 메소드를 담고 있는 반쪽짜리 도적 클래스입니다.\n\n```java\npublic class HalflingThief {\n\n  private StealingMethod method;\n\n  public HalflingThief(StealingMethod method) {\n    this.method = method;\n  }\n\n  public void steal() {\n    method.steal();\n  }\n\n  public void changeMethod(StealingMethod method) {\n    this.method = method;\n  }\n}\n```\n\n그리고 마지막으로, 반쪽짜리 도둑이 다른 도둑질 방법을 어떻게 활용하는지 보여줍니다.\n\n```java\n    var thief = new HalflingThief(new HitAndRunMethod());\n    thief.steal();\n    thief.changeMethod(new SubtleMethod());\n    thief.steal();\n```\n\n## 클래스 다이어그램\n\n![alt text](./etc/template_method_urm.png \"Template Method\")\n\n## 적용 가능성\n\n템플릿 메소드는 사용되어야합니다.\n\n* 알고리즘의 변하지않는 부분을 한번만 구현하고, 다양할 수 있는 행위의 구현을 서브클래스에게 맡기기 위해\n* 중복되는 코드를 피하기위해 서브클래스들 사이의 공통적인 행위를 공통 클래스에서 고려하고 현지화해야 하는 경우. 이것은 Opdyke 와 Johonson이 묘사한 \"일반화하기 위한 수정\"의 좋은 예입니다. 먼저 기존 코드들 간의 차이를 확인한 다음 새로운 동작으로 구분합니다. 마지막으로, 다른 코드들을  새로운 동작중 하나를 호출하는 템플릿 메소드로 대체합니다.\n* 서브클래스들의 확장을 컨트롤하기 위해. 특정 지점에서 \"훅\" 작업을 호출하여 해당 지점에서만 확장을 허용하는 템플릿 메서드를 정의할 수 있습니다.\n\n## 튜토리얼\n\n* [Template-method Pattern Tutorial](https://www.journaldev.com/1763/template-method-design-pattern-in-java)\n\n## 실제 사례\n\n* [javax.servlet.GenericServlet.init](https://jakarta.ee/specifications/servlet/4.0/apidocs/javax/servlet/GenericServlet.html#init--):\n  Method `GenericServlet.init(ServletConfig config)` calls the parameterless method `GenericServlet.init()` which is intended to be overridden in subclasses.\n  Method `GenericServlet.init(ServletConfig config)` is the template method in this example.\n\n## 크레딧\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/ko/visitor/README.md",
    "content": "---\ntitle: Visitor\nshortTitle: Visitor\ncategory: Behavioral\nlanguage: ko\ntag:\n - Gang of Four\n---\n\n## 의도\n\n\n객체 구조의 요소들에 대해 수행할 작업을 나타냅니다. 방문자(Visitor)는 \n연산하는 요소의 클래스를 변경하지 않고 새 연산을 정의할 수 있게 해줍니다.\n## 설명\n\n살제 예제\n\n> 육군 부대의 편성을 생각해보세요. 지휘관은 아래에 2명의 중사를 휘하에 두고 있고 각 중사들은\n> 3명의 병사를 휘하에 두고 있습니다. 위계에 따라 방문자(Visitor) 패턴이 구현되는 것을 함께 생각하면,\n> 우리는 지휘관, 중사 병사 또는 그들 모두와 상호작용하는 새로운 게체를 쉽게 만들 수 있습니다.\n\n쉽게 말하자면\n\n> 방문자(Visitor) 패턴은 데이터 구조의 노드에서 수행할 수 있는 작업들을 정의합니다.\n\nWikipedia에 의하면\n\n> 객체 지향 프로그래밍 및 소프트웨어 엔지니어링에에서, 방문자(Visitor) 패턴은\n> 알고리즘이 동작하는 객체 구조로부터 알고리즘을 분리하는 것,\n> 이 분리를 통해, 구조의 변경 없이 기본 객체 구조에 새로운 연산을 추가할 수 있도록 하는 방법입니다.\n\n**코드 예제**\n\n위의 육군 부대를 예로 들겠습니다. 먼저 `Unit` 추상화 클래스와 `UnitVisitor` 인터페이스가 있습니다.\n\n```java\npublic abstract class Unit {\n\n  private final Unit[] children;\n\n  public Unit(Unit... children) {\n    this.children = children;\n  }\n\n  public void accept(UnitVisitor visitor) {\n    Arrays.stream(children).forEach(child -> child.accept(visitor));\n  }\n}\n\npublic interface UnitVisitor {\n\n  void visit(Soldier soldier);\n\n  void visit(Sergeant sergeant);\n\n  void visit(Commander commander);\n}\n```\n\n그리고 이를 구현한 `Commander`,`Sergant`,`Soilder` 구현 클래스입니다.\n\n```java\npublic class Commander extends Unit {\n\n  public Commander(Unit... children) {\n    super(children);\n  }\n\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visit(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"commander\";\n  }\n}\n\npublic class Sergeant extends Unit {\n\n  public Sergeant(Unit... children) {\n    super(children);\n  }\n\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visit(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"sergeant\";\n  }\n}\n\npublic class Soldier extends Unit {\n\n  public Soldier(Unit... children) {\n    super(children);\n  }\n\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visit(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"soldier\";\n  }\n}\n```\n\n그리고 `UnitVisiotr`를 구현한 `CommanderVisitor`,`SergantVisitor`,`Soilder` 구현 클래스입니다.\n\n```java\n@Slf4j\npublic class CommanderVisitor implements UnitVisitor {\n\n  @Override\n  public void visit(Soldier soldier) {\n    // Do nothing\n  }\n\n  @Override\n  public void visit(Sergeant sergeant) {\n    // Do nothing\n  }\n\n  @Override\n  public void visit(Commander commander) {\n    LOGGER.info(\"Good to see you {}\", commander);\n  }\n}\n\n@Slf4j\npublic class SergeantVisitor implements UnitVisitor {\n\n  @Override\n  public void visit(Soldier soldier) {\n    // Do nothing\n  }\n\n  @Override\n  public void visit(Sergeant sergeant) {\n    LOGGER.info(\"Hello {}\", sergeant);\n  }\n\n  @Override\n  public void visit(Commander commander) {\n    // Do nothing\n  }\n}\n\n@Slf4j\npublic class SoldierVisitor implements UnitVisitor {\n\n  @Override\n  public void visit(Soldier soldier) {\n    LOGGER.info(\"Greetings {}\", soldier);\n  }\n\n  @Override\n  public void visit(Sergeant sergeant) {\n    // Do nothing\n  }\n\n  @Override\n  public void visit(Commander commander) {\n    // Do nothing\n  }\n}\n```\n\n마지막으로, 우린 방문자(Visitor)의 위력을 볼 수 있습니다.\n\n```java\ncommander.accept(new SoldierVisitor());\ncommander.accept(new SergeantVisitor());\ncommander.accept(new CommanderVisitor());\n```\n\n프로그램 실행 결과:\n\n```\nGreetings soldier\nGreetings soldier\nGreetings soldier\nGreetings soldier\nGreetings soldier\nGreetings soldier\nHello sergeant\nHello sergeant\nGood to see you commander\n```\n\n## 클래스 다이어그램\n\n![alt text](./etc/visitor_1.png \"Visitor\")\n\n## 적용 가능성\n\n일반적으로 방문자(Visitor) 패턴은 다음과 같은 상황에 사용할 수 있습니다.\n\n* 객체 구조에 다양한 인터페이스를 가진 객체의 클래스가 많이 포함되어 있고, 객체들의 구현 클래스에 따라 연산되게 하고 싶을 때 사용할 수 있습니다.\n* 객체 구조에 있는 객체들에 대해 개별적이고 서로 연관이 없는 연산들을 수행하고 싶을 때, 이러한 연산들로 인해 클래스가 \"오염(Polluting)\"되는 것을 방지하고자 합니다. 이럴 때, 방문자(Visitor)를 사용해 관련 연산을 하나의 클래스에 정의하여 유지할 수 있습니다. 객체 구조가 여러 응용 프로그램에서 공유되는 경우에는 방문자(Visitor)를 사용해 필요한 응용 프로그램에만 연산을 추가할 수 있습니다.\n* 객체 구조를 정의하는 클래스들은 거의 변경되지 않지만, 종종 새로운 연산을 정의해야 할 때가 있습니다. 객체 구조 클래스들을 변경하려면 모둔 방문자(Visitor)에 데한 인터페이스를 재정의해야 하므로 비용이 많이 들수 있습니다. 객체 구조 클래스가 자주 변경되는 경우 해당 클래스의 연산을 정의하는 것이 더 나을 수 있습니다.\n\n## 튜토리얼\n\n* [Refactoring Guru](https://refactoring.guru/design-patterns/visitor)\n* [Dzone](https://dzone.com/articles/design-patterns-visitor)\n* [Sourcemaking](https://sourcemaking.com/design_patterns/visitor)\n\n## 실제 사례\n\n* [Apache Wicket](https://github.com/apache/wicket) 구성 요소, [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)를 참조하세요.\n* [javax.lang.model.element.AnnotationValue](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValue.html) 그리고 [AnnotationValueVisitor](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValueVisitor.html)\n* [javax.lang.model.element.Element](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/Element.html) 그리고 [Element Visitor](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/ElementVisitor.html)\n* [java.nio.file.FileVisitor](http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileVisitor.html)\n\n## 크레딧\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/mr/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n     \n     # जावा मध्ये डिझाइन नमुने लागू केले\n     \n     ![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-214-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n<br/>\n\nRead in different language : [**zh**](localization/zh/README.md), [**ko**](localization/ko/README.md), [**fr**](localization/fr/README.md), [**tr**](localization/tr/README.md), [**ar**](localization/ar/README.md), [**es**](localization/es/README.md), [**pt**](localization/pt/README.md), [**id**](localization/id/README.md), [**ru**](localization/ru/README.md), [**de**](localization/de/README.md), [**ja**](localization/ja/README.md), [**vi**](localization/vi/README.md), [**ma**](localization/ma/README.md)\n\n<br/>\n\n#परिचय\n\nडिझाईन पॅटर्न हे प्रोग्रामर वापरू शकणार्‍या सर्वोत्तम, औपचारिक पद्धती आहेत\nअनुप्रयोग किंवा सिस्टम डिझाइन करताना सामान्य समस्या सोडवा.\n\nडिझाइन नमुने चाचणी केलेले, सिद्ध करून विकास प्रक्रियेस गती देऊ शकतात\nविकास नमुना.\n\nडिझाईन नमुन्यांचा पुनर्वापर केल्याने प्रमुख कारणीभूत असलेल्या सूक्ष्म समस्या टाळण्यास मदत होते\nसमस्या, आणि ते कोडर आणि आर्किटेक्टसाठी कोड वाचनीयता देखील सुधारते\nनमुन्यांशी परिचित आहेत.\n\n#सुरुवात\n\nही साइट Java डिझाइन पॅटर्न दाखवते. द्वारे उपाय विकसित केले गेले आहेत\nओपन-सोर्स समुदायातील अनुभवी प्रोग्रामर आणि आर्किटेक्ट. द\nनमुने त्यांच्या उच्च-स्तरीय वर्णनांद्वारे किंवा त्यांच्याकडे पाहून ब्राउझ केले जाऊ शकतात\nमूळ सांकेतिक शब्दकोश. स्त्रोत कोड उदाहरणे चांगल्या प्रकारे टिप्पणी केली आहेत आणि म्हणून विचार केला जाऊ शकतो\nविशिष्ट पॅटर्न कसे अंमलात आणायचे यावरील प्रोग्रामिंग ट्यूटोरियल. आम्ही सर्वात जास्त वापरतो\nलोकप्रिय युद्ध-सिद्ध ओपन-सोर्स जावा तंत्रज्ञान.\n\nआपण सामग्रीमध्ये जाण्यापूर्वी, आपल्याला विविध गोष्टींशी परिचित असले पाहिजे [सॉफ्टवेअर डिझाइन तत्त्वे](https://java-design-patterns.com/principles/).\n\nसर्व रचना शक्य तितक्या सोप्या असाव्यात. तुम्ही KISS, YAGNI ने सुरुवात करावी,\nआणि शक्यतो तत्त्वे कार्य करू शकणारी सर्वात सोपी गोष्ट करा. जटिलता आणि\nनमुने केवळ तेव्हाच सादर केले जावे जेव्हा ते प्रॅक्टिकलसाठी आवश्यक असतील\nविस्तारक्षमता\n\nएकदा आपण या संकल्पनांशी परिचित झाल्यानंतर आपण मध्ये ड्रिल करणे सुरू करू शकता\n[उपलब्ध डिझाइन नमुने](https://java-design-patterns.com/patterns/) कोणत्याही\nखालील दृष्टिकोनांपैकी\n\n - नावाने विशिष्ट नमुना शोधा. एक शोधू शकत नाही? कृपया नवीन नमुना [येथे] (https://github.com/iluwatar/java-design-patterns/issues) नोंदवा.\n - `परफॉर्मन्स`, `गँग ऑफ फोर` किंवा `डेटा ऍक्सेस` यासारखे टॅग वापरणे.\n - पॅटर्न श्रेण्या, `सृजनात्मक`, `वर्तणूक` आणि इतर वापरणे.\n\nआशा आहे की, तुम्हाला या साइटवर सादर केलेले ऑब्जेक्ट-ओरिएंटेड उपाय उपयुक्त वाटतील\nतुमच्या आर्किटेक्चर्समध्ये आणि त्यांना विकसित करताना आम्हाला जेवढी मजा आली तेवढीच ती शिकण्यात मजा करा.\n# योगदान कसे द्यावे\n\nतुम्ही प्रकल्पात योगदान देण्यास इच्छुक असाल तर तुम्हाला संबंधित माहिती मिळेल\nआमचे [डेव्हलपर विकी](https://github.com/iluwatar/java-design-patterns/wiki). आम्ही मदत करू\nतुम्ही आणि तुमच्या प्रश्नांची उत्तरे [Gitter chatroom](https://gitter.im/iluwatar/java-design-patterns) मध्ये द्या.\n\n# परवाना\n\nहा प्रकल्प एमआयटी परवान्याच्या अटींनुसार परवानाकृत आहे.\n\n"
  },
  {
    "path": "localization/ne/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n\n# जाभामा लागू गरिएको डिजाइन ढाँचाहरू\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-218-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n<br>\n\nफरक भाषामा पढ्नुहोस् : [**zh**](localization/zh/README.md), [**ko**](localization/ko/README.md), [**fr**](localization/fr/README.md), [**tr**](localization/tr/README.md), [**ar**](localization/ar/README.md), [**es**](localization/es/README.md), [**pt**](localization/pt/README.md), [**id**](localization/id/README.md), [**ru**](localization/ru/README.md), [**de**](localization/de/README.md), [**ja**](localization/ja/README.md), [**vi**](localization/vi/README.md), [**bn**](localization/bn/README.md), [**np**](localization/np/README.md)\n<br>\n\n# परिचय\n\nडिजाइन ढाँचाहरू सबै भन्दा राम्रो, औपचारिक अभ्यासहरू हुन् जुन प्रोग्रामरले अनुप्रयोग वा प्रणाली डिजाइन गर्दा सामान्य समस्याहरू समाधान गर्न प्रयोग गर्न सक्छ।\n\nडिजाइन ढाँचाहरूले परीक्षण, प्रमाणित विकास प्रतिमानहरू प्रदान गरेर विकास प्रक्रियालाई गति दिन सक्छ।\n\nडिजाइन ढाँचाहरू पुन: प्रयोग गर्नाले प्रमुख समस्याहरू निम्त्याउने सूक्ष्म समस्याहरूलाई रोक्न मद्दत गर्दछ, र यसले ढाँचाहरूसँग परिचित भएका कोडरहरू र आर्किटेक्टहरूको लागि कोड पढ्न योग्यतामा पनि सुधार गर्दछ।\n\n# सुरु गर्दै\n\nयो साइटले जाभा डिजाइन ढाँचाहरू प्रदर्शन गर्दछ। समाधानहरू द्वारा विकसित गरिएको छ\nखुला स्रोत समुदायबाट अनुभवी प्रोग्रामरहरू र आर्किटेक्टहरू। द\nढाँचाहरू तिनीहरूको उच्च-स्तरको विवरणहरू वा हेरेर ब्राउज गर्न सकिन्छ\nस्रोत कोड। स्रोत कोड उदाहरणहरू राम्ररी टिप्पणी गरिएका छन् र सोच्न सकिन्छ\nएक विशिष्ट ढाँचा कसरी कार्यान्वयन गर्ने बारे प्रोग्रामिङ ट्यूटोरियल। हामी सबैभन्दा बढी प्रयोग गर्छौं\nलोकप्रिय युद्ध सिद्ध खुला स्रोत जाभा प्रविधिहरू।\n\nतपाईंले सामग्रीमा डुब्नु अघि, तपाईं विभिन्नसँग परिचित हुनुपर्छ\n[सफ्टवेयर डिजाइन सिद्धान्तहरू](https://java-design-patterns.com/principles/).\n\nसबै डिजाइनहरू सकेसम्म सरल हुनुपर्छ। चुम्बन, यज्ञीबाट सुरु गर्नुपर्छ,\nर सम्भवतः सिद्धान्तहरू काम गर्न सक्ने साधारण कुरा गर्नुहोस्। जटिलता र\nढाँचाहरू मात्र पेश गर्नुपर्छ जब तिनीहरू व्यावहारिक रूपमा आवश्यक हुन्छन्\nविस्तारशीलता।\n\nएकचोटि तपाइँ यी अवधारणाहरूसँग परिचित भएपछि तपाइँ मा ड्रिल गर्न सुरु गर्न सक्नुहुन्छ\n[उपलब्ध डिजाइन ढाँचा](https://java-design-patterns.com/patterns/) कुनै पनि द्वारा\nनिम्न दृष्टिकोणहरु को\n\n- नाम द्वारा एक विशिष्ट ढाँचा खोज्नुहोस्। एउटा भेट्टाउन सक्नुहुन्न? कृपया एउटा नयाँ ढाँचा रिपोर्ट गर्नुहोस् [यहाँ](https://github.com/iluwatar/java-design-patterns/issues).\n- `प्रदर्शन`, `Gang of Four`, वा `डेटा पहुँच` जस्ता ट्यागहरू प्रयोग गर्दै।\n- ढाँचा कोटिहरू प्रयोग गर्दै, `सृजनात्मक`, `व्यवहार`, र अन्य।\n\nआशा छ, तपाईंले यस साइटमा प्रस्तुत वस्तु-उन्मुख समाधानहरू उपयोगी पाउनुहुनेछ\nतपाईंको आर्किटेक्चरमा र तिनीहरूलाई सिक्न धेरै रमाईलो गर्नुहोस् हामीले तिनीहरूलाई विकास गर्दा।\n\n# कसरी योगदान गर्ने\nयदि तपाईं परियोजनामा ​​योगदान गर्न इच्छुक हुनुहुन्छ भने तपाईंले सान्दर्भिक जानकारी पाउनुहुनेछ\nहाम्रो [विकासकर्ता विकि](https://github.com/iluwatar/java-design-patterns/wiki). हामी मद्दत गर्नेछौं\nतपाईं र [गिटर च्याटरूम](https://gitter.im/iluwatar/java-design-patterns) मा तपाईंका प्रश्नहरूको जवाफ दिनुहोस्।\n\n# इजाजतपत्र\nयो परियोजना MIT लाइसेन्स को सर्तहरु अन्तर्गत इजाजतपत्र दिइएको छ।\n\n"
  },
  {
    "path": "localization/pt/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n\n# Padrões de projeto implementados em Java\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-170-orange.svg?style=flat-square)](#contributors-)\n\n<br/>\n\nLeia em outro idioma: [**zh**](/localization/zh/README.md), [**ko**](/localization/ko/README.md), [**fr**](/localization/fr/README.md), [**tr**](/localization/tr/README.md), [**ar**](/localization/ar/README.md), [**es**](/localization/es/README.md)\n\n<br/>\n\n# Introdução\n\nOs padrões de projeto são um conjunto das melhores práticas e soluções formalizadas que um programador pode usar para resolver problemas comuns ao projetar um aplicativo ou sistema.\n\nOs padrões de projeto podem acelerar o processo de desenvolvimento, fornecendo testes e comprovados paradigmas de desenvolvimento.\n\nReutilizar padrões de projeto ajuda a evitar problemas sutis que causam\nproblemas, e também melhora a legibilidade do código para desenvolvedores e arquitetos que\nestão familiarizados com os padrões.\n\n# Começando\n\nEste site apresenta padrões de projeto Java. As soluções foram desenvolvidas por\nprogramadores e arquitetos experientes da comunidade de código aberto. Os\npadrões podem ser acessados por meio de suas descrições de alto nível ou  por meio de seu\nCódigo fonte. Os exemplos de código-fonte são bem comentados e podem ser considerados como\ntutoriais de programação sobre como implementar um padrão específico. Nós usamos as mais\npopulares tecnologias Java de código aberto comprovadas em batalhas.\n\nAntes de mergulhar no material, você deve estar familiarizado com vários\n[Princípios de design de software](https://java-design-patterns.com/principles/).\n\nTodos os projetos devem ser o mais simples possível. Você deve começar com KISS, YAGNI,\ne fazer a coisa mais simples que poderia funcionar com os princípios. Complexidade e\nos padrões só devem ser introduzidos quando são necessários para fins práticos e\nextensibilidade.\n\nAssim que estiver familiarizado com esses conceitos, você pode começar a se aprofundar nos\n[padrões de projeto disponíveis](https://java-design-patterns.com/patterns/) por qualquer\ndas seguintes abordagens\n\n - Pesquise um padrão específico por nome. Não consegue encontrar um? Informe um novo padrão [aqui](https://github.com/iluwatar/java-design-patterns/issues).\n - Usando tags como `Performance`,` Gang of Four` ou `Acesso de dados`.\n - Usando categorias de padrões, `Criacional`,` Comportamental` e outros.\n\n Esperamos que você encontre as soluções orientadas a objetos apresentadas neste site úteis\nem suas arquiteturas e divirta-se as aprendendo tanto quanto nos divertimos ao desenvolvê-las.\n\n# Como contribuir\n\nSe você estiver disposto a contribuir para o projeto, você encontrará as informações mais relevantes em nossa [wiki do desenvolvedor](https://github.com/iluwatar/java-design-patterns/wiki). Ajudaremos você e responderemos as suas perguntas na [sala de bate-papo do Gitter](https://gitter.im/iluwatar/java-design-patterns).\n\n# Licença\n\nEste projeto está licenciado sob os termos da licença MIT.\n\n"
  },
  {
    "path": "localization/pt/abstract-factory/README.md",
    "content": "---\ntitle: Abstract Factory\ncategories: Creational\nlanguage: pt\ntag:\n- Gang of Four\n---\n\n## Também conhecido como\n\nKit\n\n## Propósito\n\nFornece uma interface para criar famílias de objetos relacionados dependentes sem especificar sua classe concreta.\n\n## Explicação\n\nExemplo do Mundo Real\n\n> Para criar um reino precisamos de objetos com um tema comum. O reino élfico precisa de um rei élfico, um castelo élfico e um exército élfico, enquanto o reino orc precisa de um rei orc, um castelo orc e um exército orc. Existe uma dependência entre os objetos do reino.\n\nEm outras palavras\n\n> Uma fábrica de fábricas; uma fábrica que agrupa outras fábricas individuais, mas relacionadas/dependentes, sem especificar sua classe concreta.\n\nDe acordo com a Wikipédia\n\n> A essência do padrão Abstract Factory é fornecer uma interface para criar famílias de objetos relacionados ou dependentes sem especificar suas classes concretas.\n\n**Exemplo Programático**\n\nTraduzindo o exemplo do reino acima. Em primeiro lugar, temos algumas interfaces e implementação para os objetos no reino.\n\n```java\npublic interface Castle {\n  String getDescription();\n}\n\npublic interface King {\n  String getDescription();\n}\n\npublic interface Army {\n  String getDescription();\n}\n\n// Elven implementations ->\npublic class ElfCastle implements Castle {\n  static final String DESCRIPTION = \"This is the elven castle!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfKing implements King {\n  static final String DESCRIPTION = \"This is the elven king!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfArmy implements Army {\n  static final String DESCRIPTION = \"This is the elven Army!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\n// Orcish implementations similarly -> ...\n\n```\n\nEm seguida, temos a abstração e as implementações para a fábrica do reino.\n\n```java\npublic interface KingdomFactory {\n  Castle createCastle();\n  King createKing();\n  Army createArmy();\n}\n\npublic class ElfKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new ElfCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new ElfKing();\n  }\n\n  @Override\n  public Army createArmy() {\n    return new ElfArmy();\n  }\n}\n\npublic class OrcKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new OrcCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new OrcKing();\n  }\n  \n  @Override\n  public Army createArmy() {\n    return new OrcArmy();\n  }\n}\n```\n\nAgora temos a fábrica abstrata que nos permite fazer uma família de objetos relacionados, ou seja, a fábrica do reino élfico cria castelo élfico, rei e exército, etc.\n\n\n```java\nvar factory = new ElfKingdomFactory();\nvar castle = factory.createCastle();\nvar king = factory.createKing();\nvar army = factory.createArmy();\n\ncastle.getDescription();\nking.getDescription();\narmy.getDescription();\n```\n\nOutput do programa:\n\n```java\nThis is the elven castle!\nThis is the elven king!\nThis is the elven Army!\n```\n\n\nAgora, podemos projetar uma fábrica para nossas diferentes fábricas do reino. Neste exemplo, criamos o `FactoryMaker`, responsável por devolver uma instância de `ElfKingdomFactory` ou `OrcKingdomFactory`.\nO cliente pode usar o `FactoryMaker` para criar uma fatoração concreta, que uma vez, produzirá diferentes objetos concretos (derivados de `Army`, `King`, `Castle`).\nNeste exemplo, também usamos um enum para parametrizar qual tipo de fábrica do reino o cliente solicitará.\n\n```java\npublic static class FactoryMaker {\n\n    public enum KingdomType {\n        ELF, ORC\n    }\n\n    public static KingdomFactory makeFactory(KingdomType type) {\n        return switch (type) {\n            case ELF -> new ElfKingdomFactory();\n            case ORC -> new OrcKingdomFactory();\n            default -> throw new IllegalArgumentException(\"KingdomType not supported.\");\n        };\n    }\n}\n\n    public static void main(String[] args) {\n        var app = new App();\n\n        LOGGER.info(\"Elf Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));\n        LOGGER.info(app.getArmy().getDescription());\n        LOGGER.info(app.getCastle().getDescription());\n        LOGGER.info(app.getKing().getDescription());\n\n        LOGGER.info(\"Orc Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));\n        --similar use of the orc factory\n    }\n```\n\n## Diagrama de classes\n\n![alt text](../../../abstract-factory/etc/abstract-factory.urm.png \"Diagrama de Classes de Abstract Factory\")\n\n\n## Aplicabilidade\n\nUse o padrão Abstract Factory quando\n\n* O sistema deve ser independente de como seus produtos são criados, compostos e representados\n* O sistema deve ser configurado com uma das várias famílias de produtos\n* A família de objetos de produtos relacionados foi projetada para ser usada em conjunto e você precisa aplicar essa restrição\n* Você deseja fornecer uma biblioteca de classes de produtos e deseja revelar apenas suas interfaces, não suas implementações\n* O tempo de vida da dependência é conceitualmente menor que o tempo de vida do consumidor.\n* Você precisa de um valor em tempo de execução para construir uma dependência específica\n* Você deseja decidir qual produto chamar de uma família em tempo de execução.\n* Você precisa fornecer um ou mais parâmetros conhecidos apenas em tempo de execução antes de resolver uma dependência.\n* Quando você precisa de consistência entre os produtos\n* Você não deseja alterar o código existente ao adicionar novos produtos ou famílias de produtos ao programa.\n\nExemplos de casos de uso\n\n* Selecionando para chamar a implementação apropriada de FileSystemAcmeService ou DatabaseAcmeService ou NetworkAcmeService em tempo de execução.\n* A escrita de casos de teste de unidade torna-se muito mais fácil\n* Ferramentas de interface do usuário para diferentes sistemas operacionais\n\n## Consequencias\n\n* A injeção de dependência em java oculta as dependências da classe de serviço que podem levar a erros de tempo de execução que seriam detectados em tempo de compilação.\n* Embora o padrão seja ótimo ao criar objetos predefinidos, adicionar novos pode ser um desafio.\n* O código se torna mais complicado do que deveria, pois muitas novas interfaces e classes são introduzidas junto com o padrão.\n\n## Tutoriais\n\n* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java) \n\n## Usos conhecidos\n\n* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)\n* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)\n* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)\n\n## Padrões relacionados\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/pt/adapter/README.md",
    "content": "---\ntitle: Adapter\ncategory: Structural\nlanguage: pt\ntag:\n - Gang of Four\n---\n\n## Também conhecido como\nWrapper\n\n## Propósito\nConverter a interface de uma classe em outra que o cliente espera.\nO padrão Adapter permite que uma classe funcione em conjunto com outras classes que não poderiam por problemas de imcompatibilidade de interfaces.\n\n## Explicação\n\nExemplo do mundo real\n\n> Considere que você possui algumas imagens no seu cartão de memória e precisa transferí-las para seu computador. Para isso, você irá precisar de algum tipo de adaptador que seja compatível com alguma entrada de seu computador, então você poderá conectar o cartão de memória no seu computador. Nesse caso, o leitor de cartões de memória é um adaptador (Adapter).\n> Outro exemplo poderia ser o famoso adaptador elétrico; um plug de três pinos não pode ser conectado a uma tomada de dois oríficios, é necessário usar um adaptador que fará com que haja compatibilidade entre a tomada e o plugue.\n> Outro exemplo ainda poderia ser um tradutor traduzindo palavras ditas por uma pessoa para outra.\n\nEm outras palavras\n\n> O padrão Adapter permite que você envolva um objeto incompatível em um adaptador que o transforma em um objeto compatível com outra classe.\n\nWikipedia diz\n\n> Em engenharia de software, o padrão Adapter é um padrão de projeto de software que permite a interface de uma classe existente ser usada como outra interface. É frequentemente usada para fazer classes já existentes funcionarem com outras, sem modificar seu código fonte.\n\n**Exemplo de programação**\n\nConsidere um capitão que pode apenas usar botes a remo e não pode navegar de outro modo.\n\nPrimeiramente, temos as interfaces `RowingBoat` e `FishingBoat`\n\n```java\npublic interface RowingBoat {\n  void row();\n}\n\n@Slf4j\npublic class FishingBoat {\n  public void sail() {\n    LOGGER.info(\"The fishing boat is sailing\");\n  }\n}\n```\n\nE o capitão espera uma implementação da interface `RowingBoat` para ser capaz de se mover\n\n```java\npublic class Captain {\n\n  private final RowingBoat rowingBoat;\n  // default constructor and setter for rowingBoat\n  public Captain(RowingBoat rowingBoat) {\n    this.rowingBoat = rowingBoat;\n  }\n\n  public void row() {\n    rowingBoat.row();\n  }\n}\n```\n\nAgora, digamos que os piratas estão chegando e nosso capitão precisa escapar, mas há apenas um bote de pesca disponível. Nós precisamos criar um adaptador que permita o capitão operar o bote de pesca com suas habilidades de condução do bote a remo.\n\n```java\n@Slf4j\npublic class FishingBoatAdapter implements RowingBoat {\n\n  private final FishingBoat boat;\n\n  public FishingBoatAdapter() {\n    boat = new FishingBoat();\n  }\n\n  @Override\n  public void row() {\n    boat.sail();\n  }\n}\n```\n\nE agora o `Captain` pode usar o `FishingBoat` para escapar dos piratas.\n\n```java\nvar captain = new Captain(new FishingBoatAdapter());\ncaptain.row();\n```\n\n## Diagrama de classes\n![alt text](./etc/adapter.urm.png \"Diagrama de classes do Adapter\")\n\n## Aplicabilidade\nUse o padrão Adapter quando\n\n* Você quer usar uma classe existente, e sua interface não combina exatamente com o que você precisa\n* Você quer criar uma classe reusável que contribui com classes não relacionadas ou não previstas, isto é, classes que não necessariamente tem interfaces compatíveis\n* Você precisa utilizar várias subclasses existentes, mas é impraticável adaptar suas interfaces criando novas subclasses para cada uma. Um adapter pode adaptar a interface da sua classe pai.\n* A maioria das aplicações que usa bibliotecas de terceiros usa apdaters como uma camada intermediária entre a aplicação e a biblioteca de terceiro para desacoplar a aplicação da biblioteca externa. Se outra biblioteca precisar ser usada, será necessário apenas adequar o adapter para essa nova biblioteca, sem necessidade de alterar muito código.\n\n## Tutoriais (em inglês)\n\n* [Dzone](https://dzone.com/articles/adapter-design-pattern-in-java)\n* [Refactoring Guru](https://refactoring.guru/design-patterns/adapter/java/example)\n* [Baeldung](https://www.baeldung.com/java-adapter-pattern)\n\n## Consequências\nClasses e objetos adapter tem diferentes prós e contras. Uma classe adapter\n\n* \tConverte o objeto adaptado para o alvo por meio de uma classe concreta. Como consequência, uma classe adapter não irá funcionar se desejamos adaptar uma classe e todas as suas subclasses.\n* \tDeixa o Adapter sobrescrever algum comportamento da classe adaptada já que o Adapter é uma subclasse da classe adaptada.\n*\tIntroduz apenas um objeto, e nenhum ponteiro indireto é necessário para obter a classe adaptada.\n\nUm objeto adapter\n\n*\tPermite um único adaptador funcionar com vários objetos adaptados, isto é, o objeto adaptado em si e todas as suas subclasses (se houver). O adapter também pode adicionar funcionalidade a todas os objetos adaptados de uma vez só.\n*\tTorna mais difícil sobrescrever o comportamento do objeto adaptado. Isso irá requerer geração de subclasses para o objeto adaptado e fazer o adapter se referir a essa subclasse em vez do objeto adaptado em si.\n\n## Exemplos do mundo real\n\n* [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)\n* [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)\n* [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-)\n* [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-)\n\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/pt/builder/README.md",
    "content": "---\ntitle: Builder\ncategories: Creational\nlanguage: pt\ntag:\n- Gang of Four\n---\n\n## Propósito\n\nSepare a construção de um objeto complexo de sua representação para que a mesma construção do\nprocesso possa criar diferentes representações.\n\n## Explicação\n\nExemplo do Mundo Real\n\n> Imagine um gerador de personagens para um jogo de RPG. A opção mais fácil é deixar que o computador\n> crie o personagem para você. Se você quiser selecionar manualmente os detalhes do personagem como\n> profissão, gênero, cor de cabelo, etc. a geração do personagem se torna um processo passo a passo que\n> termina quando todas as seleções estiverem prontas.\n\nEm outras palavras\n\n> Permite criar diferentes formas de um objeto, evitando a poluição do construtor. Útil\n> quando pode haver várias formas de um objeto. Ou quando há muitos passos envolvidos na\n> criação de um objeto.\n\nDe acordo com a Wikipédia\n\n> o Builder constrói objetos complexos passo a passo e procura evitar ser um anti-padrão.\n\nDito isso, deixe-me acrescentar um pouco sobre o que é o antipadrão do construtor. Em um ponto\nou o outro, todos nós vimos um construtor como abaixo:\n\n```java\npublic Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) {\n}\n```\n\nComo você pode ver, o número de parâmetros do construtor pode ficar rapidamente fora de controle e pode se tornar\ndifícil entender a disposição dos parâmetros. Além disso, esta lista de parâmetros pode continuar\ncrescendo se você quiser adicionar mais opções no futuro. Isso é chamado de construtor telescópico\nanti-padrão.\n\n**Exemplo Programático**\n\nA alternativa sensata é usar o padrão Builder. Em primeiro lugar, temos o nosso herói que queremos criar:\n\n```java\npublic final class Hero {\n  private final Profession profession;\n  private final String name;\n  private final HairType hairType;\n  private final HairColor hairColor;\n  private final Armor armor;\n  private final Weapon weapon;\n\n  private Hero(Builder builder) {\n    this.profession = builder.profession;\n    this.name = builder.name;\n    this.hairColor = builder.hairColor;\n    this.hairType = builder.hairType;\n    this.weapon = builder.weapon;\n    this.armor = builder.armor;\n  }\n}\n```\n\nEntão temos o builder:\n\n```java\n  public static class Builder {\n    private final Profession profession;\n    private final String name;\n    private HairType hairType;\n    private HairColor hairColor;\n    private Armor armor;\n    private Weapon weapon;\n\n    public Builder(Profession profession, String name) {\n      if (profession == null || name == null) {\n        throw new IllegalArgumentException(\"profession and name can not be null\");\n      }\n      this.profession = profession;\n      this.name = name;\n    }\n\n    public Builder withHairType(HairType hairType) {\n      this.hairType = hairType;\n      return this;\n    }\n\n    public Builder withHairColor(HairColor hairColor) {\n      this.hairColor = hairColor;\n      return this;\n    }\n\n    public Builder withArmor(Armor armor) {\n      this.armor = armor;\n      return this;\n    }\n\n    public Builder withWeapon(Weapon weapon) {\n      this.weapon = weapon;\n      return this;\n    }\n\n    public Hero build() {\n      return new Hero(this);\n    }\n  }\n```\n\nEntão pode ser usado como:\n\n```java\nvar mage = new Hero.Builder(Profession.MAGE, \"Riobard\").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();\n```\n\n## Diagrama de classes\n\n![alt text](../../../builder/etc/builder.urm.png \"Diagrama de classes Builder\")\n\n## Aplicabilidade\n\nUse o padrão Builder quando\n\n* O algoritmo para criar um objeto complexo deve ser independente das partes que compõem o objeto e de como elas são montadas\n* O processo de construção deve permitir diferentes representações para o objeto construído\n\n## Tutoriais\n\n* [Refactoring Guru](https://refactoring.guru/design-patterns/builder)\n* [Oracle Blog](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java)\n* [Journal Dev](https://www.journaldev.com/1425/builder-design-pattern-in-java)\n\n## Usos conhecidos\n\n* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)\n* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) bem como buffers semelhantes, como FloatBuffer, IntBuffer e assim por diante.\n* [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-)\n* Todas as implementações de [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)\n* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)\n* [Apache Commons Option.Builder](https://commons.apache.org/proper/commons-cli/apidocs/org/apache/commons/cli/Option.Builder.html)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/pt/caching/README.md",
    "content": "---\ntitle: Cache\ncategory: Behavioral\nlanguage: pt\ntag:\n  - Performance\n  - Cloud distributed\n---\n\n\n## Propósito\n\nO padrão de armazenamento em cache evita a custosa reaquisição de recursos por não liberá-los ou limpá-los imediatamente após o uso. Os recursos mantêm sua identidade, são mantidos em algum tipo de armazenamento de acesso rápido e são reutilizados para evitar a necessidade de buscá-los novamente.\n## Explicação\n\nExemplo de uso em mundo real:\n\n> Uma equipe está trabalhando em um site que oferece novos lares para gatos abandonados. As pessoas podem postar seus gatos no site depois de se registrarem, mas todos os novos posts precisam da aprovação de um dos moderadores do site. As contas dos moderadores do site tem um campo específico sinalizando isso e os dados são salvos em um banco de dados MongoDB. \n> Checar esse campo específico todas vez que um post é visualizado custa caro e é uma boa ideia usar armazenamento em cache nesse caso. \n\nDe modo simples:\n\n> O padrão de armazenamento em cache guarda dados que são requisitados frequentemente em um armazenamento de rápido acesso para melhorar a performance.\n\nDe acordo com a Wikipedia:\n\n>Em computação, cache é um componente de hardware ou software que guarda dados que quando futuramente solicitados, podem ser servidos de maneira mais rapida. \n>Os dados armazenados em cache podem ser o resultado de algum cálculo anterior ou a cópia de outros dados que anteriormente estava armazenados em outro lugar. \n>Um \"cache hit\" (acerto de cache) acontece quando o dado requisitado é encontrado no cache, enquanto um \"cache miss\" (falta de cache) acontece quando os dado não é encontrado no cache.\n>Os \"cache hits\" são lidos diretamente do cache, o que é mais rápido do que recalcular ou buscar os dados em outro lugar. Portante quando mais requisições forem atendidas pelo cache, mais rápido o sistema performa.\n\n**Exemplo programático**\n\nVamos primeiro analisar a camada de dados da nossa aplicação. As classes que nos interessa são `UserAccount` que é um objeto Java simples que contém detalhes da conta do usuário e a interface `DbManager` que lida com a leitura e escrita desses objetos no banco de dados. \n```java\n@Data\n@AllArgsConstructor\n@ToString\n@EqualsAndHashCode\npublic class UserAccount {\n  private String userId;\n  private String userName;\n  private String additionalInfo;\n}\n\npublic interface DbManager {\n\n  void connect();\n  void disconnect();\n  \n  UserAccount readFromDb(String userId);\n  UserAccount writeToDb(UserAccount userAccount);\n  UserAccount updateDb(UserAccount userAccount);\n  UserAccount upsertDb(UserAccount userAccount);\n}\n```\nNo exemplos, vamos demonstrar várias políticas de armazenamento de cache diferentes:\n\n* Write-through: Escreve os dados no cache e no DB em uma única transação.\n* Write-around: Escreve os dados diretamente no DB em vez de escrever no cache.\n  Write-behind: Escreve os dados no cache inicialmente enquanto os dados são escritos no banco de dados apenas quando o cache está cheio.\n  Cache-aside: Delega a responsabilidade de manter os dados sincronizados em ambas as fontes de dados (cache e DB) para a própria aplicação.\n* Read-through: Essa estratégia também está incluída nas estratégias mencionadas acima e retorna dados do cache (cache hit) para o chamador, se existir, caso contrário (cache miss), consulta o banco de dados e armazena os dados no cache para uso futuro.\n  \nThe cache implementation in `LruCache` is a hash table accompanied by a doubly \nlinked-list. The linked-list helps in capturing and maintaining the LRU data in the cache. When \ndata is queried (from the cache), added (to the cache), or updated, the data is moved to the front \nof the list to depict itself as the most-recently-used data. The LRU data is always at the end of \nthe list.\n\nA implementação de cache em `LruCache` é uma tabela hash acompanhada por uma lista duplamente encadeada - ou lista duplamente ligada (Doubly linked list). \nEssa lista ligada ajuda a capturar e manter os dados LRU (Least Recently Used - Menos Recentemente Usados) no cache.\nQuando os dados são consultados (do cache), adicionados (ao cache) ou atualizados, os dados são movidos para o início da lista como os dados mais recentemente usados. Os dados LRU estão sempre no final da lista.\n\n```java\n@Slf4j\npublic class LruCache {\n\n  static class Node {\n    String userId;\n    UserAccount userAccount;\n    Node previous;\n    Node next;\n\n    public Node(String userId, UserAccount userAccount) {\n      this.userId = userId;\n      this.userAccount = userAccount;\n    }\n  }\n  \n  /* ... omitted details ... */\n\n  public LruCache(int capacity) {\n    this.capacity = capacity;\n  }\n\n  public UserAccount get(String userId) {\n    if (cache.containsKey(userId)) {\n      var node = cache.get(userId);\n      remove(node);\n      setHead(node);\n      return node.userAccount;\n    }\n    return null;\n  }\n\n  public void set(String userId, UserAccount userAccount) {\n    if (cache.containsKey(userId)) {\n      var old = cache.get(userId);\n      old.userAccount = userAccount;\n      remove(old);\n      setHead(old);\n    } else {\n      var newNode = new Node(userId, userAccount);\n      if (cache.size() >= capacity) {\n        LOGGER.info(\"# Cache is FULL! Removing {} from cache...\", end.userId);\n        cache.remove(end.userId); // remove LRU data from cache.\n        remove(end);\n        setHead(newNode);\n      } else {\n        setHead(newNode);\n      }\n      cache.put(userId, newNode);\n    }\n  }\n\n  public boolean contains(String userId) {\n    return cache.containsKey(userId);\n  }\n  \n  public void remove(Node node) { /* ... */ }\n  public void setHead(Node node) { /* ... */ }\n  public void invalidate(String userId) { /* ... */ }\n  public boolean isFull() { /* ... */ }\n  public UserAccount getLruData() { /* ... */ }\n  public void clear() { /* ... */ }\n  public List<UserAccount> getCacheDataInListForm() { /* ... */ }\n  public void setCapacity(int newCapacity) { /* ... */ }\n}\n```\n\nA próxima camada que vamos analisar é `CacheStore`, que implementa as diferentes estratégias de armazenamento em cache.\n\n```java\n@Slf4j\npublic class CacheStore {\n\n  private static final int CAPACITY = 3;\n  private static LruCache cache;\n  private final DbManager dbManager;\n\n  /* ... details omitted ... */\n\n  public UserAccount readThrough(final String userId) {\n    if (cache.contains(userId)) {\n      LOGGER.info(\"# Found in Cache!\");\n      return cache.get(userId);\n    }\n    LOGGER.info(\"# Not found in cache! Go to DB!!\");\n    UserAccount userAccount = dbManager.readFromDb(userId);\n    cache.set(userId, userAccount);\n    return userAccount;\n  }\n\n  public void writeThrough(final UserAccount userAccount) {\n    if (cache.contains(userAccount.getUserId())) {\n      dbManager.updateDb(userAccount);\n    } else {\n      dbManager.writeToDb(userAccount);\n    }\n    cache.set(userAccount.getUserId(), userAccount);\n  }\n\n  public void writeAround(final UserAccount userAccount) {\n    if (cache.contains(userAccount.getUserId())) {\n      dbManager.updateDb(userAccount);\n      // Cache data has been updated -- remove older\n      cache.invalidate(userAccount.getUserId());\n      // version from cache.\n    } else {\n      dbManager.writeToDb(userAccount);\n    }\n  }\n\n  public static void clearCache() {\n    if (cache != null) {\n      cache.clear();\n    }\n  }\n\n  public static void flushCache() {\n    LOGGER.info(\"# flushCache...\");\n    Optional.ofNullable(cache)\n        .map(LruCache::getCacheDataInListForm)\n        .orElse(List.of())\n        .forEach(DbManager::updateDb);\n  }\n\n  /* ... omitted the implementation of other caching strategies ... */\n\n}\n```\n\nA classe `AppManager` ajuda em fazer a ponte de comunicação entre a classe principal e o backend da aplicação. A conexão com o DB é inicializada por meio dessa classe. A estratégia ou política de cache escolhida também é inicializada aqui.\nAntes do cache poder ser usado, é preciso definir o tamanho do cache.\nDependendo da estratégio de armazenamento de cache escolhida, a classe `AppManager` chamará a função (método) apropriada na classe `CacheStore`.\n\n```java\n@Slf4j\npublic final class AppManager {\n\n  private static CachingPolicy cachingPolicy;\n  private final DbManager dbManager;\n  private final CacheStore cacheStore;\n\n  private AppManager() {\n  }\n\n  public void initDb() { /* ... */ }\n\n  public static void initCachingPolicy(CachingPolicy policy) { /* ... */ }\n\n  public static void initCacheCapacity(int capacity) { /* ... */ }\n\n  public UserAccount find(final String userId) {\n    LOGGER.info(\"Trying to find {} in cache\", userId);\n    if (cachingPolicy == CachingPolicy.THROUGH\n            || cachingPolicy == CachingPolicy.AROUND) {\n      return cacheStore.readThrough(userId);\n    } else if (cachingPolicy == CachingPolicy.BEHIND) {\n      return cacheStore.readThroughWithWriteBackPolicy(userId);\n    } else if (cachingPolicy == CachingPolicy.ASIDE) {\n      return findAside(userId);\n    }\n    return null;\n  }\n\n  public void save(final UserAccount userAccount) {\n    LOGGER.info(\"Save record!\");\n    if (cachingPolicy == CachingPolicy.THROUGH) {\n      cacheStore.writeThrough(userAccount);\n    } else if (cachingPolicy == CachingPolicy.AROUND) {\n      cacheStore.writeAround(userAccount);\n    } else if (cachingPolicy == CachingPolicy.BEHIND) {\n      cacheStore.writeBehind(userAccount);\n    } else if (cachingPolicy == CachingPolicy.ASIDE) {\n      saveAside(userAccount);\n    }\n  }\n\n  public static String printCacheContent() {\n    return CacheStore.print();\n  }\n\n  /* ... details omitted ... */\n}\n```\n\nEssa é nossa classe princial e como usamos a implmentação:\n\n```java\n@Slf4j\npublic class App {\n\n  public static void main(final String[] args) {\n    boolean isDbMongo = isDbMongo(args);\n    if(isDbMongo){\n      LOGGER.info(\"Using the Mongo database engine to run the application.\");\n    } else {\n      LOGGER.info(\"Using the 'in Memory' database to run the application.\");\n    }\n    App app = new App(isDbMongo);\n    app.useReadAndWriteThroughStrategy();\n    String splitLine = \"==============================================\";\n    LOGGER.info(splitLine);\n    app.useReadThroughAndWriteAroundStrategy();\n    LOGGER.info(splitLine);\n    app.useReadThroughAndWriteBehindStrategy();\n    LOGGER.info(splitLine);\n    app.useCacheAsideStategy();\n    LOGGER.info(splitLine);\n  }\n\n  public void useReadAndWriteThroughStrategy() {\n    LOGGER.info(\"# CachingPolicy.THROUGH\");\n    appManager.initCachingPolicy(CachingPolicy.THROUGH);\n\n    var userAccount1 = new UserAccount(\"001\", \"John\", \"He is a boy.\");\n\n    appManager.save(userAccount1);\n    LOGGER.info(appManager.printCacheContent());\n    appManager.find(\"001\");\n    appManager.find(\"001\");\n  }\n\n  public void useReadThroughAndWriteAroundStrategy() { /* ... */ }\n\n  public void useReadThroughAndWriteBehindStrategy() { /* ... */ }\n\n  public void useCacheAsideStategy() { /* ... */ }\n}\n```\n\n## Diagrama de classes\n\n![alt text](./etc/caching.png \"Caching\")\n\n## Aplicabilidade\n\nUtilize os padrões de armazenamento em cache quando:\n\n* Repetidas aquisições, inicialização e liberação do mesmo recurso causam sobrecarga de desempenho desnecessária.\n\n## Padrões relacionados\n\n* [Proxy](https://java-design-patterns.com/patterns/proxy/)\n\n## Créditos\n\n* [Write-through, write-around, write-back: Cache explained](http://www.computerweekly.com/feature/Write-through-write-around-write-back-Cache-explained)\n* [Read-Through, Write-Through, Write-Behind, and Refresh-Ahead Caching](https://docs.oracle.com/cd/E15357_01/coh.360/e15723/cache_rtwtwbra.htm#COHDG5177)\n* [Cache-Aside pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/cache-aside)\n* [Java EE 8 High Performance: Master techniques such as memory optimization, caching, concurrency, and multithreading to achieve maximum performance from your enterprise applications](https://www.amazon.com/gp/product/178847306X/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=178847306X&linkId=e948720055599f248cdac47da9125ff4)\n* [Java Performance: In-Depth Advice for Tuning and Programming Java 8, 11, and Beyond](https://www.amazon.com/gp/product/1492056111/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1492056111&linkId=7e553581559b9ec04221259e52004b08)\n* [Effective Java](https://www.amazon.com/gp/product/B078H61SCH/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=B078H61SCH&linkId=f06607a0b48c76541ef19c5b8b9e7882)\n* [Java Performance: The Definitive Guide: Getting the Most Out of Your Code](https://www.amazon.com/gp/product/1449358454/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1449358454&linkId=475c18363e350630cc0b39ab681b2687)\n"
  },
  {
    "path": "localization/pt/chain-of-responsability/README.md",
    "content": "---\ntitle: Chain of responsibility\ncategory: Behavioral\nlanguage: pt\ntag:\n - Gang of Four\n---\n\n## Propósito\n\nEvitar acoplar o remetente de uma *request* ao seu destinatário, dando a mais de um objeto a chance de\nlidar com a solicitação. Encadeie os objeto recebidos e passe a solicitação ao longo da cadeia até um objeto\nlidar com isso.\n\n## Explicação\n\nExemplo do mundo real\n\n> O Rei Orc dá ordens ao seu exército. O primeiro a receber a ordem é o comandante, então\n> um oficial e depois um soldado. O comandante, o oficial e o soldado formam uma cadeia de responsabilidades.\n\n\nEm outras palavras\n\n> Ajuda a construir uma cadeia de objetos. Uma solicitação entra de uma extremidade e continua indo de um objeto\n> para outro até encontrar um manipulador adequado.\n\nWikipedia diz\n\n> Em orientação a objetos, Chain of Responsibility é um padrão cuja principal função é evitar a dependência \n> entre um objeto receptor e um objeto solicitante. Consiste em uma série de objetos receptores e de objetos\n> de solicitação, onde cada objeto de solicitação possui uma lógica interna que separa quais são tipos de \n> objetos receptores que podem ser manipulados. O restante é passado para os próximos objetos de solicitação da cadeia.\n\n**Exemplo de programação**\n\nTraduzindo nosso exemplo com os orcs acima. Primeiro, nós temos a classe `Request`:\n\n```java\npublic class Request {\n\n  private final RequestType requestType;\n  private final String requestDescription;\n  private boolean handled;\n\n  public Request(final RequestType requestType, final String requestDescription) {\n    this.requestType = Objects.requireNonNull(requestType);\n    this.requestDescription = Objects.requireNonNull(requestDescription);\n  }\n\n  public String getRequestDescription() { return requestDescription; }\n\n  public RequestType getRequestType() { return requestType; }\n\n  public void markHandled() { this.handled = true; }\n\n  public boolean isHandled() { return this.handled; }\n\n  @Override\n  public String toString() { return getRequestDescription(); }\n}\n\npublic enum RequestType {\n  DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX\n}\n```\n\nEm seguida, mostramos a hierarquia no request handler\n\n```java\npublic interface RequestHandler {\n\n    boolean canHandleRequest(Request req);\n\n    int getPriority();\n\n    void handle(Request req);\n\n    String name();\n}\n\n@Slf4j\npublic class OrcCommander implements RequestHandler {\n    @Override\n    public boolean canHandleRequest(Request req) {\n        return req.getRequestType() == RequestType.DEFEND_CASTLE;\n    }\n\n    @Override\n    public int getPriority() {\n        return 2;\n    }\n\n    @Override\n    public void handle(Request req) {\n        req.markHandled();\n        LOGGER.info(\"{} handling request \\\"{}\\\"\", name(), req);\n    }\n\n    @Override\n    public String name() {\n        return \"Orc commander\";\n    }\n}\n\n// OrcOfficer and OrcSoldier are defined similarly as OrcCommander\n\n```\n\nO Rei Orc dá as ordens e forma a cadeia\n\n```java\npublic class OrcKing {\n\n  private List<RequestHandler> handlers;\n\n  public OrcKing() {\n    buildChain();\n  }\n\n  private void buildChain() {\n    handlers = Arrays.asList(new OrcCommander(), new OrcOfficer(), new OrcSoldier());\n  }\n\n  public void makeRequest(Request req) {\n    handlers\n        .stream()\n        .sorted(Comparator.comparing(RequestHandler::getPriority))\n        .filter(handler -> handler.canHandleRequest(req))\n        .findFirst()\n        .ifPresent(handler -> handler.handle(req));\n  }\n}\n```\n\nO chain of responsibility em ação.\n\n```java\nvar king = new OrcKing();\nking.makeRequest(new Request(RequestType.DEFEND_CASTLE, \"defend castle\"));\nking.makeRequest(new Request(RequestType.TORTURE_PRISONER, \"torture prisoner\"));\nking.makeRequest(new Request(RequestType.COLLECT_TAX, \"collect tax\"));\n```\n\nA saída do console.\n\n```\nOrc commander handling request \"defend castle\"\nOrc officer handling request \"torture prisoner\"\nOrc soldier handling request \"collect tax\"\n```\n\n## Diagrama de classe\n\n![alt text](././etc/chain-of-responsibility.urm.png \"Diagrama de classe Chain of Responsibility\")\n\n## Aplicabilidade\n\nUsar Chain of Responsibility quando\n\n* Mais de um objeto pode lidar com uma solicitação, e o manipulador não é conhecido a priori. O manipulador deve ser verificado automaticamente.\n* Você deseja emitir uma solicitação para um dos vários objetos sem especificar o destinatário explicitamente.\n* O conjunto de objetos que podem lidar com uma solicitação deve ser especificado dinamicamente.\n\n## Exemplos do mundo real\n\n* [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29)\n* [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html)\n* [javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/pt/facade/README.md",
    "content": "---\ntitle: Facade\ncategory: Structural\nlanguage: pt\ntag:\n - Gang Of Four\n - Decoupling\n---\n\n## Propósito\n\nProver uma interface unificada para um conjunto de interfaces em um subsistema.\nFacade (ou fachada) define uma interface num nível mais elevado que torna o subsistema mais fácil de ser utilizado.\n\n## Explicação\n\nReal-world example\nExemplo do mundo real\n\n> Como uma mina de ouro funciona? \"Bem, os mineradores vão pro subsolo, cavam e encontram ouro!\" você pode dizer.\n> Isso é o que você acredita porque você está usando uma simples interface que a mina de ouro provê para o exterior,\n> internamente há muitas coisas a fazer para que isso aconteça. Essa interface simples para um subsistema complexo é\n> um facade.\n\nEm termos pŕaticos\n\n> O padrão Facade provê uma interface simplificada para um subsistema complexo.\n\nWikipedia diz\n\n> Um facade é um objeto que provê uma interface simplificada para um corpo maior de código fonte,\n> como uma biblioteca de uma classe.\n\n**Exemplo programático**\n\nVamos pegar nosso exemplo da mina de ouro acima. Aqui temos uma hierarquia de anão minerador.\nPrimeiro há uma classe base `DwarvenMineWorker`:\n\n```java\n\n@Slf4j\npublic abstract class DwarvenMineWorker {\n\n    public void goToSleep() {\n        LOGGER.info(\"{} goes to sleep.\", name());\n    }\n\n    public void wakeUp() {\n        LOGGER.info(\"{} wakes up.\", name());\n    }\n\n    public void goHome() {\n        LOGGER.info(\"{} goes home.\", name());\n    }\n\n    public void goToMine() {\n        LOGGER.info(\"{} goes to the mine.\", name());\n    }\n\n    private void action(Action action) {\n        switch (action) {\n            case GO_TO_SLEEP -> goToSleep();\n            case WAKE_UP -> wakeUp();\n            case GO_HOME -> goHome();\n            case GO_TO_MINE -> goToMine();\n            case WORK -> work();\n            default -> LOGGER.info(\"Undefined action\");\n        }\n    }\n\n    public void action(Action... actions) {\n        Arrays.stream(actions).forEach(this::action);\n    }\n\n    public abstract void work();\n\n    public abstract String name();\n\n    enum Action {\n        GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK\n    }\n}\n```\n\nEntão nós temos as classes concretas anão `DwarvenTunnelDigger`, `DwarvenGoldDigger` and \n`DwarvenCartOperator`: \n\n```java\n@Slf4j\npublic class DwarvenTunnelDigger extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} creates another promising tunnel.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarven tunnel digger\";\n  }\n}\n\n@Slf4j\npublic class DwarvenGoldDigger extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} digs for gold.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarf gold digger\";\n  }\n}\n\n@Slf4j\npublic class DwarvenCartOperator extends DwarvenMineWorker {\n\n  @Override\n  public void work() {\n    LOGGER.info(\"{} moves gold chunks out of the mine.\", name());\n  }\n\n  @Override\n  public String name() {\n    return \"Dwarf cart operator\";\n  }\n}\n\n```\n\nPara operar todos esses mineradores de ouro temos o `DwarvenGoldmineFacade`: \n\n```java\npublic class DwarvenGoldmineFacade {\n\n  private final List<DwarvenMineWorker> workers;\n\n  public DwarvenGoldmineFacade() {\n      workers = List.of(\n            new DwarvenGoldDigger(),\n            new DwarvenCartOperator(),\n            new DwarvenTunnelDigger());\n  }\n\n  public void startNewDay() {\n    makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE);\n  }\n\n  public void digOutGold() {\n    makeActions(workers, DwarvenMineWorker.Action.WORK);\n  }\n\n  public void endDay() {\n    makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);\n  }\n\n  private static void makeActions(Collection<DwarvenMineWorker> workers,\n      DwarvenMineWorker.Action... actions) {\n    workers.forEach(worker -> worker.action(actions));\n  }\n}\n```\n\nAgora vamos usar o facade:\n\n```java\nvar facade = new DwarvenGoldmineFacade();\nfacade.startNewDay();\nfacade.digOutGold();\nfacade.endDay();\n```\n\nSaída do programa:\n\n```java\n// Dwarf gold digger wakes up.\n// Dwarf gold digger goes to the mine.\n// Dwarf cart operator wakes up.\n// Dwarf cart operator goes to the mine.\n// Dwarven tunnel digger wakes up.\n// Dwarven tunnel digger goes to the mine.\n// Dwarf gold digger digs for gold.\n// Dwarf cart operator moves gold chunks out of the mine.\n// Dwarven tunnel digger creates another promising tunnel.\n// Dwarf gold digger goes home.\n// Dwarf gold digger goes to sleep.\n// Dwarf cart operator goes home.\n// Dwarf cart operator goes to sleep.\n// Dwarven tunnel digger goes home.\n// Dwarven tunnel digger goes to sleep.\n```\n\n## Diagrama de classe\n\n![alt text](./etc/facade.urm.png \"Diagrama de classe padrão Facade\")\n\n## Aplicabilidade\n\nUse o padrão facade quando\n\n* Você quer prover uma simples interface para um subsistema complexo. Subsistemas frequentemente\nvão ficando mais complexos conforme eles evoluem. A maioria dos padrões, quando aplicada, resulta\nem classes menores e mais numerosas. Isso faz com que o subsistema se torne mais reusável e mais\nfácil de customizar, mas também torna mais difícil de usar para clientes que não precisam de\ncustomização.\n* Há muitas dependências entre clientes e as classes de implementação de uma abstração. Introduza\num facade para desacoplar o subsistema de clientes e outros subsistemas, portanto promovendo independência\ne portabilidade para o subsistema.\n* Você quer subdividir em camadas o seu subsistema. Use um facade para definir um ponto de entrada\npara cada nível de subsistema. Se o subsistema é dependente, então você pode simplificar as dependências\nentre eles, fazendo-os se comunicarem entre si apenas pelos facades.\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/pt/factory/README.md",
    "content": "---\ntitle: Factory\ncategory: Creational\nlanguage: pt\ntag:\n - Gang of Four\n---\n\n## Também conhecido como\n\n* Simple Factory\n* Static Factory Method\n\n## Propósito\n\nFornecer um método estático encapsulado em uma classe conhecida como factory, para ocultar a lógica\nde implementação e fazer com que o código do cliente se preocupe apenas com sua utilização em vez de\ninicializar novos objetos.\n\n## Explicação\n\nExemplo de mundo real\n\n> Imagine um alquimista que está prestes a fabricar moedas. O alquimista deve ser capaz de produzir\n> moedas de ouro e cobre, e a alternância entre a fabricação destas deve ser possível sem a necessidade\n> de modificar o código fonte. O padrão factory torna isso possível fornecendo um método construtor estático\n> que pode ser chamado com parâmetros relevantes.\n\nWikipedia diz\n\n> Factory é um objeto para a criação de outros objetos - formalmente uma factory é uma função ou método\n> que retorna objetos de protótipos ou classes variadas.\n\n**Exemplo de programação**\n\nTemos uma interface `Coin` e duas implementações `GoldCoin` e `CopperCoin`.\n\n```java\npublic interface Coin {\n  String getDescription();\n}\n\npublic class GoldCoin implements Coin {\n\n  static final String DESCRIPTION = \"This is a gold coin.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\npublic class CopperCoin implements Coin {\n   \n  static final String DESCRIPTION = \"This is a copper coin.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n```\n\nO enum abaixo representa os tipos de moedas que suportamos (`GoldCoin` e `CopperCoin`).\n\n```java\n@RequiredArgsConstructor\n@Getter\npublic enum CoinType {\n\n  COPPER(CopperCoin::new),\n  GOLD(GoldCoin::new);\n\n  private final Supplier<Coin> constructor;\n}\n```\n\nEntão temos o método estático `getCoin` para criar objetos de moeda encapsulados na classe factory\n`CoinFactory`.\n\n```java\npublic class CoinFactory {\n\n  public static Coin getCoin(CoinType type) {\n    return type.getConstructor().get();\n  }\n}\n```\n\nAgora no código cliente podemos criar diferentes tipos de moedas usando a classe factory.\n\n```java\nLOGGER.info(\"The alchemist begins his work.\");\nvar coin1 = CoinFactory.getCoin(CoinType.COPPER);\nvar coin2 = CoinFactory.getCoin(CoinType.GOLD);\nLOGGER.info(coin1.getDescription());\nLOGGER.info(coin2.getDescription());\n```\n\nSaída do programa:\n\n```java\nThe alchemist begins his work.\nThis is a copper coin.\nThis is a gold coin.\n```\n\n## Diagrama de classes\n\n![alt text](./etc/factory.urm.png \"Diagrama de classes do padrão Factory\")\n\n## Aplicabilidade\n\nUtilize o padrão factory quando a preocupação é apenas em criar o objeto, e não como criar\ne gerenciá-lo.\n\nPrós\n\n* Permite manter a criação de todos os objetos em um só lugar e evita espalhar a palavra-chave 'new' pela base de código.\n* Permite escrever código desacoplado. Algumas de suas principais vantagens incluem uma melhor testabilidade, código fácil de entender, componentes substituíveis, escalabilidade e funcionalidades isoladas.\n\nContras\n\n* O código se torna mais complicado do que deveria.\n\n## Usos conhecidos\n\n* [java.util.Calendar#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)\n* [java.util.ResourceBundle#getBundle()](https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)\n* [java.text.NumberFormat#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)\n* [java.nio.charset.Charset#forName()](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)\n* [java.net.URLStreamHandlerFactory#createURLStreamHandler(String)](https://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html) (retorna objetos singleton diferentes, dependendo do protocolo)\n* [java.util.EnumSet#of()](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of(E))\n* [javax.xml.bind.JAXBContext#createMarshaller()](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--) e outros métodos parecidos.\n\n## Padrões relacionados\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/)\n\n"
  },
  {
    "path": "localization/pt/proxy/README.md",
    "content": "---\ntitle: Proxy\ncategory: Structural\nlanguage: pt\ntag:\n - Gang Of Four\n - Decoupling\n---\n\n## Também conhecido como\n\nSurrogate\n\n## Propósito\n\nFornecer um substituto para controlar o acesso ao objeto original\n\n## Explicação\n\nExemplo de mundo real\n\n> Imagine uma torre onde magos locais vão estudar os seus feitiços. A torre de marfim consegue ser\n> acedida através de uma proxy que garante que apenas os três primeiros magos podem entrar. Aqui a proxy \n> representa a funcionalidade da torre e adiciona controlo de acesso a ela.\n\nEm palavras simples\n\n> Usando um padrão proxy, a classe representa a funcionalidade de uma outra classe.\n\nWikipedia diz\n\n> Uma proxy, na sua forma mais genérica, é uma classe a funcionar como interface para algo.\n> Uma proxy é um wrapper ou objeto agente que está a ser chamado pelo cliente para aceder ao verdadeiro\n> objeto por detrás das cortinas. O uso de uma proxy pode ser apenas redirecionar para o objeto real, ou \n> pode fornecer lógica adicional. Numa proxy, funcionalidade extra também pode ser fornecida, por exemplo apanhar \n> operações no objeto real que gastam muitos recursos, ou verificar precondições antes\n> das operações no objeto real serem invocadas.\n\n**Exemplos de programação**\n\nUsando a nossa torre de magos do exemplo acima. Primeiro temos a interface `WizardTower` e a classe\n`IvoryTower`.\n\n```java\npublic interface WizardTower {\n\n  void enter(Wizard wizard);\n}\n\n@Slf4j\npublic class IvoryTower implements WizardTower {\n\n  public void enter(Wizard wizard) {\n    LOGGER.info(\"{} enters the tower.\", wizard);\n  }\n\n}\n```\n\nDepois uma simples classe `Wizard`.\n\n```java\npublic class Wizard {\n\n  private final String name;\n\n  public Wizard(String name) {\n    this.name = name;\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n}\n```\n\nDepois temos a `WizardTowerProxy` para adicionar controlo à `WizardTower`.\n\n```java\n@Slf4j\npublic class WizardTowerProxy implements WizardTower {\n\n  private static final int NUM_WIZARDS_ALLOWED = 3;\n\n  private int numWizards;\n\n  private final WizardTower tower;\n\n  public WizardTowerProxy(WizardTower tower) {\n    this.tower = tower;\n  }\n\n  @Override\n  public void enter(Wizard wizard) {\n    if (numWizards < NUM_WIZARDS_ALLOWED) {\n      tower.enter(wizard);\n      numWizards++;\n    } else {\n      LOGGER.info(\"{} is not allowed to enter!\", wizard);\n    }\n  }\n}\n```\n\nE aqui está a torre a entrar em cenário.\n\n```java\nvar proxy = new WizardTowerProxy(new IvoryTower());\nproxy.enter(new Wizard(\"Red wizard\"));\nproxy.enter(new Wizard(\"White wizard\"));\nproxy.enter(new Wizard(\"Black wizard\"));\nproxy.enter(new Wizard(\"Green wizard\"));\nproxy.enter(new Wizard(\"Brown wizard\"));\n```\n\nSaída do programa:\n\n```\nRed wizard enters the tower.\nWhite wizard enters the tower.\nBlack wizard enters the tower.\nGreen wizard is not allowed to enter!\nBrown wizard is not allowed to enter!\n```\n\n## Diagrama de classes\n\n![alt text](./etc/proxy.urm.png \"Diagrama de classes do padrão proxy\")\n\n## Aplicabilidade\n\nO proxy é aplicável quando existe a necessidade de uma referência a um objeto mais versátil ou sofisticada em vez de um simples ponteiro. Aqui estão várias situações comuns em que o padrão Proxy é aplicável.\n\n* Proxy remoto dá uma representação local de um objeto num espaço de endereçamento diferente.\n* Proxy virtual cria objetos dispendiosos quando requisitado.\n* Proxy de proteção controla o acesso ao objeto original. Proxies de proteção são úteis quando objetos deviam ter direitos de acesso diferentes.\n\nTipicamente, o padrão proxy é usado para\n\n* Controlar acesso a um outro objeto\n* Inicialização preguiçosa\n* Implementar um registro de eventos (logging)\n* Facilitar a conexão com a rede\n* Contar o número de referências para um objeto\n\n## Tutoriais\n\n* [Controlar acesso com um padrão Proxy](http://java-design-patterns.com/blog/controlling-access-with-proxy-pattern/)\n\n## Usos conhecidos\n\n* [java.lang.reflect.Proxy](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html)\n* [Apache Commons Proxy](https://commons.apache.org/proper/commons-proxy/)\n* Frameworks para Mocking [Mockito](https://site.mockito.org/), \n[Powermock](https://powermock.github.io/), [EasyMock](https://easymock.org/)\n* UIKit's da Apple [UIAppearance](https://developer.apple.com/documentation/uikit/uiappearance)\n\n## Padrões relacionados\n\n* [Ambassador](https://java-design-patterns.com/patterns/ambassador/)\n\n## Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/pt/singleton/README.md",
    "content": "---\ntitle: \"Singleton Pattern in Java: Implementing Global Access Points in Java Applications\"\nshortTitle: Singleton\ndescription: \"Explore the Singleton Pattern in Java with our comprehensive guide. Learn how to implement efficient object management for your Java applications, ensuring optimal use of resources and easy access with examples and detailed explanations.\"\ncategory: Creational\nlanguage: pt\ntag:\n  - Gang of Four\n  - Instantiation\n  - Lazy initialization\n  - Resource management\n---\n\n## Também conhecido como\n\n* Single Instance\n\n## Propósito\n\nAssegurar que a classe Java possua somente uma instância e forneça um ponto global de acesso a essa instância Singleton.\n\n## Explicação\n\nExemplo do Mundo Real\n\n> Uma analogia do mundo real para o padrão Singleton é um governo emitindo um passaporte. Em um país, cada cidadão pode receber apenas um passaporte válido por vez. O escritório de passaportes garante que nenhum passaporte duplicado seja emitido para a mesma pessoa. Sempre que um cidadão precisa viajar, ele deve usar este passaporte único, que serve como o identificador único e globalmente reconhecido para suas credenciais de viagem. Este acesso controlado e gerenciamento de instância exclusivo espelham como o padrão Singleton garante o gerenciamento eficiente de objetos em aplicativos Java.\n\nEm outras palavras\n\n> Assegura que somente um objeto de classe em particular seja criado.\n\nDe acordo com a Wikipédia\n\n> Na engenharia de software, o padrão Singleton é um padrão de design de software que restringe a instanciação de uma classe a um objeto. Isso é útil quando exatamente um objeto é necessário para coordenar ações no sistema.\n\n## Exemplo Programático\n\nJoshua Bloch, Effective Java 2nd Edition pg.18\n\n> Um tipo Enum de elemento único é a melhor maneira de implementar um Singleton\n\n```java\npublic enum EnumIvoryTower {\n  INSTANCE\n}\n```\n\nEntão para usar:\n\n```java\n    var enumIvoryTower1 = EnumIvoryTower.INSTANCE;\n    var enumIvoryTower2 = EnumIvoryTower.INSTANCE;\n    LOGGER.info(\"enumIvoryTower1={}\", enumIvoryTower1);\n    LOGGER.info(\"enumIvoryTower2={}\", enumIvoryTower2);\n```\n\nA saída do console\n\n```\nenumIvoryTower1=com.iluwatar.singleton.EnumIvoryTower@1221555852\nenumIvoryTower2=com.iluwatar.singleton.EnumIvoryTower@1221555852\n```\n\n## Quando usar\n\nUse o padrão Singleton quando\n\n* Deve haver exatamente uma instância de uma classe, e ela deve ser acessível aos clientes a partir de um ponto de acesso bem conhecido\n* Quando a única instância deve ser extensível por herança, e os clientes devem ser capazes de usar uma instância estendida sem modificar seu código\n\n## Aplicações do mundo real\n\n* A classe de Log\n* Classes de configuração em muitos aplicativos\n* Pools de conexão\n* Gerenciador de arquivos\n* [java.lang.Runtime#getRuntime()](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime%28%29)\n* [java.awt.Desktop#getDesktop()](http://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#getDesktop--)\n* [java.lang.System#getSecurityManager()](http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getSecurityManager--)\n\n## Benefícios e desafios do padrão Singleton\n\nBenefícios:\n\n* Acesso controlado à instância única.\n* Poluição reduzida do namespace.\n* Permite refinamento de operações e representação.\n* Permite um número variável de instâncias (se desejado mais de uma).\n* Mais flexível do que operações de classe.\n\nDesafios:\n\n* Difícil de testar devido ao estado global.\n* Gerenciamento de ciclo de vida potencialmente mais complexo.\n* Pode introduzir gargalos se usado em um contexto concorrente sem sincronização cuidadosa.\n\n## Outros Padrōes de Projeto Relacionados\n\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): Geralmente usado para garantir que uma classe tenha apenas uma instância.\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): O padrão Singleton pode ser implementado usando o padrāo Factory para encapsular a lógica de criação.\n* [Prototype](https://java-design-patterns.com/patterns/prototype/): Evita a necessidade de criar instâncias, pode ser usado em conjunto com o Singleton para gerenciar instâncias únicas.\n\n## Referências e Créditos\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "localization/ru/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n\n# Шаблоны проектирования на Java\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-178-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n# Введение\nШаблоны проектирования - лучший метод для решения проблем, возникающих\nво время разработки приложения или системы.\n\nШаблоны проектирования могут ускорить процесс разработки путем предоставления\nпроверенных моделей/парадигм.\n\nИспользование шаблонов повторно поможет избежать частых проблем, из-за которых\nпроисходят проблемы. А еще это повысит читаемость кода для программистов и \nархитекторов, знакомых с шаблонами.\n\n# Начало работы\n\nВ этом репозитории размещены шаблоны проектирования на Java. Они были разработаны\nпрограммистами из open source сообщества. Шаблон может быть выбран \nиз его описания или просмотром его исходного кода. Код хорошо задокументирован,\nего можно рассматривать, как учебник по программированию о конкретном шаблоне.\nМы используем самые популярные (прошедшие огонь, воду и медные трубы) технологии,\nоснованные только на ПО с открытым исходным кодом.\n\nПреждем чем нырнуть в материал, тебе следует ознакомиться с различными\n[принципами разработки ПО(англ)](https://java-design-patterns.com/principles/).\n\nВсе конструкции должны быть максимально простыми. Не делай лишнюю функциональность,\nкоторая скорей всего не пригодиться, а просто создай простую штуку, что сможет\nработать. Усложнять и вводить паттерны необходимо, лишь когда масштабируемость\nдействительно нужна.\n\nКак только ознакомитесь с этими концепциями, приступайте к изучению\n[доступных шаблонов проектирования(англ)](https://java-design-patterns.com/patterns/) любым\nиз следующих методов:\n\n- Ищите шаблон по имени. Не смогли найти такой? Сообщите об этом [здесь](https://github.com/iluwatar/java-design-patterns/issues).\n- Используя тэги, например `Performance`, `Gang of Four` или `Data access`.\n- Используя категории шаблонов `Creational`, `Behavioral` и другие.\n\nНадеемся объективно-ориентированные решения, представленные здесь будут вам \nполезны и найдут место в ваших проектах, а также вы получите такое же удовольствие \nот их изучения, какое получили мы во время их разработки.\n\n# Как принять участие в разработке\n\nЕсли вы захотите принять участие в жизни проекта, вся полезная информация находится на \nнашей [вики(англ)](https://github.com/iluwatar/java-design-patterns/wiki). Мы можем помочь\nи ответить на твои вопросы в чате [Gitter](https://gitter.im/iluwatar/java-design-patterns).\n\n# Лицензия\n\nПроект основывается на тезисах лицензии MIT.\n\n"
  },
  {
    "path": "localization/ru/abstract-factory/README.md",
    "content": "---\ntitle: Abstract Factory\ncategory: Creational\nlanguage: ru\ntag:\n - Gang of Four\n---\n\n## Альтернативные названия\nKit\n\n## Цель\nПредоставление интерфейса для создания семейств взаимосвязанных или взаимозависимых объектов без указания их конкретных классов.\n\n## Объяснение\nПример из реального мира:\n> Представьте, что вы хотите создать королевство с замком, королём и армией. Эльфийскому королевству понадобится эльфийский замок, эльфийский король и эльфийская армия, в то время как оркскому королевству понадобится оркский замок, оркский король и оркская армия. Между объектами королевства существует взаимозависимость.\n\nПростыми словами:\n> Фабрика фабрик; фабрика, которая объединяет отдельные, но взаимозависимые/взаимозаменяемые фабрики без указания их конкретных классов.\n\nВикипедия пишет:\n> Порождающий шаблон проектирования, предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя￼ их конкретных классов.￼\n\n**Программный пример**\\\nОсновываясь на примере королевства выше, во-первых, нам понадобятся интерфейсы и реализации для объектов в королевстве.\n\n```java\npublic interface Castle {\n  String getDescription();\n}\n\npublic interface King {\n  String getDescription();\n}\n\npublic interface Army {\n  String getDescription();\n}\n\n// Эльфийская реализация\npublic class ElfCastle implements Castle {\n  static final String DESCRIPTION = \"Это эльфийский замок!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfKing implements King {\n  static final String DESCRIPTION = \"Это эльфийский король!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfArmy implements Army {\n  static final String DESCRIPTION = \"Это эльфийская армия!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\n// Оркская реализация\npublic class OrcCastle implements Castle {\n  static final String DESCRIPTION = \"Это оркский замок!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class OrcKing implements King {\n  static final String DESCRIPTION = \"Это оркский король!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class OrcArmy implements Army {\n  static final String DESCRIPTION = \"Это оркская армия!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n```\n\nВо-вторых, нам понадобятся абстракция фабрики королевства, а также реализации этой абстракции:\n\n```java\npublic interface KingdomFactory {\n  Castle createCastle();\n  King createKing();\n  Army createArmy();\n}\n\npublic class ElfKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new ElfCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new ElfKing();\n  }\n\n  @Override\n  public Army createArmy() {\n    return new ElfArmy();\n  }\n}\n\npublic class OrcKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new OrcCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new OrcKing();\n  }\n  \n  @Override\n  public Army createArmy() {\n    return new OrcArmy();\n  }\n}\n```\n\nНа данный момент, у нас есть абстрактная фабрика, которая позволяет создавать семейство взаимосвязанных объектов, то есть фабрика эльфийского королевства создаёт эльфийский замок, эльфийского короля, эльфийскую армию и так далее:\n\n```java\nvar factory = new ElfKingdomFactory();\nvar castle = factory.createCastle();\nvar king = factory.createKing();\nvar army = factory.createArmy();\n\ncastle.getDescription();\nking.getDescription();\narmy.getDescription();\n```\n\nВывод программы:\n\n```\nЭто эльфийский замок!\nЭто эльфийский король!\nЭто эльфийская армия!\n```\n\nМожно спроектировать фабрику для наших различных фабрик королевств. В следующем примере, мы создали `FactoryMaker`, который ответственен за создание экземпляра `ElfKingdomFactory`, либо `OrcKingdomFactory`.\n\nКлиент может использовать класс `FactoryMaker`, чтобы создать желаемую конкретную фабрику, которая в свою очередь будет производить разные конкретные объекты, унаследованные от `Castle`, `King`, `Army`.\n\nВ этом примере использовано перечисление, чтобы параметризовать то, какую фабрику королевства запрашивает клиент:\n\n```java\npublic static class FactoryMaker {\n  public enum KingdomType {\n    ELF, ORC\n  }\n\n  public static KingdomFactory makeFactory(KingdomType type) {\n    return switch (type) {\n      case ELF -> new ElfKingdomFactory();\n      case ORC -> new OrcKingdomFactory();\n      default -> throe new IllegalArgumentException(\"Данный тип королества не поддерживается.\")\n    }\n  }\n}\n\n  public static void main(String[] args) {\n    var app = new App();\n    \n    LOGGER.info(\"Эльфийское королевство\");\n    app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));\n    LOGGER.indo(app.getCastle().getDescription());\n    LOGGER.indo(app.getKinv().getDescription());\n    LOGGER.indo(app.getArmy().getDescription());\n\n    LOGGER.info(\"Оркское королевство\");\n\n    app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));\n    LOGGER.indo(app.getCastle().getDescription());\n    LOGGER.indo(app.getKinv().getDescription());\n    LOGGER.indo(app.getArmy().getDescription());\n  }\n\n```\n\n## Диаграмма классов\n![Диаграмма классов паттерна проектирования абстрактная фабрика](../../../abstract-factory/etc/abstract-factory.urm.png)\n\n## Применимость\nИспользуйте шаблон проектирования абстрактная фабрика, когда:\n\n- Система должна быть независимой от того, как создаются, составляются и представляются её продукты;\n- Система должна быть сконфигурирована одним из нескольких семейств продуктов;\n- Семейство связанных продуктов спроектировано для совместного использования и вам необходимо обеспечить соблюдение данного ограничения;\n- Вы хотите предоставить библиотеку классов, но готовы раскрыть только их интерфейсы, но не реализацию;\n- Время жизни зависимости концептуально короче, чем время жизни потребителя;\n- Вам требуется значение времени исполнения, чтобы создать требуемую зависимость;\n- Вы хотите решить какие продукты из семейства вам нужны во время исполнения;\n- Вам нужно предоставить один или несколько параметров, которые известны только во время исполнения прежде, чем вы сможете решить зависимость;\n- В случае, когда требуется последовательность среди продуктов;\n- Вы не хотите менять существующий код, когда добавляются новые продукты или семейство продуктов в программе.\n\nПримеры сценариев использования:\n\n- Выбор необходимой реализации FileSystemAcmeService или DataBaseAcmeSerivce или NetworkAcmeService во времени выполнения;\n- Написание модульных тестов становится намного легче;\n- Элементы графического пользовательского интерфейса для различных операционных систем.\n\n## Следствия\n- Внедрение зависимости в Java скрывает зависимости класса, приводящие к ошибкам времени выполнения, которые могли-бы быть обнаружены во времени компиляции;\n- Данный паттерн проектирования отлично справляется с задачей создания уже определённых объектов, но добавление новых может быть трудоёмким;\n- Код становится сложнее, чем ему следует из-за появления большого количества новых интерфейсов и классов, которые появляются вместе с этим паттерном проектирования.\n\n## Руководства\n* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java) \n\n## Известные применения\n* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)\n* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)\n* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)\n\n## Родственные паттерны проектирования\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n\n## Благодарности\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/si/README.md",
    "content": "<!-- The line below should be a blank line C: (because it's not kramdown\n     It's smart and lovely that a blank line is required before a heading\n     Show it like this, e.g. website) -->\n\n# ජාවා නිර්මාණ රටා\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-176-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n<!-- <br/>\n\nBaca dalam bahasa lain : [**zh**](localization/zh/README.md), [**ko**](localization/ko/README.md), [**fr**](localization/fr/README.md), [**tr**](localization/tr/README.md), [**ar**](localization/ar/README.md), [**es**](localization/es/README.md), [**pt**](localization/pt/README.md), [**id**](localization/id/README.md)\n\n<br/> -->\n\n# හැදින්වීම\n\nපැන නගින ගැටළු විසඳීම සඳහා හොඳම ක්රමය නිර්මාණ රටා වේ.\n\nසැලසුම් රටා ලබා දීමෙන් සංවර්ධන ක්රියාවලිය වේගවත් කළ හැකිය.\n\nසැකිලි නැවත භාවිතා කිරීම හේතු වන පොදු ගැටළු මඟහරවා ගැනීමට උපකාරී වේ.\nගැටළු ඇතිවේ. මෙය ක්‍රමලේඛකයින් සඳහා කේතයේ කියවීමේ හැකියාවද වැඩි කරයි.\n\n\n# ආරම්භය\n\nමෙම ගබඩාව Java හි නිර්මාණ රටා සත්කාරකත්වය සපයයි. ඒවා දියුණු කළා\nවිවෘත මූලාශ්‍ර ප්‍රජාවේ ක්‍රමලේඛකයින්. රටාව තෝරා ගත හැකිය.\nඑහි විස්තරයෙන් හෝ එහි මූල කේතය බැලීමෙන්. කේතය හොඳින් ලේඛනගත කර ඇත,\nඑය නිශ්චිත රටාවක් පිළිබඳ ක්‍රමලේඛන නිබන්ධනයක් ලෙස සැලකිය හැකිය.\nඅපි වඩාත් ජනප්රිය (ගිනි, ජලය සහ තඹ පයිප්ප පරීක්ෂා කරන ලද) තාක්ෂණයන් භාවිතා කරමු,\nවිවෘත කේත මෘදුකාංග මත පමණක් පදනම් වේ.\n\nමෙයට කිමිදීමට පෙර, ඔබ විවිධත්වය ගැන හුරුපුරුදු විය යුතුය.\n[මෘදුකාංග සංවර්ධනයේ මූලධර්ම](https://java-design-patterns.com/principles/).\n\nසියලුම මෝස්තර හැකි තරම් සරල විය යුතුය. අනවශ්‍ය ක්‍රියාකාරීත්වයක් ඇති නොකරන්න\nබොහෝ දුරට ප්‍රයෝජනවත් නොවනු ඇත, නමුත් කළ හැකි සරල දෙයක් සාදන්න\nකාර්යය. පරිමාණය කිරීමේදී පමණක් රටා සංකීර්ණ කිරීම හා හඳුන්වා දීම අවශ්ය වේ\nඇත්තටම අවශ්යයි.\n\nඔබ මෙම සංකල්ප ගැන හුරුපුරුදු වූ පසු, අධ්යයනය ආරම්භ කරන්න\n[ලබා ගත හැකි නිර්මාණ රටා](https://java-design-patterns.com/patterns/)\nපහත ක්‍රම වලින්:\n\n- නමින් සැකිල්ලක් සොයන්න. එකක් හොයාගන්න බැරි වුනාද? එය වාර්තා කරන්න [මෙහි](https://github.com/iluwatar/java-design-patterns/issues).\n- `Performance`, `Gang of Four` හෝ `Data access` වැනි ටැග් භාවිතා කිරීම.\n- සැකිලි කාණ්ඩ භාවිතා කිරීම  `Creational`, `Behavioral` සහ වෙනත්.\n\n\nමෙහි ඉදිරිපත් කර ඇති වෛෂයික-නැඹුරු විසඳුම් ඔබට ප්‍රයෝජනවත් වනු ඇතැයි අපි බලාපොරොත්තු වෙමු\nප්රයෝජනවත් වන අතර ඔබේ ව්යාපෘතිවල ස්ථානයක් සොයා ගනු ඇත, ඔබට එම සතුට ලැබෙනු ඇත\nඔවුන්ගේ සංවර්ධනයේදී අපට ලැබුණු අධ්‍යයනයෙන්.\n\n# සංවර්ධනයට සහභාගී වන්නේ කෙසේද\nඔබට ව්‍යාපෘතියේ ජීවිතයට සහභාගී වීමට අවශ්‍ය නම්, සියලු ප්‍රයෝජනවත් තොරතුරු ක්‍රියාත්මක වේ\nඅපගේ [wiki](https://github.com/iluwatar/java-design-patterns/wiki). අපිට උදව් කරන්න පුළුවන්\nසහ [Gitter] කතාබස් (https://gitter.im/iluwatar/java-design-patterns) තුළ ඔබේ ප්‍රශ්නවලට පිළිතුරු දෙන්න.\n\n# බලපත්‍රය\nව්‍යාපෘතිය MIT බලපත්‍රයේ සාරාංශ මත පදනම් වේ.\n\n"
  },
  {
    "path": "localization/tr/README.md",
    "content": "<!-- Biçimlendirme nedeniyle bu satır boş bırakılmalıdır böylelikle hoş bir görüntüye sahip olabiliriz. örneğin web sitesi -->\n\n![Java CI with Maven](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI%20with%20Maven/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns) \n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-148-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n# Giriş\n\nTasarım desenleri, bir yazılım mühendisi bir uygulamayı veya sistemi tasarlarken yaygın sorunları çözmek için kullanabileceği en iyi çözüm prensipleridir.\n\nTasarım desenleri, test edilip kanıtlanmış prensipler olduğu için yazılım geliştirme sürecini hızlandırabilir.\n\nTasarım desenlerini yeniden kullanmak, büyük sorunlara neden olan ince sorunları önlemeye yardımcı olur ve aynı zamanda tasarım desenlerine alışkın olan yazılım mühendisileri ve yazılım mimarları için kod okunabilirliğini artırır.\n\n# Başlangıç\n\nBu site Java Tasarım Desenlerini sergiliyor. Çözümler, açık kaynak topluluğundan deneyimli yazılım mühendisileri ve yazılım mimarları tarafından geliştirilmiştir. Bu yazılım desenleri, detaylı açıklamalarıyla veya kaynak kodlarına bakılarak göz atılabilir. Kaynak kod örneklerinde iyi derecede açıklayıcı yorum satırlarına sahip olup ve belirli bir tasarım deseninin nasıl uygulanacağına dair programlama dersi olarak düşünülebilir. Savaşta en çok kanıtlanmış açık kaynak Java teknolojilerini kullanıyoruz.\n\nBu projeye başlamadan önce çeşitli [Yazılım Tasarım İlkelerine](https://java-design-patterns.com/principles/) aşina olmalısınız.\n\nTüm tasarımlar olabildiğince basit olmalıdır. [KISS](https://en.wikipedia.org/wiki/KISS_principle), [YAGNI](https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it) ve [Do The Simplest Thing That Could Possibly Work](https://learning.oreilly.com/library/view/extreme-programming-pocket/9781449399849/ch17.html) ilkeleri ile başlamalısınız.\n\nBu kavramlara aşina olduktan sonra, aşağıdaki yaklaşımlardan herhangi birini kullanarak [mevcut tasarım desenlerini](https://java-design-patterns.com/patterns/) derinlemesine incelemeye başlayabilirsiniz.\n\n- İsme göre belirli bir tasarım deseni arayın. Bulamadınız mı? Lütfen yeni bir tasarım deseni için [bizim ile](https://github.com/iluwatar/java-design-patterns/issues) iletişime geçin.\n- Performance, Gang of Four ya da Data access gibi etiketleri kullanın.\n- Creational(Yaratıcı Tasarım Desenleri), Behavioral(Davranışsal Tasarım Desenleri), ve Structural(Yapısal Tasarım Desenleri) gibi tasarım kategorilerini kullanın.\n\nUmarım bu sitede sunulan nesne yönelimli çözümleri yazılım mimarileriniz için yararlı bulursunuz ve onları geliştirirken bizim kadar eğlenirsiniz.\n\n# Nasıl Katkı Sağlayabilirim\n\nProjeye katkıda bulunmaya istekliysen, ilgili bilgileri [geliştirici wiki'mizde](https://github.com/iluwatar/java-design-patterns/wiki) bulabilirsin. [Gitter](https://gitter.im/iluwatar/java-design-patterns) ile size yardımcı olacağız ve sorularınızı cevaplayacağız.\n\n# Lisans\n\nBu proje, MIT lisansı koşulları altında lisanslanmıştır.\n\n"
  },
  {
    "path": "localization/tr/singleton/README.md",
    "content": "---\ntitle: Singleton\ncategory: Creational\nlanguage: tr\ntag:\n- Gang of Four\n---\n\n## Amaç\n\nBir sınıfın yalnızca bir örneğine sahip olduğundan emin olun ve ona global bir erişim noktası sağlayın.\n\n\n## Açıklama\n\nÖrnek\n\n> Büyücülerin büyülerini çalıstıkları tek bir fildişi kule olabilir. Aynı büyülü fildişi kule,\n> büyücüler tarafından her zaman kullanılır. Buradaki fildişi kulesi singleton tasarım desenine örnektir.\nÖzetle\n\n> Belirli bir sınıftan yalnızca bir nesnenin oluşturulmasını sağlar.\nWikipedia açıklaması\n\n\n\n> Yazılım mühendisliğinde, tekil desen, bir sınıfın somutlaştırılmasını tek bir nesneyle sınırlayan\n> bir yazılım tasarım modelidir.Bu,sistemdeki eylemleri koordine etmek için\n> tam olarak bir nesne gerektiğinde kullanışlıdır.\n**Örnek**\n\nJoshua Bloch, Effective Java 2nd Edition p.18\n\n> Enum singleton tasarım desenini uygulamak için en iyi yoldur.\n```java\npublic enum EnumIvoryTower {\n  INSTANCE\n}\n```\n\nTanımladıktan sonra kullanmak için:\n\n```java\nvar enumIvoryTower1 = EnumIvoryTower.INSTANCE;\nvar enumIvoryTower2 = EnumIvoryTower.INSTANCE;\nassertEquals(enumIvoryTower1, enumIvoryTower2); // true\n```\n\n## Sınıf diagramı\n\n![alt text](etc/singleton.urm.png)\n\n## Uygulanabilirlik\n\nSingleton tasarım deseni şu durumlarda kullanılmalıdır\n\n* Bir sınıfın tam olarak bir örneği olmalı ve iyi bilinen bir erişim noktasından istemciler tarafından erişilebilir olmalıdır.\n* Tek örnek alt sınıflandırma yoluyla genişletilebilir olduğunda ve istemciler, kodlarını değiştirmeden genişletilmiş bir örnek kullanabilmelidir\n\n## Use Case\n\n* Logging sınıflarında\n* Database bağlantılarını yönetmek için\n* File manager\n\n## Gerçek dünya örnekleri\n\n* [java.lang.Runtime#getRuntime()](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime%28%29)\n* [java.awt.Desktop#getDesktop()](http://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#getDesktop--)\n* [java.lang.System#getSecurityManager()](http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getSecurityManager--)\n\n\n## Sonuçlar\n\n* Kendi yaratımını ve yaşam döngüsünü kontrol ederek Tek Sorumluluk İlkesini (SRP) ihlal ediyor.\n* Bu nesne tarafından kullanılan bir nesnenin ve kaynakların serbest bırakılmasını önleyen global bir paylaşılan örnek kullanmayı teşvik eder.\n* Birbirine sıkı bağlı kod oluşturur. Singleton tasarım deseni kullanan istemci sınıflarını test etmek zorlaşır.\n* Bir Singleton tasarım deseninden alt sınıflar oluşturmak neredeyse imkansız hale gelir.\n\n## Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)"
  },
  {
    "path": "localization/ur/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n\n# جاوا میں لاگو ڈیزائن پیٹرن\n\n![Java CI](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg)\n[![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=ncloc)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)\n[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n\n[![All Contributors](https://img.shields.io/badge/all_contributors-213-orange.svg?style=flat-square)](#contributors-)\n\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n# تعارف\n\nڈیزائن پیٹرن بہترین، باضابطہ طریقے ہیں جو ایک پروگرامر ایپلی کیشن یا سسٹم کو ڈیزائن کرتے وقت عام مسائل کو حل کرنے کے لیے استعمال کر سکتا ہے۔\n\nڈیزائن کے نمونے آزمائشی، ثابت شدہ ترقیاتی نمونے فراہم کرکے ترقی کے عمل کو تیز کر سکتے ہیں۔\n\nڈیزائن کے نمونوں کو دوبارہ استعمال کرنے سے ان لطیف مسائل کو روکنے میں مدد ملتی ہے جو بڑے مسائل کا باعث بنتے ہیں، اور یہ کوڈرز اور معماروں کے لیے کوڈ پڑھنے کی اہلیت کو بھی بہتر بناتا ہے جو پیٹرن سے واقف ہیں۔\n\n# شروع کرتے ہیں\n\nیہ سائٹ جاوا ڈیزائن پیٹرنز کی نمائش کرتی ہے۔ حل اوپن سورس کمیونٹی کے تجربہ کار پروگرامرز اور آرکیٹیکٹس کے ذریعہ تیار کیے گئے ہیں۔ پیٹرن کو ان کی اعلیٰ سطحی وضاحت یا ان کے سورس کوڈ کو دیکھ کر براؤز کیا جا سکتا ہے۔ سورس کوڈ کی مثالوں پر اچھی طرح تبصرہ کیا گیا ہے اور ان کو پروگرامنگ ٹیوٹوریل کے طور پر سوچا جا سکتا ہے کہ کسی مخصوص پیٹرن کو کیسے نافذ کیا جائے۔ ہم سب سے مشہور جنگ سے ثابت شدہ اوپن سورس جاوا ٹیکنالوجیز استعمال کرتے ہیں۔\n\nمواد میں غوطہ لگانے سے پہلے، آپ کو مختلف اصولوں سے واقف ہونا چاہیے۔\n\n[سافٹ ویئر ڈیزائن کے اصول](https://java-design-patterns.com/patterns/)\n\nتمام ڈیزائن ممکنہ حد تک آسان ہونے چاہئیں۔\n\nآپ کو KISS، YAGNI، اور سب سے آسان کام کرنا چاہیے جو ممکنہ طور پر اصولوں پر کام کر سکے۔\n\nپیچیدگی اور نمونوں کو صرف اس وقت متعارف کرایا جانا چاہئے جب ان کی عملی توسیع کے لئے ضرورت ہو۔\n\nایک بار جب آپ ان تصورات سے واقف ہو جائیں تو آپ مندرجہ ذیل طریقوں میں سے کسی کے [دستیاب ڈیزائن پیٹرن](https://java-design-patterns.com/patterns/)  کے نمونوں میں ڈرلنگ شروع کر سکتے ہیں۔\n\n⚪ نام سے مخصوص پیٹرن تلاش کریں۔ ایک نہیں مل سکتا؟ براہ کرم ایک نئے پیٹرن کی اطلاع دیں۔ [یہاں](https://github.com/iluwatar/java-design-patterns/issues).\n\n   ⚪ کارکردگی'، 'گینگ آف فور' یا 'ڈیٹا تک رسائی' جیسے ٹیگز کا استعمال۔\n\n   ⚪ پیٹرن کے زمرے استعمال کرنا، 'تخلیقی'، 'رویے'، اور دیگر۔\n\nامید ہے کہ، آپ کو اس سائٹ پر پیش کردہ آبجیکٹ پر مبنی حل کارآمد معلوم ہوں گے۔\nاپنے فن تعمیرات میں اور ان کو سیکھنے میں اتنا ہی مزہ کریں جتنا ہم نے انہیں تیار کرتے وقت کیا تھا۔\n\n# شراکت کیسے کریں \n\nاگر آپ پروجیکٹ میں حصہ ڈالنے کے لیے تیار ہیں تو آپ کو متعلقہ معلومات مل جائیں گی۔\nہمارے  [ڈویلپر ویکی](https://github.com/iluwatar/java-design-patterns/wiki). ہم مدد کریں گے۔ آپ اور میں آپ کے سوالات کے جوابات [گیٹر چیٹ روم](https://gitter.im/iluwatar/java-design-patterns).\n\n\n# لائسنس\n\nیہ پروجیکٹ MIT لائسنس کی شرائط کے تحت لائسنس یافتہ ہے۔\n\n\n\n"
  },
  {
    "path": "localization/ur/abstract-document/README.md",
    "content": "---\ntitle: Abstract Document\ncategory: Structural\nlanguage: ur\ntag: \n - Extensibility\n---\n\n## ارادہ\n\nمتحرک خصوصیات کا استعمال کریں اور ٹائپ سیفٹی کو برقرار رکھتے ہوئے غیر ٹائپ شدہ زبانوں کی لچک حاصل کریں۔\n\n## وضاحت\n\nخلاصہ دستاویز کا پیٹرن اضافی، غیر جامد خصوصیات کو سنبھالنے کے قابل بناتا ہے۔ یہ پیٹرن قسم کی حفاظت اور مختلف کلاسوں کی الگ الگ خصوصیات کو انٹرفیس کے سیٹ میں فعال کرنے کے لیے خصلتوں کے تصور کا استعمال کرتا ہے۔\n\nحقیقی مثال\n\n> ایک ایسی کار پر غور کریں جو متعدد حصوں پر مشتمل ہو۔ تاہم ہم نہیں جانتے کہ آیا مخصوص کار میں واقعی تمام پرزے ہیں یا ان میں سے کچھ ۔ ہماری کاریں متحرک اور انتہائی لچکدار ہیں۔\n\nصاف لفظوں میں\n\n> خلاصہ دستاویز کا پیٹرن اشیاء کے بارے میں جانے بغیر خصوصیات کو منسلک کرنے کی اجازت دیتا ہے۔\n\nویکیپیڈیا کہتا ہے۔\n\n> ڈھیلے ٹائپ شدہ کلیدی قدر والے اسٹورز میں اشیاء کو منظم کرنے اور ٹائپ شدہ نظاروں کا استعمال کرتے ہوئے ڈیٹا کو ظاہر کرنے کے لیے آبجیکٹ پر مبنی ساختی ڈیزائن کا نمونہ۔ پیٹرن کا مقصد اجزاء کے درمیان اعلی درجے کی لچک حاصل کرنا ہے۔\nسختی سے ٹائپ کی گئی زبان میں جہاں قسم کی حفاظت کی حمایت کو کھونے کے بغیر، فلائی پر آبجیکٹ ٹری میں نئی خصوصیات شامل کی جا سکتی ہیں۔پیٹرن کلاس کی مختلف خصوصیات کو مختلف انٹرفیس میں الگ کرنے کے لیے خصلتوں کا استعمال کرتا ہے۔\n\n**پروگرامی مثال**\n\nآئیے پہلے بیس کلاسز `Document` اور `AbstractDocument` کی وضاحت کرتے ہیں۔ \nوہ بنیادی طور پر آبجیکٹ کو پراپرٹی کا نقشہ اور کسی بھی مقدار میں چائلڈ آبجیکٹ رکھتے ہیں۔\n\n```java\npublic interface Document {\n\n  Void put(String key, Object value);\n\n  Object get(String key);\n\n  <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);\n}\n\npublic abstract class AbstractDocument implements Document {\n\n  private final Map<String, Object> properties;\n\n  protected AbstractDocument(Map<String, Object> properties) {\n    Objects.requireNonNull(properties, \"properties map is required\");\n    this.properties = properties;\n  }\n\n  @Override\n  public Void put(String key, Object value) {\n    properties.put(key, value);\n    return null;\n  }\n\n  @Override\n  public Object get(String key) {\n    return properties.get(key);\n  }\n\n  @Override\n  public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {\n    return Stream.ofNullable(get(key))\n        .filter(Objects::nonNull)\n        .map(el -> (List<Map<String, Object>>) el)\n        .findAny()\n        .stream()\n        .flatMap(Collection::stream)\n        .map(constructor);\n  }\n  ...\n}\n```\nاس کے بعد ہم ایک enum `Property` اور type, price, model اور parts کے لئے انٹرفیس کا ایک سیٹ بیان کرتے ہیں۔ یہ ہمیں تخلیق کرنے کی اجازت دیتا ہے۔\nہماری `Car` کلاس میں جامد نظر آنے والا انٹرفیس۔\n\n```java\npublic enum Property {\n\n  PARTS, TYPE, PRICE, MODEL\n}\n\npublic interface HasType extends Document {\n\n  default Optional<String> getType() {\n    return Optional.ofNullable((String) get(Property.TYPE.toString()));\n  }\n}\n\npublic interface HasPrice extends Document {\n\n  default Optional<Number> getPrice() {\n    return Optional.ofNullable((Number) get(Property.PRICE.toString()));\n  }\n}\npublic interface HasModel extends Document {\n\n  default Optional<String> getModel() {\n    return Optional.ofNullable((String) get(Property.MODEL.toString()));\n  }\n}\n\npublic interface HasParts extends Document {\n\n  default Stream<Part> getParts() {\n    return children(Property.PARTS.toString(), Part::new);\n  }\n}\n```\nاب ہم 'کار' متعارف کرانے کے لیے تیار ہیں۔\n\n```java\npublic class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {\n\n  public Car(Map<String, Object> properties) {\n    super(properties);\n  }\n}\n```\n\nاور آخر کار یہ ہے کہ ہم ایک مکمل مثال میں 'کار' کو کیسے بناتے اور استعمال کرتے ہیں۔\n\n```java\n    LOGGER.info(\"Constructing parts and car\");\n\n    var wheelProperties = Map.of(\n        Property.TYPE.toString(), \"wheel\",\n        Property.MODEL.toString(), \"15C\",\n        Property.PRICE.toString(), 100L);\n\n    var doorProperties = Map.of(\n        Property.TYPE.toString(), \"door\",\n        Property.MODEL.toString(), \"Lambo\",\n        Property.PRICE.toString(), 300L);\n\n    var carProperties = Map.of(\n        Property.MODEL.toString(), \"300SL\",\n        Property.PRICE.toString(), 10000L,\n        Property.PARTS.toString(), List.of(wheelProperties, doorProperties));\n\n    var car = new Car(carProperties);\n\n    LOGGER.info(\"Here is our car:\");\n    LOGGER.info(\"-> model: {}\", car.getModel().orElseThrow());\n    LOGGER.info(\"-> price: {}\", car.getPrice().orElseThrow());\n    LOGGER.info(\"-> parts: \");\n    car.getParts().forEach(p -> LOGGER.info(\"\\t{}/{}/{}\",\n        p.getType().orElse(null),\n        p.getModel().orElse(null),\n        p.getPrice().orElse(null))\n    );\n\n    \n```\n\n## کلاس ڈایاگرام\n\n![alt text](./etc/abstract-document.png \"Abstract Document Traits and Domain\")\n\n## استعمال \n\nخلاصہ دستاویز کا پیٹرن استعمال کریں جب -\n\n* نئ  پراپرٹیز آن دی فلائی شامل کرنے کی ضرورت ہے۔\n* آپ ڈھانچے جیسے درخت میں ڈومین کو منظم کرنے کا ایک لچکدار طریقہ چاہتے ہیں۔\n* آپ کو زیادہ ڈھیلا ڈھالا نظام چاہتے ہیں۔\n\n## کریڈٹ\n\n* [Wikipedia: Abstract Document Pattern](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)\n* [Martin Fowler: Dealing with properties](http://martinfowler.com/apsupp/properties.pdf)\n* [Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4)](https://www.amazon.com/gp/product/0470059028/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0470059028&linkId=e3aacaea7017258acf184f9f3283b492)"
  },
  {
    "path": "localization/ur/abstract-factory/README.md",
    "content": "---\ntitle: Abstract Factory\ncategory: Creational\nlanguage: ur\ntag:\n - Gang of Four\n---\n\n## اس نام سے بہی جانا جاتاہے\n\nکٹ\n\n## ارادہ\nمتعلقہ یا منحصر خاندانوں کو بنانے کے لیے ایک انٹرفیس فراہم کریں۔\nاشیاء کو ان کی ٹھوس کلاسوں کی وضاحت کیے بغیر۔\n\n## وضاحت\n\nحقیقی مثال\n\n> ایک سلطنت بنانے کے لیے ہمیں ایک مشترکہ تھیم والی اشیاء کی ضرورت ہے۔ ایلوین بادشاہی کو ایلون بادشاہ، ایلون قلعہ، اور ایلوین فوج کی ضرورت ہوتی ہے جبکہ آرکیش بادشاہی کو ایک اورش بادشاہ، اورکش قلعہ، اور آرکیش فوج کی ضرورت ہوتی ہے۔ بادشاہی میں اشیاء کے درمیان انحصار ہے۔\n\nصاف لفظوں میں\n\n> کارخانوں کا ایک کارخانہ؛ ایک فیکٹری جو انفرادی لیکن متعلقہ/انحصار کارخانوں کو ان کی کنکریٹ کلاسز کی وضاحت کیے بغیر ایک ساتھ گروپ کرتی ہے۔\n\nویکیپیڈیا کہتا ہے۔\n\n> تجریدی فیکٹری پیٹرن انفرادی فیکٹریوں کے ایک گروپ کو سمیٹنے کا ایک طریقہ فراہم کرتا ہے جن کی کنکریٹ کلاسز کی وضاحت کیے بغیر ایک مشترکہ تھیم ہے۔\n\n**پروگرامی مثال**\n\nاوپر کی بادشاہی کی مثال کا ترجمہ کرنا۔ سب سے پہلے، ہمارے پاس بادشاہی میں موجود اشیاء کے لیے کچھ انٹرفیس اور نفاذ ہیں۔\n\n```java\npublic interface Castle {\n  String getDescription();\n}\n\npublic interface King {\n  String getDescription();\n}\n\npublic interface Army {\n  String getDescription();\n}\n\n// Elven implementations ->\npublic class ElfCastle implements Castle {\n  static final String DESCRIPTION = \"This is the elven castle!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfKing implements King {\n  static final String DESCRIPTION = \"This is the elven king!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfArmy implements Army {\n  static final String DESCRIPTION = \"This is the elven Army!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\n// Orcish implementations similarly -> ...\n\n```\n\nپھر ہمارے پاس کنگڈم فیکٹری کے لیے تجرید اور نفاذات ہیں۔\n\n```java\npublic interface KingdomFactory {\n  Castle createCastle();\n  King createKing();\n  Army createArmy();\n}\n\npublic class ElfKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new ElfCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new ElfKing();\n  }\n\n  @Override\n  public Army createArmy() {\n    return new ElfArmy();\n  }\n}\n\npublic class OrcKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new OrcCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new OrcKing();\n  }\n  \n  @Override\n  public Army createArmy() {\n    return new OrcArmy();\n  }\n}\n```\n\nاب ہمارے پاس ایک تجریدی کارخانہ ہے جو ہمیں متعلقہ اشیاء کا ایک خاندان بنانے دیتا ہے یعنی ایلون کنگڈم فیکٹری ایلوین قلعہ، بادشاہ اور فوج وغیرہ بناتی ہے۔\n\n```java\nvar factory = new ElfKingdomFactory();\nvar castle = factory.createCastle();\nvar king = factory.createKing();\nvar army = factory.createArmy();\n\ncastle.getDescription();\nking.getDescription();\narmy.getDescription();\n```\n\nپروگرام آؤٹ پٹ:\n\n```java\nThis is the elven castle!\nThis is the elven king!\nThis is the elven Army!\n```\nاب، ہم اپنی مختلف بادشاہی فیکٹریوں کے لیے ایک فیکٹری ڈیزائن کر سکتے ہیں۔ اس مثال میں، ہم نے `FactoryMaker` بنایا، جو کہ `ElfKingdomFactory` یا `OrcKingdomFactory` کی مثال واپس کرنے کے لئے ذمہ دار ہے۔\nکلائنٹ مطلوبہ کنکریٹ فیکٹری بنانے کے لیے 'فیکٹری میکر' کا استعمال کر سکتا ہے جو بدلے میں مختلف کنکریٹ اشیاء ('آرمی'، 'کنگ'، 'کیسل' سے ماخوذ) تیار کرے گا۔\nاس مثال میں، ہم نے پیرامیٹرائز کرنے کے لیے ایک اینوم بھی استعمال کیا کہ کلائنٹ کس قسم کی بادشاہی فیکٹری طلب کرے گا۔\n\n```java\npublic static class FactoryMaker {\n\n    public enum KingdomType {\n        ELF, ORC\n    }\n\n    public static KingdomFactory makeFactory(KingdomType type) {\n        return switch (type) {\n            case ELF -> new ElfKingdomFactory();\n            case ORC -> new OrcKingdomFactory();\n            default -> throw new IllegalArgumentException(\"KingdomType not supported.\");\n        };\n    }\n}\n\n    public static void main(String[] args) {\n        var app = new App();\n\n        LOGGER.info(\"Elf Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));\n        LOGGER.info(app.getArmy().getDescription());\n        LOGGER.info(app.getCastle().getDescription());\n        LOGGER.info(app.getKing().getDescription());\n\n        LOGGER.info(\"Orc Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));\n        --similar use of the orc factory\n    }\n```\n\n## کلاس ڈایاگرام\n\n![alt text](./etc/abstract-factory.urm.png \"Abstract Factory class diagram\")\n\n## استعمال\n\nخلاصہ فیکٹری پیٹرن کا استعمال کریں جب.\n\n* نظام کو اس بات سے آزاد ہونا چاہئے کہ اس کی مصنوعات کی تخلیق، تشکیل اور نمائندگی کیسے کی جاتی ہے۔\n* سسٹم کو مصنوعات کے متعدد خاندانوں میں سے ایک کے ساتھ ترتیب دیا جانا چاہئے۔\n* متعلقہ مصنوعات کی اشیاء کے خاندان کو ایک ساتھ استعمال کرنے کے لیے ڈیزائن کیا گیا ہے، اور آپ کو اس پابندی کو نافذ کرنے کی ضرورت ہے۔\n* آپ مصنوعات کی کلاس لائبریری فراہم کرنا چاہتے ہیں، اور آپ صرف ان کے انٹرفیس کو ظاہر کرنا چاہتے ہیں، ان کے نفاذ کو نہیں۔\n* انحصار کی زندگی تصوراتی طور پر صارف کی زندگی سے کم ہوتی ہے۔\n* کسی خاص انحصار کی تعمیر کے لیے آپ کو رن ٹائم ویلیو کی ضرورت ہے۔\n* آپ فیصلہ کرنا چاہتے ہیں کہ رن ٹائم کے وقت فیملی سے کس پروڈکٹ کو کال کرنا ہے۔\n* انحصار کو حل کرنے سے پہلے آپ کو ایک یا زیادہ پیرامیٹرز فراہم کرنے کی ضرورت ہے جو صرف رن ٹائم پر معلوم ہوتے ہیں۔\n* جب آپ کو مصنوعات کے درمیان مستقل مزاجی کی ضرورت ہو۔\n* پروگرام میں نئی مصنوعات یا مصنوعات کے خاندانوں کو شامل کرتے وقت آپ موجودہ کوڈ کو تبدیل نہیں کرنا چاہتے۔\n\n مثال کے طور پر استعمال کے معاملات\n\n * رن ٹائم پر FileSystemAcmeService یا DatabaseAcmeService یا NetworkAcmeService کے مناسب نفاذ کے لیے کال کرنے کا انتخاب کرنا۔\n * یونٹ ٹیسٹ کیس لکھنا بہت آسان ہو جاتا ہے۔\n * مختلف OS کے لیے UI ٹولز\n ## نتائج\n\n * جاوا میں انحصار کا انجیکشن سروس کلاس کے انحصار کو چھپاتا ہے جو رن ٹائم کی غلطیوں کا باعث بن سکتا ہے جو مرتب وقت پر پکڑا جاتا۔\n* اگرچہ پہلے سے طے شدہ اشیاء بناتے وقت پیٹرن بہت اچھا ہوتا ہے، نئی چیزوں کو شامل کرنا مشکل ہوسکتا ہے۔\n* کوڈ اس سے کہیں زیادہ پیچیدہ ہو جاتا ہے کیونکہ پیٹرن کے ساتھ بہت سارے نئے انٹرفیس اور کلاسز متعارف کرائے جاتے ہیں۔\n\n## سبق\n\n* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java) \n\n## معروف استعمال\n\n* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)\n* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)\n* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)\n\n## متعلقہ پیٹرن\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n\n## کریڈٹس\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)"
  },
  {
    "path": "localization/ur/active-object/README.md",
    "content": "---\ntitle: Active Object\ncategory: Concurrency\nlanguage: en\ntag:\n - Performance\n---\n\n## ارادہ\n\nفعال آبجیکٹ ڈیزائن پیٹرن ان اشیاء کے لیے طریقہ کار کی درخواست سے طریقہ کار پر عمل درآمد کو الگ کرتا ہے جو ہر ایک اپنے کنٹرول کے دھاگے میں رہتی ہے۔\nمقصد یہ ہے کہ ہم آہنگی کو متعارف کرایا جائے، غیر مطابقت پذیر طریقہ کی درخواست کا استعمال کرتے ہوئے، اور درخواستوں کو ہینڈل کرنے کے لیے شیڈولر۔\n\n## وضاحت\n\nکلاس جو فعال آبجیکٹ پیٹرن کو نافذ کرتی ہے اس میں 'مطابقت پذیر' طریقوں کا استعمال کیے بغیر خود ہم آہنگی کا طریقہ کار ہوگا۔\n\nحقیقی مثال\n\n> آرکس اپنی جنگلی پن اور ناقابل تسخیر روح کے لیے مشہور ہیں۔ ایسا لگتا ہے کہ پچھلے رویے کی بنیاد پر ان کے پاس کنٹرول کا اپنا دھاگہ ہے۔\n\nایک ایسی مخلوق کو نافذ کرنے کے لیے جس کا کنٹرول میکانزم کا اپنا دھاگہ ہے اور اس کے API کو صرف اور صرف عمل درآمد کو ظاہر نہیں کرتا ہے، ہم Active Object پیٹرن استعمال کر سکتے ہیں۔\n\n**پروگرامی مثال**\n\n```java\npublic abstract class ActiveCreature{\n  private final Logger logger = LoggerFactory.getLogger(ActiveCreature.class.getName());\n\n  private BlockingQueue<Runnable> requests;\n  \n  private String name;\n  \n  private Thread thread;\n\n  public ActiveCreature(String name) {\n    this.name = name;\n    this.requests = new LinkedBlockingQueue<Runnable>();\n    thread = new Thread(new Runnable() {\n        @Override\n        public void run() {\n          while (true) {\n            try {\n              requests.take().run();\n            } catch (InterruptedException e) { \n              logger.error(e.getMessage());\n            }\n          }\n        }\n      }\n    );\n    thread.start();\n  }\n  \n  public void eat() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} is eating!\",name());\n          logger.info(\"{} has finished eating!\",name());\n        }\n      }\n    );\n  }\n\n  public void roam() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} has started to roam the wastelands.\",name());\n        }\n      }\n    );\n  }\n  \n  public String name() {\n    return this.name;\n  }\n}\n```\n\nہم دیکھ سکتے ہیں کہ کوئی بھی کلاس جو ActiveCreature کلاس میں توسیع کرے گی اس کے پاس طریقوں کو استعمال کرنے اور اس پر عمل کرنے کے لیے اپنا کنٹرول کا دھاگہ ہوگا۔\n\nمثال کے طور پر، Orc کلاس:\n\n```java\npublic class Orc extends ActiveCreature {\n\n  public Orc(String name) {\n    super(name);\n  }\n\n}\n```\n\nاب، ہم Orcs جیسی متعدد مخلوقات بنا سکتے ہیں، انہیں کھانے اور گھومنے کو کہہ سکتے ہیں، اور وہ اسے اپنے کنٹرول کے اپنے دھاگے پر عمل میں لائیں گے:\n\n```java\n  public static void main(String[] args) {  \n    var app = new App();\n    app.run();\n  }\n  \n  @Override\n  public void run() {\n    ActiveCreature creature;\n    try {\n      for (int i = 0;i < creatures;i++) {\n        creature = new Orc(Orc.class.getSimpleName().toString() + i);\n        creature.eat();\n        creature.roam();\n      }\n      Thread.sleep(1000);\n    } catch (InterruptedException e) {\n      logger.error(e.getMessage());\n    }\n    Runtime.getRuntime().exit(1);\n  }\n```\n\n## کلاس ڈایاگرام\n\n![alt text](./etc/active-object.urm.png \"Active Object class diagram\")\n\n## سبق\n\n* [Android and Java Concurrency: The Active Object Pattern](https://www.youtube.com/watch?v=Cd8t2u5Qmvc)"
  },
  {
    "path": "localization/ur/acyclic-visitor/README.md",
    "content": "---\ntitle: Acyclic Visitor\ncategory: Behavioral\nlanguage: ur\ntag:\n - Extensibility\n---\n\n## ارادہ\n\nان درجہ بندیوں کو متاثر کیے بغیر، اور تخلیق کیے بغیر، موجودہ طبقاتی درجہ بندی میں نئے فنکشنز کو شامل کرنے کی اجازت دیں\nپریشان کن انحصار سائیکل جو GoF وزیٹر پیٹرن میں شامل ہیں۔\n\n## وضاحت\n\nحقیقی مثال\n\n> ہمارے پاس موڈیم کلاسز کا درجہ بندی ہے۔ اس درجہ بندی میں موڈیمز کو ایک بیرونی الگورتھم کی بنیاد پر دیکھنے کی ضرورت ہے۔\nفلٹرنگ کے معیار پر (کیا یہ یونکس ہے یا DOS کے موافق موڈیم)۔\n\nصاف لفظوں میں\n\n> Acyclic Visitor درجہ بندی میں ترمیم کیے بغیر فنکشنز کو موجودہ طبقاتی درجہ بندی میں شامل کرنے کی اجازت دیتا ہے۔\n\n[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) کہتے ہیں\n\n> Acyclic پیٹرن ان کو درجہ بندی میں فرق صرف موجودہ طبقاتی میں فنکشنز کو شامل کرنے کی اجازت دیتا ہے۔\n\n> درجہ بندی، اور انحصار سائیکل بنائے بغیر جو کہ GangOfFour VisitorPattern میں موروثی ہیں۔\n\n**پروگرامی مثال**\n\nیہ ہے `موڈیم` درجہ بندی۔\n\n```java\npublic abstract class Modem {\n  public abstract void accept(ModemVisitor modemVisitor);\n}\n\npublic class Zoom extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof ZoomVisitor) {\n      ((ZoomVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only ZoomVisitor is allowed to visit Zoom modem\");\n    }\n  }\n}\n\npublic class Hayes extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof HayesVisitor) {\n      ((HayesVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only HayesVisitor is allowed to visit Hayes modem\");\n    }\n  }\n}\n```\n\nاس کے بعد ہم 'ModemVisitor' کا درجہ بندی متعارف کراتے ہیں۔\n\n```java\npublic interface ModemVisitor {\n}\n\npublic interface HayesVisitor extends ModemVisitor {\n  void visit(Hayes hayes);\n}\n\npublic interface ZoomVisitor extends ModemVisitor {\n  void visit(Zoom zoom);\n}\n\npublic interface AllModemVisitor extends ZoomVisitor, HayesVisitor {\n}\n\npublic class ConfigureForDosVisitor implements AllModemVisitor {\n  ...\n  @Override\n  public void visit(Hayes hayes) {\n    LOGGER.info(hayes + \" used with Dos configurator.\");\n  }\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Dos configurator.\");\n  }\n}\n\npublic class ConfigureForUnixVisitor implements ZoomVisitor {\n  ...\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Unix configurator.\");\n  }\n}\n```\n\nآخر میں، یہاں ایکشن میں زائرین ہیں.\n\n\n```java\n    var conUnix = new ConfigureForUnixVisitor();\n    var conDos = new ConfigureForDosVisitor();\n    var zoom = new Zoom();\n    var hayes = new Hayes();\n    hayes.accept(conDos);\n    zoom.accept(conDos);\n    hayes.accept(conUnix);\n    zoom.accept(conUnix);   \n```\n\nپروگرام آؤٹ پٹ:\n\n```\n    // Hayes modem used with Dos configurator.\n    // Zoom modem used with Dos configurator.\n    // Only HayesVisitor is allowed to visit Hayes modem\n    // Zoom modem used with Unix configurator.\n```\n\n## کلاس ڈایاگرام\n\n![alt text](./etc/acyclic-visitor.png \"Acyclic Visitor\")\n\n## استعمال\n\nیہ پیٹرن استعمال کیا جا سکتا ہے:\n\n* جب آپ کو کسی موجودہ درجہ بندی میں ایک نیا فنکشن شامل کرنے کی ضرورت ہو بغیر اس درجہ بندی کو تبدیل کرنے یا متاثر کرنے کی ضرورت۔\n* جب ایسے افعال ہوتے ہیں جو درجہ بندی پر کام کرتے ہیں، لیکن ان کا تعلق خود درجہ بندی میں نہیں ہوتا ہے۔ جیسے ConfigureForDOS / ConfigureForUnix / ConfigureForX مسئلہ۔\n* جب آپ کو کسی چیز پر اس کی قسم کے لحاظ سے بہت مختلف آپریشن کرنے کی ضرورت ہوتی ہے۔\n* جب ملاحظہ کردہ کلاس کے درجہ بندی کو عنصر کلاس کے نئے مشتقات کے ساتھ کثرت سے بڑھایا جائے گا۔\n* جب عنصر کے مشتقات کو دوبارہ مرتب کرنا، دوبارہ لنک کرنا، دوبارہ جانچنا یا دوبارہ تقسیم کرنا بہت مہنگا ہوتا ہے۔\n\n## ٹیوٹوریل\n\n* [Acyclic Visitor Pattern Example](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html)\n\n## نتائج\n\nاچھائی:\n\n* طبقاتی درجہ بندی کے درمیان کوئی انحصار سائیکل نہیں ہے۔\n* اگر کوئی نیا شامل کیا جائے تو تمام زائرین کو دوبارہ مرتب کرنے کی ضرورت نہیں ہے۔\n* اگر کلاس کے درجہ بندی میں کوئی نیا ممبر ہے تو موجودہ زائرین میں تالیف کی ناکامی کا سبب نہیں بنتا ہے۔\n\nبرائی:\n\n * خلاف ورزی کرتا ہے۔ [Liskov's Substitution Principle](https://java-design-patterns.com/principles/#liskov-substitution-principle) \n یہ ظاہر کر کے کہ یہ تمام زائرین کو قبول کر سکتا ہے لیکن اصل میں صرف خاص مہمانوں میں دلچسپی رکھتا ہے۔\n*  ملاحظہ کرنے کے قابل طبقاتی درجہ بندی میں تمام اراکین کے لیے زائرین کا متوازی درجہ بندی بنانا ضروری ہے۔\n\n ## متعلقہ پیٹرن\n\n [Visitor Pattern](https://java-design-patterns.com/patterns/visitor/)\n\n\n کریڈٹس\n\n * [Acyclic Visitor by Robert C. Martin](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf)\n* [Acyclic Visitor in WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor)"
  },
  {
    "path": "localization/vi/README.md",
    "content": "# Mẫu thiết kế được hiện thực bằng Java\n\n# Giới thiệu\n\nMẫu thiết kế là phương pháp tốt nhất, được chuẩn hóa mà một lập trình viên có thể sử dụng để giải quyết các vấn đề chung khi thiết kế một ứng dụng hoặc hệ thống.\n\nMẫu thiết kế có thể đẩy nhanh quá trình phát triển bằng cách cung cấp các mô hình đã được kiểm nghiệm, chứng minh.\n\nViệc sử dụng lại các mẫu thiết kế giúp phòng ngừa các vấn đề tiềm ẩn có thể xảy ra và nó cũng cải thiện khả năng đọc hiểu mã nguồn cho các lập trình viên và người thiết kế hệ thống đã quen thuộc với các mẫu đó.\n\n# Mở đầu\n\nTrang web này giới thiệu các mẫu thiết kế được hiện thực bằng Java. Các giải pháp này đã được phát triển\nbởi các lập trình viên và người thiết kế có kinh nghiệm từ cộng đồng mã nguồn mở.\nBạn có thể tham khảo các mẫu thông qua mô tả cấp cao hoặc mã nguồn của chúng. \nCác mã nguồn mẫu được giải thích đầy đủ và được coi là hướng dẫn trực quan về cách triển khai một mẫu thiết kế cụ thể. \nChúng tôi cũng sử dụng các công nghệ Java nguồn mở đã được chứng minh thực chiến phổ biến nhất.\n\nTrước khi đào sâu vào tài liệu, bạn nên làm quen với những\n[quy tắc thiết kế](https://java-design-patterns.com/principles/).\n\nTất cả các thiết kế nên đơn giản nhất có thể. \nBạn nên bắt đầu với KISS, YAGNI, và Làm-Thứ-Đơn-Giản-Nhất-Mà-Giải-Quyết-Vấn-Đề (Do-The-Simplest-Thing-That-Could-Possibly-Work).\nSự phức tạp và các mẫu chỉ được thêm vào khi chúng thực sự cần cho sự mở rộng về sau.\n\nMột khi đã quen với các khái niệm, bạn có thể bắt đầu đào sâu\n[các mẫu thiết kế hiện có](https://java-design-patterns.com/patterns/)\nbằng các cách tiếp cận sau\n\n - Tìm kiếm một mẫu thiết kế cụ thể bằng tên. Nếu không tìm thấy, vui lòng yêu cầu một mẫu mới [ở đây](https://github.com/iluwatar/java-design-patterns/issues).\n - Sử dụng đánh dấu (tag) như `Performance`, `Gang of Four` hoặc `Data access`.\n - Sử dụng danh mục như `Creational`, `Behavioral`, vân vân.\n\nMong rằng những giải pháp hướng đối tượng ở đây sẽ mang lại lợi ích công việc cũng như niềm vui học tập cho bạn, giống như chúng tôi đã và đang được trải nghiệm trong quá trình phát triển chúng.\n\n# Đóng góp\n\nNếu bạn mong muốn đóng góp cho dự án, bạn có thể tìm kiếm thông tin liên quan ở [wiki cho nhà phát triển](https://github.com/iluwatar/java-design-patterns/wiki).\nChúng tôi sẽ giúp trả lời câu hỏi của bạn ở [Gitter](https://gitter.im/iluwatar/java-design-patterns).\n\n# Giấy phép\n\nDự án này được cấp phép theo các điều khoản của giấy phép MIT.\n"
  },
  {
    "path": "localization/vi/abstract-document/README.md",
    "content": "---\ntitle: Abstract Document\ncategory: Structural\nlanguage: vi\ntag: \n - Extensibility\n---\n\n## Mục tiêu\n\nTận dụng thuộc tính và khả năng linh động của các ngôn ngữ không định kiểu trong khi vẫn giữ được đặc tính an toàn kiểu.\n\n## Giải thích\n\nTài Liệu Trừu Tượng (thuật ngữ tiếng Anh: Abstract Document) là mẫu cho phép sử dụng các thuộc tính bổ sung, không tĩnh.\nMẫu này sử dụng khái niệm \"đặc tính\" (thuật ngữ gốc: \"trait\") để cho phép an toàn kiểu và phân tách thuộc tính của các lớp (class) khác nhau thành các tập giao diện (interface).\n\nVí dụ thực tế\n\n>  Chiếc ô tô có thể bao gồm nhiều thành phần. Tuy nhiên, chúng ta không biết liệu một chiếc ô tô cụ thể có thể chứa những thành phần nào, tất cả hay chỉ một vài thành phần nhất định. Có thể nói rằng, những chiếc ô tô này là động và rất linh hoạt.\n\nMột cách đơn giản\n\n> Mẫu tài liệu trừu tượng cho phép cấy thêm thuộc tính vào đối tượng mà không để cho nó biết về điều đó.\n\nWikipedia viết (tạm dịch)\n\n> Là mẫu hướng đối tượng loại cấu trúc dùng để tổ chức các đối tượng theo dạng lưu trữ khóa-giá trị và phơi bày dữ liệu dưới dạng định kiểu. Mục đích của mẫu này là để đạt được khả năng linh hoạt cao giữa các thành phần trong ngôn ngữ định kiểu mạnh, nơi mà những thuộc tính mới có thể được thêm vào cây đối tượng một cách linh hoạt (trong khi chạy chương trình), nhưng vẫn giữ được sự hỗ trợ của an toàn kiểu. Mẫu này sử dụng khái niệm \"đặc tính\" (thuật ngữ gốc: \"trait\") để phân tách thuộc tính của các lớp (class) thành các tập giao diện (interface).\n\n\n**Chương trình ví dụ**\n\nĐầu tiên, định nghĩa lớp cơ sở `Document` và `AbstractDocument`. \n2 lớp này định nghĩa đối tượng sẽ giữ bảng thuộc tính và các đối tượng con có kiểu bất kì. \n\n```java\npublic interface Document {\n\n  Void put(String key, Object value);\n\n  Object get(String key);\n\n  <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);\n}\n\npublic abstract class AbstractDocument implements Document {\n\n  private final Map<String, Object> properties;\n\n  protected AbstractDocument(Map<String, Object> properties) {\n    Objects.requireNonNull(properties, \"properties map is required\");\n    this.properties = properties;\n  }\n\n  @Override\n  public Void put(String key, Object value) {\n    properties.put(key, value);\n    return null;\n  }\n\n  @Override\n  public Object get(String key) {\n    return properties.get(key);\n  }\n\n  @Override\n  public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {\n    return Stream.ofNullable(get(key))\n        .filter(Objects::nonNull)\n        .map(el -> (List<Map<String, Object>>) el)\n        .findAny()\n        .stream()\n        .flatMap(Collection::stream)\n        .map(constructor);\n  }\n  ...\n}\n```\n\nTiếp theo, chúng ta định nghĩa một enum `Property` và một tập các interface cho thuộc tính: `type`, `price`, `model`, `parts`.\nĐiều này cho phép ta tạo ra một giao diện tĩnh cho lớp `Car`.\n\n```java\npublic enum Property {\n\n  PARTS, TYPE, PRICE, MODEL\n}\n\npublic interface HasType extends Document {\n\n  default Optional<String> getType() {\n    return Optional.ofNullable((String) get(Property.TYPE.toString()));\n  }\n}\n\npublic interface HasPrice extends Document {\n\n  default Optional<Number> getPrice() {\n    return Optional.ofNullable((Number) get(Property.PRICE.toString()));\n  }\n}\npublic interface HasModel extends Document {\n\n  default Optional<String> getModel() {\n    return Optional.ofNullable((String) get(Property.MODEL.toString()));\n  }\n}\n\npublic interface HasParts extends Document {\n\n  default Stream<Part> getParts() {\n    return children(Property.PARTS.toString(), Part::new);\n  }\n}\n```\n\nBây giờ, chúng ta đã sẵn sàng cho lớp `Car`.\n\n```java\npublic class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {\n\n  public Car(Map<String, Object> properties) {\n    super(properties);\n  }\n}\n```\n\nVà cuối cùng là cách khởi tạo và sử dụng `Car` trong một ví dụ hoàn chỉnh. \n\n```java\n    LOGGER.info(\"Constructing parts and car\");\n\n    var wheelProperties = Map.of(\n        Property.TYPE.toString(), \"wheel\",\n        Property.MODEL.toString(), \"15C\",\n        Property.PRICE.toString(), 100L);\n\n    var doorProperties = Map.of(\n        Property.TYPE.toString(), \"door\",\n        Property.MODEL.toString(), \"Lambo\",\n        Property.PRICE.toString(), 300L);\n\n    var carProperties = Map.of(\n        Property.MODEL.toString(), \"300SL\",\n        Property.PRICE.toString(), 10000L,\n        Property.PARTS.toString(), List.of(wheelProperties, doorProperties));\n\n    var car = new Car(carProperties);\n\n    LOGGER.info(\"Here is our car:\");\n    LOGGER.info(\"-> model: {}\", car.getModel().orElseThrow());\n    LOGGER.info(\"-> price: {}\", car.getPrice().orElseThrow());\n    LOGGER.info(\"-> parts: \");\n    car.getParts().forEach(p -> LOGGER.info(\"\\t{}/{}/{}\",\n        p.getType().orElse(null),\n        p.getModel().orElse(null),\n        p.getPrice().orElse(null))\n    );\n\n    // Constructing parts and car\n    // Here is our car:\n    // model: 300SL\n    // price: 10000\n    // parts: \n    // wheel/15C/100\n    // door/Lambo/300\n```\n\n## Sơ đồ lớp\n\n![alt text](../../../abstract-document/etc/abstract-document.png \"Abstract Document Traits and Domain\")\n\n## Ứng dụng\n\nSử dụng mẫu Tài Liệu Trừu Tượng khi\n\n* Có nhu cầu thêm các thuộc tính mới trong lúc chạy (khái niệm gốc: \"on the fly\")\n* Muốn có khả năng linh hoạt trong tổ chức nghiệp vụ dưới dạng sơ đồ cây\n* Muốn hệ thống lỏng lẻo hơn\n\n## Tham khảo\n\n* [Wikipedia: Abstract Document Pattern](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)\n* [Martin Fowler: Dealing with properties](http://martinfowler.com/apsupp/properties.pdf)\n* [Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4)](https://www.amazon.com/gp/product/0470059028/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0470059028&linkId=e3aacaea7017258acf184f9f3283b492)\n"
  },
  {
    "path": "localization/vi/abstract-factory/README.md",
    "content": "---\ntitle: Abstract Factory\ncategory: Creational\nlanguage: vi\ntag:\n - Gang of Four\n---\n\n## Còn được biết đến như\n\nKit\n\n## Mục tiêu\n\nCung cấp giao diện (interface) để khởi tạo các đối tượng liên quan \nhoặc có phụ thuộc mà không cần chỉ định các lớp cụ thể của chúng.\n\n## Giải thích\n\nNhà Máy Trừu Tượng (thuật ngữ tiếng Anh: Abstract Factory).\n\nVí dụ thực tế\n\n> Để tạo ra một vương quốc, chúng ta cần các đối tượng có chủ đề chung. Vương quốc Elf cần một vị vua Elf, lâu đài Elf và quân đội Elf trong khi vương quốc Orc cần một vị vua Orc, lâu đài Orc và quân đội Orc. Các đối tượng trong vương quốc phụ thuộc lẫn nhau.\n\nMột cách đơn giản\n\n> Một nhà máy của nhiều nhà máy; một nhà máy nhóm các nhà máy riêng lẻ nhưng có liên quan hoặc phụ thuộc lại với nhau mà không chỉ định các lớp cụ thể của chúng.\n\nWikipedia viết (tạm dịch)\n\n> Mẫu Nhà Máy Trừu Tượng cung cấp cách làm để đóng gói một nhóm các nhà máy riêng lẻ có chủ đề chung mà không cần chỉ định các lớp cụ thể của chúng\n\n**Chương trình ví dụ**\n\nSử dụng ví dụ về vương quốc đã nêu ở trên. \nTrước hết, chúng ta có một số giao diện (interface) và lớp (class) được hiện thực hóa cho các đối tượng trong vương quốc.\n\n```java\npublic interface Castle {\n  String getDescription();\n}\n\npublic interface King {\n  String getDescription();\n}\n\npublic interface Army {\n  String getDescription();\n}\n\n// Hiện thực hóa tộc Elf ->\npublic class ElfCastle implements Castle {\n  static final String DESCRIPTION = \"This is the elven castle!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfKing implements King {\n  static final String DESCRIPTION = \"This is the elven king!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfArmy implements Army {\n  static final String DESCRIPTION = \"This is the elven Army!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\n// Tương tự, hiện thực hóa tộc Orc -> ...\n\n```\n\nSau đó, chúng ta có trừu tượng hóa và hiện thực hóa cho nhà máy vương quốc.\n\n```java\npublic interface KingdomFactory {\n  Castle createCastle();\n  King createKing();\n  Army createArmy();\n}\n\npublic class ElfKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new ElfCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new ElfKing();\n  }\n\n  @Override\n  public Army createArmy() {\n    return new ElfArmy();\n  }\n}\n\npublic class OrcKingdomFactory implements KingdomFactory {\n\n  @Override\n  public Castle createCastle() {\n    return new OrcCastle();\n  }\n\n  @Override\n  public King createKing() {\n    return new OrcKing();\n  }\n  \n  @Override\n  public Army createArmy() {\n    return new OrcArmy();\n  }\n}\n```\n\nBây giờ, chúng ta có Nhà Máy Trừu Tượng cho phép chúng ta tạo một nhóm các đối tượng liên quan, tức là nhà máy vương quốc Elf tạo ra lâu đài, vua và quân đội của tộc Elf, v.v.\n\n```java\nvar factory = new ElfKingdomFactory();\nvar castle = factory.createCastle();\nvar king = factory.createKing();\nvar army = factory.createArmy();\n\ncastle.getDescription();\nking.getDescription();\narmy.getDescription();\n```\n\nĐầu ra khi chạy chương trình:\n\n```java\nThis is the elven castle!\nThis is the elven king!\nThis is the elven Army!\n```\n\nBây giờ, chúng ta có thể thiết kế một nhà máy cho các nhà máy vương quốc khác nhau. Trong ví dụ này, chúng tôi đã tạo `FactoryMaker`, chịu trách nhiệm trả về một thể hiện của` ElfKingdomFactory` hoặc `OrcKingdomFactory`.\nNgười dùng có thể sử dụng `FactoryMaker` để tạo ra nhà máy mà họ mong muốn, sau đó, `FactoryMaker` sẽ tạo ra các đối tượng cụ thể (là dẫn xuất của `Army`, `King`, `Castle`).\nTrong ví dụ này, chúng tôi cũng sử dụng một enum để tham số hóa các loại nhà máy vương quốc mà khách hàng sẽ yêu cầu.\n\n```java\npublic static class FactoryMaker {\n\n    public enum KingdomType {\n        ELF, ORC\n    }\n\n    public static KingdomFactory makeFactory(KingdomType type) {\n        return switch (type) {\n            case ELF -> new ElfKingdomFactory();\n            case ORC -> new OrcKingdomFactory();\n            default -> throw new IllegalArgumentException(\"KingdomType not supported.\");\n        };\n    }\n}\n\n    public static void main(String[] args) {\n        var app = new App();\n\n        LOGGER.info(\"Elf Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));\n        LOGGER.info(app.getArmy().getDescription());\n        LOGGER.info(app.getCastle().getDescription());\n        LOGGER.info(app.getKing().getDescription());\n\n        LOGGER.info(\"Orc Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));\n        --Tương tự với nhà máy Orc\n    }\n```\n\n## Sơ đồ lớp\n\n![alt text](../../../abstract-factory/etc/abstract-factory.urm.png \"Abstract Factory class diagram\")\n\n## Ứng dụng\nSử dụng mẫu Nhà Máy Trừu Tượng khi\n\n* Hệ thống nên độc lập với cách mà nó khởi tạo/kết hợp/trình bày sản phẩm của nó.\n* Hệ thống nên được cấu hình với một trong các họ sản phẩm.\n* Họ của các đối tượng sản phẩm được thiết kế để sử dụng cùng nhau, và bạn cần áp đặt ràng buộc này.\n* Bạn muốn cung cấp một thư viện lớp các sản phẩm, và bạn chỉ muốn tiết lộ giao diện (interface), ẩn giấu hiện thực hóa của chúng.\n* Thời gian tồn tại của đối tượng phụ thuộc thì ngắn hơn thời gian tồn tại của đối tượng sử dụng.\n* Bạn cần một/vài giá trị trong lúc chạy để khởi tạo một/vài đối tượng phụ thuộc cụ thể.\n* Bạn muốn quyết định sản phẩm nào được gọi từ một họ trong lúc chạy.\n* Bạn cần tính nhất quán giữa các sản phẩm.\n* Bạn không muốn sửa mã nguồn khi thêm những sản phẩm mới hoặc họ của các sản phẩm vào chương trình.\n\nVí dụ về ca sử dụng\n\n* Lựa chọn để gọi đến hiện thực hóa phù hợp của FileSystemAcmeService hoặc DatabaseAcmeService hoặc NetworkAcmeService trong lúc thực thi.\n* Kiểm thử đơn vị trở nên cực kì dễ dàng.\n* Công cụ giao diện cho các hệ điều hành khác nhau.\n\n## Hệ quả\n\n* Sự tiêm phụ thuộc (dependency injection) trong Java che đậy các lớp dịch vụ phụ thuộc nên nó có thể dẫn tới lỗi trong quá trình thực thi, điều mà lẽ ra có thể bắt được trong quá trình biên dịch.\n* Trong khi mẫu này sử dụng hiệu quả với các đối tượng đã được định nghĩa sẵn, thêm một/vài đối tượng mới có thể sẽ khó khăn.\n* Mã nguồn trở nên phức tạp hơn do nó có thêm giao diện (interface) và lớp (class) được giới thiệu đi kèm theo mẫu.\n\n## Hướng dẫn\n\n* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java) \n\n## Thông dụng\n\n* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)\n* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)\n* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)\n\n## Mẫu liên quan\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n\n## Tham khảo\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/vi/active-object/README.md",
    "content": "---\ntitle: Active Object\ncategory: Concurrency\nlanguage: vi\ntag:\n - Performance\n---\n\n## Mục tiêu\n\nMẫu Đối Tượng Chủ Động (tiếng Anh: Active Object) chia tách việc thực thi hàm khỏi lời gọi hàm cho các đối tượng mà mỗi đối tượng nằm trong luồng điều khiển của chúng.\nMục tiêu là tận dụng khả năng xử lý đồng thời, bằng cách sử dụng phương thức bất đồng bộ và bộ lập lịch để xử lý các yêu cầu.\n\n## Giải thích\n\nLớp hiện thực mẫu Đối Tượng Chủ Động sẽ bao gồm cơ chế tự đồng bộ (self-synchronization) nhưng không sử dụng đến phương thức/từ khóa 'synchronized'.\n\nVí dụ thực tế\n\n> Tộc Orcs được biết đến với tính cách hoang dã và không thuần hóa được. Có thể coi như họ có một luồng điều khiển riêng do họ quyết định việc thực thi mà ta không can thiệp được.\n\nĐể hiện thực hóa một sinh vật mà nó sở hữu riêng cơ chế điều khiển luồng và chỉ để lộ ra giao diện lập trình (API), chúng ta có thể sử dụng mẫu Đối Tượng Chủ Động.\n\n**Chương trình ví dụ**\n\n```java\npublic abstract class ActiveCreature{\n  private final Logger logger = LoggerFactory.getLogger(ActiveCreature.class.getName());\n\n  private BlockingQueue<Runnable> requests;\n  \n  private String name;\n  \n  private Thread thread;\n\n  public ActiveCreature(String name) {\n    this.name = name;\n    this.requests = new LinkedBlockingQueue<Runnable>();\n    thread = new Thread(new Runnable() {\n        @Override\n        public void run() {\n          while (true) {\n            try {\n              requests.take().run();\n            } catch (InterruptedException e) { \n              logger.error(e.getMessage());\n            }\n          }\n        }\n      }\n    );\n    thread.start();\n  }\n  \n  public void eat() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} is eating!\",name());\n          logger.info(\"{} has finished eating!\",name());\n        }\n      }\n    );\n  }\n\n  public void roam() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} has started to roam the wastelands.\",name());\n        }\n      }\n    );\n  }\n  \n  public String name() {\n    return this.name;\n  }\n}\n```\n\nCó thể thấy rằng mọi lớp kế thừa từ lớp `ActiveCreature` sẽ có riêng luồng điều khiển để gọi và thực thi phương thức.\n\nVí dụ lớp `Orc`:\n\n```java\npublic class Orc extends ActiveCreature {\n\n  public Orc(String name) {\n    super(name);\n  }\n  \n}\n```\n\nBây giờ, chúng ta có thể khởi tạo các sinh vật như Orcs, bảo chúng ăn (gọi hàm `eat()`) và tản bộ (gọi hàm `roam()`), và chúng sẽ thực thi trên luồng điều khiển của riêng chúng:\n\n```java\n  public static void main(String[] args) {  \n    var app = new App();\n    app.run();\n  }\n  \n  @Override\n  public void run() {\n    ActiveCreature creature;\n    try {\n      for (int i = 0;i < creatures;i++) {\n        creature = new Orc(Orc.class.getSimpleName().toString() + i);\n        creature.eat();\n        creature.roam();\n      }\n      Thread.sleep(1000);\n    } catch (InterruptedException e) {\n      logger.error(e.getMessage());\n    }\n    Runtime.getRuntime().exit(1);\n  }\n```\n\n## Sơ đồ lớp\n\n![alt text](../../../active-object/etc/active-object.urm.png \"Active Object class diagram\")\n\n## Hướng dẫn\n\n* [Android and Java Concurrency: The Active Object Pattern](https://www.youtube.com/watch?v=Cd8t2u5Qmvc)"
  },
  {
    "path": "localization/vi/acyclic-visitor/README.md",
    "content": "---\ntitle: Acyclic Visitor\ncategory: Behavioral\nlanguage: vi\ntag:\n - Extensibility\n---\n\n## Mục đích\n\nCho phép thêm các hàm mới vào cấu trúc các lớp hiện có mà không làm ảnh hưởng đến cấu trúc của chúng, đồng thời tránh tạo ra các phụ thuộc vòng (dependency cycles) của Visitor Pattern trong Gang of Four.\n\n## Giải thích\n\nVí dụ thực tế\n\n> Chúng ta có một hệ thống các lớp modem. Những modem trong hệ thống này cần được duyệt qua bởi một thuật toán bên ngoài dựa trên một tiêu chí lọc (ví dụ như chỉ lấy các loại modem tương thích với hệ điều hành Unix hoặc DOS).\n\nNói đơn giản hơn\n\n> Acyclic Visitor cho phép thêm các hàm vào các hệ thống lớp hiện có mà không cần sửa đổi cấu trúc của chúng.\n\nTheo [WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor)\n\n> Mẫu thiết kế Acyclic Visitor cho phép thêm các hàm mới vào các hệ thống lớp hiện có mà không ảnh hưởng đến các hệ thống đó, và không tạo ra các phụ thuộc vòng (dependency cycles) như là một phần không thể tránh của Visitor Pattern trong Gang of Four.\n\n**Mã nguồn mẫu**\n\nDưới đây là cấu trúc của class `Modem`.\n\n```java\npublic abstract class Modem {\n  public abstract void accept(ModemVisitor modemVisitor);\n}\n\npublic class Zoom extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof ZoomVisitor) {\n      ((ZoomVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only ZoomVisitor is allowed to visit Zoom modem\");\n    }\n  }\n}\n\npublic class Hayes extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof HayesVisitor) {\n      ((HayesVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only HayesVisitor is allowed to visit Hayes modem\");\n    }\n  }\n}\n```\n\nTiếp theo, là cấu trúc của lớp `ModemVisitor`.\n\n```java\npublic interface ModemVisitor {\n}\n\npublic interface HayesVisitor extends ModemVisitor {\n  void visit(Hayes hayes);\n}\n\npublic interface ZoomVisitor extends ModemVisitor {\n  void visit(Zoom zoom);\n}\n\npublic interface AllModemVisitor extends ZoomVisitor, HayesVisitor {\n}\n\npublic class ConfigureForDosVisitor implements AllModemVisitor {\n  ...\n  @Override\n  public void visit(Hayes hayes) {\n    LOGGER.info(hayes + \" used with Dos configurator.\");\n  }\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Dos configurator.\");\n  }\n}\n\npublic class ConfigureForUnixVisitor implements ZoomVisitor {\n  ...\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Unix configurator.\");\n  }\n}\n```\n\nCuối cùng, chúng ta sẽ thấy các lớp visitor hoạt động.\n\n```java\n    var conUnix = new ConfigureForUnixVisitor();\n    var conDos = new ConfigureForDosVisitor();\n    var zoom = new Zoom();\n    var hayes = new Hayes();\n    hayes.accept(conDos);\n    zoom.accept(conDos);\n    hayes.accept(conUnix);\n    zoom.accept(conUnix);   \n```\n\nKết quả khi chạy chương trình:\n\n```\n    // Hayes modem used with Dos configurator.\n    // Zoom modem used with Dos configurator.\n    // Only HayesVisitor is allowed to visit Hayes modem\n    // Zoom modem used with Unix configurator.\n```\n\n## Sơ đồ lớp\n![alt text](../../../acyclic-visitor/etc/acyclic-visitor.png \"Acyclic Visitor\")\n\n## Áp dụng\nMẫu thiết kế này có thể được sử dụng trong các trường hợp:\n\n* Khi bạn cần thêm một hàm mới vào một hệ thống lớp hiện có mà không cần phải sửa đổi hoặc ảnh hưởng đến hệ thống đó.\n* Khi có các hàm thao tác trên một hệ thống lớp nhưng những hàm này không nên thuộc về cùng cấu trúc của hệ thống đó. Ví dụ như vấn đề ConfigureForDOS / ConfigureForUnix / ConfigureForX.\n* Khi bạn cần thực hiện các thao tác hoàn toàn khác nhau trên một đối tượng dựa vào kiểu của nó.\n* Khi hệ thống lớp được duyệt sẽ thường xuyên được mở rộng với các lớp dẫn xuất mới của lớp Element.\n* Khi việc biên dịch lại, liên kết lại, kiểm thử lại hoặc phân phối lại các lớp dẫn xuất của Element rất tốn kém.\n\n## Hướng dẫn\n\n* [Ví dụ về mẫu thiết kế Acyclic Visitor](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html)\n\n## Kết luận\n\nMặt tích cực:\n\n* Không có phụ thuộc vòng giữa các hệ thống lớp.\n* Không cần phải biên dịch lại tất cả các lớp visitor nếu có một lớp mới được thêm vào.\n* Không gây ra lỗi biên dịch ở các lớp visitor hiện có nếu hệ thống lớp có một thành viên mới.\n\nMặt tiêu cực:\n\n* Vi phạm [Nguyên tắc thay thế của Liskov](https://java-design-patterns.com/principles/#liskov-substitution-principle) bằng cách cho thấy rằng nó có thể chấp nhận tất cả các lớp visitor nhưng thực sự chỉ quan tâm đến một số lớp visitor cụ thể.\n* Phải tạo ra một cấu trúc song song các lớp visitor cho tất cả các thành viên trong hệ thống lớp có thể được duyệt.\n\n## Các mẫu liên quan\n\n* [Visitor Pattern](https://java-design-patterns.com/patterns/visitor/)\n\n## Người đóng góp\n\n* [Acyclic Visitor bởi Robert C. Martin](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf)\n* [Acyclic Visitor trên WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor)\n"
  },
  {
    "path": "localization/vi/adapter/README.md",
    "content": "---\ntitle: Adapter\ncategory: Structural\nlanguage: vi\ntag:\n - Gang of Four\n---\n\n## Còn được gọi là\nWrapper\n\n## Mục đích\nChuyển đổi giao diện của một lớp thành một giao diện khác mà mình mong muốn. Adapter cho phép các lớp làm việc cùng nhau, mặc dù ban đầu chúng không thể làm việc cùng nhau do giao diện không tương thích.\n\n## Giải thích\n\nVí dụ thực tế\n\n> Hãy tưởng tượng rằng bạn có một số hình ảnh trên thẻ nhớ của bạn và bạn cần chuyển chúng sang máy tính của bạn. Để chuyển chúng, bạn cần một loại adapter nào đó tương thích với các cổng máy tính của bạn để bạn có thể kết nối thẻ nhớ vào máy tính của bạn. Trong trường hợp này, đầu đọc thẻ là một cái adapter.\n> Ví dụ nổi tiếng khác là adapter điện; một phích cắm ba chân không thể kết nối vào một ổ cắm hai chân, nó cần sử dụng một adapter điện để làm cho nó tương thích với ổ cắm hai chân.\n> Một ví dụ khác là thông dịch viên dịch lời của người này cho người khác hiểu được.\n\n## Nói đơn giản hơn\n\n> Mẫu Adapter cho phép bạn bọc một đối tượng ban đầu không tương thích vào một adapter để làm cho nó tương thích với một lớp khác.\n\nTheo Wikipedia\n\n> Trong kỹ thuật phần mềm, mẫu thiết kế Adapter là một mẫu thiết kế phần mềm cho phép giao diện của một lớp hiện có được sử dụng như một giao diện khác. Nó thường được sử dụng để làm cho các lớp hiện có làm việc với các lớp khác mà không cần sửa đổi mã nguồn của chúng.\n\n**Mã nguồn mẫu**\n\nHãy xem xét một thuyền trưởng chỉ có thể sử dụng thuyền chèo và không thể thả neo.\n\nĐầu tiên, chúng ta có các giao diện `RowingBoat` và `FishingBoat`\n\n```java\npublic interface RowingBoat {\n  void row();\n}\n\n@Slf4j\npublic class FishingBoat {\n  public void sail() {\n    LOGGER.info(\"The fishing boat is sailing\");\n  }\n}\n```\n\nVà thuyền trưởng mong đợi một lớp là triển khai của giao diện `RowingBoat` mà có thể di chuyển được\n\n```java\npublic class Captain {\n\n  private final RowingBoat rowingBoat;\n  // default constructor and setter for rowingBoat\n  public Captain(RowingBoat rowingBoat) {\n    this.rowingBoat = rowingBoat;\n  }\n\n  public void row() {\n    rowingBoat.row();\n  }\n}\n```\n\nBây giờ hãy nói rằng hải tặc đang đến và thuyền trưởng của chúng ta cần trốn thoát nhưng chỉ có một thuyền câu sẵn có. Chúng ta cần tạo một adapter cho phép thuyền trưởng vận hành thuyền câu với kỹ năng chèo của mình.\n\n```java\n@Slf4j\npublic class FishingBoatAdapter implements RowingBoat {\n\n  private final FishingBoat boat;\n\n  public FishingBoatAdapter() {\n    boat = new FishingBoat();\n  }\n\n  @Override\n  public void row() {\n    boat.sail();\n  }\n}\n```\n\nVà bây giờ `Captain` có thể sử dụng `FishingBoat` để trốn thoát khỏi hải tặc.\n\n```java\nvar captain = new Captain(new FishingBoatAdapter());\ncaptain.row();\n```\n\n## Sơ đồ lớp\n![alt text](../../../adapter/etc/adapter.urm.png \"Adapter class diagram\")\n\n## Áp dụng\nSử dụng mẫu Adapter khi:\n\n* Bạn muốn sử dụng một lớp hiện có, và giao diện của nó không phù hợp với giao diện bạn cần\n* Bạn muốn tạo một lớp có thể tái sử dụng làm việc với các lớp không liên quan hoặc không thể dự đoán trước, tức là các lớp không nhất thiết phải có giao diện tương thích\n* Bạn cần sử dụng nhiều lớp con hiện có, nhưng việc điều chỉnh giao diện của chúng thông qua việc kế thừa là không hiệu quả. Một đối tượng adapter có thể điều chỉnh giao diện của lớp cha của nó.\n* Hầu hết các ứng dụng sử dụng thư viện bên ngoài sử dụng adapter như một lớp trung gian giữa ứng dụng và thư viện bên ngoài. Nếu muốn sử dụng thư viện khác, chỉ cần tạo một adapter cho thư viện mới mà không cần thay đổi mã nguồn của ứng dụng.\n\n## Hướng dẫn\n\n* [Dzone](https://dzone.com/articles/adapter-design-pattern-in-java)\n* [Refactoring Guru](https://refactoring.guru/design-patterns/adapter/java/example)\n* [Baeldung](https://www.baeldung.com/java-adapter-pattern)\n\n## Kết luận \n\nLớp adapter và đối tượng adapter có những lợi ích và khả năng thích ứng khác nhau. Một lớp adapter\n\n* Chuyển đổi một lớp Adaptee để phù hợp với Target bằng cách ràng buộc với một lớp Adaptee cụ thể. Kết quả là, khi chúng ta muốn thích ứng một lớp và tất cả các lớp con của nó, thì lớp adapter sẽ không hoạt động.\n* Cho phép Adapter ghi đè một số hành vi của Adaptee vì Adapter là một lớp con của Adaptee.\n* Chỉ giới thiệu một đối tượng và không cần thêm con trỏ để truy cập gián tiếp đến Adaptee.\n\nMột đối tượng Adapter \n\n* Cho phép một Adapter làm việc với nhiều Adaptees, tức là chính Adaptee và tất cả các lớp con của nó (nếu có). Adapter cũng có thể thêm chức năng cho tất cả Adaptee cùng một lúc.\n* Làm cho việc ghi đè hành vi của Adaptee trở nên khó khăn hơn. Nó sẽ yêu cầu việc kế thừa Adaptee và làm cho Adapter tham chiếu đến lớp con thay vì chính Adaptee.\n\n## Ví dụ trong thực tế\n\n* [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)\n* [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)\n* [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-)\n* [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-)\n\n## Người đóng góp\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/vi/aggregator-microservices/README.md",
    "content": "---\ntitle: Microservices Tổng Hợp\ncategory: Architectural\nlanguage: vi\ntag:\n- Cloud distributed\n- Decoupling\n- Microservices\n---\n\n## Mục Đích\nNgười dùng chỉ cần thực hiện một lần gọi duy nhất đến dịch vụ tổng hợp, sau đó dịch vụ tổng hợp sẽ gọi dịch vụ con tương ứng.\n\n## Giải Thích\n\nVí dụ thực tế\n\n> Trang web thị trường của chúng ta cần thông tin về sản phẩm và tồn kho hiện tại của chúng. Nó thực hiện gọi đến dịch vụ tổng hợp, sau đó dịch vụ tổng hợp gọi dịch vụ thông tin sản phẩm và dịch vụ tồn kho sản phẩm, cuối cùng trả lại thông tin kết hợp.\n\n## Nói đơn giản hơn\n\n> Microservices Tổng Hợp thu thập các phần dữ liệu từ các dịch vụ con khác nhau và trả về một tổng hợp để xử lý.\n\nTheo Stack Overflow\n\n> Microservices Tổng Hợp gọi nhiều dịch vụ để đạt được chức năng được yêu cầu bởi ứng dụng.\n\n**Mã nguồn mẫu**\n\nHãy bắt đầu từ mô hình dữ liệu. Đây là lớp `Product` của chúng ta.\n\n```java\npublic class Product {\n  private String title;\n  private int productInventories;\n  // getters and setters ->\n  ...\n}\n```\n\nTiếp theo, chúng ta có thể giới thiệu Microservices `Aggregator` của chúng ta. Nó chứa các khách hàng `ProductInformationClient` và\n`ProductInventoryClient` để gọi các dịch vụ con tương ứng.\n\n```java\n@RestController\npublic class Aggregator {\n\n  @Resource\n  private ProductInformationClient informationClient;\n\n  @Resource\n  private ProductInventoryClient inventoryClient;\n\n  @RequestMapping(path = \"/product\", method = RequestMethod.GET)\n  public Product getProduct() {\n\n    var product = new Product();\n    var productTitle = informationClient.getProductTitle();\n    var productInventory = inventoryClient.getProductInventories();\n\n    //Fallback to error message\n    product.setTitle(requireNonNullElse(productTitle, \"Error: Fetching Product Title Failed\"));\n\n    //Fallback to default error inventory\n    product.setProductInventories(requireNonNullElse(productInventory, -1));\n\n    return product;\n  }\n}\n```\n\nDưới đây là bản thể của việc triển khai dịch vụ thông tin sản phẩm. Dịch vụ tồn kho cũng tương tự như thế, nó chỉ trả về số lượng tồn kho.\n\n```java\n@RestController\npublic class InformationController {\n  @RequestMapping(value = \"/information\", method = RequestMethod.GET)\n  public String getProductTitle() {\n    return \"The Product Title.\";\n  }\n}\n```\n\nBây giờ, việc gọi `Aggregator` API REST của chúng ta sẽ trả về thông tin sản phẩm.\n\n```bash\ncurl http://localhost:50004/product\n{\"title\":\"The Product Title.\",\"productInventories\":5}\n```\n\n## Sơ Đồ Lớp\n![alt text](../../../aggregator-microservices/aggregator-service/etc/aggregator-service.png \"Aggregator Microservice\")\n\n\n## Các Trường Hợp Sử Dụng\nSử dụng mẫu Microservices Tổng Hợp khi bạn cần một API chung cho các dịch vụ Microservices khác nhau, bất kể thiết bị của khách hàng.\n\n## Người Đóng Góp\n\n* [Microservice Design Patterns](http://web.archive.org/web/20190705163602/http://blog.arungupta.me/microservice-design-patterns/)\n* [Microservices Patterns: With examples in Java](https://www.amazon.com/gp/product/1617294543/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617294543&linkId=8b4e570267bc5fb8b8189917b461dc60)\n* [Architectural Patterns: Uncover essential patterns in the most indispensable realm of enterprise architecture](https://www.amazon.com/gp/product/B077T7V8RC/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=B077T7V8RC&linkId=c34d204bfe1b277914b420189f09c1a4)\n"
  },
  {
    "path": "localization/vi/builder/README.md",
    "content": "---\ntitle: Builder\ncategory: Creational\nlanguage: vi\ntag:\n    - Gang of Four\n---\n\n## Mục tiêu\n\nTách rời việc xây dựng một đối tượng phức tạp khỏi cách thể hiện của nó, để cùng một quá trình xây dựng có thể tạo ra các cách thể hiện khác nhau.\n\n## Giải thích\n\nVí dụ thực tế\n\n> Hãy tưởng tượng một trình tạo nhân vật cho trò chơi nhập vai. Cách đơn giản nhất là để máy tính tạo nhân vật cho bạn. Nếu bạn muốn chọn các chi tiết về nhân vật như nghề nghiệp, giới tính, màu tóc, v.v. thì việc tạo nhân vật trở thành một quá trình từng bước và hoàn tất khi tất cả các lựa chọn đã sẵn sàng.\n\nNói một cách đơn giản\n\n> Mẫu Builder cho phép bạn tạo ra các phiên bản khác nhau của một đối tượng trong khi tránh việc dùng hàm khởi tạo. Mẫu này hữu ích khi có thể có nhiều phiên bản của một đối tượng. Hoặc khi có nhiều bước liên quan tới việc tạo một đối tượng.\n\nTheo Wikipedia\n\n> Mẫu Builder là một mẫu thiết kế phần mềm dùng để tạo ra đối tượng, với mục đích tìm ra giải pháp cho phản thiết kế hàm khởi tạo quá nhiều tham số (telescoping constructor antipattern).\n\nĐể giải thích rõ hơn về lỗi phản thiết kế hàm khởi tạo có quá nhiều tham số là gì. Ở một thời điểm nào đó, tất cả chúng ta đều đã thấy một hàm khởi tạo như bên dưới:\n\n```java\npublic Hero(Profession profession,String name,HairType hairType,HairColor hairColor,Armor armor,Weapon weapon){\n        }\n```\n\nNhư bạn có thể thấy, số lượng tham số của hàm khởi tạo có thể nhanh chóng trở nên rất nhiều, và có thể trở nên khó khăn cho việc sắp xếp các tham số. Hơn nữa, danh sách tham số này có thể tiếp tục tăng lên nếu bạn muốn bổ sung thêm tùy chọn trong tương lai. Đây được gọi là lỗi phản thiết kế hàm khởi tạo có quá nhiều tham số.\n\n**Ví dụ lập trình**\n\nMột giải pháp hợp lý hơn là sử dụng mẫu Builder. Trước hết, chúng ta có nhân vật anh hùng mà chúng ta muốn tạo ra:\n\n```java\npublic final class Hero {\n    private final Profession profession;\n    private final String name;\n    private final HairType hairType;\n    private final HairColor hairColor;\n    private final Armor armor;\n    private final Weapon weapon;\n\n    private Hero(Builder builder) {\n        this.profession = builder.profession;\n        this.name = builder.name;\n        this.hairColor = builder.hairColor;\n        this.hairType = builder.hairType;\n        this.weapon = builder.weapon;\n        this.armor = builder.armor;\n    }\n}\n```\n\nSau đó chúng ta có lớp Builder:\n\n```java\n  public static class Builder {\n    private final Profession profession;\n    private final String name;\n    private HairType hairType;\n    private HairColor hairColor;\n    private Armor armor;\n    private Weapon weapon;\n\n    public Builder(Profession profession, String name) {\n        if (profession == null || name == null) {\n            throw new IllegalArgumentException(\"profession and name can not be null\");\n        }\n        this.profession = profession;\n        this.name = name;\n    }\n\n    public Builder withHairType(HairType hairType) {\n        this.hairType = hairType;\n        return this;\n    }\n\n    public Builder withHairColor(HairColor hairColor) {\n        this.hairColor = hairColor;\n        return this;\n    }\n\n    public Builder withArmor(Armor armor) {\n        this.armor = armor;\n        return this;\n    }\n\n    public Builder withWeapon(Weapon weapon) {\n        this.weapon = weapon;\n        return this;\n    }\n\n    public Hero build() {\n        return new Hero(this);\n    }\n}\n```\n\nSau đó nó có thể được sử dụng như sau:\n\n```java\nvar mage=new Hero.Builder(Profession.MAGE,\"Riobard\").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();\n```\n\n## Class diagram\n\n![alt text](../../../builder/etc/builder.urm.png \"Builder class diagram\")\n\n## Ứng dụng\n\nSử dụng mẫu Builder khi:\n\n* Thuật toán để tạo một đối tượng phức tạp phải độc lập với các bộ phận tạo nên đối tượng đó và cách chúng liên kết với nhau.\n* Quá trình xây dựng phải cho phép các cách thể hiện khác nhau cho đối tượng được tạo ra.\n* Đặc biệt hữu ích khi một sản phẩm cần nhiều bước để được tạo ra và khi các bước này cần được thực hiện theo một trình tự nhất định.\n\n## Các trường hợp sử dụng đã biết\n\n* Java.lang.StringBuilder\n* Java.nio.ByteBuffer cũng như các bộ đệm tương tự như FloatBuffer, IntBuffer, và các bộ đệm khác.\n* javax.swing.GroupLayout.Group#addComponent()\n\n## Hậu quả\n\nƯu điểm:\n\n* Kiểm soát tốt hơn quá trình xây dựng đối tượng so với các mẫu tạo đối tượng khác.\n* Hỗ trợ xây dựng đối tượng theo từng bước, hoãn các bước xây dựng hoặc chạy các bước đệ quy.\n* Có thể xây dựng các đối tượng đòi hỏi quá trình kết hợp phức tạp các đối tượng con. Sản phẩm cuối cùng được tách rời khỏi các bộ phận tạo nên nó, cũng như quá trình liên kết chúng.\n* Nguyên tắc Đơn Trách nhiệm. Bạn có thể tách rời mã xây dựng phức tạp khỏi logic nghiệp vụ của sản phẩm.\n\nNhược điểm:\n\n* Tổng thể độ phức tạp của code có thể tăng lên vì mẫu đòi hỏi phải tạo nhiều lớp mới.\n\n## Hướng dẫn\n\n* [Refactoring Guru](https://refactoring.guru/design-patterns/builder)\n* [Oracle Blog](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java)\n* [Journal Dev](https://www.journaldev.com/1425/builder-design-pattern-in-java)\n\n## Các trường hợp sử dụng đã biết\n\n* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)\n* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) cũng như các bộ đệm tương tự như FloatBuffer, IntBuffer, v.v.\n* [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-)\n* Tất cả các triển khai của [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)\n* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)\n* [Apache Commons Option.Builder](https://commons.apache.org/proper/commons-cli/apidocs/org/apache/commons/cli/Option.Builder.html)\n\n## Mẫu liên quan\n\n* [Step Builder](https://java-design-patterns.com/patterns/step-builder/) là một biến thể của mẫu Builder tạo ra một đối tượng phức tạp theo cách tiếp cận từng bước. Mẫu Step Builder là một lựa chọn tốt khi bạn cần xây dựng một đối tượng với nhiều tham số tùy chọn, và bạn muốn tránh lỗi phản thiết kế hàm khởi tạo có quá nhiều tham số.\n\n## Ghi nhận\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)"
  },
  {
    "path": "localization/vi/game-loop/README.md",
    "content": "---\ntitle: Game Loop (Vòng lặp trò chơi)\ncategory: Behavioral\nlanguage: vi\ntag:\n    - Concurrency\n    - Event-driven\n    - Game programming\n    - Performance\n---\n\n## Còn được gọi là\n\n* Game Cycle (Chu kỳ trò chơi)\n* Main Game Loop (Vòng lặp trò chơi chính)\n\n## Mục tiêu\n\nMẫu thiết kế Game Loop nhằm thực thi liên tục của một trò chơi, trong đó mỗi chu kỳ vòng lặp xử lý đầu vào, cập nhật trạng thái trò chơi, và hiển thị trạng thái trò chơi lên màn hình, duy trì trải nghiệm chơi mượt mà và tương tác.\n\n## Giải thích\n\nVí dụ thực tế\n\n> Game loop là quá trình chính của tất cả các luồng hiển thị trò chơi. Nó hiện diện trong tất cả các trò chơi hiện đại. Nó điều khiển việc xử lý đầu vào, cập nhật trạng thái nội bộ, hiển thị, xử lý trí tuệ nhân tạo và tất cả các quá trình khác.\n\nNói một cách đơn giản\n\n> Mẫu Game Loop đảm bảo rằng thời gian trò chơi thực thi với tốc độ bằng nhau trong tất cả các cấu hình phần cứng khác nhau.\n\nTheo Wikipedia\n\n> Thành phần trung tâm của bất kỳ trò chơi nào, từ góc độ lập trình, đều là game loop. Game loop cho phép trò chơi chạy trơn tru bất kể đầu vào của người dùng hoặc thiếu đầu vào.\n\n**Ví dụ lập trình**\n\nHãy bắt đầu với một thứ gì đó đơn giản. Đây là lớp `Bullet` (Đạn). Đạn sẽ di chuyển trong trò chơi của chúng ta. Để dễ hình dung, ta cho nó có vị trí 1 chiều.\n\n```java\npublic class Bullet {\n\n    private float position;\n\n    public Bullet() {\n        position = 0.0f;\n    }\n\n    public float getPosition() {\n        return position;\n    }\n\n    public void setPosition(float position) {\n        this.position = position;\n    }\n}\n```\n\n`GameController`  có trách nhiệm di chuyển các đối tượng trong trò chơi, bao gồm cả đạn đã đề cập bên trên.\n\n```java\npublic class GameController {\n\n    protected final Bullet bullet;\n\n    public GameController() {\n        bullet = new Bullet();\n    }\n\n    public void moveBullet(float offset) {\n        var currentPosition = bullet.getPosition();\n        bullet.setPosition(currentPosition + offset);\n    }\n\n    public float getBulletPosition() {\n        return bullet.getPosition();\n    }\n}\n```\n\nBây giờ chúng ta tạo ra một vòng lặp trò chơi (game loop). Hoặc thực tế trong ví dụ minh họa này, chúng ta có loại 3 vòng lặp trò chơi khác nhau. Hãy xem lớp cha `GameLoop` trước.\n\n```java\npublic enum GameStatus {\n\n    RUNNING,\n    STOPPED\n}\n\npublic abstract class GameLoop {\n\n    protected final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n    protected volatile GameStatus status;\n\n    protected GameController controller;\n\n    private Thread gameThread;\n\n    public GameLoop() {\n        controller = new GameController();\n        status = GameStatus.STOPPED;\n    }\n\n    public void run() {\n        status = GameStatus.RUNNING;\n        gameThread = new Thread(this::processGameLoop);\n        gameThread.start();\n    }\n\n    public void stop() {\n        status = GameStatus.STOPPED;\n    }\n\n    public boolean isGameRunning() {\n        return status == GameStatus.RUNNING;\n    }\n\n    protected void processInput() {\n        try {\n            var lag = new Random().nextInt(200) + 50;\n            Thread.sleep(lag);\n        } catch (InterruptedException e) {\n            logger.error(e.getMessage());\n        }\n    }\n\n    protected void render() {\n        var position = controller.getBulletPosition();\n        logger.info(\"Current bullet position: \" + position);\n    }\n\n    protected abstract void processGameLoop();\n}\n```\n\nĐây là cách hiện thực đầu tiên, `FrameBasedGameLoop` (Vòng lặp trò chơi dựa trên khung hình):\n\n```java\npublic class FrameBasedGameLoop extends GameLoop {\n\n    @Override\n    protected void processGameLoop() {\n        while (isGameRunning()) {\n            processInput();\n            update();\n            render();\n        }\n    }\n\n    protected void update() {\n        controller.moveBullet(0.5f);\n    }\n}\n```\n\nCuối cùng, chúng ta sẽ thực thi tất cả các vòng lặp trò chơi.\n\n```java\n    try {\n      LOGGER.info(\"Start frame-based game loop:\");\n      var frameBasedGameLoop = new FrameBasedGameLoop();\n      frameBasedGameLoop.run();\n      Thread.sleep(GAME_LOOP_DURATION_TIME);\n      frameBasedGameLoop.stop();\n      LOGGER.info(\"Stop frame-based game loop.\");\n\n      LOGGER.info(\"Start variable-step game loop:\");\n      var variableStepGameLoop = new VariableStepGameLoop();\n      variableStepGameLoop.run();\n      Thread.sleep(GAME_LOOP_DURATION_TIME);\n      variableStepGameLoop.stop();\n      LOGGER.info(\"Stop variable-step game loop.\");\n\n      LOGGER.info(\"Start fixed-step game loop:\");\n      var fixedStepGameLoop = new FixedStepGameLoop();\n      fixedStepGameLoop.run();\n      Thread.sleep(GAME_LOOP_DURATION_TIME);\n      fixedStepGameLoop.stop();\n      LOGGER.info(\"Stop variable-step game loop.\");\n      \n    } catch (InterruptedException e) {\n      LOGGER.error(e.getMessage());\n    }\n```\n\nKết quả chương trình:\n\n```Start frame-based game loop:\nCurrent bullet position: 0.5\nCurrent bullet position: 1.0\nCurrent bullet position: 1.5\nCurrent bullet position: 2.0\nCurrent bullet position: 2.5\nCurrent bullet position: 3.0\nCurrent bullet position: 3.5\nCurrent bullet position: 4.0\nCurrent bullet position: 4.5\nCurrent bullet position: 5.0\nCurrent bullet position: 5.5\nCurrent bullet position: 6.0\nStop frame-based game loop.\nStart variable-step game loop:\nCurrent bullet position: 6.5\nCurrent bullet position: 0.038\nCurrent bullet position: 0.084\nCurrent bullet position: 0.145\nCurrent bullet position: 0.1805\nCurrent bullet position: 0.28\nCurrent bullet position: 0.32\nCurrent bullet position: 0.42549998\nCurrent bullet position: 0.52849996\nCurrent bullet position: 0.57799995\nCurrent bullet position: 0.63199997\nCurrent bullet position: 0.672\nCurrent bullet position: 0.778\nCurrent bullet position: 0.848\nCurrent bullet position: 0.8955\nCurrent bullet position: 0.9635\nStop variable-step game loop.\nStart fixed-step game loop:\nCurrent bullet position: 0.0\nCurrent bullet position: 1.086\nCurrent bullet position: 0.059999995\nCurrent bullet position: 0.12999998\nCurrent bullet position: 0.24000004\nCurrent bullet position: 0.33999994\nCurrent bullet position: 0.36999992\nCurrent bullet position: 0.43999985\nCurrent bullet position: 0.5399998\nCurrent bullet position: 0.65999967\nCurrent bullet position: 0.68999964\nCurrent bullet position: 0.7299996\nCurrent bullet position: 0.79999954\nCurrent bullet position: 0.89999944\nCurrent bullet position: 0.98999935\nStop variable-step game loop.\n```\n\n## Class diagram\n\n![alt text](../../../game-loop/etc/game-loop.urm.png \"Game Loop pattern class diagram\")\n\n## Ứng dụng\n\nMẫu Game Loop được áp dụng trong mô phỏng thời gian thực và trò chơi, nơi trạng thái cần được cập nhật liên tục và nhất quán để đáp ứng đầu vào của người dùng và các sự kiện khác.\n\n## Các trường hợp ứng dụng đã biết\n\n* Trò chơi video, cả 2D và 3D, trên các nền tảng khác nhau.\n* Mô phỏng thời gian thực yêu cầu tỷ lệ khung hình ổn định để cập nhật logic và hiển thị.\n\n## Hậu quả\n\nƯu điểm:\n\n* Đảm bảo trò chơi thực thi mượt mà và nhất quán.\n* Tạo điều kiện thuận lợi cho việc đồng bộ giữa trạng thái trò chơi, đầu vào người dùng và hiển thị lên màn hình.\n* Cung cấp một cấu trúc rõ ràng để các nhà phát triển trò chơi quản lý chuyển động và thời gian trong trò chơi.\n\nNhược điểm:\n\n* Có thể dẫn đến vấn đề hiệu suất nếu vòng lặp không được quản lý tốt, đặc biệt là trong các hàm cập nhật hoặc hiển thị tốn nhiều tài nguyên.\n* Khó khăn trong việc quản lý tỷ lệ khung hình (frame rates) khác nhau trên các phần cứng khác nhau.\n\n## Các mẫu liên quan\n\n* [State](https://java-design-patterns.com/patterns/state/): Thường được sử dụng trong vòng lặp trò chơi để quản lý các trạng thái khác nhau của trò chơi (ví dụ: menu, đang chơi, tạm dừng). Mối quan hệ nằm ở việc quản lý hành vi cụ thể của trạng thái và chuyển đổi trạng thái một cách mượt mà trong vòng lặp trò chơi.\n* [Observer](https://java-design-patterns.com/patterns/observer/): Hữu ích trong vòng lặp trò chơi để xử lý sự kiện, nơi các thực thể trò chơi có thể đăng ký và phản ứng với các sự kiện (ví dụ: va chạm, ghi điểm).\n\n## Tham khảo\n\n* [Game Programming Patterns - Game Loop](http://gameprogrammingpatterns.com/game-loop.html)\n* [Game Programming Patterns](https://www.amazon.com/gp/product/0990582906/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0990582906&linkId=1289749a703b3fe0e24cd8d604d7c40b)\n* [Game Engine Architecture, Third Edition](https://www.amazon.com/gp/product/1138035459/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1138035459&linkId=94502746617211bc40e0ef49d29333ac)\n* [Real-Time Collision Detection](https://amzn.to/3W9Jj8T)"
  },
  {
    "path": "localization/zh/README.md",
    "content": "<!-- the line below needs to be an empty line C: (its because kramdown isnt\n     that smart and dearly wants an empty line before a heading to be able to\n     display it as such, e.g. website) -->\n\n# 设计模式Java版\n\n![Java CI with Maven](https://github.com/iluwatar/java-design-patterns/workflows/Java%20CI/badge.svg) [](https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/LICENSE.md)![License MIT](https://img.shields.io/badge/license-MIT-blue.svg) [](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg) [](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)![Sonarcloud Status](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=alert_status)\n\n# 介绍\n\n设计模式是程序员在设计应用程序或系统时可以用来解决常见问题的最佳形式化实践。\n\n设计模式可以通过提供经过测试的，经过验证的开发范例来加快开发过程。\n\n重用设计模式有助于防止引起重大问题的细微问题，并且还可以为熟悉模式的程序员和架构师们提高代码可读性。\n\n# 入门\n\n这个站点展示了Java设计模式。该解决方案是由开源社区中经验丰富的程序员和架构师开发的。可以通过他们高级描述或查看源代码来浏览这些设计模式。源代码示例得到了很好的注释，可以视为编程教程，以了解如何实现特定的模式。我们使用最流行的，久经考验的开源Java技术。\n\n在深入学习该材料之前，您应该熟悉各种软件设计原则。\n\n所有设计应尽可能简单。您应该从KISS，YAGNI开始，并做可能可行的最简单的事情。仅在实际可扩展性需要它们时才应引入复杂性和模式。\n\n熟悉这些概念后，您可以通过以下任何一种方法开始深入研究模式\n\n- 使用难度标签： `入门难度` ， `中等难度`和`专家难度` 。\n- 使用模式分类`创建型` ，`行为型`和其他类别。\n- 搜索特定的模式。一个也找不到？请[在这里](https://github.com/iluwatar/java-design-patterns/issues)反馈新模式。\n\n希望您在本站上找到的面向对象解决方案能够对您的体系结构很有用，并在学习它们的时候能够像我们开发它们一样有趣。\n\n# 如何做出贡献\n\n如果您愿意为该项目做出贡献，则可以在我们的[开发人员Wiki中](https://github.com/iluwatar/java-design-patterns/wiki)找到相关信息。我们将在[Gitter聊天室](https://gitter.im/iluwatar/java-design-patterns)为您提供帮助并回答您的问题。\n\n# 许可证\n\n该项目使用MIT许可证。\n\n\n"
  },
  {
    "path": "localization/zh/abstract-document/README.md",
    "content": "---\ntitle: Abstract Document\nshortTitle: Abstract Document\ncategory: Structural\nlanguage: zh\ntag: \n - Extensibility\n---\n\n## 目的\n\n使用动态属性，并在保持类型安全的同时实现非类型化语言的灵活性。\n\n## 解释\n\n抽象文档模式使您能够处理其他非静态属性。 此模式使用特征的概念来实现类型安全，并将不同类的属性分离为一组接口。\n\n真实世界例子\n\n>  考虑由多个部分组成的汽车。 但是，我们不知道特定汽车是否真的拥有所有零件，或者仅仅是零件中的一部分。 我们的汽车是动态而且非常灵活的。\n\n通俗的说\n\n> 抽象文档模式允许在对象不知道的情况下将属性附加到对象。\n\n维基百科说\n\n> 面向对象的结构设计模式，用于组织松散类型的键值存储中的对象并使用类型化的视图公开数据。 该模式的目的是在强类型语言中实现组件之间的高度灵活性，在这种语言中，可以在不丢失类型安全支持的情况下，将新属性动态地添加到对象树中。 该模式利用特征将类的不同属性分成不同的接口。\n\n**程序示例**\n\n让我们首先定义基类`Document`和`AbstractDocument`。 它们基本上使对象拥有属性映射和任意数量的子对象。\n\n```java\npublic interface Document {\n\n  Void put(String key, Object value);\n\n  Object get(String key);\n\n  <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor);\n}\n\npublic abstract class AbstractDocument implements Document {\n\n  private final Map<String, Object> properties;\n\n  protected AbstractDocument(Map<String, Object> properties) {\n    Objects.requireNonNull(properties, \"properties map is required\");\n    this.properties = properties;\n  }\n\n  @Override\n  public Void put(String key, Object value) {\n    properties.put(key, value);\n    return null;\n  }\n\n  @Override\n  public Object get(String key) {\n    return properties.get(key);\n  }\n\n  @Override\n  public <T> Stream<T> children(String key, Function<Map<String, Object>, T> constructor) {\n    return Stream.ofNullable(get(key))\n        .filter(Objects::nonNull)\n        .map(el -> (List<Map<String, Object>>) el)\n        .findAny()\n        .stream()\n        .flatMap(Collection::stream)\n        .map(constructor);\n  }\n  ...\n}\n```\n接下来，我们定义一个枚举“属性”和一组类型，价格，模型和零件的接口。 这使我们能够为Car类创建静态外观的界面。\n\n```java\npublic enum Property {\n\n  PARTS, TYPE, PRICE, MODEL\n}\n\npublic interface HasType extends Document {\n\n  default Optional<String> getType() {\n    return Optional.ofNullable((String) get(Property.TYPE.toString()));\n  }\n}\n\npublic interface HasPrice extends Document {\n\n  default Optional<Number> getPrice() {\n    return Optional.ofNullable((Number) get(Property.PRICE.toString()));\n  }\n}\npublic interface HasModel extends Document {\n\n  default Optional<String> getModel() {\n    return Optional.ofNullable((String) get(Property.MODEL.toString()));\n  }\n}\n\npublic interface HasParts extends Document {\n\n  default Stream<Part> getParts() {\n    return children(Property.PARTS.toString(), Part::new);\n  }\n}\n```\n\n现在我们准备介绍`Car`。\n\n```java\npublic class Car extends AbstractDocument implements HasModel, HasPrice, HasParts {\n\n  public Car(Map<String, Object> properties) {\n    super(properties);\n  }\n}\n```\n\n最后是完整示例中的`Car`构造和使用方式。\n\n```java\n    LOGGER.info(\"Constructing parts and car\");\n\n    var wheelProperties = Map.of(\n        Property.TYPE.toString(), \"wheel\",\n        Property.MODEL.toString(), \"15C\",\n        Property.PRICE.toString(), 100L);\n\n    var doorProperties = Map.of(\n        Property.TYPE.toString(), \"door\",\n        Property.MODEL.toString(), \"Lambo\",\n        Property.PRICE.toString(), 300L);\n\n    var carProperties = Map.of(\n        Property.MODEL.toString(), \"300SL\",\n        Property.PRICE.toString(), 10000L,\n        Property.PARTS.toString(), List.of(wheelProperties, doorProperties));\n\n    var car = new Car(carProperties);\n\n    LOGGER.info(\"Here is our car:\");\n    LOGGER.info(\"-> model: {}\", car.getModel().orElseThrow());\n    LOGGER.info(\"-> price: {}\", car.getPrice().orElseThrow());\n    LOGGER.info(\"-> parts: \");\n    car.getParts().forEach(p -> LOGGER.info(\"\\t{}/{}/{}\",\n        p.getType().orElse(null),\n        p.getModel().orElse(null),\n        p.getPrice().orElse(null))\n    );\n\n    // Constructing parts and car\n    // Here is our car:\n    // model: 300SL\n    // price: 10000\n    // parts: \n    // wheel/15C/100\n    // door/Lambo/300\n```\n\n## 类图\n\n![alt text](./etc/abstract-document.png \"Abstract Document Traits and Domain\")\n\n## 适用性\n\n使用抽象文档模式当\n\n* 需要即时添加新属性\n* 你想要一种灵活的方式来以树状结构组织域\n* 你想要更宽松的耦合系统\n\n## 鸣谢\n\n* [Wikipedia: Abstract Document Pattern](https://en.wikipedia.org/wiki/Abstract_Document_Pattern)\n* [Martin Fowler: Dealing with properties](http://martinfowler.com/apsupp/properties.pdf)\n* [Pattern-Oriented Software Architecture Volume 4: A Pattern Language for Distributed Computing (v. 4)](https://www.amazon.com/gp/product/0470059028/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0470059028&linkId=e3aacaea7017258acf184f9f3283b492)\n"
  },
  {
    "path": "localization/zh/abstract-factory/README.md",
    "content": "---\ntitle: Abstract Factory\nshortTitle: Abstract Factory\ncategory: Creational\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 或称\n\n工具包\n\n## 目的\n\n提供一个用于创建相关对象家族的接口，而无需指定其具体类。\n\n## 解释\n\n真实世界例子\n\n> 要创建一个王国，我们需要具有共同主题的对象。精灵王国需要精灵国王、精灵城堡和精灵军队，而兽人王国需要兽人国王、兽人城堡和兽人军队。王国中的对象之间存在依赖关系。\n\n通俗的说\n\n> 工厂的工厂； 一个将单个但相关/从属的工厂分组在一起而没有指定其具体类别的工厂。\n\n维基百科上说\n\n> 抽象工厂模式提供了一种封装一组具有共同主题的单个工厂而无需指定其具体类的方法\n\n**程序示例**\n\n翻译上面的王国示例。 首先，我们为王国中的对象提供了一些接口和实现。\n\n```java\npublic interface Castle {\n  String getDescription();\n}\n\npublic interface King {\n  String getDescription();\n}\n\npublic interface Army {\n  String getDescription();\n}\n\n// Elven implementations ->\npublic class ElfCastle implements Castle {\n  static final String DESCRIPTION = \"This is the Elven castle!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfKing implements King {\n  static final String DESCRIPTION = \"This is the Elven king!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\npublic class ElfArmy implements Army {\n  static final String DESCRIPTION = \"This is the Elven Army!\";\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\n// Orcish implementations similarly -> ...\n\n```\n\n然后我们有了王国工厂的抽象和实现\n\n```java\npublic interface KingdomFactory {\n  Castle createCastle();\n  King createKing();\n  Army createArmy();\n}\n\npublic class ElfKingdomFactory implements KingdomFactory {\n  public Castle createCastle() {\n    return new ElfCastle();\n  }\n  public King createKing() {\n    return new ElfKing();\n  }\n  public Army createArmy() {\n    return new ElfArmy();\n  }\n}\n\npublic class OrcKingdomFactory implements KingdomFactory {\n  public Castle createCastle() {\n    return new OrcCastle();\n  }\n  public King createKing() {\n    return new OrcKing();\n  }\n  public Army createArmy() {\n    return new OrcArmy();\n  }\n}\n```\n\n现在我们有了抽象工厂，使我们可以制作相关对象的系列，即精灵王国工厂创建了精灵城堡，国王和军队等。\n\n```java\nvar factory = new ElfKingdomFactory();\nvar castle = factory.createCastle();\nvar king = factory.createKing();\nvar army = factory.createArmy();\n\ncastle.getDescription();\nking.getDescription();\narmy.getDescription();\n```\n\n程序输出:\n\n```java\nThis is the Elven castle!\nThis is the Elven king!\nThis is the Elven Army!\n```\n\n现在，我们可以为不同的王国工厂设计工厂。 在此示例中，我们创建了FactoryMaker，负责返回ElfKingdomFactory或OrcKingdomFactory的实例。 客户可以使用FactoryMaker来创建所需的具体工厂，该工厂随后将生产不同的具体对象（军队，国王，城堡）。 在此示例中，我们还使用了一个枚举来参数化客户要求的王国工厂类型。\n\n```java\npublic static class FactoryMaker {\n\n    public enum KingdomType {\n        ELF, ORC\n    }\n\n    public static KingdomFactory makeFactory(KingdomType type) {\n        return switch (type) {\n            case ELF -> new ElfKingdomFactory();\n            case ORC -> new OrcKingdomFactory();\n            default -> throw new IllegalArgumentException(\"KingdomType not supported.\");\n        };\n    }\n}\n\n    public static void main(String[] args) {\n        var app = new App();\n\n        LOGGER.info(\"Elf Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));\n        LOGGER.info(app.getArmy().getDescription());\n        LOGGER.info(app.getCastle().getDescription());\n        LOGGER.info(app.getKing().getDescription());\n\n        LOGGER.info(\"Orc Kingdom\");\n        app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));\n        --similar use of the orc factory\n    }\n```\n\n## 类图\n\n![alt text](./etc/abstract-factory.urm.png \"Abstract Factory class diagram\")\n\n\n## 适用性\n\n在以下情况下使用抽象工厂模式\n\n* 该系统应独立于其产品的创建，组成和表示方式\n* 系统应配置有多个产品系列之一\n* 相关产品对象系列旨在一起使用，你需要强制执行此约束\n* 你想提供产品的类库，并且只想暴露它们的接口，而不是它们的实现。\n* 从概念上讲，依赖项的生存期比使用者的生存期短。\n* 你需要一个运行时值来构建特定的依赖关系\n* 你想决定在运行时从系列中调用哪种产品。\n* 你需要提供一个或更多仅在运行时才知道的参数，然后才能解决依赖关系。\n* 当你需要产品之间的一致性时\n* 在向程序添加新产品或产品系列时，您不想更改现有代码。\n\n示例场景\n\n* 在运行时在FileSystemAcmeService ，DatabaseAcmeService 或NetworkAcmeService中选择并调用一个\n* 单元测试用例的编写变得更加容易\n* 适用于不同操作系统的UI工具\n\n## 后果:\n\n* Java中的依赖注入会隐藏服务类的依赖关系，这些依赖关系可能导致运行时错误，而这些错误在编译时会被捕获。\n* 虽然在创建预定义对象时模式很好，但是添加新对象可能会很困难。\n* 由于引入了许多新的接口和类，因此代码变得比应有的复杂。\n\n## 教程\n\n* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java) \n\n## 已知使用\n\n* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html)\n* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--)\n* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--)\n\n## 相关模式\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/zh/active-object/README.md",
    "content": "---\ntitle: Active Object\nshortTitle: Active Object\ncategory: Concurrency\nlanguage: zh\ntag:\n - Performance\n---\n\n\n## 目的\n活动对象设计模式使每个驻留在其控制线程中的对象的方法执行与方法调用脱钩。 目的是通过使用异步方法调用和用于处理请求的调度程序来引入并发。\n\n## 解释\n\n实现活动对象模式的类将包含自同步机制，而无需使用“同步”方法。\n\n真实世界例子\n\n>兽人以其野性和顽强的灵魂而著称。 似乎他们有基于先前行为的控制线程。\n\n要实现具有自己的控制机制线程并仅公开其API而不公开自己的执行，我们可以使用活动对象模式。\n\n**程序示例**\n\n```java\npublic abstract class ActiveCreature{\n  private final Logger logger = LoggerFactory.getLogger(ActiveCreature.class.getName());\n\n  private BlockingQueue<Runnable> requests;\n  \n  private String name;\n  \n  private Thread thread;\n\n  public ActiveCreature(String name) {\n    this.name = name;\n    this.requests = new LinkedBlockingQueue<Runnable>();\n    thread = new Thread(new Runnable() {\n        @Override\n        public void run() {\n          while (true) {\n            try {\n              requests.take().run();\n            } catch (InterruptedException e) { \n              logger.error(e.getMessage());\n            }\n          }\n        }\n      }\n    );\n    thread.start();\n  }\n  \n  public void eat() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} is eating!\",name());\n          logger.info(\"{} has finished eating!\",name());\n        }\n      }\n    );\n  }\n\n  public void roam() throws InterruptedException {\n    requests.put(new Runnable() {\n        @Override\n        public void run() { \n          logger.info(\"{} has started to roam and the wastelands.\",name());\n        }\n      }\n    );\n  }\n  \n  public String name() {\n    return this.name;\n  }\n}\n```\n\n我们可以看到，任何将扩展ActiveCreature的类都将具有自己的控制线程来执行和调用方法。\n\n例如，兽人类：\n\n```java\npublic class Orc extends ActiveCreature {\n\n  public Orc(String name) {\n    super(name);\n  }\n\n}\n```\n\n现在，我们可以创建多个生物，例如兽人，告诉他们吃东西和散步，然后他们将在自己的控制线程上执行它：\n\n```java\n  public static void main(String[] args) {  \n    var app = new App();\n    app.run();\n  }\n  \n  @Override\n  public void run() {\n    ActiveCreature creature;\n    try {\n      for (int i = 0;i < creatures;i++) {\n        creature = new Orc(Orc.class.getSimpleName().toString() + i);\n        creature.eat();\n        creature.roam();\n      }\n      Thread.sleep(1000);\n    } catch (InterruptedException e) {\n      logger.error(e.getMessage());\n    }\n    Runtime.getRuntime().exit(1);\n  }\n```\n\n## 类图\n\n![alt text](./etc/active-object.urm.png \"Active Object class diagram\")\n"
  },
  {
    "path": "localization/zh/acyclic-visitor/README.md",
    "content": "---\ntitle: Acyclic Visitor\nshortTitle: Acyclic Visitor\ncategory: Behavioral\nlanguage: zh\ntag:\n - Extensibility\n---\n\n## 目的\n\n允许将新功能添加到现有的类层次结构中，而不会影响这些层次结构，也不会有四人帮访客模式中那样循环依赖的问题。\n\n## 解释\n\n真实世界例子\n\n> 我们有一个调制解调器类的层次结构。 需要使用基于过滤条件的外部算法（是Unix或DOS兼容的调制解调器）来访问此层次结构中的调制解调器。\n\n通俗地说\n\n> 非循环访问者允许将功能添加到现有的类层次结构中，而无需修改层次结构\n\n[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) 上说\n\n> 非循环访客模式允许将新功能添加到现有的类层次结构中，而不会影响这些层次结构，也不会创建四人帮访客模式中固有的循环依赖问题。\n\n**程序示例**\n\n这是调制解调器的层次结构。\n\n```java\npublic abstract class Modem {\n  public abstract void accept(ModemVisitor modemVisitor);\n}\n\npublic class Zoom extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof ZoomVisitor) {\n      ((ZoomVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only ZoomVisitor is allowed to visit Zoom modem\");\n    }\n  }\n}\n\npublic class Hayes extends Modem {\n  ...\n  @Override\n  public void accept(ModemVisitor modemVisitor) {\n    if (modemVisitor instanceof HayesVisitor) {\n      ((HayesVisitor) modemVisitor).visit(this);\n    } else {\n      LOGGER.info(\"Only HayesVisitor is allowed to visit Hayes modem\");\n    }\n  }\n}\n```\n\n下面我们介绍`调制解调器访问者`类结构。\n\n```java\npublic interface ModemVisitor {\n}\n\npublic interface HayesVisitor extends ModemVisitor {\n  void visit(Hayes hayes);\n}\n\npublic interface ZoomVisitor extends ModemVisitor {\n  void visit(Zoom zoom);\n}\n\npublic interface AllModemVisitor extends ZoomVisitor, HayesVisitor {\n}\n\npublic class ConfigureForDosVisitor implements AllModemVisitor {\n  ...\n  @Override\n  public void visit(Hayes hayes) {\n    LOGGER.info(hayes + \" used with Dos configurator.\");\n  }\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Dos configurator.\");\n  }\n}\n\npublic class ConfigureForUnixVisitor implements ZoomVisitor {\n  ...\n  @Override\n  public void visit(Zoom zoom) {\n    LOGGER.info(zoom + \" used with Unix configurator.\");\n  }\n}\n```\n\n最后，这里是访问者的实践。\n\n```java\n    var conUnix = new ConfigureForUnixVisitor();\n    var conDos = new ConfigureForDosVisitor();\n    var zoom = new Zoom();\n    var hayes = new Hayes();\n    hayes.accept(conDos);\n    zoom.accept(conDos);\n    hayes.accept(conUnix);\n    zoom.accept(conUnix);   \n```\n\n程序输出:\n\n```\n    // Hayes modem used with Dos configurator.\n    // Zoom modem used with Dos configurator.\n    // Only HayesVisitor is allowed to visit Hayes modem\n    // Zoom modem used with Unix configurator.\n```\n\n## 类图\n\n![alt text](./etc/acyclic-visitor.png \"Acyclic Visitor\")\n\n## 适用性\n\n以下情况可以使用此模式：\n\n* 需要在现有层次结构中添加新功能而无需更改或影响该层次结构时。\n* 当某些功能在层次结构上运行，但不属于层次结构本身时。 例如 ConfigureForDOS / ConfigureForUnix / ConfigureForX问题。\n* 当您需要根据对象的类型对对象执行非常不同的操作时。\n* 当访问的类层次结构将经常使用元素类的新派生进行扩展时。\n* 当重新编译，重新链接，重新测试或重新分发派生元素非常昂贵时。\n\n## 结果\n\n好处:\n\n* 类层次结构之间没有依赖关系循环。\n* 如果添加了新访客，则无需重新编译所有访客。\n* 如果类层次结构具有新成员，则不会导致现有访问者中的编译失败。\n\n坏处:\n\n* 通过证明它可以接受所有访客，但实际上仅对特定访客感兴趣，从而违反了[Liskov的替代原则](https://java-design-patterns.com/principles/#liskov-substitution-principle)\n* 必须为可访问的类层次结构中的所有成员创建访问者的并行层次结构。\n\n## 相关的模式\n\n* [Visitor Pattern](https://java-design-patterns.com/patterns/visitor/)\n\n## 鸣谢\n\n* [Acyclic Visitor by Robert C. Martin](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf)\n* [Acyclic Visitor in WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor)\n"
  },
  {
    "path": "localization/zh/adapter/README.md",
    "content": "---\ntitle: Adapter\nshortTitle: Adapter\ncategory: Structural\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 又被称为\n包装器\n\n## 目的\n将一个接口转换成另一个客户所期望的接口。适配器让那些本来因为接口不兼容的类可以合作无间。\n\n## 解释\n\n现实世界例子\n\n> 考虑有这么一种情况，在你的存储卡中有一些照片，你想将其传到你的电脑中。为了传送数据，你需要某种能够兼容你电脑接口的适配器以便你的储存卡能连上你的电脑。在这种情况下，读卡器就是一个适配器。\n> 另一个例子就是注明的电源适配器；三脚插头不能插在两脚插座上，需要一个电源适配器来使其能够插在两脚插座上。\n> 还有一个例子就是翻译官，他翻译一个人对另一个人说的话。\n\n用直白的话来说\n\n> 适配器模式让你可以把不兼容的对象包在适配器中，以让其兼容其他类。\n\n维基百科中说\n\n> 在软件工程中，适配器模式是一种可以让现有类的接口把其作为其他接口来使用的设计模式。它经常用来使现有的类和其他类能够工作并且不用修改其他类的源代码。\n\n**编程样例(对象适配器)**\n\n假如有一个船长他只会划船，但不会航行。\n\n首先我们有接口`RowingBoat`和`FishingBoat`\n\n```java\npublic interface RowingBoat {\n  void row();\n}\n\n@Slf4j\npublic class FishingBoat {\n  public void sail() {\n    LOGGER.info(\"The fishing boat is sailing\");\n  }\n}\n```\n船长希望有一个`RowingBoat`接口的实现，这样就可以移动\n\n```java\npublic class Captain {\n\n  private final RowingBoat rowingBoat;\n  // default constructor and setter for rowingBoat\n  public Captain(RowingBoat rowingBoat) {\n    this.rowingBoat = rowingBoat;\n  }\n\n  public void row() {\n    rowingBoat.row();\n  }\n}\n```\n\n现在海盗来了，我们的船长需要逃跑但是只有一个渔船可用。我们需要创建一个可以让船长使用其划船技能来操作渔船的适配器。\n\n```java\n@Slf4j\npublic class FishingBoatAdapter implements RowingBoat {\n\n  private final FishingBoat boat;\n\n  public FishingBoatAdapter() {\n    boat = new FishingBoat();\n  }\n\n  @Override\n  public void row() {\n    boat.sail();\n  }\n}\n\n```\n\n现在 `船长` 可以使用`FishingBoat`接口来逃离海盗了。\n\n```java\nvar captain = new Captain(new FishingBoatAdapter());\ncaptain.row();\n```\n\n## 类图\n![alt text](./etc/adapter.urm.png \"Adapter class diagram\")\n\n\n## 应用\n使用适配器模式当\n\n* 你想使用一个已有类，但是它的接口不能和你需要的所匹配\n* 你需要创建一个可重用类，该类与不相关或不可预见的类进行协作，即不一定具有兼容接口的类\n* 你需要使用一些现有的子类，但是子类化他们每一个的子类来进行接口的适配是不现实的。一个对象适配器可以适配他们父类的接口。\n* 大多数使用第三方类库的应用使用适配器作为一个在应用和第三方类库间的中间层来使应用和类库解耦。如果必须使用另一个库，则只需使用一个新库的适配器而无需改变应用程序的代码。\n\n## 后果:\n类和对象适配器有不同的权衡取舍。一个类适配器\n\n*\t适配被适配者到目标接口，需要保证只有一个具体的被适配者类。作为结果，当我们想适配一个类和它所有的子类时，类适配器将不会起作用。\n*\t可以让适配器重写一些被适配者的行为，因为适配器是被适配者的子类。\n*\t只引入了一个对象，并且不需要其他指针间接访问被适配者。\n\n对象适配器\t\n\n*\t一个适配器可以和许多被适配者工作，也就是被适配者自己和所有它的子类。适配器同时可以为所有被适配者添加功能。\n*\t覆盖被适配者的行为变得更难。需要子类化被适配者然后让适配器引用这个子类不是被适配者。\n\n\n## 现实世界的案例\n\n* [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29)\n* [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-)\n* [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-)\n* [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-)\n\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n\n```\n\n```"
  },
  {
    "path": "localization/zh/aggregator-microservices/README.md",
    "content": "---\ntitle: Aggregator Microservices\nshortTitle: Aggregator Microservices\ncategory: Architectural\nlanguage: zh\ntag:\n- Cloud distributed\n- Decoupling\n- Microservices\n---\n\n## 意图\n\n用户对聚合器服务进行一次调用，然后聚合器将调用每个相关的微服务。\n\n## 解释\n\n真实世界例子\n\n> 我们的网络市场需要有关产品及其当前库存的信息。 它调用聚合服务，聚合服务依次调用产品信息微服务和产品库存微服务，返回组合信息。\n\n通俗地说\n\n> 聚合器微服务从各种微服务中收集数据，并返回一个聚合数据以进行处理。\n\nStack Overflow上说\n\n> 聚合器微服务调用多个服务以实现应用程序所需的功能。\n\n**程序示例**\n\n让我们从数据模型开始。 这是我们的`产品`。\n\n```java\npublic class Product {\n  private String title;\n  private int productInventories;\n  // getters and setters ->\n  ...\n}\n```\n\n接下来，我们将介绍我们的聚合器微服务。 它包含用于调用相应微服务的客户端`ProductInformationClient`和` ProductInventoryClient`。\n\n```java\n@RestController\npublic class Aggregator {\n\n  @Resource\n  private ProductInformationClient informationClient;\n\n  @Resource\n  private ProductInventoryClient inventoryClient;\n\n  @RequestMapping(path = \"/product\", method = RequestMethod.GET)\n  public Product getProduct() {\n\n    var product = new Product();\n    var productTitle = informationClient.getProductTitle();\n    var productInventory = inventoryClient.getProductInventories();\n\n    //Fallback to error message\n    product.setTitle(requireNonNullElse(productTitle, \"Error: Fetching Product Title Failed\"));\n\n    //Fallback to default error inventory\n    product.setProductInventories(requireNonNullElse(productInventory, -1));\n\n    return product;\n  }\n}\n```\n\n这是产品信息微服务的精华实现。 库存微服务类似，它只返回库存计数。\n\n```java\n@RestController\npublic class InformationController {\n  @RequestMapping(value = \"/information\", method = RequestMethod.GET)\n  public String getProductTitle() {\n    return \"The Product Title.\";\n  }\n}\n```\n\nNow calling our `Aggregator` REST API returns the product information.\n\n现在调用我们的聚合器 REST API会返回产品信息。\n\n```bash\ncurl http://localhost:50004/product\n{\"title\":\"The Product Title.\",\"productInventories\":5}\n```\n\n## 类图\n\n![alt text](./etc/aggregator-service.png \"Aggregator Microservice\")\n\n## 适用性\n\n当需要各种微服务的统一API时，无论客户端设备如何，都可以使用Aggregator微服务模式。\n\n## 鸣谢\n\n* [Microservice Design Patterns](http://web.archive.org/web/20190705163602/http://blog.arungupta.me/microservice-design-patterns/)\n* [Microservices Patterns: With examples in Java](https://www.amazon.com/gp/product/1617294543/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617294543&linkId=8b4e570267bc5fb8b8189917b461dc60)\n* [Architectural Patterns: Uncover essential patterns in the most indispensable realm of enterprise architecture](https://www.amazon.com/gp/product/B077T7V8RC/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=B077T7V8RC&linkId=c34d204bfe1b277914b420189f09c1a4)\n"
  },
  {
    "path": "localization/zh/ambassador/README.md",
    "content": "---\ntitle: Ambassador\nshortTitle: Ambassador\ncategory: Structural\nlanguage: zh\ntag:\n  - Decoupling\n  - Cloud distributed\n---\n\n## 目的\n\n在客户端上提供帮助程序服务实例，并从共享资源上转移常用功能。\n\n## 解释\n\n真实世界例子\n\n> 远程服务有许多客户端访问它提供的功能。 该服务是旧版应用程序，无法更新。 用户的大量请求导致连接问题。新的请求频率规则需要同时实现延迟检测和客户端日志功能。\n\n通俗的说\n\n> 使用“大使”模式，我们可以实现来自客户端的频率较低的轮询以及延迟检查和日志记录。\n\n微软文档做了如下阐述\n\n> 可以将大使服务视为与客户端位于同一位置的进程外代理。 此模式对于以语言不可知的方式减轻常见的客户端连接任务（例如监视，日志记录，路由，安全性（如TLS）和弹性模式）的工作很有用。 它通常与旧版应用程序或其他难以修改的应用程序一起使用，以扩展其网络功能。 它还可以使专业团队实现这些功能。\n\n**程序示例**\n\n有了上面的介绍我们将在这个例子中模仿功能。我们有一个用远程服务实现的接口，同时也是大使服务。\n\n```java\ninterface RemoteServiceInterface {\n    long doRemoteFunction(int value) throws Exception;\n}\n```\n\n表示为单例的远程服务。\n\n```java\npublic class RemoteService implements RemoteServiceInterface {\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(RemoteService.class);\n    private static RemoteService service = null;\n\n    static synchronized RemoteService getRemoteService() {\n        if (service == null) {\n            service = new RemoteService();\n        }\n        return service;\n    }\n\n    private RemoteService() {}\n\n    @Override\n    public long doRemoteFunction(int value) {\n        long waitTime = (long) Math.floor(Math.random() * 1000);\n\n        try {\n            sleep(waitTime);\n        } catch (InterruptedException e) {\n            LOGGER.error(\"Thread sleep interrupted\", e);\n        }\n\n        return waitTime >= 200 ? value * 10 : -1;\n    }\n}\n```\n\n服务大使添加了像日志和延迟检测的额外功能\n\n```java\npublic class ServiceAmbassador implements RemoteServiceInterface {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(ServiceAmbassador.class);\n  private static final int RETRIES = 3;\n  private static final int DELAY_MS = 3000;\n\n  ServiceAmbassador() {\n  }\n\n  @Override\n  public long doRemoteFunction(int value) {\n    return safeCall(value);\n  }\n\n  private long checkLatency(int value) {\n    var startTime = System.currentTimeMillis();\n    var result = RemoteService.getRemoteService().doRemoteFunction(value);\n    var timeTaken = System.currentTimeMillis() - startTime;\n\n    LOGGER.info(\"Time taken (ms): \" + timeTaken);\n    return result;\n  }\n\n  private long safeCall(int value) {\n    var retries = 0;\n    var result = (long) FAILURE;\n\n    for (int i = 0; i < RETRIES; i++) {\n      if (retries >= RETRIES) {\n        return FAILURE;\n      }\n\n      if ((result = checkLatency(value)) == FAILURE) {\n        LOGGER.info(\"Failed to reach remote: (\" + (i + 1) + \")\");\n        retries++;\n        try {\n          sleep(DELAY_MS);\n        } catch (InterruptedException e) {\n          LOGGER.error(\"Thread sleep state interrupted\", e);\n        }\n      } else {\n        break;\n      }\n    }\n    return result;\n  }\n}\n```\n\n客户端具有用于与远程服务进行交互的本地服务大使：\n\n```java\npublic class Client {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(Client.class);\n  private final ServiceAmbassador serviceAmbassador = new ServiceAmbassador();\n\n  long useService(int value) {\n    var result = serviceAmbassador.doRemoteFunction(value);\n    LOGGER.info(\"Service result: \" + result);\n    return result;\n  }\n}\n```\n\n这是两个使用该服务的客户端。\n\n```java\npublic class App {\n  public static void main(String[] args) {\n    var host1 = new Client();\n    var host2 = new Client();\n    host1.useService(12);\n    host2.useService(73);\n  }\n}\n```\n\nHere's the output for running the example:\n\n```java\nTime taken (ms): 111\nService result: 120\nTime taken (ms): 931\nFailed to reach remote: (1)\nTime taken (ms): 665\nFailed to reach remote: (2)\nTime taken (ms): 538\nFailed to reach remote: (3)\nService result: -1\n```\n\n## 类图\n\n![alt text](./etc/ambassador.urm.png \"Ambassador class diagram\")\n\n## 适用性\n\n大使适用于无法修改或极难修改的旧式远程服务。 可以在客户端上实现连接性的功能，而无需更改远程服务。\n\n* 大使提供了用于远程服务的本地接口。\n* 大使在客户端上提供日志记录，断路，重试和安全性。\n\n## 典型用例\n\n* 控制对另一个对象的访问\n* 实现日志\n* 卸载远程服务任务\n* 简化网络连接\n\n## 已知使用\n\n* [Kubernetes-native API gateway for microservices](https://github.com/datawire/ambassador)\n\n## 相关模式\n\n* [Proxy](https://java-design-patterns.com/patterns/proxy/)\n\n## 鸣谢\n\n* [Ambassador pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/ambassador)\n* [Designing Distributed Systems: Patterns and Paradigms for Scalable, Reliable Services](https://books.google.co.uk/books?id=6BJNDwAAQBAJ&pg=PT35&lpg=PT35&dq=ambassador+pattern+in+real+world&source=bl&ots=d2e7GhYdHi&sig=Lfl_MDnCgn6lUcjzOg4GXrN13bQ&hl=en&sa=X&ved=0ahUKEwjk9L_18rrbAhVpKcAKHX_KA7EQ6AEIWTAI#v=onepage&q=ambassador%20pattern%20in%20real%20world&f=false)\n"
  },
  {
    "path": "localization/zh/api-gateway/README.md",
    "content": "---\ntitle: API Gateway\nshortTitle: API Gateway\ncategory: Architectural\nlanguage: zh\ntag:\n  - Cloud distributed\n  - Decoupling\n  - Microservices\n---\n\n## 目的\n\nAPI网关将所有对微服务的调用聚合到一起。用户对API网关进行一次调用，然后API网关调用每个相关的微服务。\n\n## 解释\n\n使用微服务模式，客户端可能需要来自多个不同微服务的数据。 如果客户端直接调用每个微服务，则可能会导致更长的加载时间，因为客户端将不得不为每个调用的微服务发出网络请求。此外，让客户端调用每个微服务会直接将客户端与该微服务相关联-如果微服务的内部实现发生了变化（例如，如果将来某个时候合并了两个微服务），或者微服务的位置（主机和端口） 更改，则必须更新使用这些微服务的每个客户端。\n\nAPI网关模式的目的是缓解其中的一些问题。 在API网关模式中，在客户端和微服务之间放置了一个附加实体（API网关）。API网关的工作是将对微服务的调用进行聚合。 客户端不是一次单独调用每个微服务，而是一次调用API网关。 然后，API网关调用客户端所需的每个微服务。\n\n真实世界例子\n\n> 我们正在为电子商务站点实现微服务和API网关模式。 在此系统中，API网关调用Image和Price微服务。\n\n通俗地说\n\n> 对于使用微服务架构实现的系统，API是聚合微服务调用的入口点。 \n\n维基百科说\n\n> API网关是充当API前置，接收API请求，执行限制和安全策略，将请求传递到后端服务，然后将响应传递回请求者的服务器。网关通常包括一个转换引擎，以实时地编排和修改请求和响应。 网关可以提供收集分析数据和提供缓存等功能。网关还可以提供支持身份验证，授权，安全性，审计和法规遵从性的功能。\n\n**程序示例**\n\n此实现展示了电子商务站点的API网关模式。` ApiGateway`分别使用` ImageClientImpl`和` PriceClientImpl`来调用Image和Price微服务。 在桌面设备上查看该网站的客户可以看到价格信息和产品图片，因此` ApiGateway`会调用这两种微服务并在`DesktopProduct`模型中汇总数据。 但是，移动用户只能看到价格信息。 他们看不到产品图片。 对于移动用户，`ApiGateway`仅检索价格信息，并将其用于填充`MobileProduct`模型。\n\n这个是图像微服务的实现。\n\n```java\npublic interface ImageClient {\n  String getImagePath();\n}\n\npublic class ImageClientImpl implements ImageClient {\n  @Override\n  public String getImagePath() {\n    var httpClient = HttpClient.newHttpClient();\n    var httpGet = HttpRequest.newBuilder()\n        .GET()\n        .uri(URI.create(\"http://localhost:50005/image-path\"))\n        .build();\n\n    try {\n      var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n      return httpResponse.body();\n    } catch (IOException | InterruptedException e) {\n      e.printStackTrace();\n    }\n\n    return null;\n  }\n}\n```\n\n这里是价格服务的实现。\n\n```java\npublic interface PriceClient {\n  String getPrice();\n}\n\npublic class PriceClientImpl implements PriceClient {\n\n  @Override\n  public String getPrice() {\n    var httpClient = HttpClient.newHttpClient();\n    var httpGet = HttpRequest.newBuilder()\n        .GET()\n        .uri(URI.create(\"http://localhost:50006/price\"))\n        .build();\n\n    try {\n      var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n      return httpResponse.body();\n    } catch (IOException | InterruptedException e) {\n      e.printStackTrace();\n    }\n\n    return null;\n  }\n}\n```\n\n在这里，我们可以看到API网关如何将请求映射到微服务。\n\n```java\npublic class ApiGateway {\n\n  @Resource\n  private ImageClient imageClient;\n\n  @Resource\n  private PriceClient priceClient;\n\n  @RequestMapping(path = \"/desktop\", method = RequestMethod.GET)\n  public DesktopProduct getProductDesktop() {\n    var desktopProduct = new DesktopProduct();\n    desktopProduct.setImagePath(imageClient.getImagePath());\n    desktopProduct.setPrice(priceClient.getPrice());\n    return desktopProduct;\n  }\n\n  @RequestMapping(path = \"/mobile\", method = RequestMethod.GET)\n  public MobileProduct getProductMobile() {\n    var mobileProduct = new MobileProduct();\n    mobileProduct.setPrice(priceClient.getPrice());\n    return mobileProduct;\n  }\n}\n```\n\n## 类图\n![alt text](./etc/api-gateway.png \"API Gateway\")\n\n## 适用性\n\n在以下情况下使用API网关模式\n\n* 你正在使用微服务架构，并且需要聚合单点来进行微服务调用。\n\n## 鸣谢\n\n* [microservices.io - API Gateway](http://microservices.io/patterns/apigateway.html)\n* [NGINX - Building Microservices: Using an API Gateway](https://www.nginx.com/blog/building-microservices-using-an-api-gateway/)\n* [Microservices Patterns: With examples in Java](https://www.amazon.com/gp/product/1617294543/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617294543&linkId=ac7b6a57f866ac006a309d9086e8cfbd)\n* [Building Microservices: Designing Fine-Grained Systems](https://www.amazon.com/gp/product/1491950358/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1491950358&linkId=4c95ca9831e05e3f0dadb08841d77bf1)\n"
  },
  {
    "path": "localization/zh/arrange-act-assert/README.md",
    "content": "---\ntitle: Arrange/Act/Assert\nshortTitle: Arrange/Act/Assert\ncategory: Idiom\nlanguage: zh\ntag:\n - Testing\n---\n\n## 或称\n\nGiven/When/Then\n\n## 意图\n\n安排/执行/断言（AAA）是组织单元测试的一种模式。\n\n它将测试分为三个清晰而独特的步骤：\n\n1. 安排：执行测试所需的设置和初始化。\n2. 执行：采取测试所需的行动。\n3. 断言：验证测试结果。\n\n## 解释\n\n这种模式有几个明显的好处。 它在测试的设置，操作和结果之间建立了清晰的分隔。 这种结构使代码更易于阅读和理解。 如果按顺序排列步骤并格式化代码以将它们分开，则可以扫描测试并快速了解其功能。\n\n当您编写测试时，它还会强制执行一定程度的纪律。 您必须清楚地考虑您的测试将执行的三个步骤。 由于您已经有了大纲，因此可以使同时编写测试变得更加自然。\n\n真实世界例子\n\n> 我们需要为一个类编写全面而清晰的单元测试套件。\n\n通俗地说\n\n> 安排/执行/断言是一种测试模式，将测试分为三个清晰的步骤以方便维护。\n\nWikiWikiWeb 上说\n\n> 安排/执行/断言是用于在单元测试方法中排列和格式化代码的模式。\n\n**程序示例**\n\n让我们首先介绍要进行单元测试的`Cash`类。\n\n```java\npublic class Cash {\n\n  private int amount;\n\n  Cash(int amount) {\n    this.amount = amount;\n  }\n\n  void plus(int addend) {\n    amount += addend;\n  }\n\n  boolean minus(int subtrahend) {\n    if (amount >= subtrahend) {\n      amount -= subtrahend;\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  int count() {\n    return amount;\n  }\n}\n```\n\n然后我们根据安排/ 执行 / 断言模式编写单元测试。 注意每个单元测试的步骤是分开的清晰的。\n\n```java\nclass CashAAATest {\n\n  @Test\n  void testPlus() {\n    //Arrange\n    var cash = new Cash(3);\n    //Act\n    cash.plus(4);\n    //Assert\n    assertEquals(7, cash.count());\n  }\n\n  @Test\n  void testMinus() {\n    //Arrange\n    var cash = new Cash(8);\n    //Act\n    var result = cash.minus(5);\n    //Assert\n    assertTrue(result);\n    assertEquals(3, cash.count());\n  }\n\n  @Test\n  void testInsufficientMinus() {\n    //Arrange\n    var cash = new Cash(1);\n    //Act\n    var result = cash.minus(6);\n    //Assert\n    assertFalse(result);\n    assertEquals(1, cash.count());\n  }\n\n  @Test\n  void testUpdate() {\n    //Arrange\n    var cash = new Cash(5);\n    //Act\n    cash.plus(6);\n    var result = cash.minus(3);\n    //Assert\n    assertTrue(result);\n    assertEquals(8, cash.count());\n  }\n}\n```\n\n## 适用性\n\n使用 安排/执行/断言 模式当\n\n* 你需要结构化你的单元测试代码这样它们可以更好的阅读，维护和增强。\n\n## 鸣谢\n\n* [Arrange, Act, Assert: What is AAA Testing?](https://blog.ncrunch.net/post/arrange-act-assert-aaa-testing.aspx)\n* [Bill Wake: 3A – Arrange, Act, Assert](https://xp123.com/articles/3a-arrange-act-assert/)\n* [Martin Fowler: GivenWhenThen](https://martinfowler.com/bliki/GivenWhenThen.html)\n* [xUnit Test Patterns: Refactoring Test Code](https://www.amazon.com/gp/product/0131495054/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0131495054&linkId=99701e8f4af2f7e8dd50d720c9b63dbf)\n* [Unit Testing Principles, Practices, and Patterns](https://www.amazon.com/gp/product/1617296279/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617296279&linkId=74c75cf22a63c3e4758ae08aa0a0cc35)\n* [Test Driven Development: By Example](https://www.amazon.com/gp/product/0321146530/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0321146530&linkId=5c63a93d8c1175b84ca5087472ef0e05)\n"
  },
  {
    "path": "localization/zh/async-method-invocation/README.md",
    "content": "---\ntitle: Async Method Invocation\nshortTitle: Async Method Invocation\ncategory: Concurrency\nlanguage: zh\ntag:\n - Reactive\n---\n\n## 意图\n\n异步方法调用是一个调用线程在等待任务结果时不会阻塞的模式。模式为多个独立的任务提供并行的处理方式并且通过回调或等到它们全部完成来接收任务结果。\n\n## 解释\n\n真实世界例子\n\n> 发射火箭是一项令人激动的事务。任务指挥官发出了发射命令，经过一段不确定的时间后，火箭要么成功发射，要么惨遭失败。\n\n通俗地说\n\n> 异步方法调用开始任务处理，并在任务完成之前立即返回。 任务处理的结果稍后返回给调用方。\n\n维基百科说\n\n> 在多线程计算机编程中，异步方法调用（AMI），也称为异步方法调用或异步模式，是一种设计模式，其中在等待被调用的代码完成时不会阻塞调用站点。 而是在执行结果到达时通知调用线程。轮询调用结果是不希望的选项。\n\n**程序示例**\n\n在此示例中，我们正在发射太空火箭并部署月球漫游车。该应用演示了异步方法调用模式。 模式的关键部分是`AsyncResult`（用于异步评估值的中间容器），`AsyncCallback`（可以在任务完成时被执行）和`AsyncExecutor`（用于管理异步任务的执行）。\n\n```java\npublic interface AsyncResult<T> {\n  boolean isCompleted();\n  T getValue() throws ExecutionException;\n  void await() throws InterruptedException;\n}\n```\n\n```java\npublic interface AsyncCallback<T> {\n  void onComplete(T value, Optional<Exception> ex);\n}\n```\n\n```java\npublic interface AsyncExecutor {\n  <T> AsyncResult<T> startProcess(Callable<T> task);\n  <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback);\n  <T> T endProcess(AsyncResult<T> asyncResult) throws ExecutionException, InterruptedException;\n}\n```\n\n`ThreadAsyncExecutor`是`AsyncExecutor`的实现。 接下来将突出显示其一些关键部分。\n\n```java\npublic class ThreadAsyncExecutor implements AsyncExecutor {\n\n  @Override\n  public <T> AsyncResult<T> startProcess(Callable<T> task) {\n    return startProcess(task, null);\n  }\n\n  @Override\n  public <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback) {\n    var result = new CompletableResult<>(callback);\n    new Thread(\n            () -> {\n              try {\n                result.setValue(task.call());\n              } catch (Exception ex) {\n                result.setException(ex);\n              }\n            },\n            \"executor-\" + idx.incrementAndGet())\n        .start();\n    return result;\n  }\n\n  @Override\n  public <T> T endProcess(AsyncResult<T> asyncResult)\n      throws ExecutionException, InterruptedException {\n    if (!asyncResult.isCompleted()) {\n      asyncResult.await();\n    }\n    return asyncResult.getValue();\n  }\n}\n```\n\n然后，我们准备发射一些火箭，看看一切是如何协同工作的。\n\n```java\npublic static void main(String[] args) throws Exception {\n  // 构造一个将执行异步任务的新执行程序\n  var executor = new ThreadAsyncExecutor();\n\n  // 以不同的处理时间开始一些异步任务，最后两个使用回调处理程序\n  final var asyncResult1 = executor.startProcess(lazyval(10, 500));\n  final var asyncResult2 = executor.startProcess(lazyval(\"test\", 300));\n  final var asyncResult3 = executor.startProcess(lazyval(50L, 700));\n  final var asyncResult4 = executor.startProcess(lazyval(20, 400), callback(\"Deploying lunar rover\"));\n  final var asyncResult5 =\n      executor.startProcess(lazyval(\"callback\", 600), callback(\"Deploying lunar rover\"));\n\n  // 在当前线程中模拟异步任务正在它们自己的线程中执行\n  Thread.sleep(350); // 哦，兄弟，我们在这很辛苦\n  log(\"Mission command is sipping coffee\");\n\n  // 等待任务完成\n  final var result1 = executor.endProcess(asyncResult1);\n  final var result2 = executor.endProcess(asyncResult2);\n  final var result3 = executor.endProcess(asyncResult3);\n  asyncResult4.await();\n  asyncResult5.await();\n\n  // log the results of the tasks, callbacks log immediately when complete\n  // 记录任务结果的日志， 回调的日志会在回调完成时立刻记录\n  log(\"Space rocket <\" + result1 + \"> launch complete\");\n  log(\"Space rocket <\" + result2 + \"> launch complete\");\n  log(\"Space rocket <\" + result3 + \"> launch complete\");\n}\n```\n\n这是程序控制台的输出。\n\n```java\n21:47:08.227 [executor-2] INFO com.iluwatar.async.method.invocation.App - Space rocket <test> launched successfully\n21:47:08.269 [main] INFO com.iluwatar.async.method.invocation.App - Mission command is sipping coffee\n21:47:08.318 [executor-4] INFO com.iluwatar.async.method.invocation.App - Space rocket <20> launched successfully\n21:47:08.335 [executor-4] INFO com.iluwatar.async.method.invocation.App - Deploying lunar rover <20>\n21:47:08.414 [executor-1] INFO com.iluwatar.async.method.invocation.App - Space rocket <10> launched successfully\n21:47:08.519 [executor-5] INFO com.iluwatar.async.method.invocation.App - Space rocket <callback> launched successfully\n21:47:08.519 [executor-5] INFO com.iluwatar.async.method.invocation.App - Deploying lunar rover <callback>\n21:47:08.616 [executor-3] INFO com.iluwatar.async.method.invocation.App - Space rocket <50> launched successfully\n21:47:08.617 [main] INFO com.iluwatar.async.method.invocation.App - Space rocket <10> launch complete\n21:47:08.617 [main] INFO com.iluwatar.async.method.invocation.App - Space rocket <test> launch complete\n21:47:08.618 [main] INFO com.iluwatar.async.method.invocation.App - Space rocket <50> launch complete\n```\n\n# 类图\n\n![alt text](./etc/async-method-invocation.png \"Async Method Invocation\")\n\n## 适用性\n\n在以下情况下使用异步方法调用模式\n\n* 您有多个可以并行运行的独立任务\n* 您需要提高一组顺序任务的性能\n* 您的处理能力或长时间运行的任务数量有限，并且调用方不应等待任务执行完毕\n\n## 真实世界例子\n\n* [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html)\n* [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)\n* [ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html)\n* [Task-based Asynchronous Pattern](https://msdn.microsoft.com/en-us/library/hh873175.aspx)\n"
  },
  {
    "path": "localization/zh/balking/README.md",
    "content": "---\ntitle: Balking\nshortTitle: Balking\ncategory: Concurrency\nlanguage: zh\ntag:\n - Decoupling\n---\n\n## 意图\n\n止步模式用于防止对象在不完整或不合适的状态下执行某些代码。\n\n## 解释\n\n真实世界例子\n\n> 洗衣机中有一个开始按钮，用于启动衣物洗涤。当洗衣机处于非活动状态时，按钮将按预期工作，但是如果已经在洗涤，则按钮将不起任何作用。\n\n通俗地说\n\n> 使用止步模式，仅当对象处于特定状态时才执行特定代码。\n\n维基百科说\n\n> 禁止模式是一种软件设计模式，仅当对象处于特定状态时才对对象执行操作。例如，一个对象读取zip压缩文件并在压缩文件没打开的时候调用get方法，对象将在请求的时候”止步“。\n\n**程序示例**\n\n在此示例中，` WashingMachine`是一个具有两个状态的对象，可以处于两种状态：ENABLED和WASHING。 如果机器已启用，则使用线程安全方法将状态更改为WASHING。 另一方面，如果已经进行了清洗并且任何其他线程执行`wash（）`，则它将不执行该操作，而是不执行任何操作而返回。\n\n这里是`WashingMachine` 类相关的部分。\n\n```java\n@Slf4j\npublic class WashingMachine {\n\n  private final DelayProvider delayProvider;\n  private WashingMachineState washingMachineState;\n\n  public WashingMachine(DelayProvider delayProvider) {\n    this.delayProvider = delayProvider;\n    this.washingMachineState = WashingMachineState.ENABLED;\n  }\n\n  public WashingMachineState getWashingMachineState() {\n    return washingMachineState;\n  }\n\n  public void wash() {\n    synchronized (this) {\n      var machineState = getWashingMachineState();\n      LOGGER.info(\"{}: Actual machine state: {}\", Thread.currentThread().getName(), machineState);\n      if (this.washingMachineState == WashingMachineState.WASHING) {\n        LOGGER.error(\"Cannot wash if the machine has been already washing!\");\n        return;\n      }\n      this.washingMachineState = WashingMachineState.WASHING;\n    }\n    LOGGER.info(\"{}: Doing the washing\", Thread.currentThread().getName());\n    this.delayProvider.executeAfterDelay(50, TimeUnit.MILLISECONDS, this::endOfWashing);\n  }\n\n  public synchronized void endOfWashing() {\n    washingMachineState = WashingMachineState.ENABLED;\n    LOGGER.info(\"{}: Washing completed.\", Thread.currentThread().getId());\n  }\n}\n```\n\n这里是一个`WashingMachine`所使用的`DelayProvider`简单接口。\n\n```java\npublic interface DelayProvider {\n  void executeAfterDelay(long interval, TimeUnit timeUnit, Runnable task);\n}\n```\n\n现在，我们使用`WashingMachine`介绍该应用程序。\n\n```java\n  public static void main(String... args) {\n    final var washingMachine = new WashingMachine();\n    var executorService = Executors.newFixedThreadPool(3);\n    for (int i = 0; i < 3; i++) {\n      executorService.execute(washingMachine::wash);\n    }\n    executorService.shutdown();\n    try {\n      executorService.awaitTermination(10, TimeUnit.SECONDS);\n    } catch (InterruptedException ie) {\n      LOGGER.error(\"ERROR: Waiting on executor service shutdown!\");\n      Thread.currentThread().interrupt();\n    }\n  }\n```\n\n下面是程序的输出。\n\n```\n14:02:52.268 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Actual machine state: ENABLED\n14:02:52.272 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Doing the washing\n14:02:52.272 [pool-1-thread-3] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-3: Actual machine state: WASHING\n14:02:52.273 [pool-1-thread-3] ERROR com.iluwatar.balking.WashingMachine - Cannot wash if the machine has been already washing!\n14:02:52.273 [pool-1-thread-1] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-1: Actual machine state: WASHING\n14:02:52.273 [pool-1-thread-1] ERROR com.iluwatar.balking.WashingMachine - Cannot wash if the machine has been already washing!\n14:02:52.324 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - 14: Washing completed.\n```\n\n## 类图\n\n![alt text](./etc/balking.png \"Balking\")\n\n## 适用性\n\n\n使用止步模式当\n\n* 您只想在对象处于特定状态时才对其调用操作\n* 对象通常仅处于容易暂时停止但状态未知的状态\n\n## 相关模式\n\n* [保护性暂挂模式](https://java-design-patterns.com/patterns/guarded-suspension/)\n* [双重检查锁模式](https://java-design-patterns.com/patterns/double-checked-locking/)\n\n## 鸣谢\n\n* [Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML, 2nd Edition, Volume 1](https://www.amazon.com/gp/product/0471227293/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0471227293&linkId=0e39a59ffaab93fb476036fecb637b99)\n"
  },
  {
    "path": "localization/zh/bridge/README.md",
    "content": "---\ntitle: Bridge\nshortTitle: Bridge\ncategory: Structural\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 又被称为\n\n手柄/身体模式\n\n## 目的\n\n将抽象与其实现分离，以便二者可以独立变化。\n\n## 解释\n\n真实世界例子\n\n> 考虑一下你拥有一种具有不同附魔的武器，并且应该允许将具有不同附魔的不同武器混合使用。 你会怎么做？ 为每个附魔创建每种武器的多个副本，还是只是创建单独的附魔并根据需要为武器设置它？ 桥接模式使您可以进行第二次操作。\n\n通俗的说\n\n> 桥接模式是一个更推荐组合而不是继承的模式。将实现细节从一个层次结构推送到具有单独层次结构的另一个对象。\n\n维基百科说\n\n> 桥接模式是软件工程中使用的一种设计模式，旨在“将抽象与其实现分离，从而使两者可以独立变化”\n\n**程序示例**\n\n翻译一下上面的武器示例。下面我们有武器的类层级：\n\n```java\npublic interface Weapon {\n  void wield();\n  void swing();\n  void unwield();\n  Enchantment getEnchantment();\n}\n\npublic class Sword implements Weapon {\n\n  private final Enchantment enchantment;\n\n  public Sword(Enchantment enchantment) {\n    this.enchantment = enchantment;\n  }\n\n  @Override\n  public void wield() {\n    LOGGER.info(\"The sword is wielded.\");\n    enchantment.onActivate();\n  }\n\n  @Override\n  public void swing() {\n    LOGGER.info(\"The sword is swinged.\");\n    enchantment.apply();\n  }\n\n  @Override\n  public void unwield() {\n    LOGGER.info(\"The sword is unwielded.\");\n    enchantment.onDeactivate();\n  }\n\n  @Override\n  public Enchantment getEnchantment() {\n    return enchantment;\n  }\n}\n\npublic class Hammer implements Weapon {\n\n  private final Enchantment enchantment;\n\n  public Hammer(Enchantment enchantment) {\n    this.enchantment = enchantment;\n  }\n\n  @Override\n  public void wield() {\n    LOGGER.info(\"The hammer is wielded.\");\n    enchantment.onActivate();\n  }\n\n  @Override\n  public void swing() {\n    LOGGER.info(\"The hammer is swinged.\");\n    enchantment.apply();\n  }\n\n  @Override\n  public void unwield() {\n    LOGGER.info(\"The hammer is unwielded.\");\n    enchantment.onDeactivate();\n  }\n\n  @Override\n  public Enchantment getEnchantment() {\n    return enchantment;\n  }\n}\n```\n\n这里是单独的附魔类结构：\n\n```java\npublic interface Enchantment {\n  void onActivate();\n  void apply();\n  void onDeactivate();\n}\n\npublic class FlyingEnchantment implements Enchantment {\n\n  @Override\n  public void onActivate() {\n    LOGGER.info(\"The item begins to glow faintly.\");\n  }\n\n  @Override\n  public void apply() {\n    LOGGER.info(\"The item flies and strikes the enemies finally returning to owner's hand.\");\n  }\n\n  @Override\n  public void onDeactivate() {\n    LOGGER.info(\"The item's glow fades.\");\n  }\n}\n\npublic class SoulEatingEnchantment implements Enchantment {\n\n  @Override\n  public void onActivate() {\n    LOGGER.info(\"The item spreads bloodlust.\");\n  }\n\n  @Override\n  public void apply() {\n    LOGGER.info(\"The item eats the soul of enemies.\");\n  }\n\n  @Override\n  public void onDeactivate() {\n    LOGGER.info(\"Bloodlust slowly disappears.\");\n  }\n}\n```\n\n这里是两种层次结构的实践：\n\n```java\nvar enchantedSword = new Sword(new SoulEatingEnchantment());\nenchantedSword.wield();\nenchantedSword.swing();\nenchantedSword.unwield();\n// The sword is wielded.\n// The item spreads bloodlust.\n// The sword is swinged.\n// The item eats the soul of enemies.\n// The sword is unwielded.\n// Bloodlust slowly disappears.\n\nvar hammer = new Hammer(new FlyingEnchantment());\nhammer.wield();\nhammer.swing();\nhammer.unwield();\n// The hammer is wielded.\n// The item begins to glow faintly.\n// The hammer is swinged.\n// The item flies and strikes the enemies finally returning to owner's hand.\n// The hammer is unwielded.\n// The item's glow fades.\n```\n\n\n\n## 类图\n\n![alt text](./etc/bridge.urm.png \"Bridge class diagram\")\n\n## 适用性\n\n使用桥接模式当\n\n* 你想永久性的避免抽象和他的实现之间的绑定。有可能是这种情况，当实现需要被选择或者在运行时切换。\n* 抽象和他们的实现应该能通过写子类来扩展。这种情况下，桥接模式让你可以组合不同的抽象和实现并独立的扩展他们。\n* 对抽象的实现的改动应当不会对客户产生影响；也就是说，他们的代码不必重新编译。\n* 你有种类繁多的类。这样的类层次结构表明需要将一个对象分为两部分。Rumbaugh 使用术语“嵌套归纳”来指代这种类层次结构。\n* 你想在多个对象间分享一种实现（可能使用引用计数），这个事实应该对客户隐藏。一个简单的示例是Coplien的String类，其中多个对象可以共享同一字符串表示形式\n\n## 教程\n\n* [Bridge Pattern Tutorial](https://www.journaldev.com/1491/bridge-design-pattern-java)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/zh/builder/README.md",
    "content": "---\ntitle: Builder\nshortTitle: Builder\ncategory: Creational\nlanguage: zh\ntag:\n - Gang of Four\n\n---\n\n## 目的\n\n将复杂对象的构造与其表示分开，以便同一构造过程可以创建不同的表示。\n\n## 解释\n\n现实世界例子\n\n> 想象一个角色扮演游戏的角色生成器。最简单的选择是让计算机为你创建角色。但是如果你想选择一些像专业，性别，发色等角色细节时，这个角色生成就变成了一个渐进的过程。当所有选择完成时，该过程也将完成。\n\n用通俗的话说\n\n> 允许你创建不同口味的对象同时避免构造器污染。当一个对象可能有几种口味，或者一个对象的创建涉及到很多步骤时会很有用。\n\n维基百科说\n\n> 建造者模式是一种对象创建的软件设计模式，旨在为伸缩构造器反模式寻找一个解决方案。\n\n说了这么多，让我补充一下什么是伸缩构造函数反模式。我们肯定都见过像下面这样的构造器：\n\n```java\npublic Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) {\n}\n```\n\n就像你看到的构造器参数的数量很快就会失控同时参数的排列方式可能变得难以理解。另外，如果您将来希望添加更多选项，则此参数列表可能会继续增长。这就被称伸缩构造器反模式。\n\n**编程示例**\n\n明智的选择是使用建造者模式。首先我们有一个英雄要创建。\n\n```java\npublic final class Hero {\n  private final Profession profession;\n  private final String name;\n  private final HairType hairType;\n  private final HairColor hairColor;\n  private final Armor armor;\n  private final Weapon weapon;\n\n  private Hero(Builder builder) {\n    this.profession = builder.profession;\n    this.name = builder.name;\n    this.hairColor = builder.hairColor;\n    this.hairType = builder.hairType;\n    this.weapon = builder.weapon;\n    this.armor = builder.armor;\n  }\n}\n```\n\n然后我们有创建者\n\n```java\n  public static class Builder {\n    private final Profession profession;\n    private final String name;\n    private HairType hairType;\n    private HairColor hairColor;\n    private Armor armor;\n    private Weapon weapon;\n\n    public Builder(Profession profession, String name) {\n      if (profession == null || name == null) {\n        throw new IllegalArgumentException(\"profession and name can not be null\");\n      }\n      this.profession = profession;\n      this.name = name;\n    }\n\n    public Builder withHairType(HairType hairType) {\n      this.hairType = hairType;\n      return this;\n    }\n\n    public Builder withHairColor(HairColor hairColor) {\n      this.hairColor = hairColor;\n      return this;\n    }\n\n    public Builder withArmor(Armor armor) {\n      this.armor = armor;\n      return this;\n    }\n\n    public Builder withWeapon(Weapon weapon) {\n      this.weapon = weapon;\n      return this;\n    }\n\n    public Hero build() {\n      return new Hero(this);\n    }\n  }\n```\n\n然后可以这样使用\n\n```java\nvar mage = new Hero.Builder(Profession.MAGE, \"Riobard\").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();\n```\n\n## 类图\n\n![alt text](./etc/builder.urm.png \"Builder class diagram\")\n\n## 适用性\n\n使用建造者模式当\n\n* 创建复杂对象的算法应独立于组成对象的零件及其组装方式\n* 构造过程必须允许所构造的对象具有不同的表示形式\n\n## Java世界例子\n\n* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)\n* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) as well as similar buffers such as FloatBuffer, IntBuffer and so on.\n* [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-)\n* All implementations of [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)\n* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)\n* [Apache Commons Option.Builder](https://commons.apache.org/proper/commons-cli/apidocs/org/apache/commons/cli/Option.Builder.html)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)"
  },
  {
    "path": "localization/zh/business-delegate/README.md",
    "content": "---\ntitle: Business Delegate\nshortTitle: Business Delegate\ncategory: Structural\nlanguage: zh\ntag:\n - Decoupling\n---\n\n## 意图\n\n业务委托模式在表示层和业务层之间添加了一个抽象层。 通过使用该模式，我们获得了各层之间的松散耦合，并封装了有关如何定位，连接到组成应用程序的业务对象以及与之交互的逻辑。\n\n## 解释\n\n真实世界例子\n\n> 手机应用程序承诺将现有的任何电影流式传输到您的手机。它捕获用户的搜索字符串，并将其传递给业务委托层。业务委托层选择最合适的视频流服务，然后从那里播放视频。\n\n通俗的说\n\n> 业务委托模式在表示层和业务层之间添加了一个抽象层。 \n\n维基百科说\n\n> 业务委托是一种Java EE设计模式。 该模式旨在减少业务服务与连接的表示层之间的耦合，并隐藏服务的实现细节（包括EJB体系结构的查找和可访问性）。 业务代表充当适配器，以从表示层调用业务对象。\n\n**程序示例**\n\n首先，我们有视频流服务的抽象类和一些它的实现。\n\n```java\npublic interface VideoStreamingService {\n  void doProcessing();\n}\n\n@Slf4j\npublic class NetflixService implements VideoStreamingService {\n  @Override\n  public void doProcessing() {\n    LOGGER.info(\"NetflixService is now processing\");\n  }\n}\n\n@Slf4j\npublic class YouTubeService implements VideoStreamingService {\n  @Override\n  public void doProcessing() {\n    LOGGER.info(\"YouTubeService is now processing\");\n  }\n}\n```\n\n然后我们有一个查找服务来决定我们使用哪个视频流服务。\n\n```java\n@Setter\npublic class BusinessLookup {\n\n  private NetflixService netflixService;\n  private YouTubeService youTubeService;\n\n  public VideoStreamingService getBusinessService(String movie) {\n    if (movie.toLowerCase(Locale.ROOT).contains(\"die hard\")) {\n      return netflixService;\n    } else {\n      return youTubeService;\n    }\n  }\n}\n```\n\n业务委托类使用业务查找服务将电影播放请求路由到合适的视频流服务。\n\n```java\n@Setter\npublic class BusinessDelegate {\n\n  private BusinessLookup lookupService;\n\n  public void playbackMovie(String movie) {\n    VideoStreamingService videoStreamingService = lookupService.getBusinessService(movie);\n    videoStreamingService.doProcessing();\n  }\n}\n```\n\n移动客户端利用业务委托来调用业务层。\n\n```java\npublic class MobileClient {\n\n  private final BusinessDelegate businessDelegate;\n\n  public MobileClient(BusinessDelegate businessDelegate) {\n    this.businessDelegate = businessDelegate;\n  }\n\n  public void playbackMovie(String movie) {\n    businessDelegate.playbackMovie(movie);\n  }\n}\n```\n\n最后我们展示完整示例。\n\n```java\n  public static void main(String[] args) {\n\n    // prepare the objects\n    var businessDelegate = new BusinessDelegate();\n    var businessLookup = new BusinessLookup();\n    businessLookup.setNetflixService(new NetflixService());\n    businessLookup.setYouTubeService(new YouTubeService());\n    businessDelegate.setLookupService(businessLookup);\n\n    // create the client and use the business delegate\n    var client = new MobileClient(businessDelegate);\n    client.playbackMovie(\"Die Hard 2\");\n    client.playbackMovie(\"Maradona: The Greatest Ever\");\n  }\n```\n\n这是控制台的输出。\n\n```\n21:15:33.790 [main] INFO com.iluwatar.business.delegate.NetflixService - NetflixService is now processing\n21:15:33.794 [main] INFO com.iluwatar.business.delegate.YouTubeService - YouTubeService is now processing\n```\n\n## 类图\n\n![alt text](./etc/business-delegate.urm.png \"Business Delegate\")\n\n## 相关模式\n\n* [服务定位器模式](https://java-design-patterns.com/patterns/service-locator/)\n\n## 适用性\n\n使用业务委托模式当\n\n* 你希望表示层和业务层之间的松散耦合\n* 你想编排对多个业务服务的调用\n* 你希望封装查找服务和服务调用\n\n## 教程\n\n* [Business Delegate Pattern at TutorialsPoint](https://www.tutorialspoint.com/design_pattern/business_delegate_pattern.htm)\n\n## 鸣谢\n\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://www.amazon.com/gp/product/0130648841/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0130648841&linkId=a0100de2b28c71ede8db1757fb2b5947)\n"
  },
  {
    "path": "localization/zh/bytecode/README.md",
    "content": "---\ntitle: Bytecode\nshortTitle: Bytecode\ncategory: Behavioral\nlanguage: zh\ntag:\n - Game programming\n---\n\n## 意图\n\n允许编码行为作为虚拟机的指令。\n\n## 解释\n\n真实世界例子\n\n> 一个团队正在开发一款新的巫师对战游戏。巫师的行为需要经过精心的调整和上百次的游玩测试。每次当游戏设计师想改变巫师行为时都让程序员去修改代码这是不妥的，所以巫师行为以数据驱动的虚拟机方式实现。\n\n通俗地说\n\n> 字节码模式支持由数据而不是代码驱动的行为。\n\n[Gameprogrammingpatterns.com](https://gameprogrammingpatterns.com/bytecode.html) 中做了如下阐述：\n\n> 指令集定义了可以执行的低级操作。一系列指令被编码为字节序列。虚拟机一次一条地执行这些指令，中间的值用栈处理。通过组合指令，可以定义复杂的高级行为。\n\n**程序示例**\n\n其中最重要的游戏对象是`巫师`类。\n\n```java\n@AllArgsConstructor\n@Setter\n@Getter\n@Slf4j\npublic class Wizard {\n\n  private int health;\n  private int agility;\n  private int wisdom;\n  private int numberOfPlayedSounds;\n  private int numberOfSpawnedParticles;\n\n  public void playSound() {\n    LOGGER.info(\"Playing sound\");\n    numberOfPlayedSounds++;\n  }\n\n  public void spawnParticles() {\n    LOGGER.info(\"Spawning particles\");\n    numberOfSpawnedParticles++;\n  }\n}\n```\n\n下面我们展示虚拟机可用的指令。每个指令对于如何操作栈中的数据都有自己的语义。例如，增加指令，其取得栈顶的两个元素并把结果压入栈中。\n\n```java\n@AllArgsConstructor\n@Getter\npublic enum Instruction {\n\n  LITERAL(1),         // e.g. \"LITERAL 0\", push 0 to stack\n  SET_HEALTH(2),      // e.g. \"SET_HEALTH\", pop health and wizard number, call set health\n  SET_WISDOM(3),      // e.g. \"SET_WISDOM\", pop wisdom and wizard number, call set wisdom\n  SET_AGILITY(4),     // e.g. \"SET_AGILITY\", pop agility and wizard number, call set agility\n  PLAY_SOUND(5),      // e.g. \"PLAY_SOUND\", pop value as wizard number, call play sound\n  SPAWN_PARTICLES(6), // e.g. \"SPAWN_PARTICLES\", pop value as wizard number, call spawn particles\n  GET_HEALTH(7),      // e.g. \"GET_HEALTH\", pop value as wizard number, push wizard's health\n  GET_AGILITY(8),     // e.g. \"GET_AGILITY\", pop value as wizard number, push wizard's agility\n  GET_WISDOM(9),      // e.g. \"GET_WISDOM\", pop value as wizard number, push wizard's wisdom\n  ADD(10),            // e.g. \"ADD\", pop 2 values, push their sum\n  DIVIDE(11);         // e.g. \"DIVIDE\", pop 2 values, push their division\n  // ...\n}\n```\n\n我们示例的核心是`虚拟机`类。 它将指令作为输入并执行它们以提供游戏对象行为。\n\n```java\n@Getter\n@Slf4j\npublic class VirtualMachine {\n\n  private final Stack<Integer> stack = new Stack<>();\n\n  private final Wizard[] wizards = new Wizard[2];\n\n  public VirtualMachine() {\n    wizards[0] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),\n        0, 0);\n    wizards[1] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),\n        0, 0);\n  }\n\n  public VirtualMachine(Wizard wizard1, Wizard wizard2) {\n    wizards[0] = wizard1;\n    wizards[1] = wizard2;\n  }\n\n  public void execute(int[] bytecode) {\n    for (var i = 0; i < bytecode.length; i++) {\n      Instruction instruction = Instruction.getInstruction(bytecode[i]);\n      switch (instruction) {\n        case LITERAL:\n          // Read the next byte from the bytecode.\n          int value = bytecode[++i];\n          // Push the next value to stack\n          stack.push(value);\n          break;\n        case SET_AGILITY:\n          var amount = stack.pop();\n          var wizard = stack.pop();\n          setAgility(wizard, amount);\n          break;\n        case SET_WISDOM:\n          amount = stack.pop();\n          wizard = stack.pop();\n          setWisdom(wizard, amount);\n          break;\n        case SET_HEALTH:\n          amount = stack.pop();\n          wizard = stack.pop();\n          setHealth(wizard, amount);\n          break;\n        case GET_HEALTH:\n          wizard = stack.pop();\n          stack.push(getHealth(wizard));\n          break;\n        case GET_AGILITY:\n          wizard = stack.pop();\n          stack.push(getAgility(wizard));\n          break;\n        case GET_WISDOM:\n          wizard = stack.pop();\n          stack.push(getWisdom(wizard));\n          break;\n        case ADD:\n          var a = stack.pop();\n          var b = stack.pop();\n          stack.push(a + b);\n          break;\n        case DIVIDE:\n          a = stack.pop();\n          b = stack.pop();\n          stack.push(b / a);\n          break;\n        case PLAY_SOUND:\n          wizard = stack.pop();\n          getWizards()[wizard].playSound();\n          break;\n        case SPAWN_PARTICLES:\n          wizard = stack.pop();\n          getWizards()[wizard].spawnParticles();\n          break;\n        default:\n          throw new IllegalArgumentException(\"Invalid instruction value\");\n      }\n      LOGGER.info(\"Executed \" + instruction.name() + \", Stack contains \" + getStack());\n    }\n  }\n\n  public void setHealth(int wizard, int amount) {\n    wizards[wizard].setHealth(amount);\n  }\n  // other setters ->\n  // ...\n}\n```\n\n现在我们可以展示使用虚拟机的完整示例。\n\n```java\n  public static void main(String[] args) {\n\n    var vm = new VirtualMachine(\n        new Wizard(45, 7, 11, 0, 0),\n        new Wizard(36, 18, 8, 0, 0));\n\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"GET_HEALTH\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"GET_AGILITY\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 0\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"GET_WISDOM\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"ADD\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"LITERAL 2\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"DIVIDE\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"ADD\"));\n    vm.execute(InstructionConverterUtil.convertToByteCode(\"SET_HEALTH\"));\n  }\n```\n\n下面是控制台输出。\n\n```\n16:20:10.193 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0]\n16:20:10.196 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_HEALTH, Stack contains [0, 45]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_AGILITY, Stack contains [0, 45, 7]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 7, 0]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_WISDOM, Stack contains [0, 45, 7, 11]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 45, 18]\n16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 18, 2]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed DIVIDE, Stack contains [0, 45, 9]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 54]\n16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed SET_HEALTH, Stack contains []\n```\n\n## 类图\n\n![alt text](./etc/bytecode.urm.png \"Bytecode class diagram\")\n\n## 适用性\n\n\n\n当您需要定义很多行为并且游戏的实现语言不合适时，请使用字节码模式，因为：\n\n* 它的等级太低，使得编程变得乏味或容易出错。\n* 由于编译时间慢或其他工具问题，迭代它需要很长时间。\n* 它有太多的信任。 如果您想确保定义的行为不会破坏游戏，您需要将其与代码库的其余部分进行沙箱化。\n\n## 相关模式\n\n* [Interpreter](https://java-design-patterns.com/patterns/interpreter/)\n\n## 鸣谢\n\n* [Game programming patterns](http://gameprogrammingpatterns.com/bytecode.html)\n"
  },
  {
    "path": "localization/zh/caching/README.md",
    "content": "---\ntitle: Caching\nshortTitle: Caching\ncategory: Behavioral\nlanguage: zh\ntag:\n  - Performance\n  - Cloud distributed\n---\n\n## 目的\n为了避免昂贵的资源重新获取，方法是在资源使用后不立即释放资源。资源保留其身份，保留在某些快速访问的存储中，并被重新使用，以避免再次获取它们。\n\n## 类图\n![alt text](./etc/caching.png \"Caching\")\n\n## 适用性\n在以下情况下使用缓存模式\n\n* 重复获取，初始化和释放同一资源会导致不必要的性能开销。\n\n## 鸣谢\n\n* [Write-through, write-around, write-back: Cache explained](http://www.computerweekly.com/feature/Write-through-write-around-write-back-Cache-explained)\n* [Read-Through, Write-Through, Write-Behind, and Refresh-Ahead Caching](https://docs.oracle.com/cd/E15357_01/coh.360/e15723/cache_rtwtwbra.htm#COHDG5177)\n* [Cache-Aside pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/cache-aside)\n"
  },
  {
    "path": "localization/zh/callback/README.md",
    "content": "---\ntitle: Callback\nshortTitle: Callback\ncategory: Idiom\nlanguage: zh\ntag:\n - Reactive\n---\n\n## 目的\n回调是一部分被当为参数来传递给其他代码的可执行代码，接收方的代码可以在一些方便的时候来调用它。\n\n## 解释\n\n真实世界例子\n\n> 我们需要被通知当执行的任务结束时。我们为调用者传递一个回调方法然后等它调用通知我们。\n\n通俗的讲\n\n\n> 回调是一个用来传递给调用者的方法，它将在定义的时刻被调用。 \n\n维基百科说\n\n> 在计算机编程中，回调又被称为“稍后调用”函数，可以是任何可执行的代码用来作为参数传递给其他代码；其它代码被期望在给定时间内调用回调方法。\n\n**编程示例**\n\n回调是一个只有一个方法的简单接口。\n\n```java\npublic interface Callback {\n\n  void call();\n}\n```\n\n下面我们定义一个任务它将在任务执行完成后执行回调。\n\n```java\npublic abstract class Task {\n\n  final void executeWith(Callback callback) {\n    execute();\n    Optional.ofNullable(callback).ifPresent(Callback::call);\n  }\n\n  public abstract void execute();\n}\n\npublic final class SimpleTask extends Task {\n\n  private static final Logger LOGGER = getLogger(SimpleTask.class);\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"Perform some important activity and after call the callback method.\");\n  }\n}\n```\n\n最后这里是我们如何执行一个任务然后接收一个回调当它完成时。\n\n```java\n    var task = new SimpleTask();\n    task.executeWith(() -> LOGGER.info(\"I'm done now.\"));\n```\n## 类图\n![alt text](./etc/callback.png \"Callback\")\n\n## 适用性\n使用回调模式当\n* 当一些同步或异步架构动作必须在一些定义好的活动执行后执行时。\n\n## Java例子\n\n* [CyclicBarrier](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29) 构造函数可以接受回调，该回调将在每次障碍被触发时触发。\n"
  },
  {
    "path": "localization/zh/chain/README.md",
    "content": "---\ntitle: Chain of responsibility\nshortTitle: Chain of responsibility\ncategory: Behavioral\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 目的\n通过给多个对象一个处理请求的机会，避免请求的发送者和它的接收者耦合。串联接收对象并在链条中传递请求直到一个对象处理它。\n\n## 解释\n\n真实世界例子\n\n> 兽王大声命令他的军队。最近响应的是指挥官，然后是军官，然后是士兵。指挥官，军官，士兵这里就形成了一个责任链。\n\n通俗的说\n\n> 它帮助构建一串对象。请求从一个对象中进入并结束然后进入到一个个对象中直到找到合适的处理器。\n\n维基百科说\n\n> 在面向对象设计中，责任链模式是一种由源命令对象和一系列处理对象组成的设计模式。每个处理对象包含了其定义的可处理的命令对象类型的逻辑。剩下的会传递给链条中的下一个处理对象。\n\n**程序示例**\n\n用上面的兽人来翻译我们的示例。首先我们有请求类\n\n```java\npublic class Request {\n\n  private final RequestType requestType;\n  private final String requestDescription;\n  private boolean handled;\n\n  public Request(final RequestType requestType, final String requestDescription) {\n    this.requestType = Objects.requireNonNull(requestType);\n    this.requestDescription = Objects.requireNonNull(requestDescription);\n  }\n\n  public String getRequestDescription() { return requestDescription; }\n\n  public RequestType getRequestType() { return requestType; }\n\n  public void markHandled() { this.handled = true; }\n\n  public boolean isHandled() { return this.handled; }\n\n  @Override\n  public String toString() { return getRequestDescription(); }\n}\n\npublic enum RequestType {\n  DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX\n}\n```\n\n然后是请求处理器的层次结构\n\n```java\n@Slf4j\npublic abstract class RequestHandler {\n  private final RequestHandler next;\n\n  public RequestHandler(RequestHandler next) {\n    this.next = next;\n  }\n\n  public void handleRequest(Request req) {\n    if (next != null) {\n      next.handleRequest(req);\n    }\n  }\n\n  protected void printHandling(Request req) {\n    LOGGER.info(\"{} handling request \\\"{}\\\"\", this, req);\n  }\n\n  @Override\n  public abstract String toString();\n}\n\npublic class OrcCommander extends RequestHandler {\n  public OrcCommander(RequestHandler handler) {\n    super(handler);\n  }\n\n  @Override\n  public void handleRequest(Request req) {\n    if (req.getRequestType().equals(RequestType.DEFEND_CASTLE)) {\n      printHandling(req);\n      req.markHandled();\n    } else {\n      super.handleRequest(req);\n    }\n  }\n\n  @Override\n  public String toString() {\n    return \"Orc commander\";\n  }\n}\n\n// OrcOfficer和OrcSoldier的定义与OrcCommander类似\n\n```\n\n然后我们有兽王下达命令并形成链条\n\n```java\npublic class OrcKing {\n  RequestHandler chain;\n\n  public OrcKing() {\n    buildChain();\n  }\n\n  private void buildChain() {\n    chain = new OrcCommander(new OrcOfficer(new OrcSoldier(null)));\n  }\n\n  public void makeRequest(Request req) {\n    chain.handleRequest(req);\n  }\n}\n```\n\n然后这样使用它\n\n```java\nvar king = new OrcKing();\nking.makeRequest(new Request(RequestType.DEFEND_CASTLE, \"defend castle\")); // Orc commander handling request \"defend castle\"\nking.makeRequest(new Request(RequestType.TORTURE_PRISONER, \"torture prisoner\")); // Orc officer handling request \"torture prisoner\"\nking.makeRequest(new Request(RequestType.COLLECT_TAX, \"collect tax\")); // Orc soldier handling request \"collect tax\"\n```\n\n## 类图\n![alt text](./etc/chain-of-responsibility.urm.png \"Chain of Responsibility class diagram\")\n\n## 适用性\n使用责任链模式当\n\n* 多于一个对象可能要处理请求，并且处理器并不知道一个优先级。处理器应自动确定。\n* 你想对多个对象之一发出请求而无需明确指定接收者\n* 处理请求的对象集合应该被动态指定时\n\n## Java世界例子\n\n* [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29)\n* [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html)\n* [javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/zh/circuit-breaker/README.md",
    "content": "---\ntitle: Circuit Breaker\nshortTitle: Circuit Breaker\ncategory: Behavioral\nlanguage: zh\ntag:\n  - Performance\n  - Decoupling\n  - Cloud distributed\n---\n\n## 意图\n\n以这样一种方式处理昂贵的远程服务调用，即单个服务/组件的故障不会导致整个应用程序宕机，我们可以尽快重新连接到服务。\n\n## 解释\n\n真实世界例子\n\n> 想象一个 Web 应用程序，它同时具有用于获取数据的本地文件/图像和远程服务。 这些远程服务有时可能健康且响应迅速，或者由于各种原因可能在某 个时间点变得缓慢和无响应。因此，如果其中一个远程服务缓慢或未成功响应，我们的应用程序将尝试使用多个线程/进程从远程服务获取响应，很快它们都会挂起（也称为 [线程饥饿][thread starvation](https://en.wikipedia.org/wiki/Starvation_(computer_science)))导致我们的整个 Web 应用程序崩溃。我们应该能够检测到这种情况并向用户显示适当的消息，以便他/她可以探索不受远程服务故障影响的应用程序的其他部分。 同时，其他正常工作的服务应保持正常运行，不受此故障的影响。\n>\n\n通俗地说\n\n> 断路器允许优雅地处理失败的远程服务。当我们应用程序的所有部分彼此高度解耦时，它特别有用，一个组件的故障并不意味着其他部分将停止工作。\n\n维基百科说\n\n> 断路器是现代软件开发中使用的一种设计模式。 它用于检测故障并封装防止故障不断重复发生、维护期间、临时外部系统故障或意外系统困难的逻辑。\n\n## 程序示例\n\nSo, how does this all come together? With the above example in mind we will imitate the \nfunctionality in a simple example. A monitoring service mimics the web app and makes both local and \nremote calls.\n\n那么，这一切是如何结合在一起的呢？ 记住上面的例子，我们将在一个简单的例子中模仿这个功能。 监控服务模仿 Web 应用程序并进行本地和远程调用。\n\n服务架构如下：\n\n![alt text](./etc/ServiceDiagram.png \"Service Diagram\")\n\n在代码方面，最终用户应用程序是：\n\n```java\n@Slf4j\npublic class App {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var serverStartTime = System.nanoTime();\n\n    var delayedService = new DelayedRemoteService(serverStartTime, 5);\n    var delayedServiceCircuitBreaker = new DefaultCircuitBreaker(delayedService, 3000, 2,\n        2000 * 1000 * 1000);\n\n    var quickService = new QuickRemoteService();\n    var quickServiceCircuitBreaker = new DefaultCircuitBreaker(quickService, 3000, 2,\n        2000 * 1000 * 1000);\n\n    // 创建一个可以进行本地和远程调用的监控服务对象\n    var monitoringService = new MonitoringService(delayedServiceCircuitBreaker,\n        quickServiceCircuitBreaker);\n\n    // 获取本地资源\n    LOGGER.info(monitoringService.localResourceResponse());\n\n    // 从延迟服务中获取响应 2 次，以满足失败阈值\n    LOGGER.info(monitoringService.delayedServiceResponse());\n    LOGGER.info(monitoringService.delayedServiceResponse());\n\n    // 在超过故障阈值限制后获取延迟服务断路器的当前状态\n    // 现在是打开状态\n    LOGGER.info(delayedServiceCircuitBreaker.getState());\n\n     // 同时，延迟服务宕机，从健康快速服务获取响应\n    LOGGER.info(monitoringService.quickServiceResponse());\n    LOGGER.info(quickServiceCircuitBreaker.getState());\n\n    // 等待延迟的服务响应\n    try {\n      LOGGER.info(\"Waiting for delayed service to become responsive\");\n      Thread.sleep(5000);\n    } catch (InterruptedException e) {\n      e.printStackTrace();\n    }\n    // 检查延时断路器的状态，应该是HALF_OPEN\n    LOGGER.info(delayedServiceCircuitBreaker.getState());\n\n    // 从延迟服务中获取响应，现在应该是健康的\n    LOGGER.info(monitoringService.delayedServiceResponse());\n    // 获取成功响应后，它的状态应该是关闭。\n    LOGGER.info(delayedServiceCircuitBreaker.getState());\n  }\n}\n```\n\n监控服务类:\n\n```java\npublic class MonitoringService {\n\n  private final CircuitBreaker delayedService;\n\n  private final CircuitBreaker quickService;\n\n  public MonitoringService(CircuitBreaker delayedService, CircuitBreaker quickService) {\n    this.delayedService = delayedService;\n    this.quickService = quickService;\n  }\n\n  // 假设：本地服务不会失败，无需将其包装在断路器逻辑中\n  public String localResourceResponse() {\n    return \"Local Service is working\";\n  }\n\n  /**\n   * Fetch response from the delayed service (with some simulated startup time).\n   *\n   * @return response string\n   */\n  public String delayedServiceResponse() {\n    try {\n      return this.delayedService.attemptRequest();\n    } catch (RemoteServiceException e) {\n      return e.getMessage();\n    }\n  }\n\n  /**\n   * Fetches response from a healthy service without any failure.\n   *\n   * @return response string\n   */\n  public String quickServiceResponse() {\n    try {\n      return this.quickService.attemptRequest();\n    } catch (RemoteServiceException e) {\n      return e.getMessage();\n    }\n  }\n}\n```\n可以看出，它直接调用获取本地资源，但它将对远程（昂贵）服务的调用包装在断路器对象中，防止故障如下：\n\n```java\npublic class DefaultCircuitBreaker implements CircuitBreaker {\n\n    private final long timeout;\n    private final long retryTimePeriod;\n    private final RemoteService service;\n    long lastFailureTime;\n    private String lastFailureResponse;\n    int failureCount;\n    private final int failureThreshold;\n    private State state;\n    private final long futureTime = 1000 * 1000 * 1000 * 1000;\n\n    /**\n     * Constructor to create an instance of Circuit Breaker.\n     *\n     * @param timeout          Timeout for the API request. Not necessary for this simple example\n     * @param failureThreshold Number of failures we receive from the depended service before changing\n     *                         state to 'OPEN'\n     * @param retryTimePeriod  Time period after which a new request is made to remote service for\n     *                         status check.\n     */\n    DefaultCircuitBreaker(RemoteService serviceToCall, long timeout, int failureThreshold,\n                          long retryTimePeriod) {\n        this.service = serviceToCall;\n        //  我们从关闭状态开始希望一切都是正常的\n        this.state = State.CLOSED;\n        this.failureThreshold = failureThreshold;\n        // API的超时时间.\n        // 用于在超过限制时中断对远程资源的调用\n        this.timeout = timeout;\n        this.retryTimePeriod = retryTimePeriod;\n        //An absurd amount of time in future which basically indicates the last failure never happened\n        this.lastFailureTime = System.nanoTime() + futureTime;\n        this.failureCount = 0;\n    }\n\n    // 重置所有\n    @Override\n    public void recordSuccess() {\n        this.failureCount = 0;\n        this.lastFailureTime = System.nanoTime() + futureTime;\n        this.state = State.CLOSED;\n    }\n\n    @Override\n    public void recordFailure(String response) {\n        failureCount = failureCount + 1;\n        this.lastFailureTime = System.nanoTime();\n        // Cache the failure response for returning on open state\n        this.lastFailureResponse = response;\n    }\n\n    // 根据 failureThreshold、failureCount 和 lastFailureTime 评估当前状态。\n    protected void evaluateState() {\n        if (failureCount >= failureThreshold) { //Then something is wrong with remote service\n            if ((System.nanoTime() - lastFailureTime) > retryTimePeriod) {\n                // 我们已经等得够久了，应该尝试检查服务是否已启动\n                state = State.HALF_OPEN;\n            } else {\n                // 服务可能仍会出现故障\n                state = State.OPEN;\n            }\n        } else {\n            // 一切正常\n            state = State.CLOSED;\n        }\n    }\n\n    @Override\n    public String getState() {\n        evaluateState();\n        return state.name();\n    }\n\n    /**\n     * Break the circuit beforehand if it is known service is down Or connect the circuit manually if\n     * service comes online before expected.\n     *\n     * @param state State at which circuit is in\n     */\n    @Override\n    public void setState(State state) {\n        this.state = state;\n        switch (state) {\n            case OPEN -> {\n                this.failureCount = failureThreshold;\n                this.lastFailureTime = System.nanoTime();\n            }\n            case HALF_OPEN -> {\n                this.failureCount = failureThreshold;\n                this.lastFailureTime = System.nanoTime() - retryTimePeriod;\n            }\n            default -> this.failureCount = 0;\n        }\n    }\n\n    /**\n     * Executes service call.\n     *\n     * @return Value from the remote resource, stale response or a custom exception\n     */\n    @Override\n    public String attemptRequest() throws RemoteServiceException {\n        evaluateState();\n        if (state == State.OPEN) {\n            // 如果电路处于打开状态，则返回缓存的响应\n            return this.lastFailureResponse;\n        } else {\n            // 如果电路未打开，则发出 API 请求\n            try {\n                //在实际应用程序中，这将在线程中运行，并且将利用断路器的超时参数来了解服务\n                // 是否正在工作。 在这里，我们根据服务器响应本身模拟\n                var response = service.call();\n                // api 响应正常，重置所有。\n                recordSuccess();\n                return response;\n            } catch (RemoteServiceException ex) {\n                recordFailure(ex.getMessage());\n                throw ex;\n            }\n        }\n    }\n}\n```\n\n上述模式如何防止失败？ 让我们通过它实现的这个有限状态机来理解。\n\n![alt text](./etc/StateDiagram.png \"State Diagram\")\n\n- 我们使用某些参数初始化断路器对象：`timeout`、`failureThreshold` 和 `retryTimePeriod`，这有助于确定 API 的弹性。\n- 最初，我们处于“关闭”状态，没有发生对 API 的远程调用。\n- 每次调用成功时，我们都会将状态重置为开始时的状态。\n- 如果失败次数超过某个阈值，我们将进入“open”状态，这就像开路一样，阻止远程服务调用，从而节省资源。  （这里，我们从 API 返回名为 ```stale response``` 的响应）\n- 一旦超过重试超时时间，我们就会进入“半开”状态并再次调用远程服务以检查服务是否正常工作，以便我们可以提供新鲜内容。 失败将其设置回“打开”状态，并在重试超时时间后进行另一次尝试，而成功将其设置为“关闭”状态，以便一切重新开始正常工作。\n\n## 类图\n\n![alt text](./etc/circuit-breaker.urm.png \"Circuit Breaker class diagram\")\n\n## 适用性\n\n在以下情况下使用断路器模式\n\n- 构建一个容错应用程序，其中某些服务的故障不应导致整个应用程序宕机。\n- 构建一个持续运行（永远在线）的应用程序，这样它的组件就可以在不完全关闭的情况下升级。\n\n## 相关模式\n\n- [Retry Pattern](https://github.com/iluwatar/java-design-patterns/tree/master/retry)\n\n## 真实世界例子\n\n* [Spring Circuit Breaker module](https://spring.io/guides/gs/circuit-breaker)\n* [Netflix Hystrix API](https://github.com/Netflix/Hystrix)\n\n## 鸣谢\n\n* [Understanding Circuit Breaker Pattern](https://itnext.io/understand-circuitbreaker-design-pattern-with-simple-practical-example-92a752615b42)\n* [Martin Fowler on Circuit Breaker](https://martinfowler.com/bliki/CircuitBreaker.html)\n* [Fault tolerance in a high volume, distributed system](https://medium.com/netflix-techblog/fault-tolerance-in-a-high-volume-distributed-system-91ab4faae74a)\n* [Circuit Breaker pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker)\n"
  },
  {
    "path": "localization/zh/cloud-static-content-hosting/README.md",
    "content": "---\ntitle: Static Content Hosting\nshortTitle: Static Content Hosting\ncategory: Cloud\nlanguage: zh\ntag:\n- Cloud distributed\n---\n\n## 意图\n\n将静态内容部署到基于云的存储服务，该服务可以将它们直接交付给客户端。 这可以减少对昂贵计算实例的需求。\n\n## 解释\n\n真实世界例子\n\n> 全球性的营销网站（静态内容）需要快速的部署以开始吸引潜在的客户。为了将托管费用和维护成本降至最低，使用云托管存储服务和内容交付网络。\n\n通俗地说\n\n> 静态内容托管模式利用云原生存储服务来存储内容和全球内容交付网络，将其缓存在世界各地的多个数据中心。 在静态网站上，单个网页包含静态内容。 它们还可能包含客户端脚本，例如 Javascript。相比之下，动态网站依赖于服务器端处理，包括服务器端脚本，如 PHP、JSP 或 ASP.NET。\n\n维基百科说\n\n> 与由 Web 应用程序生成的动态网页相反，静态网页（有时称为平面网页或固定网页）是完全按照存储的方式传送到用户的网页浏览器的网页。静态网页适用于从不或很少需要更新的内容，尽管现代\n> Web 模板系统正在改变这一点。可以将大量静态页面作为文件进行维护，没有自动化工具（例如静态站点生成器）是不切实际的。\n\n**示例**\n\n![alt text](./etc/static-content-hosting.png \"Static Content Hosting\")\n\n在这个例子中我们使用AWS S3创建一个静态网站，并利用 AWS Cloudfront 在全球范围内分发内容。\n\n1. 首先你需要一个AWS账户，你可以在这个创建一个免费的：[AWS Free Tier](https://aws.amazon.com/free/free-tier/)\n\n2. 登陆 [AWS控制台](https://console.aws.amazon.com/console/home?nc2=h_ct&src=header-signin)\n\n3. 进入身份和接入管理服务 (IAM) .\n\n4. 创建一个仅具有此应用程序必要权限的IAM用户。\n\n   * 点击 `用户`\n   * 点击 `添加用户`. 选择你想要的 `用户名`， `接入类型`应该是 `编程式接入`. 点击 `下一步: 权限`.\n   * 选择 `直接附加已存在的策略`. 选择 `AmazonS3FullAccess` 和 `CloudFrontFullAccess`. Click `下一步: 标签`.\n   * 没有需要的标签, 所以直接点击 `下一步: 回顾`.\n   * 检查呈现的信息，没问题的话点击`创建用户`\n   * 完成这个示例所需要的`访问秘钥Id`和`访问秘钥密码`将会呈现在你面前，请妥善保管。\n   * 点击 `关闭`.\n\n5. [安装AWS 命令行工具 (AWS CLI)](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv1.html) 来获得编程式访问AWS云。\n\n6. 使用`aws configure`命令来配置AWS CLI [说明书](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)\n\n7. 为web站点创建AWS S3 bucket。 注意S3 bucket名字必须要在全球范围内唯一。\n\n\n   *  语法是 `aws s3 mb <bucket name>`  [说明书](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-buckets-creating)\n   * 比如 `aws s3 mb s3://my-static-website-jh34jsjmg`\n   * 使用列出现有存储桶的命令`aws s3 ls`验证存储桶是否已成功创建\n\n8. 使用命令`aws s3 website`来配置bucket作为web站点。  [说明书](https://docs.aws.amazon.com/cli/latest/reference/s3/website.html).\n\n   * 比如`aws s3 website s3://my-static-website-jh34jsjmg --index-document index.html --error-document error.html`\n\n9. 上传内容到bucket中。\n   * 首先创建内容，至少包含`index.html`和`error.html`文档。\n   * 上传内容到你的bucket中。 [说明书](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-copy)\n   * 比如`aws s3 cp index.html s3://my-static-website-jh34jsjmg` and `aws s3 cp error.html s3://my-static-website-jh34jsjmg`\n\n10. 然后我们需要设置bucket的策略以允许读取访问。\n\n    * 使用以下内容创建`policy.json`（注意需要将bucket名称替换为自己的）。\n\n    ```json\n    {\n        \"Version\": \"2012-10-17\",\n        \"Statement\": [\n            {\n                \"Sid\": \"PublicReadGetObject\",\n                \"Effect\": \"Allow\",\n                \"Principal\": \"*\",\n                \"Action\": \"s3:GetObject\",\n                \"Resource\": \"arn:aws:s3:::my-static-website-jh34jsjmg/*\"\n            }\n        ]\n    }\n    ```\n\n    * 根据这些设置桶策略[说明书](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-bucket-policy.html)\n    * 比如 `aws s3api put-bucket-policy --bucket my-static-website-jh34jsjmg --policy file://policy.json`\n\n11. 使用浏览器测试web站点。\n\n    * web站点的URL格式是 `http://<bucket-name>.s3-website-<region-name>.amazonaws.com`\n    * 比如 这个站点创建在 `eu-west-1` 区域 ,名字是 `my-static-website-jh34jsjmg` 所以它可以通过 `http://my-static-website-jh34jsjmg.s3-website-eu-west-1.amazonaws.com`来访问。\n\n12. 为web站点创建CloudFormation 分发。\n\n    * 语法文档在这里 [this reference](https://docs.aws.amazon.com/cli/latest/reference/cloudfront/create-distribution.html)\n    * 比如，最简单的方式是使用命令l `aws cloudfront create-distribution --origin-domain-name my-static-website-jh34jsjmg.s3.amazonaws.com --default-root-object index.html`\n    * 也支持JSON格式的配置 比如使用 `--distribution-config file://dist-config.json` 来传递分发的配置文件参数\n    * 命令的舒勇将显示准确的分配配置项，包括包括可用于测试的生成的 CloudFront 域名，例如 `d2k3xwnaqa8nqx.cloudfront.net`\n    * CloudFormation 分发部署需要一些时间，但一旦完成，您的网站就会从全球各地的数据中心提供服务！\n\n13. 就是这样！ 您已经实现了一个静态网站，其内容分发网络以闪电般的速度在世界各地提供服务。\n\n    * 要更新网站，您需要更新 S3 存储桶中的对象并使 CloudFront 分配中的对象无效\n    * 要从 AWS CLI 执行此操作，请参阅 [this reference](https://docs.aws.amazon.com/cli/latest/reference/cloudfront/create-invalidation.html)\n    * 您可能想要做的进一步开发是通过 https 提供内容并为您的站点添加域名\n\n## 适用性\n\n当您想要执行以下操作时，请使用静态内容托管模式：\n\n* 最小化包含一些静态资源的网站和应用程序的托管成本。\n* 使用静态内容构建全球可用的网站\n* 监控网站流量、带宽使用、成本等。\n\n## 典型用例\n\n* 具有全球影响力的网站\n* 静态网站生成器生成的内容\n* 没有动态内容要求的网站\n\n## 真实世界例子\n\n* [Java Design Patterns web site](https://java-design-patterns.com)\n\n## 鸣谢\n\n* [Static Content Hosting pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/static-content-hosting)\n"
  },
  {
    "path": "localization/zh/collection-pipeline/README.md",
    "content": "---\ntitle: Collection Pipeline\nshortTitle: Collection Pipeline\ncategory: Functional\nlanguage: zh\ntag:\n - Reactive\n---\n\n## 释义\n**集合管道（Collection Pipeline）**包含**函数组合（Function Composition）**和**集合管道（Collection Pipeline）**两组合概念，这是两种函数式编程模式，你可以在代码中结合这两种模式来进行集合迭代。\n在函数式编程中，可以通过一系列较小的模块化函数或操作来编排复杂的操作。这一系列函数被称为函数组合。当一个数据集合流经一个函数组合时，它就成为一个集合管道。函数组合和集合管道是函数式编程中经常使用的两种设计模式。\n\n## 类图\n![alt text](./etc/collection-pipeline.png \"Collection Pipeline\")\n\n## 适用场景\n在以下场景适用集合管道模式：\n\n* 当你想执行一组连续的算子操作，其中一个算子收集的输出需要被输入到下一个算子中\n* 当你在代码中需要使用大量的中间状态语句时\n* 当你在代码中使用大量的循环语句时\n\n## 引用\n\n* [Function composition and the Collection Pipeline pattern](https://www.ibm.com/developerworks/library/j-java8idioms2/index.html)\n* [Martin Fowler](https://martinfowler.com/articles/collection-pipeline/)\n* [Java8 Streams](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html)"
  },
  {
    "path": "localization/zh/combinator/README.md",
    "content": "---\ntitle: Combinator\nshortTitle: Combinator\ncategory: Idiom\nlanguage: zh\ntag:\n - Reactive\n---\n\n## 或称\n\n构图模式\n\n## 目的\n\n功能模式代表了一种以组合功能为中心的图书馆组织风格。\n简单地说，有一些类型 T，一些用于构造类型 T 的“原始”值的函数，以及一些可以以各种方式组合类型 T 的值以构建更复杂的类型 T 值的“组合器”。\n\n## 解释\n\n真实世界例子\n\n> 在计算机科学中，组合逻辑被用作计算的简化模型，用于可计算性理论和证明理论。 尽管组合逻辑很简单，但它捕获了计算的许多基本特征。\n> \n\n通俗的说\n> 组合器允许从先前定义的“事物”创建新的“事物”。\n> \n\n维基百科说\n\n> 组合器是一个高阶函数，仅使用函数应用程序和之前定义的组合器来定义其参数的结果。\n> \n\n**程序示例**\n\n翻译上面的组合器示例。 首先，我们有一个由几个方法`contains`, `not`, `or`, `and`组成的接口。\n\n```java\n// 用于查找文本中的行的功能界面。\npublic interface Finder {\n\n\t// 在文本中查找行的函数。\n\tList<String> find(String text);\n\n\t// 函数{@link #find(String)}的简单实现。\n\tstatic Finder contains(String word) {\n    \t\treturn txt -> Stream.of(txt.split(\"\\n\"))\n        \t\t.filter(line -> line.toLowerCase().contains(word.toLowerCase()))\n        \t\t.collect(Collectors.toList());\n  \t}\n\n\t// 组合器：not。\n\tdefault Finder not(Finder notFinder) {\n    \t\treturn txt -> {\n      \t\t\tList<String> res = this.find(txt);\n      \t\t\tres.removeAll(notFinder.find(txt));\n      \t\t\treturn res;\n    \t\t\t};\n  \t}\n\n\t// 组合器：or。\n\tdefault Finder or(Finder orFinder) {\n    \t\treturn txt -> {\n      \t\t\tList<String> res = this.find(txt);\n      \t\t\tres.addAll(orFinder.find(txt));\n      \t\t\treturn res;\n    \t\t\t};\n\t}\n\n\t// 组合器：and。\n\tdefault Finder and(Finder andFinder) {\n    \t\treturn\n        \ttxt -> this\n            \t\t.find(txt)\n            \t\t.stream()\n            \t\t.flatMap(line -> andFinder.find(line).stream())\n            \t\t.collect(Collectors.toList());\n  \t}\n\t...\n}\n```\n\n然后我们还有另一个组合器用于一些复杂的查找器`advancedFinder`, `filteredFinder`, `specializedFinder`和`expandedFinder`。\n\n```java\n// 由简单取景器组成的复杂取景器。\npublic class Finders {\n\n\tprivate Finders() {\n  \t}\n\n\t// Finder 用于查找复杂的查询。\n\tpublic static Finder advancedFinder(String query, String orQuery, String notQuery) {\n    \t\treturn\n        \t\tFinder.contains(query)\n            \t\t\t.or(Finder.contains(orQuery))\n            \t\t\t.not(Finder.contains(notQuery));\n\t}\n\n\t// 过滤查找器也会查找包含排除查询的查询。\n\tpublic static Finder filteredFinder(String query, String... excludeQueries) {\n\t\tvar finder = Finder.contains(query);\n\n    \t\tfor (String q : excludeQueries) {\n      \t\t\tfinder = finder.not(Finder.contains(q));\n    \t\t}\n    \t\treturn finder;\n\t}\n\n\t// 专门查询。 每个下一个查询都会在上一个结果中查找。\n\tpublic static Finder specializedFinder(String... queries) {\n    \t\tvar finder = identMult();\n\n\t\tfor (String query : queries) {\n      \t\t\tfinder = finder.and(Finder.contains(query));\n    \t\t}\n    \t\treturn finder;\n  \t}\n\n\t// 扩展查询。 寻找替代品。\n\tpublic static Finder expandedFinder(String... queries) {\n    \t\tvar finder = identSum();\n\n    \t\tfor (String query : queries) {\n      \t\t\tfinder = finder.or(Finder.contains(query));\n    \t\t}\n   \t\treturn finder;\n  \t}\n\t...\n}\n```\n\n现在我们已经创建了组合器的接口和方法。 现在我们有一个处理这些组合器的应用程序。\n\n```java\nvar queriesOr = new String[]{\"many\", \"Annabel\"};\nvar finder = Finders.expandedFinder(queriesOr);\nvar res = finder.find(text());\nLOGGER.info(\"the result of expanded(or) query[{}] is {}\", queriesOr, res);\n\nvar queriesAnd = new String[]{\"Annabel\", \"my\"};\nfinder = Finders.specializedFinder(queriesAnd);\nres = finder.find(text());\nLOGGER.info(\"the result of specialized(and) query[{}] is {}\", queriesAnd, res);\n\nfinder = Finders.advancedFinder(\"it was\", \"kingdom\", \"sea\");\nres = finder.find(text());\nLOGGER.info(\"the result of advanced query is {}\", res);\n\nres = Finders.filteredFinder(\" was \", \"many\", \"child\").find(text());\nLOGGER.info(\"the result of filtered query is {}\", res);\n\nprivate static String text() {\n    return\n        \"It was many and many a year ago,\\n\"\n            + \"In a kingdom by the sea,\\n\"\n            + \"That a maiden there lived whom you may know\\n\"\n            + \"By the name of ANNABEL LEE;\\n\"\n            + \"And this maiden she lived with no other thought\\n\"\n            + \"Than to love and be loved by me.\\n\"\n            + \"I was a child and she was a child,\\n\"\n            + \"In this kingdom by the sea;\\n\"\n            + \"But we loved with a love that was more than love-\\n\"\n            + \"I and my Annabel Lee;\\n\"\n            + \"With a love that the winged seraphs of heaven\\n\"\n            + \"Coveted her and me.\";\n  }\n```\n\n**程序输出:**\n\n```java\nthe result of expanded(or) query[[many, Annabel]] is [It was many and many a year ago,, By the name of ANNABEL LEE;, I and my Annabel Lee;]\nthe result of specialized(and) query[[Annabel, my]] is [I and my Annabel Lee;]\nthe result of advanced query is [It was many and many a year ago,]\nthe result of filtered query is [But we loved with a love that was more than love-]\n```\n\n现在我们可以设计我们的应用程序，使其具有查询查找功能`expandedFinder`, `specializedFinder`, `advancedFinder`, `filteredFinder`，这些功能均派生自`contains`, `or`, `not`, `and`。\n\n\n## 类图\n![alt text](./etc/combinator.urm.png \"Combinator class diagram\")\n\n## 适用性\n在以下情况下使用组合器模式：\n\n- 您可以从更简单的值创建更复杂的值，但具有相同的类型（它们的组合）\n\n## 好处\n\n- 从开发人员的角度来看，API 由领域中的术语组成。\n- 组合阶段和应用阶段之间有明显的区别。\n- 首先构造一个实例，然后执行它。\n- 这使得该模式适用于并行环境。\n\n\n## 现实世界的例子\n\n- java.util.function.Function#compose\n- java.util.function.Function#andThen\n\n## 鸣谢\n\n- [Example for java](https://gtrefs.github.io/code/combinator-pattern/)\n- [Combinator pattern](https://wiki.haskell.org/Combinator_pattern)\n- [Combinatory logic](https://wiki.haskell.org/Combinatory_logic)\n"
  },
  {
    "path": "localization/zh/command/README.md",
    "content": "---\ntitle: Command\nshortTitle: Command\ncategory: Behavioral\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 或称\n行动, 事务模式\n\n## 目的\n将请求封装为对象，从而使你可以将具有不同请求的客户端参数化，队列或记录请求，并且支持可撤销操作。\n\n## 解释\n真实世界例子\n\n> 有一个巫师在地精上施放咒语。咒语在地精上一一执行。第一个咒语使地精缩小，第二个使他不可见。然后巫师将咒语一个个的反转。这里的每一个咒语都是一个可撤销的命令对象。\n\n用通俗的话说\n\n> 用命令对象的方式存储请求以在将来时可以执行它或撤销它。\n\n维基百科说\n\n> 在面向对象编程中，命令模式是一种行为型设计模式，它把在稍后执行的一个动作或触发的一个事件所需要的所有信息封装到一个对象中。\n\n**编程示例**\n\n这是巫师和地精的示例代码。让我们从巫师类开始。\n\n```java\npublic class Wizard {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(Wizard.class);\n\n  private final Deque<Runnable> undoStack = new LinkedList<>();\n  private final Deque<Runnable> redoStack = new LinkedList<>();\n\n  public Wizard() {}\n\n  public void castSpell(Command command, Target target) {\n    LOGGER.info(\"{} casts {} at {}\", this, command, target);\n    command.execute(target);\n    undoStack.offerLast(command);\n  }\n\n  public void undoLastSpell() {\n    if (!undoStack.isEmpty()) {\n      var previousSpell = undoStack.pollLast();\n      redoStack.offerLast(previousSpell);\n      LOGGER.info(\"{} undoes {}\", this, previousSpell);\n      previousSpell.undo();\n    }\n  }\n\n  public void redoLastSpell() {\n    if (!redoStack.isEmpty()) {\n      var previousSpell = redoStack.pollLast();\n      undoStack.offerLast(previousSpell);\n      LOGGER.info(\"{} redoes {}\", this, previousSpell);\n      previousSpell.redo();\n    }\n  }\n\n  @Override\n  public String toString() {\n    return \"Wizard\";\n  }\n}\n```\n\n接下来我们介绍咒语层级\n\n```java\npublic interface Command {\n\n  void execute(Target target);\n\n  void undo();\n\n  void redo();\n\n  String toString();\n}\n\npublic class InvisibilitySpell implements Command {\n\n  private Target target;\n\n  @Override\n  public void execute(Target target) {\n    target.setVisibility(Visibility.INVISIBLE);\n    this.target = target;\n  }\n\n  @Override\n  public void undo() {\n    if (target != null) {\n      target.setVisibility(Visibility.VISIBLE);\n    }\n  }\n\n  @Override\n  public void redo() {\n    if (target != null) {\n      target.setVisibility(Visibility.INVISIBLE);\n    }\n  }\n\n  @Override\n  public String toString() {\n    return \"Invisibility spell\";\n  }\n}\n\npublic class ShrinkSpell implements Command {\n\n  private Size oldSize;\n  private Target target;\n\n  @Override\n  public void execute(Target target) {\n    oldSize = target.getSize();\n    target.setSize(Size.SMALL);\n    this.target = target;\n  }\n\n  @Override\n  public void undo() {\n    if (oldSize != null && target != null) {\n      var temp = target.getSize();\n      target.setSize(oldSize);\n      oldSize = temp;\n    }\n  }\n\n  @Override\n  public void redo() {\n    undo();\n  }\n\n  @Override\n  public String toString() {\n    return \"Shrink spell\";\n  }\n}\n```\n\n最后我们有咒语的目标地精。\n\n```java\npublic abstract class Target {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(Target.class);\n\n  private Size size;\n\n  private Visibility visibility;\n\n  public Size getSize() {\n    return size;\n  }\n\n  public void setSize(Size size) {\n    this.size = size;\n  }\n\n  public Visibility getVisibility() {\n    return visibility;\n  }\n\n  public void setVisibility(Visibility visibility) {\n    this.visibility = visibility;\n  }\n\n  @Override\n  public abstract String toString();\n\n  public void printStatus() {\n    LOGGER.info(\"{}, [size={}] [visibility={}]\", this, getSize(), getVisibility());\n  }\n}\n\npublic class Goblin extends Target {\n\n  public Goblin() {\n    setSize(Size.NORMAL);\n    setVisibility(Visibility.VISIBLE);\n  }\n\n  @Override\n  public String toString() {\n    return \"Goblin\";\n  }\n\n}\n```\n\n最后是整个示例的实践。\n\n```java\nvar wizard = new Wizard();\nvar goblin = new Goblin();\ngoblin.printStatus();\n// Goblin, [size=normal] [visibility=visible]\nwizard.castSpell(new ShrinkSpell(), goblin);\n// Wizard casts Shrink spell at Goblin\ngoblin.printStatus();\n// Goblin, [size=small] [visibility=visible]\nwizard.castSpell(new InvisibilitySpell(), goblin);\n// Wizard casts Invisibility spell at Goblin\ngoblin.printStatus();\n// Goblin, [size=small] [visibility=invisible]\nwizard.undoLastSpell();\n// Wizard undoes Invisibility spell\ngoblin.printStatus();\n// Goblin, [size=small] [visibility=visible]\n```\n\n## 类图\n![alt text](./etc/command.png \"Command\")\n\n## 适用性\n使用命令模式当你想\n\n* 通过操作将对象参数化。您可以使用回调函数（即，已在某处注册以便稍后调用的函数）以过程语言表示这种参数化。命令是回调的一种面向对象替代方案。\n* 在不同的时间指定，排队和执行请求。一个命令对象的生存期可以独立于原始请求。如果请求的接收方可以以地址空间无关的方式来表示，那么你可以将请求的命令对象传输到其他进程并在那里执行请求。\n* 支持撤销。命令的执行操作可以在命令本身中存储状态以反转其效果。命令接口必须有添加的反执行操作，该操作可以逆转上一次执行调用的效果。执行的命令存储在历史列表中。无限撤消和重做通过分别向后和向前遍历此列表来实现，分别调用unexecute和execute。\n* 支持日志记录更改，以便在系统崩溃时可以重新应用它们。通过使用加载和存储操作扩展命令接口，你可以保留更改的永久日志。从崩溃中恢复涉及从磁盘重新加载记录的命令，并通过执行操作重新执行它们。\n* 通过原始的操作来构建一个以高级操作围绕的系统。这种结构在支持事务的信息系统中很常见。事务封装了一组数据更改。命令模式提供了一种对事务进行建模的方法。命令具有公共接口，让你以相同的方式调用所有事务。该模式还可以通过新的事务来轻松扩展系统。\n\n## 典型用例\n\n* 保留请求历史\n* 实现回调功能\n* 实现撤销功能\n\n## Java世界例子\n\n* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)\n* [org.junit.runners.model.Statement](https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/runners/model/Statement.java)\n* [Netflix Hystrix](https://github.com/Netflix/Hystrix/wiki)\n* [javax.swing.Action](http://docs.oracle.com/javase/8/docs/api/javax/swing/Action.html)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n"
  },
  {
    "path": "localization/zh/commander/README.md",
    "content": "---\ntitle: Commander\nshortTitle: Commander\ncategory: Concurrency\nlanguage: zh\ntag:\n - Cloud distributed\n---\n\n## 目的\n\n> 用于处理执行分布式事务时可能遇到的所有问题。\n\n## 类图\n![alt text](./etc/commander.urm.png \"Commander class diagram\")\n\n## 适用场合\n当我们需要提交两个数据库去完成事务，提交不是原子性且可能因此造成问题时，适合用这个设计模式。\n\n## 解释\n处理分布式事务很棘手，但如果我们不仔细处理，可能会带来不想要的后果。假设我们有一个电子商务网站，它有一个支付微服务和一个运输微服务。如果当前运输可用，但支付服务不可用，或者反之，当我们已经收到用户的订单后，我们应该如何处理？我们需要有一个机制来处理这些情况。我们必须将订单指向其中一个服务（在这个例子中是运输），然后将订单添加到另一个服务的数据库中（在这个例子中是支付），因为两个数据库不能原子地更新。如果我们当前无法做到这一点，应该有一个队列，可以将这个请求排队，并且必须有一个机制，允许队列中出现失败。所有这些都需要通过不断的重试，在保证幂等性（即使请求多次，变化只应用一次）的情况下，由一个指挥类来完成，以达到最终一致性的状态。\n\n## 鸣谢\n\n* [Distributed Transactions: The Icebergs of Microservices](https://www.grahamlea.com/2016/08/distributed-transactions-microservices-icebergs/)\n"
  },
  {
    "path": "localization/zh/composite/README.md",
    "content": "---\ntitle: Composite\nshortTitle: Composite\ncategory: Structural\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 目的\n\n将对象组合成树结构以表示部分整体层次结构。 组合可以使客户统一对待单个对象和组合对象。\n\n## 解释\n\n真实世界例子\n\n> 每个句子由单词组成，单词又由字符组成。这些对象中的每一个都是可打印的，它们可以在它们之前或之后打印一些内容，例如句子始终以句号结尾，单词始终在其前面有空格。\n\n通俗的说\n\n> 组合模式使客户能够以统一的方式对待各个对象。\n\n维基百科说\n\n> 在软件工程中，组合模式是一种分区设计模式。组合模式中，一组对象将像一个对象的单独实例一样被对待。组合的目的是将对象“组成”树状结构，以表示部分整体层次结构。实现组合模式可使客户统一对待单个对象和组合对象。\n\n**程序示例**\n\n使用上面的句子例子。 这里我们有基类`LetterComposite`和不同的可打印类型`Letter`，`Word`和`Sentence`。\n\n```java\npublic abstract class LetterComposite {\n\n  private final List<LetterComposite> children = new ArrayList<>();\n\n  public void add(LetterComposite letter) {\n    children.add(letter);\n  }\n\n  public int count() {\n    return children.size();\n  }\n\n  protected void printThisBefore() {\n  }\n\n  protected void printThisAfter() {\n  }\n\n  public void print() {\n    printThisBefore();\n    children.forEach(LetterComposite::print);\n    printThisAfter();\n  }\n}\n\npublic class Letter extends LetterComposite {\n\n  private final char character;\n\n  public Letter(char c) {\n    this.character = c;\n  }\n\n  @Override\n  protected void printThisBefore() {\n    System.out.print(character);\n  }\n}\n\npublic class Word extends LetterComposite {\n\n  public Word(List<Letter> letters) {\n    letters.forEach(this::add);\n  }\n\n  public Word(char... letters) {\n    for (char letter : letters) {\n      this.add(new Letter(letter));\n    }\n  }\n\n  @Override\n  protected void printThisBefore() {\n    System.out.print(\" \");\n  }\n}\n\npublic class Sentence extends LetterComposite {\n\n  public Sentence(List<Word> words) {\n    words.forEach(this::add);\n  }\n\n  @Override\n  protected void printThisAfter() {\n    System.out.print(\".\");\n  }\n}\n```\n\n然后我们有一个消息携带者来携带消息。\n\n```java\npublic class Messenger {\n\n  LetterComposite messageFromOrcs() {\n\n    var words = List.of(\n        new Word('W', 'h', 'e', 'r', 'e'),\n        new Word('t', 'h', 'e', 'r', 'e'),\n        new Word('i', 's'),\n        new Word('a'),\n        new Word('w', 'h', 'i', 'p'),\n        new Word('t', 'h', 'e', 'r', 'e'),\n        new Word('i', 's'),\n        new Word('a'),\n        new Word('w', 'a', 'y')\n    );\n\n    return new Sentence(words);\n\n  }\n\n  LetterComposite messageFromElves() {\n\n    var words = List.of(\n        new Word('M', 'u', 'c', 'h'),\n        new Word('w', 'i', 'n', 'd'),\n        new Word('p', 'o', 'u', 'r', 's'),\n        new Word('f', 'r', 'o', 'm'),\n        new Word('y', 'o', 'u', 'r'),\n        new Word('m', 'o', 'u', 't', 'h')\n    );\n\n    return new Sentence(words);\n\n  }\n\n}\n```\n\n然后它可以这样使用:\n\n```java\nvar orcMessage = new Messenger().messageFromOrcs();\norcMessage.print(); // Where there is a whip there is a way.\nvar elfMessage = new Messenger().messageFromElves();\nelfMessage.print(); // Much wind pours from your mouth.\n```\n\n## 类图\n\n![alt text](./etc/composite.urm.png \"Composite class diagram\")\n\n## 适用性\n\n使用组合模式当\n\n* 你想要表示对象的整体层次结构\n* 你希望客户能够忽略组合对象和单个对象之间的差异。 客户将统一对待组合结构中的所有对象。\n\n## 真实世界例子\n\n* [java.awt.Container](http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html) and [java.awt.Component](http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html)\n* [Apache Wicket](https://github.com/apache/wicket) component tree, see [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java) and [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/zh/composite-entity/README.md",
    "content": "---\ntitle: Composite Entity\nshortTitle: Composite Entity\ncategory: Structural\nlanguage: zh\ntag:\n - Enterprise Integration Pattern\n---\n\n## 含义\n\n复合实体模式用于对一组相关联的持久化对象进行建模、描述和管理，用于取代对这组对象描述为单独粒度的实体。\n\n## 解释\n\n现实例子\n\n> 对于一个控制台对象，需要管理许多接口功能。通过使用复合实体模式，将消息对象、信号对象等依赖性对象组合在一起，直接使用单个对象对其进行控制。\n\n简单地说\n\n> 复合实体模式允许使用一个统一对象来管理一组相互关联的对象\n\n**编程示例**\n\n我们需要一个通用的解决方案来解决上述的控制台问题。我们引入了以下的通用复合对象。\n\n```java\npublic abstract class DependentObject<T> {\n\n  T data;\n\n  public void setData(T message) {\n    this.data = message;\n  }\n\n  public T getData() {\n    return data;\n  }\n}\n\npublic abstract class CoarseGrainedObject<T> {\n\n  DependentObject<T>[] dependentObjects;\n\n  public void setData(T... data) {\n    IntStream.range(0, data.length).forEach(i -> dependentObjects[i].setData(data[i]));\n  }\n\n  public T[] getData() {\n    return (T[]) Arrays.stream(dependentObjects).map(DependentObject::getData).toArray();\n  }\n}\n\n```\n\n专用的 `console` 复合实体继承自这个基类，如下所示。\n\n```java\npublic class MessageDependentObject extends DependentObject<String> {\n\n}\n\npublic class SignalDependentObject extends DependentObject<String> {\n\n}\n\npublic class ConsoleCoarseGrainedObject extends CoarseGrainedObject<String> {\n\n  @Override\n  public String[] getData() {\n    super.getData();\n    return new String[]{\n        dependentObjects[0].getData(), dependentObjects[1].getData()\n    };\n  }\n\n  public void init() {\n    dependentObjects = new DependentObject[]{\n        new MessageDependentObject(), new SignalDependentObject()};\n  }\n}\n\npublic class CompositeEntity {\n\n  private final ConsoleCoarseGrainedObject console = new ConsoleCoarseGrainedObject();\n\n  public void setData(String message, String signal) {\n    console.setData(message, signal);\n  }\n\n  public String[] getData() {\n    return console.getData();\n  }\n}\n```\n\n现在我们使用 `console` 复合实体来进行消息对象、信号对象的分配。\n\n```java\nvar console = new CompositeEntity();\nconsole.init();\nconsole.setData(\"No Danger\", \"Green Light\");\nArrays.stream(console.getData()).forEach(LOGGER::info);\nconsole.setData(\"Danger\", \"Red Light\");\nArrays.stream(console.getData()).forEach(LOGGER::info);\n```\n\n## 类图\n\n![alt text](./etc/composite_entity.urm.png \"Composite Entity Pattern\")\n\n## 适用场景\n\n复合实体模式适用于以下场景：\n\n* 你想要通过一个对象来管理多个依赖对象，已调整对象之间的细化程度。同时将依赖对象的生命周期托管到这个粗粒度的复合实体对象。\n## 引用\n\n* [Composite Entity Pattern in wikipedia](https://en.wikipedia.org/wiki/Composite_entity_pattern)"
  },
  {
    "path": "localization/zh/converter/README.md",
    "content": "---\ntitle: Converter\nshortTitle: Converter\ncategory: Creational\nlanguage: zh\ntag:\n - Decoupling\n---\n\n## 目的\n\n转换器模式的目的是提供相应类型之间双向转换的通用方法，允许进行干净的实现，而类型之间无需相互了解。此外，Converter模式引入了双向集合映射，从而将样板代码减少到最少。\n\n## 解释\n\n真实世界例子\n\n> 在真实的应用中经常有这种情况，数据库层包含需要被转换成业务逻辑层DTO来使用的实体。对于潜在的大量类进行类似的映射，我们需要一种通用的方法来实现这一点。\n\n通俗的说\n\n> 转换器模式让一个类的实例映射成另一个类的实例变得简单\n\n**程序示例**\n\n我们需要一个通用的方案来解决映射问题。让我们来介绍一个通用的转换器。\n\n```java\npublic class Converter<T, U> {\n\n  private final Function<T, U> fromDto;\n  private final Function<U, T> fromEntity;\n\n  public Converter(final Function<T, U> fromDto, final Function<U, T> fromEntity) {\n    this.fromDto = fromDto;\n    this.fromEntity = fromEntity;\n  }\n\n  public final U convertFromDto(final T dto) {\n    return fromDto.apply(dto);\n  }\n\n  public final T convertFromEntity(final U entity) {\n    return fromEntity.apply(entity);\n  }\n\n  public final List<U> createFromDtos(final Collection<T> dtos) {\n    return dtos.stream().map(this::convertFromDto).collect(Collectors.toList());\n  }\n\n  public final List<T> createFromEntities(final Collection<U> entities) {\n    return entities.stream().map(this::convertFromEntity).collect(Collectors.toList());\n  }\n}\n```\n\n专属的转换器像下面一样从基类继承。\n\n```java\npublic class UserConverter extends Converter<UserDto, User> {\n\n  public UserConverter() {\n    super(UserConverter::convertToEntity, UserConverter::convertToDto);\n  }\n\n  private static UserDto convertToDto(User user) {\n    return new UserDto(user.getFirstName(), user.getLastName(), user.isActive(), user.getUserId());\n  }\n\n  private static User convertToEntity(UserDto dto) {\n    return new User(dto.getFirstName(), dto.getLastName(), dto.isActive(), dto.getEmail());\n  }\n\n}\n```\n\n现在，在User和UserDto之间的映射变得轻而易举。\n\n```java\nvar userConverter = new UserConverter();\nvar dtoUser = new UserDto(\"John\", \"Doe\", true, \"whatever[at]wherever.com\");\nvar user = userConverter.convertFromDto(dtoUser);\n```\n\n## 类图\n\n![alt text](./etc/converter.png \"Converter Pattern\")\n\n## 适用性\n\n在下面这些情况下使用转换器模式：\n\n* 如果你的类型在逻辑上相互对应，并需要在它们之间转换实体\n* 当你想根据上下文提供不同的类型转换方式时\n* 每当你引入DTO（数据传输对象）时你可能都需要将其转换为\n  DO\n\n## 鸣谢\n\n* [Converter](http://www.xsolve.pl/blog/converter-pattern-in-java-8/)\n"
  },
  {
    "path": "localization/zh/crtp/README.md",
    "content": "---\ntitle: Curiously Recurring Template Pattern\nshortTitle: Curiously Recurring Template Pattern\nlanguage: zh\ncategory: Structural\ntag:\n- Extensibility\n- Instantiation\n---\n\n## 名称/分类\n\nCuriously Recurring Template Pattern，CRTP，奇异递归模板模式\n\n## 别名\n\n递归类型绑定，递归泛型\n\n## 目的\n\n允许派生组件从与派生类型兼容的基本组件继承某些功能。\n\n## 解释\n\n真实世界的例子\n\n> 对于正在策划赛事的综合格斗推广活动来说，确保在相同重量级的运动员之间组织比赛至关重要。这样可以防止体型明显不同的拳手之间的不匹配，例如重量级拳手与雏量级拳手的对决。\n\n用通俗的话来讲\n\n> 使类型中的某些方法接受特定于其子类型的参数。\n\n维基百科介绍\n\n> 奇异递归模板模式（curiously recurring template pattern，CRTP）是C++模板编程时的一种惯用法：其中类X派生自使用X本身作为模板参数的类模板实例化。\n\n**程序示例**\n\n让我们来定义通用接口Fighter\n\n```java\npublic interface Fighter<T> {\n\n  void fight(T t);\n\n}\n```\n\nMmaFighter类用于实例化按重量级别区分的拳手\n\n``` Java\npublic class MmaFighter<T extends MmaFighter<T>> implements Fighter<T> {\n\n  private final String name;\n  private final String surname;\n  private final String nickName;\n  private final String speciality;\n\n  public MmaFighter(String name, String surname, String nickName, String speciality) {\n    this.name = name;\n    this.surname = surname;\n    this.nickName = nickName;\n    this.speciality = speciality;\n  }\n\n  @Override\n  public void fight(T opponent) {\n    LOGGER.info(\"{} is going to fight against {}\", this, opponent);\n  }\n\n  @Override\n  public String toString() {\n    return name + \" \\\"\" + nickName + \"\\\" \" + surname;\n  }\n```\n\n以下是 MmaFighter 的一些子类型\n\n```Java\nclass MmaBantamweightFighter extends MmaFighter<MmaBantamweightFighter> {\n\n  public MmaBantamweightFighter(String name, String surname, String nickName, String speciality) {\n    super(name, surname, nickName, speciality);\n  }\n\n}\n\npublic class MmaHeavyweightFighter extends MmaFighter<MmaHeavyweightFighter> {\n\n  public MmaHeavyweightFighter(String name, String surname, String nickName, String speciality) {\n    super(name, surname, nickName, speciality);\n  }\n\n}\n```\n\n允许拳手与相同重量级的对手交手，如果对手是不同重量级，则会出现错误\n\n``` Java\nMmaBantamweightFighter fighter1 = new MmaBantamweightFighter(\"Joe\", \"Johnson\", \"The Geek\", \"Muay Thai\");\nMmaBantamweightFighter fighter2 = new MmaBantamweightFighter(\"Ed\", \"Edwards\", \"The Problem Solver\", \"Judo\");\nfighter1.fight(fighter2); // This is fine\n\nMmaHeavyweightFighter fighter3 = new MmaHeavyweightFighter(\"Dave\", \"Davidson\", \"The Bug Smasher\", \"Kickboxing\");\nMmaHeavyweightFighter fighter4 = new MmaHeavyweightFighter(\"Jack\", \"Jackson\", \"The Pragmatic\", \"Brazilian Jiu-Jitsu\");\nfighter3.fight(fighter4); // This is fine too\n\nfighter1.fight(fighter3); // This will raise a compilation error\n```\n\n## 类图\n\n![alt text](etc/crtp.png \"CRTP class diagram\")\n\n## 适用性\n\n在以下情况下使用CRTP\n\n* 在对象层次结构中链接方法时存在类型冲突\n* 您想使用一个参数化的类方法，该方法可以接受类的子类作为参数，从而可以应用于继承自类的对象\n* 您希望某些方法仅适用于相同类型的实例，例如实现相互比较。\n\n## 教程\n\n* [The NuaH Blog](https://nuah.livejournal.com/328187.html)\n* Yogesh Umesh Vaity answer to [What does \"Recursive type bound\" in Generics mean?](https://stackoverflow.com/questions/7385949/what-does-recursive-type-bound-in-generics-mean)\n\n## 已知用途\n\n* [java.lang.Enum](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Enum.html)\n\n## 鸣谢\n\n* [How do I decrypt \"Enum<E extends Enum\\<E>>\"?](http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ106)\n* Chapter 5 Generics, Item 30 in [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n"
  },
  {
    "path": "localization/zh/dao/README.md",
    "content": "---\ntitle: Data Access Object\nshortTitle: Data Access Object\ncategory: Architectural\nlanguage: zh\ntag:\n - Data access\n---\n\n## 目的\n\n对象为某种类型的数据库或其他持久性机制提供了抽象接口。\n\n## 解释\n\n真实世界例子\n\n> 有一组客户数据需要持久化到数据库中。 我们需要整个额外的增删改查操作以便操作客户数据。\n\n通俗的说\n\n> DAO是我们通过基本持久性机制提供的接口。\n\n维基百科说\n\n> 在计算机软件中，数据访问对象（DAO）是一种模式，可为某种类型的数据库或其他持久性机制提供抽象接口。\n\n**程序示例**\n\n通过我们的客户示例，下面是基本的`客户`实体。\n\n```java\npublic class Customer {\n\n  private int id;\n  private String firstName;\n  private String lastName;\n\n  public Customer(int id, String firstName, String lastName) {\n    this.id = id;\n    this.firstName = firstName;\n    this.lastName = lastName;\n  }\n  // getters and setters ->\n  ...\n}\n```\n\n这是`CustomerDao`接口及其两个不同的实现。\n\nHere's the `CustomerDao` interface and two different implementations for it. `InMemoryCustomerDao` \n将简单的客户数据映射保存在内存中 而`DBCustomerDao`是真正的RDBMS实现。\n\n```java\npublic interface CustomerDao {\n\n  Stream<Customer> getAll() throws Exception;\n\n  Optional<Customer> getById(int id) throws Exception;\n\n  boolean add(Customer customer) throws Exception;\n\n  boolean update(Customer customer) throws Exception;\n\n  boolean delete(Customer customer) throws Exception;\n}\n\npublic class InMemoryCustomerDao implements CustomerDao {\n\n  private final Map<Integer, Customer> idToCustomer = new HashMap<>();\n\n  // implement the interface using the map\n  ...\n}\n\npublic class DbCustomerDao implements CustomerDao {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(DbCustomerDao.class);\n\n  private final DataSource dataSource;\n\n  public DbCustomerDao(DataSource dataSource) {\n    this.dataSource = dataSource;\n  }\n\n  // implement the interface using the data source\n  ...\n```\n\n最后，这是我们使用DAO管理客户数据的方式。\n\n```java\n    final var dataSource = createDataSource();\n    createSchema(dataSource);\n    final var customerDao = new DbCustomerDao(dataSource);\n    \n    addCustomers(customerDao);\n    log.info(ALL_CUSTOMERS);\n    try (var customerStream = customerDao.getAll()) {\n      customerStream.forEach((customer) -> log.info(customer.toString()));\n    }\n    log.info(\"customerDao.getCustomerById(2): \" + customerDao.getById(2));\n    final var customer = new Customer(4, \"Dan\", \"Danson\");\n    customerDao.add(customer);\n    log.info(ALL_CUSTOMERS + customerDao.getAll());\n    customer.setFirstName(\"Daniel\");\n    customer.setLastName(\"Danielson\");\n    customerDao.update(customer);\n    log.info(ALL_CUSTOMERS);\n    try (var customerStream = customerDao.getAll()) {\n      customerStream.forEach((cust) -> log.info(cust.toString()));\n    }\n    customerDao.delete(customer);\n    log.info(ALL_CUSTOMERS + customerDao.getAll());\n    \n    deleteSchema(dataSource);\n```\n\n程序输出:\n\n```java\ncustomerDao.getAllCustomers(): \nCustomer{id=1, firstName='Adam', lastName='Adamson'}\nCustomer{id=2, firstName='Bob', lastName='Bobson'}\nCustomer{id=3, firstName='Carl', lastName='Carlson'}\ncustomerDao.getCustomerById(2): Optional[Customer{id=2, firstName='Bob', lastName='Bobson'}]\ncustomerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@7cef4e59\ncustomerDao.getAllCustomers(): \nCustomer{id=1, firstName='Adam', lastName='Adamson'}\nCustomer{id=2, firstName='Bob', lastName='Bobson'}\nCustomer{id=3, firstName='Carl', lastName='Carlson'}\nCustomer{id=4, firstName='Daniel', lastName='Danielson'}\ncustomerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@2db0f6b2\ncustomerDao.getAllCustomers(): \nCustomer{id=1, firstName='Adam', lastName='Adamson'}\nCustomer{id=2, firstName='Bob', lastName='Bobson'}\nCustomer{id=3, firstName='Carl', lastName='Carlson'}\ncustomerDao.getCustomerById(2): Optional[Customer{id=2, firstName='Bob', lastName='Bobson'}]\ncustomerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@12c8a2c0\ncustomerDao.getAllCustomers(): \nCustomer{id=1, firstName='Adam', lastName='Adamson'}\nCustomer{id=2, firstName='Bob', lastName='Bobson'}\nCustomer{id=3, firstName='Carl', lastName='Carlson'}\nCustomer{id=4, firstName='Daniel', lastName='Danielson'}\ncustomerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@6ec8211c\n```\n\n## 类图\n\n![alt text](./etc/dao.png \"Data Access Object\")\n\n## 适用性\n\n在以下情况下，请使用数据访问对象：:\n\n* 当您要巩固如何访问数据层时。\n* 当您要避免编写多个数据检索/持久层时。\n\n## 鸣谢\n\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n"
  },
  {
    "path": "localization/zh/data-bus/README.md",
    "content": "---\ntitle: Data Bus\nshortTitle: Data Bus\ncategory: Architectural\nlanguage: zh\ntag:\n - Decoupling\n---\n\n## 含义\n\n数据总线模式（译者：实际上，就是 Event-Bus 消息总线模式）允许在一个应用程序的组件之间收发消息/事件，而不需要这些组件相互感知，它们只需要知道所发送/接收的消息/事件的类型即可。\n\n## 类图\n![data bus pattern uml diagram](./etc/data-bus.urm.png \"Data Bus pattern\")\n\n## 适用场景\n可以在以下场景使用数据总线模式：\n\n* 你希望由你的组件自己决定要接收哪些信息/事件\n* 你希望实现多对多的通信\n* 你希望你的组件不需要感知彼此\n\n## 相关模式\n数据总线类似于以下设计模式：\n\n* 中介者模式（Mediator pattern），由数据总线成员自己决定是否要接受任何给定的消息。\n* 观察者模式（Observer pattern），但进一步支持了多对多的通信。\n* 发布/订阅模式（Publish/Subscribe pattern），但是数据总线将发布者和订阅者解耦。"
  },
  {
    "path": "localization/zh/data-mapper/README.md",
    "content": "---\ntitle: Data Mapper\nshortTitle: Data Mapper\ncategory: Architectural\nlanguage: zh\ntag:\n - Decoupling\n---\n\n## 含义\n一个用于在持久化对象和数据库之间传输数据的映射器，同时保持它们之间和映射器本身的独立性。\n\n## 类图\n![alt text](./etc/data-mapper.png \"Data Mapper\")\n\n## 适用场景\n数据映射器适用于以下场景：\n\n* 当你想把数据对象从数据库访问层解耦时时\n* 当你想编写多个数据查询/持久化实现时\n\n## 引用\n\n* [Data Mapper](http://richard.jp.leguen.ca/tutoring/soen343-f2010/tutorials/implementing-data-mapper/)"
  },
  {
    "path": "localization/zh/data-transfer-object/README.md",
    "content": "---\ntitle: Data Transfer Object\nshortTitle: Data Transfer Object\ncategory: Architectural\nlanguage: zh\ntag:\n - Performance\n---\n\n## 目的\n\n次将具有多个属性的数据从客户端传递到服务器，以避免多次调用远程服务器。\n\n## 解释\n\n真实世界例子\n\n> 我们需要从远程数据库中获取有关客户的信息。 我们不使用一次查询一个属性，而是使用DTO一次传送所有相关属性。\n\n通俗的说\n\n> 使用DTO，可以通过单个后端查询获取相关信息。\n\n维基百科说\n\n> 在编程领域，数据传输对象（DTO）是在进程之间承载数据的对象。 使用它的动机是，通常依靠远程接口（例如Web服务）来完成进程之间的通信，在这种情况下，每个调用都是昂贵的操作。\n> \n> 因为每个（方法）调用的大部分成本与客户端和服务器之间的往返时间有关，所以减少调用数量的一种方法是使用一个对象（DTO）来聚合将要在多次调用间传输的数据，但仅由一个调用提供。\n\n**程序示例**\n\n让我们来介绍我们简单的`CustomerDTO` 类\n\n```java\npublic class CustomerDto {\n  private final String id;\n  private final String firstName;\n  private final String lastName;\n\n  public CustomerDto(String id, String firstName, String lastName) {\n    this.id = id;\n    this.firstName = firstName;\n    this.lastName = lastName;\n  }\n\n  public String getId() {\n    return id;\n  }\n\n  public String getFirstName() {\n    return firstName;\n  }\n\n  public String getLastName() {\n    return lastName;\n  }\n}\n```\n\n`CustomerResource` 类充当客户信息的服务器。\n\n```java\npublic class CustomerResource {\n  private final List<CustomerDto> customers;\n\n  public CustomerResource(List<CustomerDto> customers) {\n    this.customers = customers;\n  }\n\n  public List<CustomerDto> getAllCustomers() {\n    return customers;\n  }\n\n  public void save(CustomerDto customer) {\n    customers.add(customer);\n  }\n\n  public void delete(String customerId) {\n    customers.removeIf(customer -> customer.getId().equals(customerId));\n  }\n}\n```\n\n现在拉取客户信息变得简单自从我们有了DTOs。\n\n```java\n    var allCustomers = customerResource.getAllCustomers();\n    allCustomers.forEach(customer -> LOGGER.info(customer.getFirstName()));\n    // Kelly\n    // Alfonso\n```\n\n## 类图\n\n![alt text](./etc/data-transfer-object.urm.png \"data-transfer-object\")\n\n## 适用性\n\n使用数据传输对象模式当\n\n* 客户端请求多种信息。信息都是相关的\n* 当你想提高获取资源的性能\n* 你想降低远程方法调用的次数\n\n## 鸣谢\n\n* [Design Pattern - Transfer Object Pattern](https://www.tutorialspoint.com/design_pattern/transfer_object_pattern.htm)\n* [Data Transfer Object](https://msdn.microsoft.com/en-us/library/ff649585.aspx)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321127420&linkCode=as2&tag=javadesignpat-20&linkId=014237a67c9d46f384b35e10151956bd)\n"
  },
  {
    "path": "localization/zh/decorator/README.md",
    "content": "---\ntitle: Decorator\nshortTitle: Decorator\ncategory: Structural\nlanguage: zh\ntag:\n - Gang Of Four\n - Extensibility\n---\n\n## 或称\n包装器\n\n## 目的\n动态的为对象附加额外的职责。装饰器为子类提供了灵活的替代方案，以扩展功能。\n\n## 解释\n\n真实世界例子\n\n> 附近的山丘上住着一个愤怒的巨魔。通常它是徒手的，但有时它有武器。为了武装巨魔不必创建新的巨魔，而是用合适的武器动态的装饰它。\n\n通俗的说\n\n> 装饰者模式让你可以在运行时通过把对象包装进一个装饰类对象中来动态的改变一个对象的行为。\n\n维基百科说\n\n> 在面向对象的编程中，装饰器模式是一种设计模式，它允许将行为静态或动态地添加到单个对象中，而不会影响同一类中其他对象的行为。装饰器模式通常对于遵守单一责任原则很有用，因为它允许将功能划分到具有唯一关注领域的类之间。\n\n**程序示例**\n\n以巨魔的为例。首先我有有一个简单的巨魔，实现了巨魔接口。\n\n```java\npublic interface Troll {\n  void attack();\n  int getAttackPower();\n  void fleeBattle();\n}\n\n@Slf4j\npublic class SimpleTroll implements Troll {\n\n  @Override\n  public void attack() {\n    LOGGER.info(\"The troll tries to grab you!\");\n  }\n\n  @Override\n  public int getAttackPower() {\n    return 10;\n  }\n\n  @Override\n  public void fleeBattle() {\n    LOGGER.info(\"The troll shrieks in horror and runs away!\");\n  }\n}\n```\n\n下面我们想为巨魔添加球棒。我们可以用装饰者来动态的实现。\n\n```java\n@Slf4j\npublic class ClubbedTroll implements Troll {\n\n  private final Troll decorated;\n\n  public ClubbedTroll(Troll decorated) {\n    this.decorated = decorated;\n  }\n\n  @Override\n  public void attack() {\n    decorated.attack();\n    LOGGER.info(\"The troll swings at you with a club!\");\n  }\n\n  @Override\n  public int getAttackPower() {\n    return decorated.getAttackPower() + 10;\n  }\n\n  @Override\n  public void fleeBattle() {\n    decorated.fleeBattle();\n  }\n}\n```\n\n这里是巨魔的实战\n\n```java\n// simple troll\nvar troll = new SimpleTroll();\ntroll.attack(); // The troll tries to grab you!\ntroll.fleeBattle(); // The troll shrieks in horror and runs away!\n\n// change the behavior of the simple troll by adding a decorator\nvar clubbedTroll = new ClubbedTroll(troll);\nclubbedTroll.attack(); // The troll tries to grab you! The troll swings at you with a club!\nclubbedTroll.fleeBattle(); // The troll shrieks in horror and runs away!\n```\n\n## 类图\n![alt text](./etc/decorator.urm.png \"Decorator pattern class diagram\")\n\n## 适用性\n使用装饰者\n\n* 动态透明地向单个对象添加职责，即不影响其他对象\n* 对于可以撤销的责任\n* 当通过子类化进行扩展是不切实际的。有时可能会有大量的独立扩展，并且会产生大量的子类来支持每种组合。 否则类定义可能被隐藏或无法用于子类化。\n\n## 教程\n* [Decorator Pattern Tutorial](https://www.journaldev.com/1540/decorator-design-pattern-in-java-example)\n\n## Java世界的例子\n * [java.io.InputStream](http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html), [java.io.OutputStream](http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html),\n [java.io.Reader](http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html) and [java.io.Writer](http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html)\n * [java.util.Collections#synchronizedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedCollection-java.util.Collection-)\n * [java.util.Collections#unmodifiableXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableCollection-java.util.Collection-)\n * [java.util.Collections#checkedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedCollection-java.util.Collection-java.lang.Class-)\n\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n"
  },
  {
    "path": "localization/zh/delegation/README.md",
    "content": "---\ntitle: Delegation\nshortTitle: Delegation\ncategory: Structural\nlanguage: zh\ntag:\n - Decoupling\n---\n\n## 或称\n代理模式\n\n## 目的\n它是一种让对象将某种行为向外部表达，但实际上将实现该行为的责任委托给关联对象的技术。\n\n## 类图\n![alt text](./etc/delegation.png \"Delegate\")\n\n## 适用性\n使用委托模式以实现以下目的\n\n* 降低类的耦合性\n* 组件的行为相同，但是意识到这种情况将来可能会改变。\n\n## 鸣谢\n\n* [Delegate Pattern: Wikipedia ](https://en.wikipedia.org/wiki/Delegation_pattern)\n* [Proxy Pattern: Wikipedia ](https://en.wikipedia.org/wiki/Proxy_pattern)\n"
  },
  {
    "path": "localization/zh/dependency-injection/README.md",
    "content": "---\ntitle: Dependency Injection\nshortTitle: Dependency Injection\ncategory: Creational\nlanguage: zh\ntag:\n - Decoupling\n---\n\n## 目的\n\n依赖注入是一种软件设计模式，其中一个或多个依赖项（或服务）被注入或通过引用传递到一个依赖对象（或客户端）中，并成为客户端状态的一部分。该模式将客户的依赖关系的创建与其自身的行为分开，这使程序设计可以松散耦合，并遵循控制反转和单一职责原则。\n\n## 解释\n\n真实世界例子\n\n> 老巫师喜欢不时地装满烟斗抽烟。 但是，他不想只依赖一个烟草品牌，而是希望能够互换使用它们。 \n\n通俗的说\n\n> 依赖注入将客户端依赖的创建与其自身行为分开。\n\n维基百科说\n\n> 在软件工程中，依赖注入是一种对象接收其依赖的其他对象的技术。 这些其他对象称为依赖项。\n\n**程序示例**\n\n先介绍一下烟草接口和具体的品牌。\n\n```java\npublic abstract class Tobacco {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(Tobacco.class);\n\n  public void smoke(Wizard wizard) {\n    LOGGER.info(\"{} smoking {}\", wizard.getClass().getSimpleName(),\n        this.getClass().getSimpleName());\n  }\n}\n\npublic class SecondBreakfastTobacco extends Tobacco {\n}\n\npublic class RivendellTobacco extends Tobacco {\n}\n\npublic class OldTobyTobacco extends Tobacco {\n}\n```\n\n下面是老巫师的类的层次结构。\n\n```java\npublic interface Wizard {\n\n  void smoke();\n}\n\npublic class AdvancedWizard implements Wizard {\n\n  private final Tobacco tobacco;\n\n  public AdvancedWizard(Tobacco tobacco) {\n    this.tobacco = tobacco;\n  }\n\n  @Override\n  public void smoke() {\n    tobacco.smoke(this);\n  }\n}\n```\n\n最后我们可以看到给老巫师任意品牌的烟草是多么的简单。\n\n```java\n    var advancedWizard = new AdvancedWizard(new SecondBreakfastTobacco());\n    advancedWizard.smoke();\n```\n\n## 类图\n\n![alt text](./etc/dependency-injection.png \"Dependency Injection\")\n\n## 适用性\n\n使用依赖注入当：\n\n- 当你需要从对象中移除掉具体的实现内容时\n\n* 使用模拟对象或存根隔离地启用类的单元测试\n\n## 鸣谢\n\n* [Dependency Injection Principles, Practices, and Patterns](https://www.amazon.com/gp/product/161729473X/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=161729473X&linkId=57079257a5c7d33755493802f3b884bd)\n* [Clean Code: A Handbook of Agile Software Craftsmanship](https://www.amazon.com/gp/product/0132350882/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0132350882&linkCode=as2&tag=javadesignpat-20&linkId=2c390d89cc9e61c01b9e7005c7842871)\n* [Java 9 Dependency Injection: Write loosely coupled code with Spring 5 and Guice](https://www.amazon.com/gp/product/1788296257/ref=as_li_tl?ie=UTF8&tag=javadesignpat-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=1788296257&linkId=4e9137a3bf722a8b5b156cce1eec0fc1)\n* [Google Guice Tutorial: Open source Java based dependency injection framework](https://www.amazon.com/gp/product/B083P7DZ8M/ref=as_li_tl?ie=UTF8&tag=javadesignpat-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B083P7DZ8M&linkId=04f0f902c877921e45215b624a124bfe)\n"
  },
  {
    "path": "localization/zh/dirty-flag/README.md",
    "content": "---\ntitle: Dirty Flag\nshortTitle: Dirty Flag\ncategory: Behavioral\nlanguage: zh\ntag:\n - Game programming\n - Performance\n---\n\n## 或称\n* 是否脏 模式\n\n## 目的\n避免昂贵资源的重新获取。资源保留其身份，保留在某些快速访问的存储中，并被重新使用以避免再次获取它们。\n\n## 类图\n![alt text](./etc/dirty-flag.png \"Dirty Flag\")\n\n## 适用性\n在以下情况下使用脏标志模式\n\n* 重复获取，初始化，释放相同资源所导致不必要的性能开销\n\n## 鸣谢\n\n* [Design Patterns: Dirty Flag](https://www.takeupcode.com/podcast/89-design-patterns-dirty-flag/)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)\n"
  },
  {
    "path": "localization/zh/double-checked-locking/README.md",
    "content": "---\ntitle: Double Checked Locking\nshortTitle: Double Checked Locking\ncategory: Idiom\nlanguage: zh\ntag:\n - Performance\n---\n\n## 含义\n通过先测试锁定标准（\"锁提示\"）而不实际获取锁的方式来减少获取锁的开销。只有当锁定标准检查表明需要锁定时，才进行实际的锁定逻辑。\n\n## 类图\n![alt text](./etc/double_checked_locking_1.png \"Double Checked Locking\")\n\n## 适用场景\n在以下场景适合使用双重锁检查模式：\n\n* 在创建对象时有存在并发的访问。如单例模式中，你想创建同一个类的单个实例，如果存在两个或更多的线程对实例进行判空，仅仅检查该该实例是否为空可能是不够的。\n* 在一个方法上存在并发访问，该方法的行为是根据一些约束条件而改变，而这些约束条件在该方法中也会发生变化。"
  },
  {
    "path": "localization/zh/facade/README.md",
    "content": "---\ntitle: Facade\nshortTitle: Facade\ncategory: Structural\nlanguage: zh\ntag:\n - Gang Of Four\n - Decoupling\n---\n\n## 目的\n为一个子系统中的一系列接口提供一个统一的接口。外观定义了一个更高级别的接口以便子系统更容易使用。\n\n## 解释\n\n真实世界的例子\n\n> 一个金矿是怎么工作的？“嗯，矿工下去然后挖金子！”你说。这是你所相信的因为你在使用一个金矿对外提供的一个简单接口，在内部它要却要做很多事情。这个简单的接口对复杂的子系统来说就是一个外观。\n\n用通俗的话说\n\n> 外观模式为一个复杂的子系统提供一个简单的接口。\n\n维基百科说\n\n> 外观是为很大体量的代码（比如类库）提供简单接口的一种对象。\n\n**程序示例**\n\n使用上面金矿的例子。这里我们有矮人的矿工等级制度。\n\n```java\n\n@Slf4j\npublic abstract class DwarvenMineWorker {\n\n    public void goToSleep() {\n        LOGGER.info(\"{} goes to sleep.\", name());\n    }\n\n    public void wakeUp() {\n        LOGGER.info(\"{} wakes up.\", name());\n    }\n\n    public void goHome() {\n        LOGGER.info(\"{} goes home.\", name());\n    }\n\n    public void goToMine() {\n        LOGGER.info(\"{} goes to the mine.\", name());\n    }\n\n    private void action(Action action) {\n        switch (action) {\n            case GO_TO_SLEEP -> goToSleep();\n            case WAKE_UP -> wakeUp();\n            case GO_HOME -> goHome();\n            case GO_TO_MINE -> goToMine();\n            case WORK -> work();\n            default -> LOGGER.info(\"Undefined action\");\n        }\n    }\n\n    public void action(Action... actions) {\n        Arrays.stream(actions).forEach(this::action);\n    }\n\n    public abstract void work();\n\n    public abstract String name();\n\n    enum Action {\n        GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK\n    }\n}\n\n@Slf4j\npublic class DwarvenTunnelDigger extends DwarvenMineWorker {\n\n    @Override\n    public void work() {\n        LOGGER.info(\"{} creates another promising tunnel.\", name());\n    }\n\n    @Override\n    public String name() {\n        return \"Dwarven tunnel digger\";\n    }\n}\n\n@Slf4j\npublic class DwarvenGoldDigger extends DwarvenMineWorker {\n\n    @Override\n    public void work() {\n        LOGGER.info(\"{} digs for gold.\", name());\n    }\n\n    @Override\n    public String name() {\n        return \"Dwarf gold digger\";\n    }\n}\n\n@Slf4j\npublic class DwarvenCartOperator extends DwarvenMineWorker {\n\n    @Override\n    public void work() {\n        LOGGER.info(\"{} moves gold chunks out of the mine.\", name());\n    }\n\n    @Override\n    public String name() {\n        return \"Dwarf cart operator\";\n    }\n}\n\n```\n\n为了操纵所有这些矿工我们有了这个外观\n\n```java\npublic class DwarvenGoldmineFacade {\n\n  private final List<DwarvenMineWorker> workers;\n\n  public DwarvenGoldmineFacade() {\n      workers = List.of(\n            new DwarvenGoldDigger(),\n            new DwarvenCartOperator(),\n            new DwarvenTunnelDigger());\n  }\n\n  public void startNewDay() {\n    makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE);\n  }\n\n  public void digOutGold() {\n    makeActions(workers, DwarvenMineWorker.Action.WORK);\n  }\n\n  public void endDay() {\n    makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);\n  }\n\n  private static void makeActions(Collection<DwarvenMineWorker> workers,\n      DwarvenMineWorker.Action... actions) {\n    workers.forEach(worker -> worker.action(actions));\n  }\n}\n```\n\n现在来使用外观\n\n```java\nDwarvenGoldmineFacade facade = new DwarvenGoldmineFacade();\nfacade.startNewDay();\n// Dwarf gold digger wakes up.\n// Dwarf gold digger goes to the mine.\n// Dwarf cart operator wakes up.\n// Dwarf cart operator goes to the mine.\n// Dwarven tunnel digger wakes up.\n// Dwarven tunnel digger goes to the mine.\nfacade.digOutGold();\n// Dwarf gold digger digs for gold.\n// Dwarf cart operator moves gold chunks out of the mine.\n// Dwarven tunnel digger creates another promising tunnel.\nfacade.endDay();\n// Dwarf gold digger goes home.\n// Dwarf gold digger goes to sleep.\n// Dwarf cart operator goes home.\n// Dwarf cart operator goes to sleep.\n// Dwarven tunnel digger goes home.\n// Dwarven tunnel digger goes to sleep.\n```\n\n## 类图\n![alt text](./etc/facade.urm.png \"Facade pattern class diagram\")\n\n## 适用性\n使用外观模式当\n\n* 你想为一个复杂的子系统提供一个简单的接口。随着子系统的发展，它们通常会变得更加复杂。多数模式在应用时会导致更多和更少的类。这使子系统更可重用，更易于自定义，但是对于不需要自定义它的客户来说，使用它也变得更加困难。 外观可以提供子系统的简单默认视图，足以满足大多数客户端的需求。只有需要更多可定制性的客户才需要查看外观外的东西（原子系统提供的接口）。\n* 客户端与抽象的实现类之间存在许多依赖关系。 引入外观以使子系统与客户端和其他子系统分离，从而提高子系统的独立性和可移植性。\n* 您想对子系统进行分层。 使用外观来定义每个子系统级别的入口点。 如果子系统是相关的，则可以通过使子系统仅通过其外观相互通信来简化它们之间的依赖性。\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/zh/factory/README.md",
    "content": "---\ntitle: Factory\nshortTitle: Factory\ncategory: Creational\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 也被称为\n\n* 简单工厂\n* 静态工厂方法\n\n## 含义\n\n在工厂类中提供一个封装的静态工厂方法，用于隐藏对象初始化细节，使客户端代码可以专注于使用，而不用关心类的初始化过程。\n\n## 解释\n\n现实例子\n\n>\n> 假设我们有一个需要连接到 SQL Server 的 Web 应用，但现在我们需要切换到连接 Oracle。为了不修改现有代码的情况下做到这一点，我们需要实现简单工厂模式。在这种模式下，可以通过调用一个静态方法来创建与给定数据库的连接。\n\n维基百科\n\n> 工厂类是一个用于创建其他对象的对象 -- 从形式上看，工厂方法是一个用于返回不同原型或类型的函数或方法。\n\n**编程示例**\n\n我们有一个  `Car` 接口，以及实现类 `Ford`, `Ferrari`。\n\n```java\npublic interface Car {\n  String getDescription();\n}\n\npublic class Ford implements Car {\n\n  static final String DESCRIPTION = \"This is Ford.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n\npublic class Ferrari implements Car {\n   \n  static final String DESCRIPTION = \"This is Ferrari.\";\n\n  @Override\n  public String getDescription() {\n    return DESCRIPTION;\n  }\n}\n```\n\nEnumeration above represents types of cars that we support (`Ford` and `Ferrari`).\n\n以下的枚举用于表示支持的 `Car` 类型（`Ford` 和 `Ferrari`）\n\n```java\npublic enum CarType {\n  \n  FORD(Ford::new), \n  FERRARI(Ferrari::new);\n  \n  private final Supplier<Car> constructor; \n  \n  CarType(Supplier<Car> constructor) {\n    this.constructor = constructor;\n  }\n  \n  public Supplier<Car> getConstructor() {\n    return this.constructor;\n  }\n}\n```\n接着我们实现了一个静态方法  `getCar` 用于封装工厂类 `CarsFactory`  创建 `Car` 具体对象实例的细节。\n\n```java\npublic class CarsFactory {\n  \n  public static Car getCar(CarType type) {\n    return type.getConstructor().get();\n  }\n}\n```\n\n现在我们可以在客户端代码中通过工厂类创建不同类型的 `Car` 对象实例。\n\n```java\nvar car1 = CarsFactory.getCar(CarType.FORD);\nvar car2 = CarsFactory.getCar(CarType.FERRARI);\nLOGGER.info(car1.getDescription());\nLOGGER.info(car2.getDescription());\n```\n\n程序输出：\n\n```java\nThis is Ford.\nThis is Ferrari.\n```\n\n## 类图\n\n![alt text](./etc/factory.urm.png \"Factory pattern class diagram\")\n\n## 适用场景\n\n在你只关心对象的创建，但不关心如何创建、管理它的时候，请使用简单工厂模式。\n\n**优点**\n\n* 可以把对象创建代码集中在一个地方，避免在代码库存散布 \"new\" 关键字。\n* 可以让代码更加低耦合。它的一些主要优点包括更好的可测试性、更好的可读性、组件可替换性、可拓展性、更好的隔离性。\n\n**缺点**\n\n* 会使代码变得比原来的更加复杂一些。\n\n## 现实案例\n\n* [java.util.Calendar#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)\n* [java.util.ResourceBundle#getBundle()](https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)\n* [java.text.NumberFormat#getInstance()](https://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)\n* [java.nio.charset.Charset#forName()](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)\n* [java.net.URLStreamHandlerFactory#createURLStreamHandler(String)](https://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html) (Returns different singleton objects, depending on a protocol)\n* [java.util.EnumSet#of()](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of(E))\n* [javax.xml.bind.JAXBContext#createMarshaller()](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--) and other similar methods.\n\n## 相关模式\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/)\n* [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/)\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/)\n\n"
  },
  {
    "path": "localization/zh/factory-kit/README.md",
    "content": "---\ntitle: Factory Kit\nshortTitle: Factory Kit\ncategory: Creational\nlanguage: zh\ntag:\n - Extensibility\n---\n\n## 含义\n使用分离的构建器和工厂接口来定义一个不可变内容的工厂。\n\n## 类图\n![alt text](./etc/factory-kit.png \"Factory Kit\")\n\n## 适用场景\n工厂套件模式适用于与以下场景：\n\n* 一个类无法预知它需要创建的对象的类别\n- 你只是想要一个新的自定义构建器(builder)的实例，而非全局的构建器\n- 你明确地想要定义对象的类型，而且工厂可以创建这些对象\n- 你想要分离构建器(builder)和创建器(creator)接口\n\n## 引用\n\n* [Design Pattern Reloaded by Remi Forax: ](https://www.youtube.com/watch?v=-k2X7guaArU)"
  },
  {
    "path": "localization/zh/factory-method/README.md",
    "content": "---\ntitle: Factory Method\nshortTitle: Factory Method\ncategory: Creational\nlanguage: zh\ntag:\n - Extensibility\n - Gang Of Four\n---\n\n## Also known as\n# 或称\n\n虚拟构造器\n\n## 目的\n为创建一个对象定义一个接口，但是让子类决定实例化哪个类。工厂方法允许类将实例化延迟到子类。\n\n## 解释\n真实世界例子\n\n> 铁匠生产武器。精灵需要精灵武器，而兽人需要兽人武器。根据客户来召唤正确类型的铁匠。\n\n通俗的说\n\n> 它为类提供了一种把实例化的逻辑委托给子类的方式。\n\n维基百科上说\n\n> 在基于类的编程中，工厂方法模式是一种创建型设计模式用来解决创建对象的问题，而不需要指定将要创建对象的确切类。这是通过调用工厂方法创建对象来完成的，而不是通过调用构造器。该工厂方法在接口中指定并由子类实现，或者在基类实现并可以选择由子类重写。\n\n **程序示例**\n\n以上面的铁匠为例，首先我们有铁匠的接口和一些它的实现。\n\n```java\npublic interface Blacksmith {\n  Weapon manufactureWeapon(WeaponType weaponType);\n}\n\npublic class ElfBlacksmith implements Blacksmith {\n  public Weapon manufactureWeapon(WeaponType weaponType) {\n    return ELFARSENAL.get(weaponType);\n  }\n}\n\npublic class OrcBlacksmith implements Blacksmith {\n  public Weapon manufactureWeapon(WeaponType weaponType) {\n    return ORCARSENAL.get(weaponType);\n  }\n}\n```\n\n现在随着客户的到来，会召唤出正确类型的铁匠并制造出要求的武器。\n\n```java\nvar blacksmith = new ElfBlacksmith();\nblacksmith.manufactureWeapon(WeaponType.SPEAR);\nblacksmith.manufactureWeapon(WeaponType.AXE);\n// Elvish weapons are created\n```\n\n## 类图\n![alt text](./etc/factory-method.urm.png \"Factory Method pattern class diagram\")\n\n## 适用性\n使用工厂方法模式当\n\n* 一个类无法预料它所要必须创建的对象的类\n* 一个类想要它的子类来指定它要创建的对象\n* 类将责任委派给几个帮助子类中的一个，而你想定位了解是具体之中的哪一个\n\n## Java中的例子\n\n* [java.util.Calendar](http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)\n* [java.util.ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)\n* [java.text.NumberFormat](http://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)\n* [java.nio.charset.Charset](http://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)\n* [java.net.URLStreamHandlerFactory](http://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html#createURLStreamHandler-java.lang.String-)\n* [java.util.EnumSet](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of-E-)\n* [javax.xml.bind.JAXBContext](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/zh/interpreter/README.md",
    "content": "---\ntitle: Interpreter\nshortTitle: Interpreter\ncategory: Behavioral\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 目的\n给定一种语言，请定义其语法的表示形式，以及使用该表示形式来解释该语言中的句子的解释器。\n\n## 类图\n![alt text](./etc/interpreter_1.png \"Interpreter\")\n\n## 适用性\n有一种要解释的语言时，请使用解释器模式，并且可以将语言中的语句表示为抽象语法树。解释器模式在以下情况下效果最佳\n\n* 语法很简单。 对于复杂的语法，语法的类层次结构变得庞大且难以管理。 在这种情况下，解析器生成器之类的工具是更好的选择。 他们可以在不构建抽象语法树的情况下解释表达式，这可以节省空间并可能节省时间\n* 效率不是关键问题。 通常，最有效的解释器不是通过直接解释解析树来实现的，而是先将其转换为另一种形式。 例如，正则表达式通常会转换为状态机。 但是即使这样，翻译器也可以通过解释器模式实现，因此该模式仍然适用。\n\n## 真实世界例子\n\n* [java.util.Pattern](http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html)\n* [java.text.Normalizer](http://docs.oracle.com/javase/8/docs/api/java/text/Normalizer.html)\n* All subclasses of [java.text.Format](http://docs.oracle.com/javase/8/docs/api/java/text/Format.html)\n* [javax.el.ELResolver](http://docs.oracle.com/javaee/7/api/javax/el/ELResolver.html)\n\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/zh/iterator/README.md",
    "content": "---\ntitle: Iterator\nshortTitle: Iterator\ncategory: Behavioral\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 又被称为\n游标\n\n## 目的\n提供一种在不暴露其基础表示的情况下顺序访问聚合对象的元素的方法。\n\n## 解释\n\n真实世界例子\n\n> 百宝箱包含一组魔法物品。有多种物品，例如戒指，药水和武器。可以使用藏宝箱提供的迭代器按类型浏览商品。\n\n通俗地说\n\n> 容器可以提供与表示形式无关的迭代器接口，以提供对元素的访问。\n\n维基百科说\n\n> 在面向对象的编程中，迭代器模式是一种设计模式，其中迭代器用于遍历容器并访问容器的元素。\n\n**程序示例**\n\n在我们的示例中包含物品的藏宝箱是主要类。\n\n```java\npublic class TreasureChest {\n\n  private final List<Item> items;\n\n  public TreasureChest() {\n    items = List.of(\n        new Item(ItemType.POTION, \"Potion of courage\"),\n        new Item(ItemType.RING, \"Ring of shadows\"),\n        new Item(ItemType.POTION, \"Potion of wisdom\"),\n        new Item(ItemType.POTION, \"Potion of blood\"),\n        new Item(ItemType.WEAPON, \"Sword of silver +1\"),\n        new Item(ItemType.POTION, \"Potion of rust\"),\n        new Item(ItemType.POTION, \"Potion of healing\"),\n        new Item(ItemType.RING, \"Ring of armor\"),\n        new Item(ItemType.WEAPON, \"Steel halberd\"),\n        new Item(ItemType.WEAPON, \"Dagger of poison\"));\n  }\n\n  public Iterator<Item> iterator(ItemType itemType) {\n    return new TreasureChestItemIterator(this, itemType);\n  }\n\n  public List<Item> getItems() {\n    return new ArrayList<>(items);\n  }\n}\n\npublic class Item {\n\n  private ItemType type;\n  private final String name;\n\n  public Item(ItemType type, String name) {\n    this.setType(type);\n    this.name = name;\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n\n  public ItemType getType() {\n    return type;\n  }\n\n  public final void setType(ItemType type) {\n    this.type = type;\n  }\n}\n\npublic enum ItemType {\n\n  ANY, WEAPON, RING, POTION\n\n}\n```\n\n迭代器接口极度简单。\n\n```java\npublic interface Iterator<T> {\n\n  boolean hasNext();\n\n  T next();\n}\n```\n\n在以下示例中，我们遍历在宝箱中找到的戒指类型物品。\n\n```java\nvar itemIterator = TREASURE_CHEST.iterator(ItemType.RING);\nwhile (itemIterator.hasNext()) {\n  LOGGER.info(itemIterator.next().toString());\n}\n// Ring of shadows\n// Ring of armor\n```\n\n## 类图\n![alt text](./etc/iterator_1.png \"Iterator\")\n\n## 适用性\n以下情况使用迭代器模式\n\n* 在不暴露其内部表示的情况下访问聚合对象的内容\n* 为了支持聚合对象的多种遍历方式\n* 提供一个遍历不同聚合结构的统一接口\n\n## Java世界例子\n\n* [java.util.Iterator](http://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html)\n* [java.util.Enumeration](http://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/zh/monitor/README.md",
    "content": "---\ntitle: Monitor\nshortTitle: Monitor\ncategory: Concurrency\nlanguage: zh\ntag:\n - Performance\n---\n\n## 或称\n\n监控对象模式\n\n## 目的\n\n主要目的是为多个线程或进程提供一种结构化和受控的方式来安全地访问和操作共享资源，例如变量、数据结构或代码的关键部分，而不会导致冲突或竞争条件。\n\n## 解释\n\n通俗的说\n\n> 监视器模式用于强制对数据进行单线程访问。 一次只允许一个线程在监视器对象内执行代码。\n\n维基百科说\n\n> 在并发编程（也称为并行编程）中，监视器是一种同步构造，它允许线程具有互斥性和等待（阻止）特定条件变为假的能力。 监视器还具有向其他线程发出信号通知其条件已满足的机制。\n\n**程序示例**\n\n考虑有一家银行通过转账方式将钱从一个帐户转移到另一个帐户。 它是`同步`意味着只有一个线程可以访问此方法，因为如果许多线程访问它并在同一时间将资金从一个帐户转移到另一个帐户，则余额会发生变化！\n \n```\nclass Bank {\n\n     private int[] accounts;\n     Logger logger;\n \n     public Bank(int accountNum, int baseAmount, Logger logger) {\n         this.logger = logger;\n         accounts = new int[accountNum];\n         Arrays.fill(accounts, baseAmount);\n     }\n \n     public synchronized void transfer(int accountA, int accountB, int amount) {\n         if (accounts[accountA] >= amount) {\n             accounts[accountB] += amount;\n             accounts[accountA] -= amount;\n             logger.info(\"Transferred from account :\" + accountA + \" to account :\" + accountB + \" , amount :\" + amount + \" . balance :\" + getBalance());\n         }\n     }\n```\n\ngetBalance 始终返回总金额，并且每次转账后总金额应相同\n\n```\n     private synchronized int getBalance() {\n         int balance = 0;\n         for (int account : accounts) {\n             balance += account;\n         }\n         return balance;\n     }\n }\n```\n\n## 类图\n![alt text](./etc/monitor.urm.png \"Monitor class diagram\")\n\n## 适用性\n\n监视器设计模式应该用于具有需要由多个线程或进程同时访问和操作的共享资源的情况。 此模式在需要同步以防止竞争条件、数据损坏和不一致状态的情况下特别有用。 以下是您应该考虑使用监视器模式的一些情况：\n\n1. **共享数据**：当您的应用程序涉及需要由多个线程访问和更新的共享数据结构、变量或资源时。 监视器确保一次只有一个线程可以访问共享资源，从而防止冲突并确保数据一致性。\n\n2. **关键部分**：当您有代码的关键部分一次只需要由一个线程执行时。 关键部分是操作共享资源的代码部分，并发访问可能会导致问题。 监视器有助于确保在任何给定时间只有一个线程可以执行关键部分。\n\n3. **线程安全**：当您需要确保线程安全而不是仅仅依赖锁和信号量等低级同步机制时。 监视器提供了封装同步和资源管理的更高级别的抽象。\n\n4. **等待和发信号**：当您遇到线程需要等待满足某些条件才能继续操作时。 监视器通常包含线程等待特定条件以及其他线程在满足条件时通知它们的机制。\n\n5. **死锁预防**：当您希望通过提供结构化方式来获取和释放共享资源上的锁来防止死锁时。 监视器通过确保资源访问得到良好管理来帮助避免常见的死锁情况。\n\n6. **并发数据结构**：当您实现并发数据结构（例如队列、堆栈或哈希表）时，多个线程需要操作该结构，同时保持其完整性。\n\n7. **资源共享**：当多个线程需要共享有限的资源时，例如连接数据库或访问网络套接字。 监视器可以帮助以受控方式管理这些资源的分配和释放。\n\n8. **改进可维护性**：当您想要将同步逻辑和共享资源管理封装在单个对象中时，改进代码组织并使并发相关代码更容易推理。\n\n但是，需要注意的是，监视器模式可能并不最适合所有并发场景。 在某些情况下，其他同步机制（例如锁、信号量或并发数据结构）可能更合适。 此外，现代编程语言和框架通常提供更高级别的并发结构，抽象出低级别同步的复杂性。\n\n在应用监视器模式之前，建议彻底分析应用程序的并发需求，并选择最适合您需求的同步方法，同时考虑性能、复杂性和可用语言功能等因素。\n\n## 相关模式\n\n* Active object\n* Double-checked locking\n"
  },
  {
    "path": "localization/zh/observer/README.md",
    "content": "---\ntitle: Observer\nshortTitle: Observer\ncategory: Behavioral\nlanguage: zh\ntag:\n - Gang Of Four\n - Reactive\n---\n\n## Also known as\n## 又被称为\n\n家属，发布订阅模式\n\n## 目的\n\n定义一种一对多的对象依赖关系这样当一个对象改变状态时，所有依赖它的对象都将自动通知或更新。\n\n## 解释\n\n真实世界例子\n\n> 在遥远的土地上生活着霍比特人和兽人的种族。他们都是户外生活的人所以他们密切关注天气的变化。可以说他们不断地关注着天气。\n\n通俗的说\n\n> 注册成为一个观察者以接收对象状态的改变。\n\n维基百科说\n\n> 观察者模式是这样的一种软件设计模式：它有一个被称为主题的对象，维护着一个所有依赖于它的依赖者清单，也就是观察者清单，当主题的状态发生改变时，主题通常会调用观察者的方法来自动通知观察者们。\n\n**编程示例**\n\n让我们先来介绍天气观察者的接口以及我们的种族，兽人和霍比特人。\n\n```java\npublic interface WeatherObserver {\n\n  void update(WeatherType currentWeather);\n}\n\n@Slf4j\npublic class Orcs implements WeatherObserver {\n\n  @Override\n  public void update(WeatherType currentWeather) {\n    LOGGER.info(\"The orcs are facing \" + currentWeather.getDescription() + \" weather now\");\n  }\n}\n\n@Slf4j\npublic class Hobbits implements WeatherObserver {\n\n  @Override\n  public void update(WeatherType currentWeather) {\n    switch (currentWeather) {\n      LOGGER.info(\"The hobbits are facing \" + currentWeather.getDescription() + \" weather now\");\n  }\n}\n```\n\n然后这里是不断变化的天气。\n\n```java\n@Slf4j\npublic class Weather {\n\n  private WeatherType currentWeather;\n  private final List<WeatherObserver> observers;\n\n  public Weather() {\n    observers = new ArrayList<>();\n    currentWeather = WeatherType.SUNNY;\n  }\n\n  public void addObserver(WeatherObserver obs) {\n    observers.add(obs);\n  }\n\n  public void removeObserver(WeatherObserver obs) {\n    observers.remove(obs);\n  }\n\n  /**\n   * Makes time pass for weather.\n   */\n  public void timePasses() {\n    var enumValues = WeatherType.values();\n    currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length];\n    LOGGER.info(\"The weather changed to {}.\", currentWeather);\n    notifyObservers();\n  }\n\n  private void notifyObservers() {\n    for (var obs : observers) {\n      obs.update(currentWeather);\n    }\n  }\n}\n```\n\n这是完整的示例。\n\n```java\n    var weather = new Weather();\n    weather.addObserver(new Orcs());\n    weather.addObserver(new Hobbits());\n\n    weather.timePasses();\n    // The weather changed to rainy.\n    // The orcs are facing rainy weather now\n    // The hobbits are facing rainy weather now\n    weather.timePasses();\n    // The weather changed to windy.\n    // The orcs are facing windy weather now\n    // The hobbits are facing windy weather now\n    weather.timePasses();\n    // The weather changed to cold.\n    // The orcs are facing cold weather now\n    // The hobbits are facing cold weather now\n    weather.timePasses();\n    // The weather changed to sunny.\n    // The orcs are facing sunny weather now\n    // The hobbits are facing sunny weather now\n```\n\n## Class diagram\n![alt text](./etc/observer.png \"Observer\")\n\n## 应用\n在下面任何一种情况下都可以使用观察者模式\n\n* 当抽象具有两个方面时，一个方面依赖于另一个方面。将这些方面封装在单独的对象中，可以使你分别进行更改和重用\n* 当一个对象的改变的同时需要改变其他对象，同时你又不知道有多少对象需要改变时\n* 当一个对象可以通知其他对象而无需假设这些对象是谁时。换句话说，你不想让这些对象紧耦合。\n\n## 典型用例\n\n* 一个对象的改变导致其他对象的改变\n\n## Java中的例子\n\n* [java.util.Observer](http://docs.oracle.com/javase/8/docs/api/java/util/Observer.html)\n* [java.util.EventListener](http://docs.oracle.com/javase/8/docs/api/java/util/EventListener.html)\n* [javax.servlet.http.HttpSessionBindingListener](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionBindingListener.html)\n* [RxJava](https://github.com/ReactiveX/RxJava)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Java Generics and Collections](https://www.amazon.com/gp/product/0596527756/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596527756&linkCode=as2&tag=javadesignpat-20&linkId=246e5e2c26fe1c3ada6a70b15afcb195)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/zh/private-class-data/README.md",
    "content": "---\ntitle: Private Class Data\nshortTitle: Private Class Data\ncategory: Idiom\nlanguage: zh\ntag:\n - Data access\n---\n\n## 目的\n\n私有类数据设计模式试图通过限制属性的可见性来减少属性的暴露。 通过将它们封装在单个Data对象中，可以减少类属性的数量。\n\n## 解释\n\n真实世界例子\n\n> 想象一下你在为家人做晚餐炖汤。你想阻止家庭成员在你烹饪时偷偷品尝菜品，否则后面可能东西不够吃了。\n\n通俗的说\n\n> 私有类数据模式通过将数据与使用它的方法分离到维护数据状态的类中，从而防止了对不可变数据的操纵。\n\n维基百科说\n\n> 私有类数据是计算机编程中的一种设计模式，用于封装类属性及其操作。\n\n**程序示例**\n\n使用上面炖汤的例子。 首先我们有 `炖汤`类 ，它的属性没有被私有类数据保护，从而使炖菜的成分对类方法易变。\n\n```java\npublic class Stew {\n  private static final Logger LOGGER = LoggerFactory.getLogger(Stew.class);\n  private int numPotatoes;\n  private int numCarrots;\n  private int numMeat;\n  private int numPeppers;\n  public Stew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) {\n    this.numPotatoes = numPotatoes;\n    this.numCarrots = numCarrots;\n    this.numMeat = numMeat;\n    this.numPeppers = numPeppers;\n  }\n  public void mix() {\n    LOGGER.info(\"Mixing the stew we find: {} potatoes, {} carrots, {} meat and {} peppers\",\n        numPotatoes, numCarrots, numMeat, numPeppers);\n  }\n  public void taste() {\n    LOGGER.info(\"Tasting the stew\");\n    if (numPotatoes > 0) {\n      numPotatoes--;\n    }\n    if (numCarrots > 0) {\n      numCarrots--;\n    }\n    if (numMeat > 0) {\n      numMeat--;\n    }\n    if (numPeppers > 0) {\n      numPeppers--;\n    }\n  }\n}\n```\n\n现在，我们有了` ImmutableStew`类，其中的数据受`StewData`类保护。 现在，其中的方法无法处理`ImmutableStew`类的数据。\n\n```java\npublic class StewData {\n  private final int numPotatoes;\n  private final int numCarrots;\n  private final int numMeat;\n  private final int numPeppers;\n  public StewData(int numPotatoes, int numCarrots, int numMeat, int numPeppers) {\n    this.numPotatoes = numPotatoes;\n    this.numCarrots = numCarrots;\n    this.numMeat = numMeat;\n    this.numPeppers = numPeppers;\n  }\n  public int getNumPotatoes() {\n    return numPotatoes;\n  }\n  public int getNumCarrots() {\n    return numCarrots;\n  }\n  public int getNumMeat() {\n    return numMeat;\n  }\n  public int getNumPeppers() {\n    return numPeppers;\n  }\n}\npublic class ImmutableStew {\n  private static final Logger LOGGER = LoggerFactory.getLogger(ImmutableStew.class);\n  private final StewData data;\n  public ImmutableStew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) {\n    data = new StewData(numPotatoes, numCarrots, numMeat, numPeppers);\n  }\n  public void mix() {\n    LOGGER\n        .info(\"Mixing the immutable stew we find: {} potatoes, {} carrots, {} meat and {} peppers\",\n            data.getNumPotatoes(), data.getNumCarrots(), data.getNumMeat(), data.getNumPeppers());\n  }\n}\n```\n\n让我们尝试创建每个类的实例并调用其方法：\n\n```java\nvar stew = new Stew(1, 2, 3, 4);\nstew.mix();   // Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers\nstew.taste(); // Tasting the stew\nstew.mix();   // Mixing the stew we find: 0 potatoes, 1 carrots, 2 meat and 3 peppers\nvar immutableStew = new ImmutableStew(2, 4, 3, 6);\nimmutableStew.mix();  // Mixing the immutable stew we find: 2 potatoes, 4 carrots, 3 meat and 6 peppers\n```\n\n## 类图\n\n![alt text](./etc/private-class-data.png \"Private Class Data\")\n\n## 适用性\n\n在以下情况下使用私有类数据模式\n\n* 您要阻止对类数据成员的写访问。\n"
  },
  {
    "path": "localization/zh/producer-consumer/README.md",
    "content": "---\ntitle: Producer Consumer\nshortTitle: Producer Consumer\ncategory: Concurrency\nlanguage: zh\ntag:\n - Reactive\n---\n\n## 目的\n生产者消费者设计模式是一种经典的并发模式，通过将工作与执行工作任务分开来减少生产者与消费者之间的耦合。\n\n## 类图\n![alt text](./etc/producer-consumer.png \"Producer Consumer\")\n\n## 适用性\n在以下情况下使用生产者消费者\n\n* 通过将工作分成生产和消费两个工作进程来解耦系统\n* 解决生产工作和消费工作需要不同时间的问题\n"
  },
  {
    "path": "localization/zh/proxy/README.md",
    "content": "---\ntitle: Proxy\nshortTitle: Proxy\ncategory: Structural\nlanguage: zh\ntag:\n - Gang Of Four\n - Decoupling\n---\n\n## 又被称为\n\n替代（代孕）模式\n\n## 目的\n\n为另一个对象提供代理或占位符以控制对其的访问。\n\n## 解释\n\n真实世界例子\n\n> 想象有一个塔，当地的巫师去那里学习他们的法术。象牙塔只能够通过代理来进入以此来保证只有首先3个巫师才能进入。这里的代理就代表的塔的功能并添加访问控制。\n\n通俗的说\n\n> 使用代理模式，一个类代表另一个类的功能。\n\n维基百科说\n\n> 在最一般的形式上，代理是一个类，它充当与其他对象的接口。代理是客户端调用的包装器或代理对象，以访问后台的实际服务对象。代理本身可以简单地转发到真实对象，也可以提供其他逻辑。在代理中，可以提供额外的功能，例如在对实对象的操作占用大量资源时进行缓存，或者在对实对象的操作被调用之前检查前提条件。\n\n**程序示例**\n\n使用上面的巫师塔为例。首先我们有**巫师塔**接口和**象牙塔**类 。\n\n```java\npublic interface WizardTower {\n\n  void enter(Wizard wizard);\n}\n\npublic class IvoryTower implements WizardTower {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(IvoryTower.class);\n\n  public void enter(Wizard wizard) {\n    LOGGER.info(\"{} enters the tower.\", wizard);\n  }\n\n}\n```\n\n然后有个简单的巫师类。\n\n```java\npublic class Wizard {\n\n  private final String name;\n\n  public Wizard(String name) {\n    this.name = name;\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n}\n```\n\n然后我们有巫师塔代理类为巫师塔添加访问控制。\n\n```java\npublic class WizardTowerProxy implements WizardTower {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(WizardTowerProxy.class);\n\n  private static final int NUM_WIZARDS_ALLOWED = 3;\n\n  private int numWizards;\n\n  private final WizardTower tower;\n\n  public WizardTowerProxy(WizardTower tower) {\n    this.tower = tower;\n  }\n\n  @Override\n  public void enter(Wizard wizard) {\n    if (numWizards < NUM_WIZARDS_ALLOWED) {\n      tower.enter(wizard);\n      numWizards++;\n    } else {\n      LOGGER.info(\"{} is not allowed to enter!\", wizard);\n    }\n  }\n}\n```\n\n然后这是进入塔的场景。\n\n```java\nvar proxy = new WizardTowerProxy(new IvoryTower());\nproxy.enter(new Wizard(\"Red wizard\"));\nproxy.enter(new Wizard(\"White wizard\"));\nproxy.enter(new Wizard(\"Black wizard\"));\nproxy.enter(new Wizard(\"Green wizard\"));\nproxy.enter(new Wizard(\"Brown wizard\"));\n```\n\n程序输出：\n\n```\nRed wizard enters the tower.\nWhite wizard enters the tower.\nBlack wizard enters the tower.\nGreen wizard is not allowed to enter!\nBrown wizard is not allowed to enter!\n```\n\n## 类图\n\n![alt text](./etc/proxy.urm.png \"Proxy pattern class diagram\")\n\n## 适用性\n\n代理适用于需要比简单指针更广泛或更复杂的对象引用的情况。这是代理模式适用的几种常见情况。\n\n* 远程代理为不同地址空间中的对象提供了本地代表。\n* 虚拟代理根据需要创建昂贵的对象。\n* 保护代理控制对原始对象的访问。当对象有不同的接入权限时保护代理很有用。\n\n## 典型用例\n\n* 对象的访问控制\n* 懒加载\n* 实现日志记录\n* 简化网络连接\n* 对象的访问计数\n\n## 教程\n\n* [Controlling Access With Proxy Pattern](http://java-design-patterns.com/blog/controlling-access-with-proxy-pattern/)\n\n## 已知使用\n\n* [java.lang.reflect.Proxy](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html)\n* [Apache Commons Proxy](https://commons.apache.org/proper/commons-proxy/)\n* Mocking frameworks [Mockito](https://site.mockito.org/), \n[Powermock](https://powermock.github.io/), [EasyMock](https://easymock.org/)\n\n## 相关设计模式\n\n* [Ambassador](https://java-design-patterns.com/patterns/ambassador/)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n"
  },
  {
    "path": "localization/zh/servant/README.md",
    "content": "---\ntitle: Servant\nshortTitle: Servant\ncategory: Behavioral\nlanguage: zh\ntag:\n- Decoupling\n---\n\n## 含义\n仆人类被用于向一组类提供一些行为，区别于在每个类定义行为-或者当我们无法排除\n公共父类中的这种行为，这些行为在仆人类被定义一次\n\n## 解释\n\n现实例子\n\n> 国王、王后和其他宫廷皇室成员需要仆人为他们提供饮食、准备饮料等服务\n\n简单地说\n\n> 确保一个仆人对象为一组被服务的对象提供一些特定的服务\n\n维基百科\n\n> 在软件工程中，仆人模式定义了一个对象，用于向一组类提供某些功能，而无需在每个类中定义该功能。 仆人是一个类，其实例（甚至只是类）提供了处理所需服务的方法，而仆人为其（或与谁）做某事的对象被视为参数。\n\n**编程示例**\n\n那些能够为其他宫廷皇室成员提供服务的仆人类\n\n```java\n/**\n * Servant.\n */\npublic class Servant {\n\n  public String name;\n\n  /**\n   * Constructor.\n   */\n  public Servant(String name) {\n    this.name = name;\n  }\n\n  public void feed(Royalty r) {\n    r.getFed();\n  }\n\n  public void giveWine(Royalty r) {\n    r.getDrink();\n  }\n\n  public void giveCompliments(Royalty r) {\n    r.receiveCompliments();\n  }\n\n  /**\n   * Check if we will be hanged.\n   */\n  public boolean checkIfYouWillBeHanged(List<Royalty> tableGuests) {\n    return tableGuests.stream().allMatch(Royalty::getMood);\n  }\n}\n```\n\n皇家是一个接口，它被国王和女王类实现，以获取仆人的服务\n\n```java\ninterface Royalty {\n\n    void getFed();\n\n    void getDrink();\n\n    void changeMood();\n\n    void receiveCompliments();\n\n    boolean getMood();\n}\n```\n国王类正在实现皇家接口\n```java\npublic class King implements Royalty {\n\n    private boolean isDrunk;\n    private boolean isHungry = true;\n    private boolean isHappy;\n    private boolean complimentReceived;\n\n    @Override\n    public void getFed() {\n        isHungry = false;\n    }\n\n    @Override\n    public void getDrink() {\n        isDrunk = true;\n    }\n\n    public void receiveCompliments() {\n        complimentReceived = true;\n    }\n\n    @Override\n    public void changeMood() {\n        if (!isHungry && isDrunk) {\n            isHappy = true;\n        }\n        if (complimentReceived) {\n            isHappy = false;\n        }\n    }\n\n    @Override\n    public boolean getMood() {\n        return isHappy;\n    }\n}\n```\n女王类正在实现皇家接口\n```java\npublic class Queen implements Royalty {\n\n    private boolean isDrunk = true;\n    private boolean isHungry;\n    private boolean isHappy;\n    private boolean isFlirty = true;\n    private boolean complimentReceived;\n\n    @Override\n    public void getFed() {\n        isHungry = false;\n    }\n\n    @Override\n    public void getDrink() {\n        isDrunk = true;\n    }\n\n    public void receiveCompliments() {\n        complimentReceived = true;\n    }\n\n    @Override\n    public void changeMood() {\n        if (complimentReceived && isFlirty && isDrunk && !isHungry) {\n            isHappy = true;\n        }\n    }\n\n    @Override\n    public boolean getMood() {\n        return isHappy;\n    }\n\n    public void setFlirtiness(boolean f) {\n        this.isFlirty = f;\n    }\n\n}\n```\n\n然后，为了使用:\n\n```java\npublic class App {\n\n    private static final Servant jenkins = new Servant(\"Jenkins\");\n    private static final Servant travis = new Servant(\"Travis\");\n\n    /**\n     * Program entry point.\n     */\n    public static void main(String[] args) {\n        scenario(jenkins, 1);\n        scenario(travis, 0);\n    }\n\n    /**\n     * Can add a List with enum Actions for variable scenarios.\n     */\n    public static void scenario(Servant servant, int compliment) {\n        var k = new King();\n        var q = new Queen();\n\n        var guests = List.of(k, q);\n\n        // feed\n        servant.feed(k);\n        servant.feed(q);\n        // serve drinks\n        servant.giveWine(k);\n        servant.giveWine(q);\n        // compliment\n        servant.giveCompliments(guests.get(compliment));\n\n        // outcome of the night\n        guests.forEach(Royalty::changeMood);\n\n        // check your luck\n        if (servant.checkIfYouWillBeHanged(guests)) {\n            LOGGER.info(\"{} will live another day\", servant.name);\n        } else {\n            LOGGER.info(\"Poor {}. His days are numbered\", servant.name);\n        }\n    }\n}\n```\n\n程序输出\n\n```\nJenkins will live another day\nPoor Travis. His days are numbered\n```\n\n\n## 类图\n![alt text](./etc/servant-pattern.png \"Servant\")\n\n## 适用场景\n在什么时候使用仆人模式\n\n* 当我们希望某些对象执行一个公共操作并且不想将该操作定义为每个类中的方法时\n\n## 鸣谢\n\n* [Let's Modify the Objects-First Approach into Design-Patterns-First](http://edu.pecinovsky.cz/papers/2006_ITiCSE_Design_Patterns_First.pdf)\n"
  },
  {
    "path": "localization/zh/sharding/README.md",
    "content": "---\ntitle: Sharding\nshortTitle: Sharding\ncategory: Behavioral\nlanguage: zh\ntag:  \n - Performance\n - Cloud distributed\n---\n\n## 含义 \n分片模式是指将数据存储划分为水平分区或分片。每个分片都有相同的模式，但持有自己独特的数据子集。\n\n一个分片本身就是一个数据存储（它可以包含许多不同类型的实体的数据），运行在作为存储节点的服务器上。\n\n## 类图\n![alt text](./etc/sharding.urm.png \"Sharding pattern class diagram\")\n\n## 适用场景 \n这种设计模式提供了一下的好处：\n\n- 你可以通过增加在额外的存储节点上，运行的更多分片来实现系统扩容。\n- 系统可以使用现成的廉价硬件，而不是为每个存储节点使用专门（或者昂贵）的服务器硬件。\n- 你可以通过平衡各分片之间的工作负载来减少竞争，以提高性能。\n- 在云环境中，分片可以在物理上靠近访问该节点数据的用户。\n\n## 引用\n\n* [Sharding pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/sharding)"
  },
  {
    "path": "localization/zh/singleton/README.md",
    "content": "---\ntitle: Singleton\nshortTitle: Singleton\ncategory: Creational\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 目的\n\n确保一个类只有一个实例，并为其提供一个全局访问点。\n\n## 解释\n\n情境示例\n\n> 巫师们之在一个象牙塔中学习他们的魔法，并且始终使用同一座附魔的象牙塔。\n> \n> 这里的象牙塔是一个单例对象。\n\n通俗来说\n\n> 对于一个特定的类，确保只会创建一个对象。\n\n维基百科说\n\n> 在软件工程中，单例模式是一种软件设计模式，它将类的实例化限制为一个对象。当系统中只需要一个对象来协调各种操作时，这种模式非常有用。\n\n**程序示例**\n\n详见 Joshua Bloch, Effective Java 2nd Edition p.18。\n\n> 一个只有一个元素的枚举类型是实现单例模式的最佳方式。\n\n```java\npublic enum EnumIvoryTower {\n  INSTANCE\n}\n```\n\n使用：\n\n```java\n    var enumIvoryTower1 = EnumIvoryTower.INSTANCE;\n    var enumIvoryTower2 = EnumIvoryTower.INSTANCE;\n    LOGGER.info(\"enumIvoryTower1={}\", enumIvoryTower1);\n    LOGGER.info(\"enumIvoryTower2={}\", enumIvoryTower2);\n```\n\n控制台输出：\n\n```\nenumIvoryTower1=com.iluwatar.singleton.EnumIvoryTower@1221555852\nenumIvoryTower2=com.iluwatar.singleton.EnumIvoryTower@1221555852\n```\n\n## 类图\n\n![alt text](./etc/singleton.urm.png \"Singleton pattern class diagram\")\n\n## 适用性\n\n当满足以下情况时，使用单例模式：\n\n* 确保一个类只有一个实例，并且客户端能够通过一个众所周知的访问点访问该实例。\n* 唯一的实例能够被子类扩展, 同时客户端不需要修改代码就能使用扩展后的实例。\n\n一些典型的单例模式用例包括：\n\n* logging类\n* 管理与数据库的链接\n* 文件管理器（File manager）\n\n## 已知使用\n\n* [java.lang.Runtime#getRuntime()](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime%28%29)\n* [java.awt.Desktop#getDesktop()](http://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#getDesktop--)\n* [java.lang.System#getSecurityManager()](http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getSecurityManager--)\n\n\n## 影响\n\n* 通过控制实例的创建和生命周期，违反了单一职责原则（SRP）。\n* 鼓励使用全局共享实例，组织了对象及其使用的资源被释放。     \n* 代码变得耦合，给客户端的测试带来难度。\n* 单例模式的设计可能会使得子类化（继承）单例变得几乎不可能\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/zh/state/README.md",
    "content": "---\ntitle: State\nshortTitle: State\ncategory: Behavioral\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 又被称为\n对象状态\n\n## 目的\n允许对象在内部状态改变时改变它的行为。对象看起来好像修改了它的类。\n\n## 解释\n真实世界例子\n\n> 当在长毛象的自然栖息地观察长毛象时，似乎它会根据情况来改变自己的行为。它开始可能很平静但是随着时间推移当它检测到威胁时它会对周围的环境感到愤怒和危险。\n\n通俗的说\n\n> 状态模式允许对象改变它的行为。\n\n维基百科说\n\n> 状态模式是一种允许对象在内部状态改变时改变它的行为的行为型设计模式。这种模式接近于有限状态机的概念。状态模式可以被理解为策略模式，它能够通过调用在模式接口中定义的方法来切换策略。\n\n**编程示例**\n\n这里是模式接口和它具体的实现。\n\n```java\npublic interface State {\n\n  void onEnterState();\n\n  void observe();\n}\n\npublic class PeacefulState implements State {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(PeacefulState.class);\n\n  private final Mammoth mammoth;\n\n  public PeacefulState(Mammoth mammoth) {\n    this.mammoth = mammoth;\n  }\n\n  @Override\n  public void observe() {\n    LOGGER.info(\"{} is calm and peaceful.\", mammoth);\n  }\n\n  @Override\n  public void onEnterState() {\n    LOGGER.info(\"{} calms down.\", mammoth);\n  }\n}\n\npublic class AngryState implements State {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(AngryState.class);\n\n  private final Mammoth mammoth;\n\n  public AngryState(Mammoth mammoth) {\n    this.mammoth = mammoth;\n  }\n\n  @Override\n  public void observe() {\n    LOGGER.info(\"{} is furious!\", mammoth);\n  }\n\n  @Override\n  public void onEnterState() {\n    LOGGER.info(\"{} gets angry!\", mammoth);\n  }\n}\n```\n\n然后这里是包含状态的长毛象。\n\n```java\npublic class Mammoth {\n\n  private State state;\n\n  public Mammoth() {\n    state = new PeacefulState(this);\n  }\n\n  public void timePasses() {\n    if (state.getClass().equals(PeacefulState.class)) {\n      changeStateTo(new AngryState(this));\n    } else {\n      changeStateTo(new PeacefulState(this));\n    }\n  }\n\n  private void changeStateTo(State newState) {\n    this.state = newState;\n    this.state.onEnterState();\n  }\n\n  @Override\n  public String toString() {\n    return \"The mammoth\";\n  }\n\n  public void observe() {\n    this.state.observe();\n  }\n}\n```\n\n然后这里是长毛象随着时间的推移后的整个行为示例。\n\n```java\n    var mammoth = new Mammoth();\n    mammoth.observe();\n    mammoth.timePasses();\n    mammoth.observe();\n    mammoth.timePasses();\n    mammoth.observe();\n    \n    // The mammoth gets angry!\n    // The mammoth is furious!\n    // The mammoth calms down.\n    // The mammoth is calm and peaceful.\n```\n\n## 类图\n![alt text](./etc/state_urm.png \"State\")\n\n## 适用性\n\n在以下两种情况下，请使用State模式\n\n* 对象的行为取决于它的状态，并且它必须在运行时根据状态更改其行为。\n* 根据对象状态的不同，操作有大量的条件语句。此状态通常由一个或多个枚举常量表示。通常，几个操作将包含此相同的条件结构。状态模式把条件语句的分支分别放入单独的类中。这样一来，你就可以将对象的状态视为独立的对象，该对象可以独立于其他对象而变化。\n\n## Java中例子\n\n* [javax.faces.lifecycle.Lifecycle#execute()](http://docs.oracle.com/javaee/7/api/javax/faces/lifecycle/Lifecycle.html#execute-javax.faces.context.FacesContext-) controlled by [FacesServlet](http://docs.oracle.com/javaee/7/api/javax/faces/webapp/FacesServlet.html), the behavior is dependent on current phase of lifecycle.\n* [JDiameter - Diameter State Machine](https://github.com/npathai/jdiameter/blob/master/core/jdiameter/api/src/main/java/org/jdiameter/api/app/State.java)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/zh/step-builder/README.md",
    "content": "---\ntitle: Step Builder\nshortTitle: Step Builder\ncategory: Creational\nlanguage: zn\ntag:\n - Instantiation\n---\n\n## 又被称为\n分步构建\n\n## 目的\n这是构建者模式的一个扩展，完全指导用户创建对象，没有混淆的机会。\n用户体验会大大提升，因为他只能看到下一个步骤的方法，直到适当的时机才会出现构建对象的“build”方法。\n\n## 类图\n![alt text](./etc/step-builder.png \"Step Builder\")\n\n## 应用\n使用分布构建模式当创建复杂对象的算法需要独立于组成对象的部分以及它们的组装方式，且构造过程必须允许对象有不同的表示形式，并且在此过程中顺序很重要时。\n\n## 鸣谢\n\n* [Marco Castigliego - Step Builder](http://rdafbn.blogspot.co.uk/2012/07/step-builder-pattern_28.html)\n"
  },
  {
    "path": "localization/zh/strategy/README.md",
    "content": "---\ntitle: Strategy\nshortTitle: Strategy\ncategory: Behavioral\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 又被称为\n政策（方针）模式\n\n## 目的\n\n定义一个家族算法，并封装好其中每一个，使它们可以互相替换。策略模式使算法的变化独立于使用它的客户。\n\n## 解释\n\n现实世界例子\n\n> 屠龙是一项危险的职业。有经验将会使它变得简单。经验丰富的屠龙者对不同类型的龙有不同的战斗策略。       \n\n直白点说\n\n> 策略模式允许在运行时选择最匹配的算法。\n\n维基百科上说\n\n> 在程序编程领域，策略模式（又叫政策模式）是一种启用在运行时选择算法的行为型软件设计模式。\n\n**编程实例**\n\n让我们先介绍屠龙的策略模式接口和它的实现。\n\n```java\n@FunctionalInterface\npublic interface DragonSlayingStrategy {\n\n  void execute();\n}\n\n@Slf4j\npublic class MeleeStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"With your Excalibur you sever the dragon's head!\");\n  }\n}\n\n@Slf4j\npublic class ProjectileStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"You shoot the dragon with the magical crossbow and it falls dead on the ground!\");\n  }\n}\n\n@Slf4j\npublic class SpellStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\");\n  }\n}\n```\n\n现在有一个强力的屠龙者要基于上面的组件来选择他的战斗策略。\n\n```java\npublic class DragonSlayer {\n\n  private DragonSlayingStrategy strategy;\n\n  public DragonSlayer(DragonSlayingStrategy strategy) {\n    this.strategy = strategy;\n  }\n\n  public void changeStrategy(DragonSlayingStrategy strategy) {\n    this.strategy = strategy;\n  }\n\n  public void goToBattle() {\n    strategy.execute();\n  }\n}\n```\n\n最后是屠龙者的行动。\n\n```java\n    LOGGER.info(\"Green dragon spotted ahead!\");\n    var dragonSlayer = new DragonSlayer(new MeleeStrategy());\n    dragonSlayer.goToBattle();\n    LOGGER.info(\"Red dragon emerges.\");\n    dragonSlayer.changeStrategy(new ProjectileStrategy());\n    dragonSlayer.goToBattle();\n    LOGGER.info(\"Black dragon lands before you.\");\n    dragonSlayer.changeStrategy(new SpellStrategy());\n    dragonSlayer.goToBattle();\n    \n    // Green dragon spotted ahead!\n    // With your Excalibur you sever the dragon's head!\n    // Red dragon emerges.\n    // You shoot the dragon with the magical crossbow and it falls dead on the ground!\n    // Black dragon lands before you.\n    // You cast the spell of disintegration and the dragon vaporizes in a pile of dust!    \n```\n\n## 类图\n![alt text](./etc/strategy_urm.png \"Strategy\")\n\n## 应用\n使用策略模式当\n\n* 许多相关的类只是行为不同。策略模式提供了一种为一种类配置多种行为的能力。\n* 你需要一种算法的不同变体。比如，你可能定义反应不用时间空间权衡的算法。当这些算法的变体使用类的层次结构来实现时就可以使用策略模式。\n* 一个算法使用的数据客户不应该对其知晓。使用策略模式来避免暴露复杂的，特定于算法的数据结构。\n* 一个类定义了许多行为，这些行为在其操作中展现为多个条件语句。移动相关的条件分支到它们分别的策略类中来代替这些条件语句。\n\n## 教学\n\n* [Strategy Pattern Tutorial](https://www.journaldev.com/1754/strategy-design-pattern-in-java-example-tutorial)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/zh/table-module/README.md",
    "content": "---\ntitle: Table Module\nshortTitle: Table Module\ncategory: Structural\nlanguage: zh\ntag:\n - Data access\n---\n\n## 又被称为\n表模块\n\n## Intent\n表模块模式将域逻辑按数据库中的每个表组织为一个类，并且一个类的单个实例包含将对数据执行的各种过程。\n\n## Explanation\n\n现实世界例子\n\n> 当处理一个用户系统时，我们需要在用户表上进行一些操作。在这种情况下，我们可以使用表模块模式。我们可以创建一个名为 UserTableModule 的类，并初始化该类的一个实例，来处理用户表中所有行的业务逻辑。\n\n直白点说\n\n> 一个单独的实例，处理数据库表或视图中所有行的业务逻辑。\n\n**编程实例**\n\n在用户系统的示例中，我们需要处理用户登录和用户注册的域逻辑。我们可以使用表模块模式，并创建UserTableModule类的一个实例来处理用户表中所有行的业务逻辑。\n\n以下是基本的User实体。\n\n```java\n@Setter\n@Getter\n@ToString\n@EqualsAndHashCode\n@AllArgsConstructor\npublic class User {\n  private int id;\n  private String username;\n  private String password;\n}\n```\n\n下面的是 `UserTableModule` 类.\n\n```java\npublic class UserTableModule {\n  private final DataSource dataSource;\n  private Connection connection = null;\n  private ResultSet resultSet = null;\n  private PreparedStatement preparedStatement = null;\n\n  public UserTableModule(final DataSource userDataSource) {\n    this.dataSource = userDataSource;\n  }\n  \n  /**\n   * Login using username and password.\n   *\n   * @param username the username of a user\n   * @param password the password of a user\n   * @return the execution result of the method\n   * @throws SQLException if any error\n   */\n  public int login(final String username, final String password) throws SQLException {\n  \t\t// Method implementation.\n\n  }\n\n  /**\n   * Register a new user.\n   *\n   * @param user a user instance\n   * @return the execution result of the method\n   * @throws SQLException if any error\n   */\n  public int registerUser(final User user) throws SQLException {\n  \t\t// Method implementation.\n  }\n}\n```\n\n在App类中，我们使用UserTableModule的一个实例来处理用户登录和注册。\n\n```java\n// Create data source and create the user table.\nfinal var dataSource = createDataSource();\ncreateSchema(dataSource);\nuserTableModule = new UserTableModule(dataSource);\n\n//Initialize two users.\nvar user1 = new User(1, \"123456\", \"123456\");\nvar user2 = new User(2, \"test\", \"password\");\n\n//Login and register using the instance of userTableModule.\nuserTableModule.registerUser(user1);\nuserTableModule.login(user1.getUsername(), user1.getPassword());\nuserTableModule.login(user2.getUsername(), user2.getPassword());\nuserTableModule.registerUser(user2);\nuserTableModule.login(user2.getUsername(), user2.getPassword());\n\ndeleteSchema(dataSource);\n```\n\n程序输出：\n\n```java\n12:22:13.095 [main] INFO com.iluwatar.tablemodule.UserTableModule - Register successfully!\n12:22:13.117 [main] INFO com.iluwatar.tablemodule.UserTableModule - Login successfully!\n12:22:13.128 [main] INFO com.iluwatar.tablemodule.UserTableModule - Fail to login!\n12:22:13.136 [main] INFO com.iluwatar.tablemodule.UserTableModule - Register successfully!\n12:22:13.144 [main] INFO com.iluwatar.tablemodule.UserTableModule - Login successfully!\n```\n\n## 类图\n\n![](etc/table-module.urm.png \"table module\")\n\n## 应用\n使用表模块模式当：\n\n- 域逻辑简单且数据呈表格形式。\n- 应用程序仅使用少量共享的常见的面向表格的数据结构。\n\n## 教学\n\n- [Transaction Script](https://java-design-patterns.com/patterns/transaction-script/)\n\n- [Domain Model](https://java-design-patterns.com/patterns/domain-model/)\n\n## 鸣谢\n\n* [Table Module Pattern](http://wiki3.cosc.canterbury.ac.nz/index.php/Table_module_pattern)\n* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0321127420&linkId=18acc13ba60d66690009505577c45c04)\n* [Architecture patterns: domain model and friends](https://inviqa.com/blog/architecture-patterns-domain-model-and-friends)"
  },
  {
    "path": "localization/zh/template-method/README.md",
    "content": "---\ntitle: Template method\nshortTitle: Template method\ncategory: Behavioral\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 目的\n在一个操作中定义算法的骨架，将某些步骤推迟到子类。模板方法允许子类重新定义算法的某些步骤，而无需更改算法的结构。\n\n## 解释\n真实世界例子\n\n> 偷东西的一般步骤是相同的。 首先，选择目标，然后以某种方式使其迷惑，最后，你偷走了该物品。然而这些步骤有很多实现方式。\n\n通俗的说\n\n> 模板方法模式在父类中列出一般的步骤然后让具体的子类定义实现细节。\n\n维基百科说\n\n> 在面向对象的编程中，模板方法是Gamma等人确定的行为设计模式之一。在《设计模式》一书中。模板方法是父类中一个方法，通常是一个抽象父类，根据许多高级步骤定义了操作的骨架。这些步骤本身由与模板方法在同一类中的其他帮助程序方法实现。\n\n**编程示例**\n\n让我们首先介绍模板方法类及其具体实现。\n\n```java\npublic abstract class StealingMethod {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(StealingMethod.class);\n\n  protected abstract String pickTarget();\n\n  protected abstract void confuseTarget(String target);\n\n  protected abstract void stealTheItem(String target);\n\n  public void steal() {\n    var target = pickTarget();\n    LOGGER.info(\"The target has been chosen as {}.\", target);\n    confuseTarget(target);\n    stealTheItem(target);\n  }\n}\n\npublic class SubtleMethod extends StealingMethod {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(SubtleMethod.class);\n\n  @Override\n  protected String pickTarget() {\n    return \"shop keeper\";\n  }\n\n  @Override\n  protected void confuseTarget(String target) {\n    LOGGER.info(\"Approach the {} with tears running and hug him!\", target);\n  }\n\n  @Override\n  protected void stealTheItem(String target) {\n    LOGGER.info(\"While in close contact grab the {}'s wallet.\", target);\n  }\n}\n\npublic class HitAndRunMethod extends StealingMethod {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(HitAndRunMethod.class);\n\n  @Override\n  protected String pickTarget() {\n    return \"old goblin woman\";\n  }\n\n  @Override\n  protected void confuseTarget(String target) {\n    LOGGER.info(\"Approach the {} from behind.\", target);\n  }\n\n  @Override\n  protected void stealTheItem(String target) {\n    LOGGER.info(\"Grab the handbag and run away fast!\");\n  }\n}\n```\n\n这是包含模板方法的半身贼类。\n\n```java\npublic class HalflingThief {\n\n  private StealingMethod method;\n\n  public HalflingThief(StealingMethod method) {\n    this.method = method;\n  }\n\n  public void steal() {\n    method.steal();\n  }\n\n  public void changeMethod(StealingMethod method) {\n    this.method = method;\n  }\n}\n```\n最后，我们展示半身人贼如何利用不同的偷窃方法。\n\n```java\n    var thief = new HalflingThief(new HitAndRunMethod());\n    thief.steal();\n    thief.changeMethod(new SubtleMethod());\n    thief.steal();\n```\n\n## 类图\n![alt text](./etc/template_method_urm.png \"Template Method\")\n\n## 适用性\n\n使用模板方法模式可以\n\n* 一次性实现一个算法中不变的部分并将其留给子类来实现可能变化的行为。\n* 子类之间的共同行为应分解并集中在一个共同类中，以避免代码重复。如Opdyke和Johnson所描述的，这是“重构概括”的一个很好的例子。你首先要确定现有代码中的差异，然后将差异拆分为新的操作。最后，将不同的代码替换为调用这些新操作之一的模板方法。\n* 控制子类扩展。您可以定义一个模板方法，该方法在特定点调用“ 钩子”操作，从而仅允许在这些点进行扩展\n\n## 教程\n\n* [Template-method Pattern Tutorial](https://www.journaldev.com/1763/template-method-design-pattern-in-java)\n\n## Java例子\n\n* [javax.servlet.GenericServlet.init](https://jakarta.ee/specifications/servlet/4.0/apidocs/javax/servlet/GenericServlet.html#init--): \nMethod `GenericServlet.init(ServletConfig config)` calls the parameterless method `GenericServlet.init()` which is intended to be overridden in subclasses.\nMethod `GenericServlet.init(ServletConfig config)` is the template method in this example.\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "localization/zh/trampoline/README.md",
    "content": "---\ntitle: Trampoline\nshortTitle: Trampoline\ncategory: Behavioral\nlanguage: zh\ntag:\n- Performance\n---\n\n## 目的\n\n蹦床模式是用于在 Java 中递归地实现算法，而不会破坏堆栈，并且可以交错地执行函数，而无需将它们编码在一起。\n\n## 解释\n\n递归是一种常用的技术，用于以分而治之的方式解决算法问题。例如，计算斐波那契累加和与阶乘。在这类问题中，递归比循环更简单直接。此外，递归可能需要更少的代\n码并且看起来更简明。有一种说法是，每个递归问题都可以使用循环来解决，但代价是编写更难以理解的代码。然而，递归型解决方案有一个很大的警告。对于每个\n递归调用，通常需要存储一个中间值，并且可用的栈内存有限。栈内存不足会导致栈溢出错误并停止程序执行。蹦床模式是一种允许在 Java 中定义递归算法而无需破坏\n堆栈的技巧。\n\n现实世界例子\n\n> 使用蹦床模式进行递归斐波那契计算，不存在堆栈溢出问题。\n\n通俗地说\n\n> 蹦床模式允许递归而不会耗尽栈内存。\n\n维基百科上说\n\n> 在 Java 中，蹦床是指使用反射来避免使用内部类，例如在事件侦听器中。反射调用的整理操作时间换成了内部类的整理操作空间。 Java 中的蹦床通常涉及创建 GenericListener 以将事件传递到外部类。\n\n**编程实例**\n\n这是 Java 中的蹦床实现。\n\n当在返回的蹦床上调用 `get` 时，只要返回的具体实例是蹦床，内部就会在返回的蹦床上迭代调用跳转，并在返回的实例完成后停止。\n\n```java\npublic interface Trampoline<T> {\n\n  T get();\n\n  default Trampoline<T> jump() {\n    return this;\n  }\n\n  default T result() {\n    return get();\n  }\n\n  default boolean complete() {\n    return true;\n  }\n\n  static <T> Trampoline<T> done(final T result) {\n    return () -> result;\n  }\n\n  static <T> Trampoline<T> more(final Trampoline<Trampoline<T>> trampoline) {\n    return new Trampoline<T>() {\n      @Override\n      public boolean complete() {\n        return false;\n      }\n\n      @Override\n      public Trampoline<T> jump() {\n        return trampoline.result();\n      }\n\n      @Override\n      public T get() {\n        return trampoline(this);\n      }\n\n      T trampoline(final Trampoline<T> trampoline) {\n        return Stream.iterate(trampoline, Trampoline::jump)\n            .filter(Trampoline::complete)\n            .findFirst()\n            .map(Trampoline::result)\n            .orElseThrow();\n      }\n    };\n  }\n}\n```\n\n使用蹦床获取斐波那契值。\n\n```java\npublic static void main(String[] args) {\n    LOGGER.info(\"Start calculating war casualties\");\n    var result = loop(10, 1).result();\n    LOGGER.info(\"The number of orcs perished in the war: {}\", result);\n}\n\npublic static Trampoline<Integer> loop(int times, int prod) {\n    if (times == 0) {\n        return Trampoline.done(prod);\n    } else {\n        return Trampoline.more(() -> loop(times - 1, prod * times));\n    }\n}\n```\n\n程序输出：\n\n```java\n19:22:24.462 [main] INFO com.iluwatar.trampoline.TrampolineApp - Start calculating war casualties\n19:22:24.472 [main] INFO com.iluwatar.trampoline.TrampolineApp - The number of orcs perished in the war: 3628800\n```\n\n## 类图\n\n![alt text](./etc/trampoline_urm.png \"Trampoline pattern class diagram\")\n\n## 适用场景\n\n使用蹦床模式时\n* 用于实现尾递归函数。该模式允许切换无堆栈操作。\n* 用于在同一线程上交错执行两个或多个函数。\n\n## 现实案例\n\n* [cyclops-react](https://github.com/aol/cyclops-react)\n\n## 鸣谢\n\n* [Trampolining: a practical guide for awesome Java Developers](https://medium.com/@johnmcclean/trampolining-a-practical-guide-for-awesome-java-developers-4b657d9c3076)\n* [Trampoline in java ](http://mindprod.com/jgloss/trampoline.html)\n* [Laziness, trampolines, monoids and other functional amenities: this is not your father's Java](https://www.slideshare.net/mariofusco/lazine)\n* [Trampoline implementation](https://github.com/bodar/totallylazy/blob/master/src/com/googlecode/totallylazy/Trampoline.java)\n* [What is a trampoline function?](https://stackoverflow.com/questions/189725/what-is-a-trampoline-function)\n* [Modern Java in Action: Lambdas, streams, functional and reactive programming](https://www.amazon.com/gp/product/1617293563/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617293563&linkId=ad53ae6f9f7c0982e759c3527bd2595c)\n* [Java 8 in Action: Lambdas, Streams, and functional-style programming](https://www.amazon.com/gp/product/1617291994/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=1617291994&linkId=e3e5665b0732c59c9d884896ffe54f4f)\n"
  },
  {
    "path": "localization/zh/unit-of-work/README.md",
    "content": "---\ntitle: Unit Of Work\nshortTitle: Unit Of Work\ncategory: Architectural\nlanguage: zn\ntag:\n - Data access\n - Performance\n---\n\n## 又被称为\n工作单元\n\n## 目的\n\n当一个业务事务完成时，所有的更新都作为一个大的工作单元一次性发送，以最小化数据库的往返次数进行持久化。\n\n## 解释\n\n现实世界例子\n\n> 武器商人拥有一个包含武器信息的数据库。\n> 全城的商贩们都在不断地更新这些信息，这导致数据库服务器的负载很高。\n> 为了使负载更易于管理，我们应用了工作单元模式，将许多小的更新批量发送。\n\n用直白的话来说\n\n> 工作单元将许多小的数据库更新合并成一个批次。\n> 以优化往返次数。\n\n[MartinFowler.com](https://martinfowler.com/eaaCatalog/unitOfWork.html) 中说\n\n> 维护一个受业务事务影响的对象列表。\n> 并协调写出更改和解决并发问题。\n\n**编程样例**\n\n以下是要持久化到数据库中的 `Weapon` 的实体。\n\n```java\n@Getter\n@RequiredArgsConstructor\npublic class Weapon {\n    private final Integer id;\n    private final String name;\n}\n```\n\n实现的核心是 `ArmsDealer` 实现了工作单元模式。\n它维护了一个需要完成的数据库操作映射 (`context`) 当调用 `commit` 时\n它会一次性批量应用这些操作。\n\n```java\npublic interface IUnitOfWork<T> {\n    \n  String INSERT = \"INSERT\";\n  String DELETE = \"DELETE\";\n  String MODIFY = \"MODIFY\";\n\n  void registerNew(T entity);\n\n  void registerModified(T entity);\n\n  void registerDeleted(T entity);\n\n  void commit();\n}\n\n@Slf4j\n@RequiredArgsConstructor\npublic class ArmsDealer implements IUnitOfWork<Weapon> {\n\n    private final Map<String, List<Weapon>> context;\n    private final WeaponDatabase weaponDatabase;\n\n    @Override\n    public void registerNew(Weapon weapon) {\n        LOGGER.info(\"Registering {} for insert in context.\", weapon.getName());\n        register(weapon, UnitActions.INSERT.getActionValue());\n    }\n\n    @Override\n    public void registerModified(Weapon weapon) {\n        LOGGER.info(\"Registering {} for modify in context.\", weapon.getName());\n        register(weapon, UnitActions.MODIFY.getActionValue());\n\n    }\n\n    @Override\n    public void registerDeleted(Weapon weapon) {\n        LOGGER.info(\"Registering {} for delete in context.\", weapon.getName());\n        register(weapon, UnitActions.DELETE.getActionValue());\n    }\n\n    private void register(Weapon weapon, String operation) {\n        var weaponsToOperate = context.get(operation);\n        if (weaponsToOperate == null) {\n            weaponsToOperate = new ArrayList<>();\n        }\n        weaponsToOperate.add(weapon);\n        context.put(operation, weaponsToOperate);\n    }\n\n    /**\n     * All UnitOfWork operations are batched and executed together on commit only.\n     */\n    @Override\n    public void commit() {\n        if (context == null || context.size() == 0) {\n            return;\n        }\n        LOGGER.info(\"Commit started\");\n        if (context.containsKey(UnitActions.INSERT.getActionValue())) {\n            commitInsert();\n        }\n\n        if (context.containsKey(UnitActions.MODIFY.getActionValue())) {\n            commitModify();\n        }\n        if (context.containsKey(UnitActions.DELETE.getActionValue())) {\n            commitDelete();\n        }\n        LOGGER.info(\"Commit finished.\");\n    }\n\n    private void commitInsert() {\n        var weaponsToBeInserted = context.get(UnitActions.INSERT.getActionValue());\n        for (var weapon : weaponsToBeInserted) {\n            LOGGER.info(\"Inserting a new weapon {} to sales rack.\", weapon.getName());\n            weaponDatabase.insert(weapon);\n        }\n    }\n\n    private void commitModify() {\n        var modifiedWeapons = context.get(UnitActions.MODIFY.getActionValue());\n        for (var weapon : modifiedWeapons) {\n            LOGGER.info(\"Scheduling {} for modification work.\", weapon.getName());\n            weaponDatabase.modify(weapon);\n        }\n    }\n\n    private void commitDelete() {\n        var deletedWeapons = context.get(UnitActions.DELETE.getActionValue());\n        for (var weapon : deletedWeapons) {\n            LOGGER.info(\"Scrapping {}.\", weapon.getName());\n            weaponDatabase.delete(weapon);\n        }\n    }\n}\n```\n\n以下描述了整个应用是如何组装起来的。\n\n```java\n// create some weapons\nvar enchantedHammer = new Weapon(1, \"enchanted hammer\");\nvar brokenGreatSword = new Weapon(2, \"broken great sword\");\nvar silverTrident = new Weapon(3, \"silver trident\");\n\n// create repository\nvar weaponRepository = new ArmsDealer(new HashMap<String, List<Weapon>>(), new WeaponDatabase());\n\n// perform operations on the weapons\nweaponRepository.registerNew(enchantedHammer);\nweaponRepository.registerModified(silverTrident);\nweaponRepository.registerDeleted(brokenGreatSword);\nweaponRepository.commit();\n```\n\n以下是控制台输出。\n\n```\n21:39:21.984 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Registering enchanted hammer for insert in context.\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Registering silver trident for modify in context.\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Registering broken great sword for delete in context.\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Commit started\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Inserting a new weapon enchanted hammer to sales rack.\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Scheduling silver trident for modification work.\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Scrapping broken great sword.\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Commit finished.\n```\n\n## 类图\n\n![alt text](./etc/unit-of-work.urm.png \"unit-of-work\")\n\n## 应用\n\n在以下情况时使用单元模式\n\n* 为了优化数据库事务所需的时间。\n* 作为工作单元将更改发送到数据库，确保事务的原子性。\n* 为了减少数据库调用的次数。\n\n## 教程\n\n* [Repository and Unit of Work Pattern](https://www.programmingwithwolfgang.com/repository-and-unit-of-work-pattern/)\n* [Unit of Work - a Design Pattern](https://mono.software/2017/01/13/unit-of-work-a-design-pattern/)\n\n## 鸣谢\n\n* [Design Pattern - Unit Of Work Pattern](https://www.codeproject.com/Articles/581487/Unit-of-Work-Design-Pattern)\n* [Unit Of Work](https://martinfowler.com/eaaCatalog/unitOfWork.html)\n* [Patterns of Enterprise Application Architecture](https://www.amazon.com/gp/product/0321127420/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321127420&linkCode=as2&tag=javadesignpat-20&linkId=d9f7d37b032ca6e96253562d075fcc4a)\n"
  },
  {
    "path": "localization/zh/update-method/README.md",
    "content": "---  \ntitle: Update Method\nshortTitle: Update Method\ncategory: Behavioral\nlanguage: zn\ntag:  \n - Game programming\n---  \n\n## 又被称为\n更新方法\n\n## 目的\n更新方法模式通过告诉每个对象一次处理一个行为帧来模拟一组独立的对象。\n\n## 解释\n游戏世界维护了一个对象的集合。每个对象都实现了一个更新方法，用来模拟该对象行为的一帧。在每一帧中，游戏会更新集合中的每一个对象。\n\n要了解更多关于游戏循环是如何运行的，以及何时调用更新方法，请参考“游戏循环模式”。\n\n## 类图\n![alt text](./etc/update-method.urm.png \"Update Method pattern class diagram\")\n\n## 应用 \n如果说游戏循环模式是自切面包以来最好的东西，那么更新方法模式就是它的黄油。有很多玩家与动态实体互动的游戏都以某种形式使用这个模式。如果游戏里有宇航兵、龙、火星人、幽灵或运动员，那么它很可能使用了这种模式。\n\n然而，如果游戏更为抽象，且移动的部分不像是生动的角色，而更像是棋盘上的棋子，那么这种模式往往并不合适。在像国际象棋这样的游戏中，你不需要同时模拟所有的棋子，也可能不需要告诉每一个兵卒在每一帧都更新自己。\n\n当以下情况发生时，更新方法工作得很好：\n\n- 你的游戏中有许多对象或系统需要同时运行。\n- 每个对象的行为大部分都独立于其他对象。\n- 这些对象需要随时间进行模拟。\n\n## 鸣谢\n  \n* [Game Programming Patterns - Update Method](http://gameprogrammingpatterns.com/update-method.html)\n"
  },
  {
    "path": "localization/zh/value-object/README.md",
    "content": "---\ntitle: Value Object\nshortTitle: Value Object\ncategory: Creational\nlanguage: zn\ntag:\n - Instantiation\n---\n\n## 又被称为\n值对象\n\n## 目的\n\n提供的对象应遵循值语义而不是引用语义。这意味着两个值对象的相等性不是基于它们的身份。只要两个值对象的值相同，即使它们不是同一个对象，它们也被认为是相等的。\n\n## 解释\n\n现实世界例子\n\n> 在一个角色扮演游戏中，有一个用于英雄属性统计的类。\n> 这些统计属性包括力量、智慧和运气等特征。\n> 当所有的属性都相同时，不同英雄的统计数据应被认为是相等的。\n\n用直白的话来说\n\n> 当值对象的属性有相同的值时，它们是相等的。\n\n维基百科中说\n\n> 在计算机科学中，值对象是一个代表简单实体的小对象。\n> 其相等性不是基于身份的：即当两个值对象有相同的值的时候。\n> 它们是相等的，而不必要是同一个对象。\n\n**编程样例**\n\n这里是作为值对象的 `HeroStat` 类。 请注意使用了\n[Lombok's `@Value`](https://projectlombok.org/features/Value) 注解。\n\n```java\n@Value(staticConstructor = \"valueOf\")\nclass HeroStat {\n\n    int strength;\n    int intelligence;\n    int luck;\n}\n```\n\n这个示例创建了三个不同的 `HeroStat`s 并比较了它们的相等性。\n\n```java\nvar statA = HeroStat.valueOf(10, 5, 0);\nvar statB = HeroStat.valueOf(10, 5, 0);\nvar statC = HeroStat.valueOf(5, 1, 8);\n\nLOGGER.info(statA.toString());\nLOGGER.info(statB.toString());\nLOGGER.info(statC.toString());\n\nLOGGER.info(\"Is statA and statB equal : {}\", statA.equals(statB));\nLOGGER.info(\"Is statA and statC equal : {}\", statA.equals(statC));\n```\n\n以下是控制台的输出。\n\n```\n20:11:12.199 [main] INFO com.iluwatar.value.object.App - HeroStat(strength=10, intelligence=5, luck=0)\n20:11:12.202 [main] INFO com.iluwatar.value.object.App - HeroStat(strength=10, intelligence=5, luck=0)\n20:11:12.202 [main] INFO com.iluwatar.value.object.App - HeroStat(strength=5, intelligence=1, luck=8)\n20:11:12.202 [main] INFO com.iluwatar.value.object.App - Is statA and statB equal : true\n20:11:12.203 [main] INFO com.iluwatar.value.object.App - Is statA and statC equal : false\n```\n\n## 类图\n\n![alt text](./etc/value-object.png \"Value Object\")\n\n## 应用\n\n当满足以下情况时，使用值对象：\n\n* 对象的相等性需要基于对象的值\n\n## 现实世界的案例\n\n* [java.util.Optional](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html)\n* [java.time.LocalDate](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html)\n* [joda-time, money, beans](http://www.joda.org/)\n\n## 鸣谢\n\n* [Patterns of Enterprise Application Architecture](http://www.martinfowler.com/books/eaa.html)\n* [ValueObject](https://martinfowler.com/bliki/ValueObject.html)\n* [VALJOs - Value Java Objects : Stephen Colebourne's blog](http://blog.joda.org/2014/03/valjos-value-java-objects.html)\n* [Value Object : Wikipedia](https://en.wikipedia.org/wiki/Value_object)\n* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)\n"
  },
  {
    "path": "localization/zh/version-number/README.md",
    "content": "---\ntitle: Version Number\nshortTitle: Version Number\ncategory: Concurrency\nlanguage: zh\ntag:\n - Data access\n - Microservices\n---\n\n## 名字 / 分类\n\n版本号\n\n## 或称\n\n实体版本控制，乐观锁。\n\n## 目的\n\n解决多个客户端尝试同时更新同一实体时的并发冲突。\n\n## 解释\n\n现实世界的例子\n\n> 爱丽丝（Alice）和鲍勃（Bob）正在管理书，该书存储在数据库中。 我们的英雄们正在同时进行更改，我们需要某种机制来防止他们相互覆盖。\n\n通俗地说\n\n> 版本号模式可防止对同一实体进行并发更新。\n\n维基百科说\n\n> 乐观并发控制假设多个事务可以频繁完成而不会互相干扰。 在运行时，事务使用数据资源而不获取这些资源的锁。 在提交之前，每个事务都将验证没有其他事务修改了已读取的数据。如果检查发现有冲突的修改，则提交的事务将回滚并可以重新启动。\n\n**程序示例**\n\n我们有`Book` 已版本化的实体，它有一个复制构造函数。\n\n```java\npublic class Book {\n  private long id;\n  private String title = \"\";\n  private String author = \"\";\n\n  private long version = 0; // version number\n\n  public Book(Book book) {\n    this.id = book.id;\n    this.title = book.title;\n    this.author = book.author;\n    this.version = book.version;\n  }\n\n  // getters and setters are omitted here\n}\n```\n\n我们还有一个 `BookRepository`, 它实现了并发控制。\n\n```java\npublic class BookRepository {\n  private final Map<Long, Book> collection = new HashMap<>();\n\n  public void update(Book book) throws BookNotFoundException, VersionMismatchException {\n    if (!collection.containsKey(book.getId())) {\n      throw new BookNotFoundException(\"Not found book with id: \" + book.getId());\n    }\n\n    var latestBook = collection.get(book.getId());\n    if (book.getVersion() != latestBook.getVersion()) {\n      throw new VersionMismatchException(\n        \"Tried to update stale version \" + book.getVersion()\n          + \" while actual version is \" + latestBook.getVersion()\n      );\n    }\n\n    // update version, including client representation - modify by reference here\n    book.setVersion(book.getVersion() + 1);\n\n    // save book copy to repository\n    collection.put(book.getId(), new Book(book));\n  }\n\n  public Book get(long bookId) throws BookNotFoundException {\n    if (!collection.containsKey(bookId)) {\n      throw new BookNotFoundException(\"Not found book with id: \" + bookId);\n    }\n\n    // return copy of the book\n    return new Book(collection.get(bookId));\n  }\n}\n```\n\n这是实践中的并发控制：\n\n```java\nvar bookId = 1;\n// Alice and Bob took the book concurrently\nfinal var aliceBook = bookRepository.get(bookId);\nfinal var bobBook = bookRepository.get(bookId);\n\naliceBook.setTitle(\"Kama Sutra\"); // Alice has updated book title\nbookRepository.update(aliceBook); // and successfully saved book in database\nLOGGER.info(\"Alice updates the book with new version {}\", aliceBook.getVersion());\n\n// now Bob has the stale version of the book with empty title and version = 0\n// while actual book in database has filled title and version = 1\nbobBook.setAuthor(\"Vatsyayana Mallanaga\"); // Bob updates the author\ntry {\n  LOGGER.info(\"Bob tries to update the book with his version {}\", bobBook.getVersion());\n  bookRepository.update(bobBook); // Bob tries to save his book to database\n} catch (VersionMismatchException e) {\n  // Bob update fails, and book in repository remained untouchable\n  LOGGER.info(\"Exception: {}\", e.getMessage());\n  // Now Bob should reread actual book from repository, do his changes again and save again\n}\n```\n\n程序输出：\n\n```java\nAlice updates the book with new version 1\nBob tries to update the book with his version 0\nException: Tried to update stale version 0 while actual version is 1\n```\n\n## 类图\n\n![alt text](./etc/version-number.urm.png \"Version Number pattern class diagram\")\n\n## 适用性\n\n将版本号用于：\n\n* 解决对数据的并发写访问\n* 强的数据一致性\n\n## 教程\n* [Version Number Pattern Tutorial](http://www.java2s.com/Tutorial/Java/0355__JPA/VersioningEntity.htm)\n\n## 已知用途\n * [Hibernate](https://vladmihalcea.com/jpa-entity-version-property-hibernate/)\n * [Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html#index-versioning)\n * [Apache Solr](https://lucene.apache.org/solr/guide/6_6/updating-parts-of-documents.html)\n\n## 意义\n版本号模式允许实现并发控制，通常通过乐观离线锁模式来完成。\n\n## 相关模式\n* [Optimistic Offline Lock](https://martinfowler.com/eaaCatalog/optimisticOfflineLock.html)\n\n## 鸣谢\n* [Optimistic Locking in JPA](https://www.baeldung.com/jpa-optimistic-locking)\n* [JPA entity versioning](https://www.byteslounge.com/tutorials/jpa-entity-versioning-version-and-optimistic-locking)\n* [J2EE Design Patterns](http://ommolketab.ir/aaf-lib/axkwht7wxrhvgs2aqkxse8hihyu9zv.pdf)\n"
  },
  {
    "path": "localization/zh/visitor/README.md",
    "content": "---\ntitle: Visitor\nshortTitle: Visitor\ncategory: Behavioral\nlanguage: zh\ntag:\n - Gang of Four\n---\n\n## 目的\n\n表示要在对象结构的元素上执行的操作。访问者可让你定义新操作，而无需更改其所操作元素的类。\n\n## 解释\n\n真实世界例子\n\n> 考虑有一个带有军队单位的树形结构。指挥官下有两名中士，每名中士下有三名士兵。基于这个层级结构实现访问者模式，我们可以轻松创建与指挥官，中士，士兵或所有人员互动的新对象\n\n通俗的说\n\n> 访问者模式定义可以在数据结构的节点上执行的操作。\n\n维基百科说\n\n> 在面向对象的程序设计和软件工程中，访问者设计模式是一种将算法与操作对象的结构分离的方法。这种分离的实际结果是能够在不修改结构的情况下向现有对象结构添加新操作。\n\n**程序示例**\n\n使用上面的军队单元的例子，我们首先由单位和单位访问器类型。\n\n```java\npublic abstract class Unit {\n\n  private final Unit[] children;\n\n  public Unit(Unit... children) {\n    this.children = children;\n  }\n\n  public void accept(UnitVisitor visitor) {\n    Arrays.stream(children).forEach(child -> child.accept(visitor));\n  }\n}\n\npublic interface UnitVisitor {\n\n  void visitSoldier(Soldier soldier);\n\n  void visitSergeant(Sergeant sergeant);\n\n  void visitCommander(Commander commander);\n}\n```\n\n然后我们有具体的单元。\n\n```java\npublic class Commander extends Unit {\n\n  public Commander(Unit... children) {\n    super(children);\n  }\n\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visitCommander(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"commander\";\n  }\n}\n\npublic class Sergeant extends Unit {\n\n  public Sergeant(Unit... children) {\n    super(children);\n  }\n\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visitSergeant(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"sergeant\";\n  }\n}\n\npublic class Soldier extends Unit {\n\n  public Soldier(Unit... children) {\n    super(children);\n  }\n\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visitSoldier(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"soldier\";\n  }\n}\n```\n\n然后有一些具体的访问者。\n\n```java\npublic class CommanderVisitor implements UnitVisitor {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(CommanderVisitor.class);\n\n  @Override\n  public void visitSoldier(Soldier soldier) {\n    // Do nothing\n  }\n\n  @Override\n  public void visitSergeant(Sergeant sergeant) {\n    // Do nothing\n  }\n\n  @Override\n  public void visitCommander(Commander commander) {\n    LOGGER.info(\"Good to see you {}\", commander);\n  }\n}\n\npublic class SergeantVisitor implements UnitVisitor {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(SergeantVisitor.class);\n\n  @Override\n  public void visitSoldier(Soldier soldier) {\n    // Do nothing\n  }\n\n  @Override\n  public void visitSergeant(Sergeant sergeant) {\n    LOGGER.info(\"Hello {}\", sergeant);\n  }\n\n  @Override\n  public void visitCommander(Commander commander) {\n    // Do nothing\n  }\n}\n\npublic class SoldierVisitor implements UnitVisitor {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(SoldierVisitor.class);\n\n  @Override\n  public void visitSoldier(Soldier soldier) {\n    LOGGER.info(\"Greetings {}\", soldier);\n  }\n\n  @Override\n  public void visitSergeant(Sergeant sergeant) {\n    // Do nothing\n  }\n\n  @Override\n  public void visitCommander(Commander commander) {\n    // Do nothing\n  }\n}\n```\n\n最后，来看看实践中访问者模式的力量。\n\n```java\ncommander.accept(new SoldierVisitor());\ncommander.accept(new SergeantVisitor());\ncommander.accept(new CommanderVisitor());\n```\n\n程序输出:\n\n```\nGreetings soldier\nGreetings soldier\nGreetings soldier\nGreetings soldier\nGreetings soldier\nGreetings soldier\nHello sergeant\nHello sergeant\nGood to see you commander\n```\n\n## Class diagram\n\n![alt text](./etc/visitor_1.png \"Visitor\")\n\n## 适用性\n\n使用访问者模式当\n\n* 对象结构包含许多具有不同接口的对象类，并且你希望根据这些对象的具体类对这些对象执行操作。\n* 需要对对象结构中的对象执行许多不同且不相关的操作，并且你想避免使用这些操作“污染”它们的类。 访问者可以通过在一个类中定义相关操作来将它们保持在一起。当许多应用程序共享对象结构时，请使用访问者模式将操作仅放在需要它们的那些应用程序中\n* 定义对象结构的类很少变化，但是你经常想在结构上定义新的操作。更改对象结构类需要重新定义所有访问者的接口，这可能会导致成本高昂。如果对象结构类经常更改，则最好在这些类中定义操作。\n\n## 真实例子\n\n* [Apache Wicket](https://github.com/apache/wicket) component tree, see [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)\n* [javax.lang.model.element.AnnotationValue](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValue.html) and [AnnotationValueVisitor](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValueVisitor.html)\n* [javax.lang.model.element.Element](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/Element.html) and [Element Visitor](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/ElementVisitor.html)\n* [java.nio.file.FileVisitor](http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileVisitor.html)\n\n## 鸣谢\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)\n* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)\n* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)\n"
  },
  {
    "path": "lockable-object/README.md",
    "content": "---\ntitle: \"Lockable Object Pattern in Java: Implementing Robust Synchronization Mechanisms\"\nshortTitle: Lockable Object\ndescription: \"Learn about the Lockable Object design pattern in Java. Explore its usage, real-world examples, benefits, and how it ensures thread safety and resource management in multithreaded environments.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Decoupling\n  - Encapsulation\n  - Security\n  - Synchronization\n  - Thread management\n---\n\n## Also known as\n\n* Resource Lock\n* Mutual Exclusion Object\n\n## Intent of Lockable Object Design Pattern\n\nThe Lockable Object pattern in Java aims to control access to a shared resource in a multithreaded environment, ensuring thread safety by providing a mechanism for resource locking, ensuring that only one thread can access the resource at a time.\n\n## Detailed Explanation of Lockable Object Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a shared printer in a busy office as an analogous real-world example of the Lockable Object design pattern in Java. This pattern ensures that only one thread can access the resource at a time, thus maintaining concurrency control and synchronization. Multiple employees need to print documents throughout the day, but the printer can only handle one print job at a time. To manage this, there's a locking system in place—much like a lockable object in programming—that ensures when one person is printing, others must wait their turn. This prevents print jobs from overlapping or interfering with each other, ensuring that each document is printed correctly and in the order it was sent, mirroring the concept of thread synchronization and resource locking in software development.\n\nIn plain words\n\n> The Lockable Object design pattern ensures safe access to a shared resource in a multithreaded environment by allowing only one thread to access the resource at a time through locking mechanisms.\n\nWikipedia says\n\n> In computer science, a lock or mutex (from mutual exclusion) is a synchronization primitive that prevents state from being modified or accessed by multiple threads of execution at once. Locks enforce mutual exclusion concurrency control policies, and with a variety of possible methods there exist multiple unique implementations for different applications.\n\nSequence diagram\n\n![Lockable Object Sequence Diagram](./etc/lockable-object-sequence-diagram.png)\n\n## Programmatic Example of Lockable Object Pattern in Java\n\nThe Lockable Object pattern is a concurrency control design pattern in Java that allows only one thread to access a shared resource at a time, ensuring mutual exclusion and preventing data corruption. Instead of using the `synchronized` keyword on the methods to be synchronized, the object which implements the Lockable interface handles the request.\n\nIn this example, we have a `SwordOfAragorn` object that implements the `Lockable` interface. Multiple `Creature` objects, represented by `Elf`, `Orc`, and `Human` classes, are trying to acquire the sword. Each `Creature` is wrapped in a `Feind` object that implements `Runnable`, allowing each creature to attempt to acquire the sword in a separate thread.\n\nHere's the `Lockable` interface:\n\n```java\npublic interface Lockable {\n  boolean isLocked();\n  Creature getLocker();\n  boolean acquire(Creature creature);\n  void release(Creature creature);\n}\n```\n\nThe `SwordOfAragorn` class implements this interface:\n\n```java\npublic class SwordOfAragorn implements Lockable {\n  // Implementation details...\n}\n```\n\nThe `Creature` class and its subclasses (`Elf`, `Orc`, `Human`) represent different creatures that can try to acquire the sword:\n\n```java\npublic abstract class Creature {\n  // Implementation details...\n}\n\npublic class Elf extends Creature {\n  // Implementation details...\n}\n\npublic class Orc extends Creature {\n  // Implementation details...\n}\n\npublic class Human extends Creature {\n  // Implementation details...\n}\n```\n\nThe `Feind` class wraps a `Creature` and a `Lockable` object, and implements `Runnable`:\n\n```java\npublic class Feind implements Runnable {\n  private final Creature creature;\n  private final Lockable target;\n\n  public Feind(@NonNull Creature feind, @NonNull Lockable target) {\n    this.creature = feind;\n    this.target = target;\n  }\n\n  @Override\n  public void run() {\n    if (!creature.acquire(target)) {\n      fightForTheSword(creature, target.getLocker(), target);\n    } else {\n      LOGGER.info(\"{} has acquired the sword!\", target.getLocker().getName());\n    }\n  }\n\n  // Additional methods...\n}\n```\n\nIn the `App` class, multiple `Feind` objects are created and submitted to an `ExecutorService`, each in a separate thread:\n\n```java\npublic class App implements Runnable {\n  @Override\n  public void run() {\n    var sword = new SwordOfAragorn();\n    List<Creature> creatures = new ArrayList<>();\n    // Creation of creatures...\n    ExecutorService service = Executors.newFixedThreadPool(totalFiends);\n    for (var i = 0; i < totalFiends; i = i + MULTIPLICATION_FACTOR) {\n      service.submit(new Feind(creatures.get(i), sword));\n      service.submit(new Feind(creatures.get(i + 1), sword));\n      service.submit(new Feind(creatures.get(i + 2), sword));\n    }\n    // Additional code...\n  }\n}\n```\n\nThis example demonstrates the Lockable Object pattern by showing how multiple threads can attempt to acquire a lock on a shared resource, with only one thread being able to acquire the lock at a time.\n\n## When to Use the Lockable Object Pattern in Java\n\n* Use the Lockable Object pattern in Java when you need to prevent data corruption by multiple threads accessing a shared resource concurrently, ensuring thread safety and robust shared resource management.\n* Suitable for systems where thread safety is critical and data integrity must be maintained across various operations.\n\n## Real-World Applications of Lockable Object Pattern in Java\n\n* Java’s synchronized keyword and the Lock interfaces in the java.util.concurrent.locks package implement lockable objects to manage synchronization.\n\n## Benefits and Trade-offs of Lockable Object Pattern\n\nBenefits:\n\n* Ensures data consistency and prevents race conditions.\n* Provides clear structure for managing access to shared resources.\n\nTrade-offs:\n\n* Can lead to decreased performance due to overhead of acquiring and releasing locks.\n* Potential for deadlocks if not implemented and managed carefully.\n\n## Related Java Design Patterns\n\n* [Monitor Object](https://java-design-patterns.com/patterns/monitor/): Both patterns manage access to shared resources; Monitor Object combines synchronization and encapsulation of the condition variable.\n* [Read/Write Lock](https://java-design-patterns.com/patterns/reader-writer-lock/): Specialization of Lockable Object for scenarios where read operations outnumber write operations.\n\n## References and Credits\n\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n* [Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects](https://amzn.to/3UgC24V)\n"
  },
  {
    "path": "lockable-object/etc/lockable-object.urm.puml",
    "content": "@startuml\npackage com.iluwatar.lockableobject.domain {\n  abstract class Creature {\n    - LOGGER : Logger {static}\n    - damage : int\n    - health : int\n    ~ instruments : Set<Lockable>\n    - name : String\n    - type : CreatureType\n    + Creature(name : String)\n    + acquire(lockable : Lockable) : boolean\n    + attack(creature : Creature)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getDamage() : int\n    + getHealth() : int\n    + getInstruments() : Set<Lockable>\n    + getName() : String\n    + getType() : CreatureType\n    + hashCode() : int\n    + hit(damage : int)\n    + isAlive() : boolean\n    + kill()\n    + setDamage(damage : int)\n    + setHealth(health : int)\n    + setInstruments(instruments : Set<Lockable>)\n    + setName(name : String)\n    + setType(type : CreatureType)\n    + toString() : String\n  }\n  enum CreatureType {\n    + ELF {static}\n    + HUMAN {static}\n    + ORC {static}\n    + valueOf(name : String) : CreatureType {static}\n    + values() : CreatureType[] {static}\n  }\n  class Elf {\n    + Elf(name : String)\n  }\n  class Feind {\n    - LOGGER : Logger {static}\n    - feind : Creature\n    - target : Lockable\n    + Feind(feind : Creature, target : Lockable)\n    - fightForTheSword(reacher : Creature, holder : Creature, sword : Lockable)\n    + run()\n  }\n  class Human {\n    + Human(name : String)\n  }\n  class Orc {\n    + Orc(name : String)\n  }\n}\npackage com.iluwatar.lockableobject {\n  class App {\n    - LOGGER : Logger {static}\n    - MULTIPLICATION_FACTOR : int {static}\n    - WAIT_TIME : int {static}\n    - WORKERS : int {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  interface Lockable {\n    + getLocker() : Creature {abstract}\n    + getName() : String {abstract}\n    + isLocked() : boolean {abstract}\n    + lock(Creature) : boolean {abstract}\n    + unlock(Creature) {abstract}\n  }\n  class SwordOfAragorn {\n    - LOGGER : Logger {static}\n    - NAME : String {static}\n    - locker : Creature\n    - synchronizer : Object\n    + SwordOfAragorn()\n    + getLocker() : Creature\n    + getName() : String\n    + isLocked() : boolean\n    + lock(creature : Creature) : boolean\n    + unlock(creature : Creature)\n  }\n}\nCreature -->  \"-type\" CreatureType\nCreature -->  \"-instruments\" Lockable\nFeind -->  \"-feind\" Creature\nFeind -->  \"-target\" Lockable\nSwordOfAragorn -->  \"-locker\" Creature\nSwordOfAragorn ..|> Lockable \nElf --|> Creature \nHuman --|> Creature \nOrc --|> Creature \n@enduml"
  },
  {
    "path": "lockable-object/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>lockable-object</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <!-- Maven assembly plugin is invoked with default setting which we have\n                in parent pom and specifying the class having main method -->\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.lockableobject.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "lockable-object/src/main/java/com/iluwatar/lockableobject/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject;\n\nimport com.iluwatar.lockableobject.domain.Creature;\nimport com.iluwatar.lockableobject.domain.Elf;\nimport com.iluwatar.lockableobject.domain.Feind;\nimport com.iluwatar.lockableobject.domain.Human;\nimport com.iluwatar.lockableobject.domain.Orc;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Lockable Object pattern is a concurrency pattern. Instead of using the \"synchronized\" word\n * upon the methods to be synchronized, the object which implements the Lockable interface handles\n * the request.\n *\n * <p>In this example, we create a new Lockable object with the SwordOfAragorn implementation of it.\n * Afterward we create 6 Creatures with the Elf, Orc and Human implementations and assign them each\n * to a Fiend object and the Sword is the target object. Because there is only one Sword, and it\n * uses the Lockable Object pattern, only one creature can hold the sword at a given time. When the\n * sword is locked, any other alive Fiends will try to lock, which will result in a race to lock the\n * sword.\n */\n@Slf4j\npublic class App implements Runnable {\n\n  private static final int WAIT_TIME = 3;\n  private static final int WORKERS = 2;\n  private static final int MULTIPLICATION_FACTOR = 3;\n\n  /**\n   * main method.\n   *\n   * @param args as arguments for the main method.\n   */\n  public static void main(String[] args) {\n    var app = new App();\n    app.run();\n  }\n\n  @Override\n  public void run() {\n    // The target object for this example.\n    var sword = new SwordOfAragorn();\n    // Creation of creatures.\n    List<Creature> creatures = new ArrayList<>();\n    for (var i = 0; i < WORKERS; i++) {\n      creatures.add(new Elf(String.format(\"Elf %s\", i)));\n      creatures.add(new Orc(String.format(\"Orc %s\", i)));\n      creatures.add(new Human(String.format(\"Human %s\", i)));\n    }\n    int totalFiends = WORKERS * MULTIPLICATION_FACTOR;\n    ExecutorService service = Executors.newFixedThreadPool(totalFiends);\n    // Attach every creature and the sword is a Fiend to fight for the sword.\n    for (var i = 0; i < totalFiends; i = i + MULTIPLICATION_FACTOR) {\n      service.submit(new Feind(creatures.get(i), sword));\n      service.submit(new Feind(creatures.get(i + 1), sword));\n      service.submit(new Feind(creatures.get(i + 2), sword));\n    }\n    // Wait for program to terminate.\n    try {\n      if (!service.awaitTermination(WAIT_TIME, TimeUnit.SECONDS)) {\n        LOGGER.info(\"The master of the sword is now {}.\", sword.getLocker().getName());\n      }\n    } catch (InterruptedException e) {\n      LOGGER.error(e.getMessage());\n      Thread.currentThread().interrupt();\n    } finally {\n      service.shutdown();\n    }\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/main/java/com/iluwatar/lockableobject/Lockable.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject;\n\nimport com.iluwatar.lockableobject.domain.Creature;\n\n/** This interface describes the methods to be supported by a lockable-object. */\npublic interface Lockable {\n\n  /**\n   * Checks if the object is locked.\n   *\n   * @return true if it is locked.\n   */\n  boolean isLocked();\n\n  /**\n   * locks the object with the creature as the locker.\n   *\n   * @param creature as the locker.\n   * @return true if the object was locked successfully.\n   */\n  boolean lock(Creature creature);\n\n  /**\n   * Unlocks the object.\n   *\n   * @param creature as the locker.\n   */\n  void unlock(Creature creature);\n\n  /**\n   * Gets the locker.\n   *\n   * @return the Creature that holds the object. Returns null if no one is locking.\n   */\n  Creature getLocker();\n\n  /**\n   * Returns the name of the object.\n   *\n   * @return the name of the object.\n   */\n  String getName();\n}\n"
  },
  {
    "path": "lockable-object/src/main/java/com/iluwatar/lockableobject/LockingException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject;\n\nimport java.io.Serial;\n\n/** An exception regarding the locking process of a Lockable object. */\npublic class LockingException extends RuntimeException {\n\n  @Serial private static final long serialVersionUID = 8556381044865867037L;\n\n  public LockingException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/main/java/com/iluwatar/lockableobject/SwordOfAragorn.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject;\n\nimport com.iluwatar.lockableobject.domain.Creature;\nimport lombok.NonNull;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * An implementation of a Lockable object. This is the Sword of Aragorn and every creature wants to\n * possess it!\n */\n@Slf4j\npublic class SwordOfAragorn implements Lockable {\n\n  private Creature locker;\n  private final Object synchronizer;\n  private static final String NAME = \"The Sword of Aragorn\";\n\n  public SwordOfAragorn() {\n    this.locker = null;\n    this.synchronizer = new Object();\n  }\n\n  @Override\n  public boolean isLocked() {\n    return this.locker != null;\n  }\n\n  @Override\n  public boolean lock(@NonNull Creature creature) {\n    synchronized (synchronizer) {\n      LOGGER.info(\"{} is now trying to acquire {}!\", creature.getName(), this.getName());\n      if (!isLocked()) {\n        locker = creature;\n        return true;\n      } else {\n        if (!locker.getName().equals(creature.getName())) {\n          return false;\n        }\n      }\n    }\n    return false;\n  }\n\n  @Override\n  public void unlock(@NonNull Creature creature) {\n    synchronized (synchronizer) {\n      if (locker != null && locker.getName().equals(creature.getName())) {\n        locker = null;\n        LOGGER.info(\"{} is now free!\", this.getName());\n      }\n      if (locker != null) {\n        throw new LockingException(\"You cannot unlock an object you are not the owner of.\");\n      }\n    }\n  }\n\n  @Override\n  public Creature getLocker() {\n    return this.locker;\n  }\n\n  @Override\n  public String getName() {\n    return NAME;\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Creature.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject.domain;\n\nimport com.iluwatar.lockableobject.Lockable;\nimport java.util.HashSet;\nimport java.util.Set;\nimport lombok.Getter;\nimport lombok.NonNull;\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * An abstract class of a creature that wanders across the wasteland. It can attack, get hit and\n * acquire a Lockable object.\n */\n@Getter\n@Setter\n@Slf4j\npublic abstract class Creature {\n\n  private String name;\n  private CreatureType type;\n  private int health;\n  private int damage;\n  Set<Lockable> instruments;\n\n  protected Creature(@NonNull String name) {\n    this.name = name;\n    this.instruments = new HashSet<>();\n  }\n\n  /**\n   * Reaches for the Lockable and tried to hold it.\n   *\n   * @param lockable as the Lockable to lock.\n   * @return true of Lockable was locked by this creature.\n   */\n  public boolean acquire(@NonNull Lockable lockable) {\n    if (lockable.lock(this)) {\n      instruments.add(lockable);\n      return true;\n    }\n    return false;\n  }\n\n  /** Terminates the Creature and unlocks all the Lockable that it possesses. */\n  public synchronized void kill() {\n    LOGGER.info(\"{} {} has been slayed!\", type, name);\n    for (Lockable lockable : instruments) {\n      lockable.unlock(this);\n    }\n    this.instruments.clear();\n  }\n\n  /**\n   * Attacks a foe.\n   *\n   * @param creature as the foe to be attacked.\n   */\n  public synchronized void attack(@NonNull Creature creature) {\n    creature.hit(getDamage());\n  }\n\n  /**\n   * When a creature gets hit it removed the amount of damage from the creature's life.\n   *\n   * @param damage as the damage that was taken.\n   */\n  public synchronized void hit(int damage) {\n    if (damage < 0) {\n      throw new IllegalArgumentException(\"Damage cannot be a negative number\");\n    }\n    if (isAlive()) {\n      setHealth(getHealth() - damage);\n      if (!isAlive()) {\n        kill();\n      }\n    }\n  }\n\n  /**\n   * Checks if the creature is still alive.\n   *\n   * @return true of creature is alive.\n   */\n  public synchronized boolean isAlive() {\n    return getHealth() > 0;\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/main/java/com/iluwatar/lockableobject/domain/CreatureStats.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject.domain;\n\nimport lombok.Getter;\n\n/** Attribute constants of each Creature implementation. */\npublic enum CreatureStats {\n  ELF_HEALTH(90),\n  ELF_DAMAGE(40),\n  ORC_HEALTH(70),\n  ORC_DAMAGE(50),\n  HUMAN_HEALTH(60),\n  HUMAN_DAMAGE(60);\n\n  @Getter final int value;\n\n  CreatureStats(int value) {\n    this.value = value;\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/main/java/com/iluwatar/lockableobject/domain/CreatureType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject.domain;\n\n/** Constants of supported creatures. */\npublic enum CreatureType {\n  ORC,\n  HUMAN,\n  ELF\n}\n"
  },
  {
    "path": "lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Elf.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject.domain;\n\n/** An Elf implementation of a Creature. */\npublic class Elf extends Creature {\n\n  /**\n   * A constructor that initializes the attributes of an elf.\n   *\n   * @param name as the name of the creature.\n   */\n  public Elf(String name) {\n    super(name);\n    setType(CreatureType.ELF);\n    setDamage(CreatureStats.ELF_DAMAGE.getValue());\n    setHealth(CreatureStats.ELF_HEALTH.getValue());\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Feind.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject.domain;\n\nimport com.iluwatar.lockableobject.Lockable;\nimport java.security.SecureRandom;\nimport lombok.NonNull;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** A Feind is a creature that wants to possess a Lockable object. */\npublic class Feind implements Runnable {\n\n  private final Creature creature;\n  private final Lockable target;\n  private final SecureRandom random;\n  private static final Logger LOGGER = LoggerFactory.getLogger(Feind.class.getName());\n\n  /**\n   * public constructor.\n   *\n   * @param feind as the creature to lock to he lockable.\n   * @param target as the target object.\n   */\n  public Feind(@NonNull Creature feind, @NonNull Lockable target) {\n    this.creature = feind;\n    this.target = target;\n    this.random = new SecureRandom();\n  }\n\n  @Override\n  public void run() {\n    if (!creature.acquire(target)) {\n      fightForTheSword(creature, target.getLocker(), target);\n    } else {\n      LOGGER.info(\"{} has acquired the sword!\", target.getLocker().getName());\n    }\n  }\n\n  /**\n   * Keeps on fighting until the Lockable is possessed.\n   *\n   * @param reacher as the source creature.\n   * @param holder as the foe.\n   * @param sword as the Lockable to possess.\n   */\n  private void fightForTheSword(Creature reacher, @NonNull Creature holder, Lockable sword) {\n    LOGGER.info(\"A duel between {} and {} has been started!\", reacher.getName(), holder.getName());\n    boolean randBool;\n    while (this.target.isLocked() && reacher.isAlive() && holder.isAlive()) {\n      randBool = random.nextBoolean();\n      if (randBool) {\n        reacher.attack(holder);\n      } else {\n        holder.attack(reacher);\n      }\n    }\n    if (reacher.isAlive()) {\n      if (!reacher.acquire(sword)) {\n        fightForTheSword(reacher, sword.getLocker(), sword);\n      } else {\n        LOGGER.info(\"{} has acquired the sword!\", reacher.getName());\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Human.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject.domain;\n\n/** A human implementation of a Creature. */\npublic class Human extends Creature {\n\n  /**\n   * A constructor that initializes the attributes of a human.\n   *\n   * @param name as the name of the creature.\n   */\n  public Human(String name) {\n    super(name);\n    setType(CreatureType.HUMAN);\n    setDamage(CreatureStats.HUMAN_DAMAGE.getValue());\n    setHealth(CreatureStats.HUMAN_HEALTH.getValue());\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/main/java/com/iluwatar/lockableobject/domain/Orc.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject.domain;\n\n/** An Orc implementation of a Creature. */\npublic class Orc extends Creature {\n  /**\n   * A constructor that initializes the attributes of an orc.\n   *\n   * @param name as the name of the creature.\n   */\n  public Orc(String name) {\n    super(name);\n    setType(CreatureType.ORC);\n    setDamage(CreatureStats.ORC_DAMAGE.getValue());\n    setHealth(CreatureStats.ORC_HEALTH.getValue());\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/test/java/com/iluwatar/lockableobject/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n\n  @Test\n  void shouldExecuteApplicationAsRunnableWithoutException() {\n    assertDoesNotThrow(() -> (new App()).run());\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/test/java/com/iluwatar/lockableobject/CreatureTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject;\n\nimport com.iluwatar.lockableobject.domain.Creature;\nimport com.iluwatar.lockableobject.domain.CreatureStats;\nimport com.iluwatar.lockableobject.domain.CreatureType;\nimport com.iluwatar.lockableobject.domain.Elf;\nimport com.iluwatar.lockableobject.domain.Orc;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass CreatureTest {\n\n  private Creature orc;\n  private Creature elf;\n  private Lockable sword;\n\n  @BeforeEach\n  void init() {\n    elf = new Elf(\"Elf test\");\n    orc = new Orc(\"Orc test\");\n    sword = new SwordOfAragorn();\n  }\n\n  @Test\n  void baseTest() {\n    Assertions.assertEquals(\"Elf test\", elf.getName());\n    Assertions.assertEquals(CreatureType.ELF, elf.getType());\n    Assertions.assertThrows(NullPointerException.class, () -> new Elf(null));\n    Assertions.assertThrows(NullPointerException.class, () -> elf.acquire(null));\n    Assertions.assertThrows(NullPointerException.class, () -> elf.attack(null));\n    Assertions.assertThrows(IllegalArgumentException.class, () -> elf.hit(-10));\n  }\n\n  @Test\n  void hitTest() {\n    elf.hit(CreatureStats.ELF_HEALTH.getValue() / 2);\n    Assertions.assertEquals(CreatureStats.ELF_HEALTH.getValue() / 2, elf.getHealth());\n    elf.hit(CreatureStats.ELF_HEALTH.getValue() / 2);\n    Assertions.assertFalse(elf.isAlive());\n\n    Assertions.assertEquals(0, orc.getInstruments().size());\n    Assertions.assertTrue(orc.acquire(sword));\n    Assertions.assertEquals(1, orc.getInstruments().size());\n    orc.kill();\n    Assertions.assertEquals(0, orc.getInstruments().size());\n  }\n\n  @Test\n  void testFight() throws InterruptedException {\n    killCreature(elf, orc);\n    Assertions.assertTrue(elf.isAlive());\n    Assertions.assertFalse(orc.isAlive());\n    Assertions.assertTrue(elf.getHealth() > 0);\n    Assertions.assertTrue(orc.getHealth() <= 0);\n  }\n\n  @Test\n  void testAcqusition() throws InterruptedException {\n    Assertions.assertTrue(elf.acquire(sword));\n    Assertions.assertEquals(elf.getName(), sword.getLocker().getName());\n    Assertions.assertTrue(elf.getInstruments().contains(sword));\n    Assertions.assertFalse(orc.acquire(sword));\n    killCreature(orc, elf);\n    Assertions.assertTrue(orc.acquire(sword));\n    Assertions.assertEquals(orc, sword.getLocker());\n  }\n\n  void killCreature(Creature source, Creature target) {\n    while (target.isAlive()) {\n      source.attack(target);\n    }\n  }\n\n  @Test\n  void invalidDamageTest() {\n    Assertions.assertThrows(IllegalArgumentException.class, () -> elf.hit(-50));\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/test/java/com/iluwatar/lockableobject/ExceptionsTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass ExceptionsTest {\n\n  private static final String MSG = \"test\";\n\n  @Test\n  void testException() {\n    Exception e;\n    try {\n      throw new LockingException(MSG);\n    } catch (LockingException ex) {\n      e = ex;\n    }\n    Assertions.assertEquals(MSG, e.getMessage());\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/test/java/com/iluwatar/lockableobject/FeindTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject;\n\nimport com.iluwatar.lockableobject.domain.Creature;\nimport com.iluwatar.lockableobject.domain.Elf;\nimport com.iluwatar.lockableobject.domain.Feind;\nimport com.iluwatar.lockableobject.domain.Orc;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass FeindTest {\n\n  private Creature elf;\n  private Creature orc;\n  private Lockable sword;\n\n  @BeforeEach\n  void init() {\n    elf = new Elf(\"Nagdil\");\n    orc = new Orc(\"Ghandar\");\n    sword = new SwordOfAragorn();\n  }\n\n  @Test\n  void nullTests() {\n    Assertions.assertThrows(NullPointerException.class, () -> new Feind(null, null));\n    Assertions.assertThrows(NullPointerException.class, () -> new Feind(elf, null));\n    Assertions.assertThrows(NullPointerException.class, () -> new Feind(null, sword));\n  }\n\n  @Test\n  void testBaseCase() throws InterruptedException {\n    var base = new Thread(new Feind(orc, sword));\n    Assertions.assertNull(sword.getLocker());\n    base.start();\n    base.join();\n    Assertions.assertEquals(orc, sword.getLocker());\n    var extend = new Thread(new Feind(elf, sword));\n    extend.start();\n    extend.join();\n    Assertions.assertTrue(sword.isLocked());\n\n    sword.unlock(elf.isAlive() ? elf : orc);\n    Assertions.assertNull(sword.getLocker());\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/test/java/com/iluwatar/lockableobject/SubCreaturesTests.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject;\n\nimport com.iluwatar.lockableobject.domain.CreatureStats;\nimport com.iluwatar.lockableobject.domain.Elf;\nimport com.iluwatar.lockableobject.domain.Human;\nimport com.iluwatar.lockableobject.domain.Orc;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass SubCreaturesTests {\n\n  @Test\n  void statsTest() {\n    var elf = new Elf(\"Limbar\");\n    var orc = new Orc(\"Dargal\");\n    var human = new Human(\"Jerry\");\n    Assertions.assertEquals(CreatureStats.ELF_HEALTH.getValue(), elf.getHealth());\n    Assertions.assertEquals(CreatureStats.ELF_DAMAGE.getValue(), elf.getDamage());\n    Assertions.assertEquals(CreatureStats.ORC_DAMAGE.getValue(), orc.getDamage());\n    Assertions.assertEquals(CreatureStats.ORC_HEALTH.getValue(), orc.getHealth());\n    Assertions.assertEquals(CreatureStats.HUMAN_DAMAGE.getValue(), human.getDamage());\n    Assertions.assertEquals(CreatureStats.HUMAN_HEALTH.getValue(), human.getHealth());\n  }\n}\n"
  },
  {
    "path": "lockable-object/src/test/java/com/iluwatar/lockableobject/TheSwordOfAragornTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.lockableobject;\n\nimport com.iluwatar.lockableobject.domain.Human;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass TheSwordOfAragornTest {\n\n  @Test\n  void basicSwordTest() {\n    var sword = new SwordOfAragorn();\n    Assertions.assertNotNull(sword.getName());\n    Assertions.assertNull(sword.getLocker());\n    Assertions.assertFalse(sword.isLocked());\n    var human = new Human(\"Tupac\");\n    Assertions.assertTrue(human.acquire(sword));\n    Assertions.assertEquals(human, sword.getLocker());\n    Assertions.assertTrue(sword.isLocked());\n  }\n\n  @Test\n  void invalidLockerTest() {\n    var sword = new SwordOfAragorn();\n    Assertions.assertThrows(NullPointerException.class, () -> sword.lock(null));\n    Assertions.assertThrows(NullPointerException.class, () -> sword.unlock(null));\n  }\n}\n"
  },
  {
    "path": "lombok.config",
    "content": "lombok.log.fieldName = LOGGER\nlombok.addLombokGeneratedAnnotation = true\n"
  },
  {
    "path": "map-reduce/README.md",
    "content": "---\ntitle: \"MapReduce Pattern in Java\"\nshortTitle: MapReduce\ndescription: \"Learn the MapReduce pattern in Java with real-world examples, class diagrams, and tutorials. Understand its intent, applicability, benefits, and known uses to enhance your design pattern knowledge.\"\ncategory: Functional\nlanguage: en\ntag:\n    - Concurrency\n    - Data processing\n    - Data transformation\n    - Functional decomposition\n    - Immutable\n    - Multithreading\n    - Scalability\n---\n\n## Also known as\n\n* Map-Reduce\n* Divide and Conquer for Data Processing\n\n## Intent of Map Reduce Design Pattern\n\nTo efficiently process large-scale datasets by dividing computation into two phases: map and reduce, which can be executed in parallel and distributed across multiple nodes.\n\n## Detailed Explanation of Map Reduce Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a large e-commerce company that wants to analyze its sales data across multiple regions. They have terabytes of transaction data stored across hundreds of servers. Using MapReduce, they can efficiently process this data to calculate total sales by product category. The Map function would process individual sales records, emitting key-value pairs of (category, sale amount). The Reduce function would then sum up all sale amounts for each category, producing the final result.\n\nIn plain words\n\n> MapReduce splits a large problem into smaller parts, processes them in parallel, and then combines the results.\n\nWikipedia says\n\n> MapReduce is a programming model and associated implementation for processing and generating big data sets with a parallel, distributed algorithm on a cluster. MapReduce consists of two main steps:\nThe Map step: The master node takes the input, divides it into smaller sub-problems, and distributes them to worker nodes. A worker node may do this again in turn, leading to a multi-level tree structure. The worker node processes the smaller problem, and passes the answer back to its master node. The Reduce step: The master node then collects the answers to all the sub-problems and combines them in some way to form the output – the answer to the problem it was originally trying to solve. This approach allows for efficient processing of vast amounts of data across multiple machines, making it a fundamental technique in big data analytics and distributed computing.\n\nFlowchart\n\n![MapReduce flowchart](./etc/mapreduce-flowchart.png)\n\n## Programmatic Example of Map Reduce in Java\n\n### 1. Map Phase (Splitting & Processing Data)\n\n* Each input string is split into words, normalized, and counted.\n* Output: A map `{word → count}` for each input string.\n\n#### `Mapper.java`\n\n```java\npublic class Mapper {\n    public static Map<String, Integer> map(String input) {\n        Map<String, Integer> wordCount = new HashMap<>();\n        String[] words = input.split(\"\\\\s+\");\n        for (String word : words) {\n            word = word.toLowerCase().replaceAll(\"[^a-z]\", \"\");\n            if (!word.isEmpty()) {\n                wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);\n            }\n        }\n        return wordCount;\n    }\n}\n```\n\nExample Input: ```\"Hello world hello\"```\nOutput: ```{hello=2, world=1}```\n\n### 2. Shuffle Phase – Grouping Words Across Inputs\n\n* Takes results from all mappers and groups values by word.\n* Output: A map `{word → list of counts}`.\n\n#### `Shuffler.java`\n\n```java\npublic class Shuffler {\n    public static Map<String, List<Integer>> shuffleAndSort(List<Map<String, Integer>> mapped) {\n        Map<String, List<Integer>> grouped = new HashMap<>();\n        for (Map<String, Integer> map : mapped) {\n            for (Map.Entry<String, Integer> entry : map.entrySet()) {\n                grouped.putIfAbsent(entry.getKey(), new ArrayList<>());\n                grouped.get(entry.getKey()).add(entry.getValue());\n            }\n        }\n        return grouped;\n    }\n}\n```\n\nExample Input: \n\n```\n[\n    {\"hello\": 2, \"world\": 1},\n    {\"hello\": 1, \"java\": 1}\n]\n```\n\nOutput: \n\n```\n{\n    \"hello\": [2, 1],\n    \"world\": [1],\n    \"java\": [1]\n}\n```\n\n### 3. Reduce Phase – Aggregating Counts\n\n* Sums the list of counts for each word.\n* Output: A sorted list of word counts in descending order.\n\n#### `Reducer.java`\n\n```java\npublic class Reducer {\n    public static List<Map.Entry<String, Integer>> reduce(Map<String, List<Integer>> grouped) {\n        Map<String, Integer> reduced = new HashMap<>();\n        for (Map.Entry<String, List<Integer>> entry : grouped.entrySet()) {\n            reduced.put(entry.getKey(), entry.getValue().stream().mapToInt(Integer::intValue).sum());\n        }\n\n        List<Map.Entry<String, Integer>> result = new ArrayList<>(reduced.entrySet());\n        result.sort(Map.Entry.comparingByValue(Comparator.reverseOrder()));\n        return result;\n    }\n}\n```\n\nExample Input:\n\n```\n{\n    \"hello\": [2, 1],\n    \"world\": [1],\n    \"java\": [1]\n}\n```\n\nOutput:\n\n```\n[\n    {\"hello\": 3},\n    {\"world\": 1},\n    {\"java\": 1}\n]\n```\n\n### 4. MapReduce Coordinator – Running the Whole Pipeline\n\n* Coordinates map, shuffle, and reduce phases.\n\n#### `MapReduce.java`\n\n```java\npublic class MapReduce {\n    public static List<Map.Entry<String, Integer>> mapReduce(List<String> inputs) {\n        List<Map<String, Integer>> mapped = new ArrayList<>();\n        for (String input : inputs) {\n            mapped.add(Mapper.map(input));\n        }\n\n        Map<String, List<Integer>> grouped = Shuffler.shuffleAndSort(mapped);\n\n        return Reducer.reduce(grouped);\n    }\n}\n```\n\n### 5. Main Execution – Example Usage\n\n* Runs the MapReduce process and prints results.\n\n#### `Main.java`\n\n```java\n  public static void main(String[] args) {\n    List<String> inputs = Arrays.asList(\n            \"Hello world hello\",\n            \"MapReduce is fun\",\n            \"Hello from the other side\",\n            \"Hello world\"\n    );\n    List<Map.Entry<String, Integer>> result = MapReduce.mapReduce(inputs);\n    for (Map.Entry<String, Integer> entry : result) {\n        System.out.println(entry.getKey() + \": \" + entry.getValue());\n    }\n}\n```\n\nOutput:\n\n```\nhello: 4\nworld: 2\nthe: 1\nother: 1\nside: 1\nmapreduce: 1\nis: 1\nfrom: 1\nfun: 1\n```\n\n## When to Use the Map Reduce Pattern in Java\n\nUse MapReduce when:\n\n* When processing large datasets that can be broken into independent chunks.\n* When data operations can be naturally divided into map (transformation) and reduce (aggregation) phases.\n* When horizontal scalability and parallelization are essential, especially in distributed or big data environments.\n* When leveraging Java-based distributed computing platforms like Hadoop or Spark.\n\n## Map Reduce Pattern Java Tutorials\n\n* [MapReduce Tutorial(Apache Hadoop)](https://hadoop.apache.org/docs/stable/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html)\n* [MapReduce Example(Simplilearn)](https://www.youtube.com/watch?v=l2clwKnrtO8)\n\n## Benefits and Trade-offs of Map Reduce Pattern\n\nBenefits:\n\n* Enables massive scalability by distributing processing across nodes.\n* Encourages a functional style, promoting immutability and stateless operations.\n* Simplifies complex data workflows by separating transformation (map) from aggregation (reduce).\n* Fault-tolerant due to isolated, recoverable processing tasks.\n\nTrade-offs:\n\n* Requires a suitable problem structure — not all tasks fit the map/reduce paradigm.\n* Data shuffling between map and reduce phases can be performance-intensive.\n* Higher complexity in debugging and optimizing distributed jobs.\n* Intermediate I/O can become a bottleneck in large-scale operations.\n\n## Real-World Applications of Map Reduce Pattern in Java\n\n* Hadoop MapReduce: Java-based framework for distributed data processing using MapReduce.\n* Apache Spark: Utilizes similar map and reduce transformations in its RDD and Dataset APIs.\n* Elasticsearch: Uses MapReduce-style aggregation pipelines for querying distributed data.\n* Google Bigtable: Underlying storage engine influenced by MapReduce principles.\n* MongoDB Aggregation Framework: Conceptually applies MapReduce in its data pipelines.\n\n## Related Java Design Patterns\n\n* [Master-Worker](https://java-design-patterns.com/patterns/master-worker/): Similar distribution of tasks among workers, with a master coordinating job execution.\n* [Pipeline](https://java-design-patterns.com/patterns/pipeline/): Can be used to chain multiple MapReduce operations into staged transformations.\n* [Iterator](https://java-design-patterns.com/patterns/iterator/): Often used under the hood to process input streams lazily in map and reduce steps.\n\n## References and Credits\n\n* [Big Data: Principles and Paradigms](https://amzn.to/3RJIGPZ)\n* [Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems](https://amzn.to/3E6VhtD)\n* [Hadoop: The Definitive Guide: Storage and Analysis at Internet Scale](https://amzn.to/4ij2y7F)\n* [Java 8 in Action: Lambdas, Streams, and functional-style programming](https://amzn.to/3QCmGXs)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3HWNf4U)\n* [Programming Pig: Dataflow Scripting with Hadoop](https://amzn.to/4cAU36K)\n* [What is MapReduce (IBM)](https://www.ibm.com/think/topics/mapreduce)\n* [Why MapReduce is not dead (Codemotion)](https://www.codemotion.com/magazine/ai-ml/big-data/mapreduce-not-dead-heres-why-its-still-ruling-in-the-cloud/)\n"
  },
  {
    "path": "map-reduce/etc/map-reduce.urm.puml",
    "content": "@startuml\npackage com.iluwatar {\n  class Main {\n    + Main()\n    + main(args : String[]) {static}\n  }\n  class MapReduce {\n    + MapReduce()\n    + mapReduce(inputs : List<String>) : List<Map.Entry<String, Integer>> {static}\n  }\n  class Mapper {\n    + Mapper()\n    + map(input : String) : Map<String, Integer> {static}\n  }\n  class Reducer {\n    + Reducer()\n    + reduce(grouped : Map<String, List<Integer>>) : List<Map.Entry<String, Integer>> {static}\n  }\n  class Shuffler {\n    + Shuffler()\n    + shuffleAndSort(mapped : List<Map<String, Integer>>) : Map<String, List<Integer>> {static}\n  }\n}\n@enduml"
  },
  {
    "path": "map-reduce/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>map-reduce</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.mapreduce.Main</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "map-reduce/src/main/java/com/iluwatar/Main.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.logging.Logger;\n\n/**\n * The Main class serves as the entry point for executing the MapReduce program. It processes a list\n * of text inputs, applies the MapReduce pattern, and prints the results.\n */\npublic class Main {\n  private static final Logger logger = Logger.getLogger(Main.class.getName());\n\n  /**\n   * The main method initiates the MapReduce process and displays the word count results.\n   *\n   * @param args Command-line arguments (not used).\n   */\n  public static void main(String[] args) {\n    List<String> inputs =\n        Arrays.asList(\n            \"Hello world hello\", \"MapReduce is fun\", \"Hello from the other side\", \"Hello world\");\n    List<Map.Entry<String, Integer>> result = MapReduce.mapReduce(inputs);\n    for (Map.Entry<String, Integer> entry : result) {\n      logger.info(entry.getKey() + \": \" + entry.getValue());\n    }\n  }\n}\n"
  },
  {
    "path": "map-reduce/src/main/java/com/iluwatar/MapReduce.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * The MapReduce class orchestrates the MapReduce process, calling the Mapper, Shuffler, and Reducer\n * components.\n */\npublic class MapReduce {\n  private MapReduce() {\n    throw new UnsupportedOperationException(\n        \"MapReduce is a utility class and cannot be instantiated.\");\n  }\n\n  /**\n   * Executes the MapReduce process on the given list of input strings.\n   *\n   * @param inputs List of input strings to be processed.\n   * @return A list of word counts sorted in descending order.\n   */\n  public static List<Map.Entry<String, Integer>> mapReduce(List<String> inputs) {\n    List<Map<String, Integer>> mapped = new ArrayList<>();\n    for (String input : inputs) {\n      mapped.add(Mapper.map(input));\n    }\n\n    Map<String, List<Integer>> grouped = Shuffler.shuffleAndSort(mapped);\n\n    return Reducer.reduce(grouped);\n  }\n}\n"
  },
  {
    "path": "map-reduce/src/main/java/com/iluwatar/Mapper.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * The Mapper class is responsible for processing an input string and generating a map of word\n * occurrences.\n */\npublic class Mapper {\n  private Mapper() {\n    throw new UnsupportedOperationException(\n        \"Mapper is a utility class and cannot be instantiated.\");\n  }\n\n  /**\n   * Splits a given input string into words and counts their occurrences.\n   *\n   * @param input The input string to be mapped.\n   * @return A map where keys are words and values are their respective counts.\n   */\n  public static Map<String, Integer> map(String input) {\n    Map<String, Integer> wordCount = new HashMap<>();\n    String[] words = input.split(\"\\\\s+\");\n    for (String word : words) {\n      word = word.toLowerCase().replaceAll(\"[^a-z]\", \"\");\n      if (!word.isEmpty()) {\n        wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);\n      }\n    }\n    return wordCount;\n  }\n}\n"
  },
  {
    "path": "map-reduce/src/main/java/com/iluwatar/Reducer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/** The Reducer class is responsible for aggregating word counts from the shuffled data. */\npublic class Reducer {\n  private Reducer() {\n    throw new UnsupportedOperationException(\n        \"Reducer is a utility class and cannot be instantiated.\");\n  }\n\n  /**\n   * Sums the occurrences of each word and sorts the results in descending order.\n   *\n   * @param grouped A map where keys are words and values are lists of their occurrences.\n   * @return A sorted list of word counts in descending order.\n   */\n  public static List<Map.Entry<String, Integer>> reduce(Map<String, List<Integer>> grouped) {\n    Map<String, Integer> reduced = new HashMap<>();\n    for (Map.Entry<String, List<Integer>> entry : grouped.entrySet()) {\n      reduced.put(entry.getKey(), entry.getValue().stream().mapToInt(Integer::intValue).sum());\n    }\n\n    List<Map.Entry<String, Integer>> result = new ArrayList<>(reduced.entrySet());\n    result.sort(Map.Entry.comparingByValue(Comparator.reverseOrder()));\n    return result;\n  }\n}\n"
  },
  {
    "path": "map-reduce/src/main/java/com/iluwatar/Shuffler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/** The Shuffler class is responsible for grouping word occurrences from multiple mappers. */\npublic class Shuffler {\n\n  private Shuffler() {\n    throw new UnsupportedOperationException(\n        \"Shuffler is a utility class and cannot be instantiated.\");\n  }\n\n  /**\n   * Merges multiple word count maps into a single grouped map.\n   *\n   * @param mapped List of maps containing word counts from the mapping phase.\n   * @return A map where keys are words and values are lists of their occurrences across inputs.\n   */\n  public static Map<String, List<Integer>> shuffleAndSort(List<Map<String, Integer>> mapped) {\n    Map<String, List<Integer>> grouped = new HashMap<>();\n    for (Map<String, Integer> map : mapped) {\n      for (Map.Entry<String, Integer> entry : map.entrySet()) {\n        grouped.putIfAbsent(entry.getKey(), new ArrayList<>());\n        grouped.get(entry.getKey()).add(entry.getValue());\n      }\n    }\n    return grouped;\n  }\n}\n"
  },
  {
    "path": "map-reduce/src/test/java/com/iluwatar/MapReduceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.*;\nimport org.junit.jupiter.api.Test;\n\nclass MapReduceTest {\n\n  @Test\n  void testMapReduce() {\n    List<String> inputs =\n        Arrays.asList(\"Hello world hello\", \"MapReduce is fun\", \"Hello from the other side\");\n\n    List<Map.Entry<String, Integer>> result = MapReduce.mapReduce(inputs);\n\n    assertEquals(\"hello\", result.get(0).getKey()); // hello = 3\n    assertEquals(3, result.get(0).getValue());\n    assertEquals(1, result.get(1).getValue());\n  }\n}\n"
  },
  {
    "path": "map-reduce/src/test/java/com/iluwatar/MapperTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.Map;\nimport org.junit.jupiter.api.Test;\n\nclass MapperTest {\n\n  @Test\n  void testMapSingleSentence() {\n    String input = \"Hello world hello\";\n    Map<String, Integer> result = Mapper.map(input);\n\n    assertEquals(2, result.get(\"hello\"));\n    assertEquals(1, result.get(\"world\"));\n  }\n\n  @Test\n  void testMapCaseInsensitivity() {\n    String input = \"HeLLo WoRLd hello WORLD\";\n    Map<String, Integer> result = Mapper.map(input);\n\n    assertEquals(2, result.get(\"hello\"));\n    assertEquals(2, result.get(\"world\"));\n  }\n}\n"
  },
  {
    "path": "map-reduce/src/test/java/com/iluwatar/ReducerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.*;\nimport org.junit.jupiter.api.Test;\n\nclass ReducerTest {\n\n  @Test\n  void testReduceWithMultipleWords() {\n    Map<String, List<Integer>> input = new HashMap<>();\n    input.put(\"apple\", Arrays.asList(2, 3, 1));\n    input.put(\"banana\", Arrays.asList(1, 1));\n    input.put(\"cherry\", List.of(4));\n\n    List<Map.Entry<String, Integer>> result = Reducer.reduce(input);\n\n    assertEquals(3, result.size());\n    assertEquals(\"apple\", result.get(0).getKey());\n    assertEquals(6, result.get(0).getValue());\n    assertEquals(\"cherry\", result.get(1).getKey());\n    assertEquals(4, result.get(1).getValue());\n    assertEquals(\"banana\", result.get(2).getKey());\n    assertEquals(2, result.get(2).getValue());\n  }\n\n  @Test\n  void testReduceWithEmptyInput() {\n    Map<String, List<Integer>> input = new HashMap<>();\n\n    List<Map.Entry<String, Integer>> result = Reducer.reduce(input);\n\n    assertTrue(result.isEmpty());\n  }\n\n  @Test\n  void testReduceWithTiedCounts() {\n    Map<String, List<Integer>> input = new HashMap<>();\n    input.put(\"tie1\", Arrays.asList(2, 2));\n    input.put(\"tie2\", Arrays.asList(1, 3));\n\n    List<Map.Entry<String, Integer>> result = Reducer.reduce(input);\n\n    assertEquals(2, result.size());\n    assertEquals(4, result.get(0).getValue());\n    assertEquals(4, result.get(1).getValue());\n    // Note: The order of tie1 and tie2 is not guaranteed in case of a tie\n  }\n}\n"
  },
  {
    "path": "map-reduce/src/test/java/com/iluwatar/ShufflerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.*;\nimport org.junit.jupiter.api.Test;\n\nclass ShufflerTest {\n\n  @Test\n  void testShuffleAndSort() {\n    List<Map<String, Integer>> mappedData =\n        Arrays.asList(Map.of(\"hello\", 1, \"world\", 2), Map.of(\"hello\", 2, \"java\", 1));\n\n    Map<String, List<Integer>> grouped = Shuffler.shuffleAndSort(mappedData);\n\n    assertEquals(Arrays.asList(1, 2), grouped.get(\"hello\"));\n    assertEquals(List.of(2), grouped.get(\"world\"));\n    assertEquals(List.of(1), grouped.get(\"java\"));\n  }\n}\n"
  },
  {
    "path": "marker-interface/.gitignore",
    "content": "/target/\n"
  },
  {
    "path": "marker-interface/README.md",
    "content": "---\ntitle: \"Marker Interface Pattern in Java: Defining Behavior Through Empty Interfaces\"\nshortTitle: Marker Interface\ndescription: \"Explore the Marker Interface pattern in Java, its benefits, real-world examples, and common uses. Learn how to use marker interfaces for metadata and special class behaviors.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Encapsulation\n  - Interface\n  - Polymorphism\n---\n\n## Also known as\n\n* Marker\n* Tagging Interface\n\n## Intent of Marker Interface Design Pattern\n\nThe Marker Interface pattern in Java is used to convey metadata about a class in a type-safe manner. Interfaces in Java that have no method declarations are known as marker interfaces. They are used to indicate that a class implementing such an interface possesses some special behavior or capability.\n\n## Detailed Explanation of Marker Interface Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a scenario in a Java library system where certain books are rare and need special handling procedures, such as restricted check-outs or specific storage conditions. Analogous to the Marker Interface pattern, we could have a marker interface called `RareBook`. Books in the library catalog that implement this interface are flagged as requiring special treatment but don't necessarily have different methods from other books.\n> \n> When a library staff member processes transactions or handles storage, the system checks if a book implements the `RareBook` interface. If it does, the system automatically enforces rules like \"Do not allow check-outs for more than three days\" or \"Store in a temperature-controlled environment.\" This use of the marker interface effectively communicates special requirements without altering how books are generally managed, serving simply as a marker for special conditions.\n\nIn plain words\n\n> The Marker Interface design pattern in Java uses empty interfaces to signal or define certain properties and behaviors of objects in a type-safe way, without requiring specific method implementations.\n\nWikipedia says\n\n> The marker interface pattern is a design pattern in computer science, used with languages that provide run-time type information about objects. It provides a means to associate metadata with a class where the language does not have explicit support for such metadata.\n> \n> To use this pattern, a class implements a marker interface (also called tagging interface) which is an empty interface, and methods that interact with instances of that class test for the existence of the interface. Whereas a typical interface specifies functionality (in the form of method declarations) that an implementing class must support, a marker interface need not do so. The mere presence of such an interface indicates specific behavior on the part of the implementing class. Hybrid interfaces, which both act as markers and specify required methods, are possible but may prove confusing if improperly used.\n\nFlowchart\n\n![Marker Interface flowchart](./etc/marker-interface-flowchart.png)\n\n## Programmatic Example of Marker Interface Pattern in Java\n\nThe Marker Interface design pattern is a design pattern in computer science that is used with languages that provide run-time type information about objects. It provides a means to associate metadata with a class where the language does not have explicit support for such metadata.\n\nIn the given Java code example, the Permission interface acts as a marker interface. Classes that implement this interface are marked as having special permissions. Let's break down the code to understand how this pattern is implemented.\n\nFirst, we define the `Permission` interface. This interface doesn't have any methods, making it a marker interface.\n\n```java\npublic interface Permission {\n  // This is a marker interface and does not contain any methods\n}\n```\n\nNext, we have two classes `Guard` and `Thief` that represent different types of characters in our application. The `Guard` class implements the `Permission` interface, indicating that objects of this class have special permissions.\n\n```java\npublic class Guard implements Permission {\n  public void enter() {\n    // Implementation of enter method\n  }\n}\n```\n\nOn the other hand, the `Thief` class does not implement the `Permission` interface, indicating that objects of this class do not have special permissions.\n\n```java\npublic class Thief {\n  public void steal() {\n    // Implementation of steal method\n  }\n\n  public void doNothing() {\n    // Implementation of doNothing method\n  }\n}\n```\n\nIn the `main` method of the `App` class, we create instances of `Guard` and `Thief`. We then use the `instanceof` operator to check if these objects implement the `Permission` interface. If an object implements the `Permission` interface, it is allowed to perform certain actions. If not, it is restricted from performing those actions.\n\n```java\npublic class App {\n  public static void main(String[] args) {\n    final var logger = LoggerFactory.getLogger(App.class);\n    var guard = new Guard();\n    var thief = new Thief();\n\n    if (guard instanceof Permission) {\n      guard.enter();\n    } else {\n      logger.info(\"You have no permission to enter, please leave this area\");\n    }\n\n    if (thief instanceof Permission) {\n      thief.steal();\n    } else {\n      thief.doNothing();\n    }\n  }\n}\n```\n\nIn this way, the Marker Interface pattern allows us to associate metadata (in this case, special permissions) with a class in a type-safe manner.\n\n## When to Use the Marker Interface Pattern in Java\n\nMarker interfaces are applicable in scenarios where you want to impose a special behavior or capability on a class, but don't want to force the class to define specific methods. This pattern is commonly used to indicate that a class conforms to a particular contract without needing to implement methods.\n\n## Real-World Applications of Marker Interface Pattern in Java\n\n* java.io.Serializable: Classes that implement this interface are capable of being serialized by the Java runtime.\n* java.lang.Cloneable: Classes that implement this interface can be cloned using the clone method in Java.\n\n## Benefits and Trade-offs of Marker Interface Pattern\n\nBenefits:\n\n* Enables type checking at compile time, allowing developers to use polymorphism to write cleaner and more flexible code.\n* Allows the addition of metadata to classes without altering their actual behavior.\n\nTrade-offs:\n\n* Can lead to empty interfaces in the codebase, which some may consider as not clean or clear in purpose.\n* Does not enforce any method implementations, which can lead to runtime errors if not properly handled.\n\n## References and Credits\n\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n"
  },
  {
    "path": "marker-interface/etc/MarkerDiagram.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.2.0\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"Guard\" project=\"marker\" file=\"/marker/src/main/java/Guard.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"416\" y=\"348\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"2\" language=\"java\" name=\"Permission\" project=\"marker\" file=\"/marker/src/main/java/Permission.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"261\" y=\"175\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"3\" language=\"java\" name=\"Thief\" project=\"marker\" file=\"/marker/src/main/java/Thief.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"236\" y=\"355\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <realization id=\"4\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "marker-interface/etc/marker-interface.urm.puml",
    "content": "@startuml\n@enduml"
  },
  {
    "path": "marker-interface/etc/marker.urm.puml",
    "content": "@startuml\n@enduml"
  },
  {
    "path": "marker-interface/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>marker-interface</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.hamcrest</groupId>\n      <artifactId>hamcrest-core</artifactId>\n      <version>3.0</version>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "marker-interface/src/main/java/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nimport org.slf4j.LoggerFactory;\n\n/**\n * Created by Alexis on 28-Apr-17. With Marker interface idea is to make empty interface and extend\n * it. Basically it is just to identify the special objects from normal objects. Like in case of\n * serialization , objects that need to be serialized must implement serializable interface (it is\n * empty interface) and down the line writeObject() method must be checking if it is an instance of\n * serializable or not.\n *\n * <p>Marker interface vs annotation Marker interfaces and marker annotations both have their uses,\n * neither of them is obsolete or always better than the other one. If you want to define a type\n * that does not have any new methods associated with it, a marker interface is the way to go. If\n * you want to mark program elements other than classes and interfaces, to allow for the possibility\n * of adding more information to the marker in the future, or to fit the marker into a framework\n * that already makes heavy use of annotation types, then a marker annotation is the correct choice\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    final var logger = LoggerFactory.getLogger(App.class);\n    var guard = new Guard();\n    var thief = new Thief();\n\n    //noinspection ConstantConditions\n    if (guard instanceof Permission) {\n      guard.enter();\n    } else {\n      logger.info(\"You have no permission to enter, please leave this area\");\n    }\n\n    //noinspection ConstantConditions\n    if (thief instanceof Permission) {\n      thief.steal();\n    } else {\n      thief.doNothing();\n    }\n  }\n}\n"
  },
  {
    "path": "marker-interface/src/main/java/Guard.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport lombok.extern.slf4j.Slf4j;\n\n/** Class defining Guard. */\n@Slf4j\npublic class Guard implements Permission {\n\n  protected void enter() {\n    LOGGER.info(\"You can enter\");\n  }\n}\n"
  },
  {
    "path": "marker-interface/src/main/java/Permission.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/** Interface without any methods Marker interface is based on that assumption. */\npublic interface Permission {}\n"
  },
  {
    "path": "marker-interface/src/main/java/Thief.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport lombok.extern.slf4j.Slf4j;\n\n/** Class defining Thief. */\n@Slf4j\npublic class Thief {\n\n  protected void steal() {\n    LOGGER.info(\"Steal valuable items\");\n  }\n\n  protected void doNothing() {\n    LOGGER.info(\"Pretend nothing happened and just leave\");\n  }\n}\n"
  },
  {
    "path": "marker-interface/src/test/java/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "marker-interface/src/test/java/GuardTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport static org.hamcrest.CoreMatchers.instanceOf;\nimport static org.hamcrest.MatcherAssert.assertThat;\n\nimport org.junit.jupiter.api.Test;\n\n/** Guard test */\nclass GuardTest {\n\n  @Test\n  void testGuard() {\n    var guard = new Guard();\n    assertThat(guard, instanceOf(Permission.class));\n  }\n}\n"
  },
  {
    "path": "marker-interface/src/test/java/ThiefTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\nimport static org.hamcrest.CoreMatchers.instanceOf;\nimport static org.hamcrest.CoreMatchers.not;\nimport static org.hamcrest.MatcherAssert.assertThat;\n\nimport org.junit.jupiter.api.Test;\n\n/** Thief test */\nclass ThiefTest {\n  @Test\n  void testThief() {\n    var thief = new Thief();\n    assertThat(thief, not(instanceOf(Permission.class)));\n  }\n}\n"
  },
  {
    "path": "master-worker/README.md",
    "content": "---\ntitle: \"Master-Worker Pattern in Java: Coordinating Concurrent Processing with Ease\"\nshortTitle: Master-Worker\ndescription: \"Discover the Master-Worker design pattern in Java. Learn how it improves concurrency, scalability, and performance through parallel task processing. Includes real-world examples and code snippets.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Multithreading\n  - Performance\n  - Scalability\n---\n\n## Also known as\n\n* Master-Slave\n* Controller-Worker\n\n## Intent of Master-Worker Design Pattern\n\nThe Master-Worker design pattern is designed to perform parallel computations by distributing tasks between a master process and multiple worker processes. This pattern enhances concurrency, performance, and scalability in software systems.\n\n## Detailed Explanation of Master-Worker Pattern with Real-World Examples\n\nReal-world example\n\n> The Master-Worker pattern optimizes parallel task processing and throughput. For instance, in a restaurant kitchen, the head chef (master) delegates tasks to line cooks (workers), who work concurrently to prepare the order. The head chef receives the orders from the dining area and breaks down each order into specific tasks, such as grilling meat, preparing salads, and cooking desserts. Each task is assigned to a different line cook based on their expertise and current workload. The line cooks work in parallel to prepare their portion of the order, while the head chef oversees the process, ensuring everything is prepared correctly and timely. Once each component of the order is ready, the head chef gathers all parts, gives them a final check, and then plates the dishes for service. This kitchen operation mimics the Master-Worker pattern by distributing and managing tasks to optimize efficiency and output.\n\nIn plain words\n\n> The Master-Worker pattern involves a master process delegating tasks to multiple worker processes, which execute them concurrently and report back, optimizing parallel task processing and throughput.\n\nWikipedia says\n\n> Master–slave is a model of asymmetric communication or control where one device or process (the master) controls one or more other devices or processes (the slaves) and serves as their communication hub. In some systems, a master is selected from a group of eligible devices, with the other devices acting in the role of slaves.\n\nSequence diagram\n\n![Master-Worker sequence diagram](./etc/master-worker-sequence-diagram.png)\n\n## Programmatic Example of Master-Worker Pattern in Java\n\nIn the provided code, the `MasterWorker` class initiates the concurrent computation process. The `Master` class divides the work among `Worker` objects, each performing its task in parallel, thus optimizing task processing and enhancing system efficiency.\n\n```java\n// The MasterWorker class acts as the main entry point for the Master-Worker system.\npublic class MasterWorker {\n  private Master master;\n\n  public MasterWorker(Master master) {\n    this.master = master;\n  }\n\n  public Result getResult(Input input) {\n    return master.computeResult(input);\n  }\n}\n```\n\nIn this code, the `MasterWorker` class is initialized with a `Master` object. The `getResult` method is used to start the computation process.\n\n```java\n// The Master class is responsible for dividing the work among the workers.\npublic abstract class Master {\n  protected List<Worker> workers;\n\n  public Master(List<Worker> workers) {\n    this.workers = workers;\n  }\n\n  public abstract Result computeResult(Input input);\n}\n```\n\nThe `Master` class has a list of `Worker` objects. The `computeResult` method is abstract and should be implemented in a subclass to define how the work is divided and how the results are aggregated.\n\n```java\n// The Worker class is responsible for performing the actual computation.\npublic abstract class Worker extends Thread {\n  protected Input input;\n\n  public void setInput(Input input) {\n    this.input = input;\n  }\n\n  public abstract Result compute();\n}\n```\n\nThe `Worker` class extends `Thread`, allowing it to perform computations in parallel. The `compute` method is abstract and should be implemented in a subclass to define the actual computation logic.\n\n```java\n// The Input and Result classes are used to encapsulate the input data and the result data.\npublic abstract class Input<T> {\n  public final T data;\n\n  public Input(T data) {\n    this.data = data;\n  }\n\n  public abstract List<Input<T>> divideData(int num);\n}\n\npublic abstract class Result<T> {\n  public final T data;\n\n  public Result(T data) {\n    this.data = data;\n  }\n}\n```\n\nThe `Input` class has a `divideData` method that is used to divide the input data into subtasks. The `Result` class simply encapsulates the result data.\n\n## When to Use the Master-Worker Pattern in Java\n\n* Suitable for scenarios where a task can be decomposed into smaller, independent tasks.\n* Useful in applications requiring concurrent execution to enhance performance.\n* Applicable in distributed computing where tasks need to be processed by multiple processors or machines.\n\n## Master-Worker Pattern Java Tutorials\n\n* [Master-Worker Pattern (Gigaspaces)](https://docs.gigaspaces.com/sbp/master-worker-pattern.html)\n\n## Real-World Applications of Master-Worker Pattern in Java\n\n* Implemented in distributed systems to manage tasks across different computing resources.\n* Used in server architectures to process multiple client requests simultaneously.\n* Utilized in scientific computation frameworks where large datasets require parallel processing.\n\n## Benefits and Trade-offs of Master-Worker Pattern\n\nBenefits:\n\n* Enhances performance by parallelizing tasks.\n* Increases responsiveness of systems handling large volumes of requests.\n* Provides a clear separation of concerns between task coordination and task execution, simplifying design.\n\nTrade-offs:\n\n* Complexity in managing synchronization and state consistency between master and workers.\n* Overhead of managing communication between master and workers, especially in distributed environments.\n\n## Related Java Design Patterns\n\n* Task Parallelism and Data Parallelism: Master-Worker utilizes these patterns to divide work into tasks or data segments.\n* [Producer-Consumer](https://java-design-patterns.com/patterns/producer-consumer/): Similar in structure but focuses on balancing production and consumption rates; Master-Worker is more about task distribution and aggregation.\n* [Pipeline](https://java-design-patterns.com/patterns/pipeline/): Both organize processing steps but Pipeline arranges them linearly whereas Master-Worker may not impose such a sequence.\n\n## References and Credits\n\n* [Distributed Systems: Principles and Paradigms](https://amzn.to/3UN2vbH)\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n* [Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects](https://amzn.to/3UgC24V)\n"
  },
  {
    "path": "master-worker/etc/master-worker-pattern.urm.puml",
    "content": "@startuml\npackage com.iluwatar.masterworker.system.systemmaster {\n  class ArrayTransposeMaster {\n    + ArrayTransposeMaster(numOfWorkers : int)\n    ~ aggregateData() : ArrayResult\n    ~ setWorkers(num : int) : ArrayList<Worker>\n  }\n  abstract class Master {\n    - allResultData : Hashtable<Integer, Result<T>>\n    - expectedNumResults : int\n    - finalResult : Result<T>\n    - numOfWorkers : int\n    - workers : ArrayList<Worker>\n    ~ Master(numOfWorkers : int)\n    ~ aggregateData() : Result<T> {abstract}\n    - collectResult(data : Result<T>, workerId : int)\n    - divideWork(input : Input<T>)\n    + doWork(input : Input<T>)\n    ~ getAllResultData() : Hashtable<Integer, Result<T>>\n    ~ getExpectedNumResults() : int\n    + getFinalResult() : Result<T>\n    ~ getWorkers() : ArrayList<Worker>\n    + receiveData(data : Result<T>, w : Worker)\n    ~ setWorkers(int) : ArrayList<Worker> {abstract}\n  }\n}\npackage com.iluwatar.masterworker.system {\n  class ArrayTransposeMasterWorker {\n    + ArrayTransposeMasterWorker()\n    ~ setMaster(numOfWorkers : int) : Master\n  }\n  abstract class MasterWorker {\n    - master : Master\n    + MasterWorker(numOfWorkers : int)\n    + getResult(input : Input<T>) : Result<T>\n    ~ setMaster(int) : Master {abstract}\n  }\n}\npackage com.iluwatar.masterworker {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class ArrayInput {\n    + ArrayInput(data : int[][])\n    + divideData(num : int) : ArrayList<Input<T>>\n    ~ makeDivisions(data : int[][], num : int) : int[] {static}\n  }\n  class ArrayResult {\n    + ArrayResult(data : int[][])\n  }\n  class ArrayUtilityMethods {\n    - LOGGER : Logger {static}\n    - RANDOM : Random {static}\n    + ArrayUtilityMethods()\n    + arraysSame(a1 : int[], a2 : int[]) : boolean {static}\n    + createRandomIntMatrix(rows : int, columns : int) : int[][] {static}\n    + matricesSame(m1 : int[][], m2 : int[][]) : boolean {static}\n    + printMatrix(matrix : int[][]) {static}\n  }\n  abstract class Input<T> {\n    + data : T\n    + Input<T>(data : T)\n    + divideData(int) : ArrayList<Input<T>> {abstract}\n  }\n  abstract class Result<T> {\n    + data : T\n    + Result<T>(data : T)\n  }\n}\nMaster -->  \"-finalResult\" Result\nMasterWorker -->  \"-master\" Master\nArrayInput --|> Input \nArrayResult --|> Result \nArrayTransposeMasterWorker --|> MasterWorker \nArrayTransposeMaster --|> Master \n@enduml"
  },
  {
    "path": "master-worker/etc/master-worker.urm.puml",
    "content": "@startuml\npackage com.iluwatar.masterworker.system.systemmaster {\n  class ArrayTransposeMaster {\n    + ArrayTransposeMaster(numOfWorkers : int)\n    ~ aggregateData() : ArrayResult\n    ~ setWorkers(num : int) : ArrayList<Worker>\n  }\n  abstract class Master {\n    - allResultData : Hashtable<Integer, Result<?>>\n    - expectedNumResults : int\n    - finalResult : Result<?>\n    - numOfWorkers : int\n    - workers : List<Worker>\n    ~ Master(numOfWorkers : int)\n    ~ aggregateData() : Result<?> {abstract}\n    - collectResult(data : Result<?>, workerId : int)\n    - divideWork(input : Input<?>)\n    + doWork(input : Input<?>)\n    ~ getAllResultData() : Hashtable<Integer, Result<?>>\n    ~ getExpectedNumResults() : int\n    + getFinalResult() : Result<?>\n    ~ getWorkers() : List<Worker>\n    + receiveData(data : Result<?>, w : Worker)\n    ~ setWorkers(int) : List<Worker> {abstract}\n  }\n}\npackage com.iluwatar.masterworker.system {\n  class ArrayTransposeMasterWorker {\n    + ArrayTransposeMasterWorker()\n    ~ setMaster(numOfWorkers : int) : Master\n  }\n  abstract class MasterWorker {\n    - master : Master\n    + MasterWorker(numOfWorkers : int)\n    + getResult(input : Input<?>) : Result<?>\n    ~ setMaster(int) : Master {abstract}\n  }\n}\npackage com.iluwatar.masterworker {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class ArrayInput {\n    + ArrayInput(data : int[][])\n    + divideData(num : int) : List<Input<int[][]>>\n    ~ makeDivisions(data : int[][], num : int) : int[] {static}\n  }\n  class ArrayResult {\n    + ArrayResult(data : int[][])\n  }\n  class ArrayUtilityMethods {\n    - LOGGER : Logger {static}\n    - RANDOM : SecureRandom {static}\n    + ArrayUtilityMethods()\n    + arraysSame(a1 : int[], a2 : int[]) : boolean {static}\n    + createRandomIntMatrix(rows : int, columns : int) : int[][] {static}\n    + matricesSame(m1 : int[][], m2 : int[][]) : boolean {static}\n    + printMatrix(matrix : int[][]) {static}\n  }\n  abstract class Input<T> {\n    + data : T\n    + Input<T>(data : T)\n    + divideData(int) : List<Input<T>> {abstract}\n  }\n  abstract class Result<T> {\n    + data : T\n    + Result<T>(data : T)\n  }\n}\nMaster -->  \"-finalResult\" Result\nMasterWorker -->  \"-master\" Master\nArrayInput --|> Input \nArrayResult --|> Result \nArrayTransposeMasterWorker --|> MasterWorker \nArrayTransposeMaster --|> Master \n@enduml"
  },
  {
    "path": "master-worker/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>master-worker</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.masterworker.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "master-worker/src/main/java/com/iluwatar/masterworker/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker;\n\nimport com.iluwatar.masterworker.system.ArrayTransposeMasterWorker;\nimport com.iluwatar.masterworker.system.MasterWorker;\nimport com.iluwatar.masterworker.system.systemmaster.ArrayTransposeMaster;\nimport com.iluwatar.masterworker.system.systemmaster.Master;\nimport com.iluwatar.masterworker.system.systemworkers.ArrayTransposeWorker;\nimport com.iluwatar.masterworker.system.systemworkers.Worker;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The <b><em>Master-Worker</em></b> pattern is used when the problem at hand can be solved by\n * dividing into multiple parts which need to go through the same computation and may need to be\n * aggregated to get final result. Parallel processing is performed using a system consisting of a\n * master and some number of workers, where a master divides the work among the workers, gets the\n * result back from them and assimilates all the results to give final result. The only\n * communication is between the master and the worker - none of the workers communicate among one\n * another and the user only communicates with the master to get required job done.\n *\n * <p>In our example, we have generic abstract classes {@link MasterWorker}, {@link Master} and\n * {@link Worker} which have to be extended by the classes which will perform the specific job at\n * hand (in this case finding transpose of matrix, done by {@link ArrayTransposeMasterWorker},\n * {@link ArrayTransposeMaster} and {@link ArrayTransposeWorker}). The Master class divides the work\n * into parts to be given to the workers, collects the results from the workers and aggregates it\n * when all workers have responded before returning the solution. The Worker class extends the\n * Thread class to enable parallel processing, and does the work once the data has been received\n * from the Master. The MasterWorker contains a reference to the Master class, gets the input from\n * the App and passes it on to the Master. These 3 classes define the system which computes the\n * result. We also have 2 abstract classes {@link Input} and {@link Result}, which contain the input\n * data and result data respectively. The Input class also has an abstract method divideData which\n * defines how the data is to be divided into segments. These classes are extended by {@link\n * ArrayInput} and {@link ArrayResult}.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var mw = new ArrayTransposeMasterWorker();\n    var rows = 10;\n    var columns = 20;\n    var inputMatrix = ArrayUtilityMethods.createRandomIntMatrix(rows, columns);\n    var input = new ArrayInput(inputMatrix);\n    var result = (ArrayResult) mw.getResult(input);\n    if (result != null) {\n      ArrayUtilityMethods.printMatrix(inputMatrix);\n      ArrayUtilityMethods.printMatrix(result.data);\n    } else {\n      LOGGER.info(\"Please enter non-zero input\");\n    }\n  }\n}\n"
  },
  {
    "path": "master-worker/src/main/java/com/iluwatar/masterworker/ArrayInput.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\n/** Class ArrayInput extends abstract class {@link Input} and contains data of type int[][]. */\npublic class ArrayInput extends Input<int[][]> {\n\n  public ArrayInput(int[][] data) {\n    super(data);\n  }\n\n  static int[] makeDivisions(int[][] data, int num) {\n    var initialDivision = data.length / num; // equally dividing\n    var divisions = new int[num];\n    Arrays.fill(divisions, initialDivision);\n    if (initialDivision * num != data.length) {\n      var extra = data.length - initialDivision * num;\n      var l = 0;\n      // equally dividing extra among all parts\n      while (extra > 0) {\n        divisions[l] = divisions[l] + 1;\n        extra--;\n        if (l == num - 1) {\n          l = 0;\n        } else {\n          l++;\n        }\n      }\n    }\n    return divisions;\n  }\n\n  @Override\n  public List<Input<int[][]>> divideData(int num) {\n    if (this.data == null) {\n      return null;\n    } else {\n      var divisions = makeDivisions(this.data, num);\n      var result = new ArrayList<Input<int[][]>>(num);\n      var rowsDone = 0; // number of rows divided so far\n      for (var i = 0; i < num; i++) {\n        var rows = divisions[i];\n        if (rows != 0) {\n          var divided = new int[rows][this.data[0].length];\n          System.arraycopy(this.data, rowsDone, divided, 0, rows);\n          rowsDone += rows;\n          var dividedInput = new ArrayInput(divided);\n          result.add(dividedInput);\n        } else {\n          break; // rest of divisions will also be 0\n        }\n      }\n      return result;\n    }\n  }\n}\n"
  },
  {
    "path": "master-worker/src/main/java/com/iluwatar/masterworker/ArrayResult.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker;\n\n/** Class ArrayResult extends abstract class {@link Result} and contains data of type int[][]. */\npublic class ArrayResult extends Result<int[][]> {\n\n  public ArrayResult(int[][] data) {\n    super(data);\n  }\n}\n"
  },
  {
    "path": "master-worker/src/main/java/com/iluwatar/masterworker/ArrayUtilityMethods.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker;\n\nimport java.security.SecureRandom;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Class ArrayUtilityMethods has some utility methods for matrices and arrays. */\n@Slf4j\npublic class ArrayUtilityMethods {\n\n  private static final SecureRandom RANDOM = new SecureRandom();\n\n  /**\n   * Method arraysSame compares 2 arrays @param a1 and @param a2 and @return whether their values\n   * are equal (boolean).\n   */\n  public static boolean arraysSame(int[] a1, int[] a2) {\n    // compares if 2 arrays have the same value\n    if (a1.length != a2.length) {\n      return false;\n    } else {\n      var answer = false;\n      for (var i = 0; i < a1.length; i++) {\n        if (a1[i] == a2[i]) {\n          answer = true;\n        } else {\n          answer = false;\n          break;\n        }\n      }\n      return answer;\n    }\n  }\n\n  /**\n   * Method matricesSame compares 2 matrices @param m1 and @param m2 and @return whether their\n   * values are equal (boolean).\n   */\n  public static boolean matricesSame(int[][] m1, int[][] m2) {\n    if (m1.length != m2.length) {\n      return false;\n    } else {\n      var answer = false;\n      for (var i = 0; i < m1.length; i++) {\n        if (arraysSame(m1[i], m2[i])) {\n          answer = true;\n        } else {\n          answer = false;\n          break;\n        }\n      }\n      return answer;\n    }\n  }\n\n  /**\n   * Method createRandomIntMatrix creates a random matrix of size @param rows and @param columns.\n   *\n   * @return it (int[][]).\n   */\n  public static int[][] createRandomIntMatrix(int rows, int columns) {\n    var matrix = new int[rows][columns];\n    for (var i = 0; i < rows; i++) {\n      for (var j = 0; j < columns; j++) {\n        // filling cells in matrix\n        matrix[i][j] = RANDOM.nextInt(10);\n      }\n    }\n    return matrix;\n  }\n\n  /** Method printMatrix prints input matrix @param matrix. */\n  public static void printMatrix(int[][] matrix) {\n    // prints out int[][]\n    for (var ints : matrix) {\n      for (var j = 0; j < matrix[0].length; j++) {\n        LOGGER.info(ints[j] + \" \");\n      }\n      LOGGER.info(\"\");\n    }\n  }\n}\n"
  },
  {
    "path": "master-worker/src/main/java/com/iluwatar/masterworker/Input.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker;\n\nimport java.util.List;\n\n/**\n * The abstract Input class, having 1 public field which contains input data, and abstract method\n * divideData.\n *\n * @param <T> T will be type of data.\n */\npublic abstract class Input<T> {\n\n  public final T data;\n\n  public Input(T data) {\n    this.data = data;\n  }\n\n  public abstract List<Input<T>> divideData(int num);\n}\n"
  },
  {
    "path": "master-worker/src/main/java/com/iluwatar/masterworker/Result.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker;\n\n/**\n * The abstract Result class, which contains 1 public field containing result data.\n *\n * @param <T> T will be type of data.\n */\npublic abstract class Result<T> {\n\n  public final T data;\n\n  public Result(T data) {\n    this.data = data;\n  }\n}\n"
  },
  {
    "path": "master-worker/src/main/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorker.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker.system;\n\nimport com.iluwatar.masterworker.system.systemmaster.ArrayTransposeMaster;\nimport com.iluwatar.masterworker.system.systemmaster.Master;\n\n/**\n * Class ArrayTransposeMasterWorker extends abstract class {@link MasterWorker} and specifically\n * solves the problem of finding transpose of input array.\n */\npublic class ArrayTransposeMasterWorker extends MasterWorker {\n\n  public ArrayTransposeMasterWorker() {\n    super(4);\n  }\n\n  @Override\n  Master setMaster(int numOfWorkers) {\n    return new ArrayTransposeMaster(numOfWorkers);\n  }\n}\n"
  },
  {
    "path": "master-worker/src/main/java/com/iluwatar/masterworker/system/MasterWorker.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker.system;\n\nimport com.iluwatar.masterworker.Input;\nimport com.iluwatar.masterworker.Result;\nimport com.iluwatar.masterworker.system.systemmaster.Master;\n\n/** The abstract MasterWorker class which contains reference to master. */\npublic abstract class MasterWorker {\n  private final Master master;\n\n  public MasterWorker(int numOfWorkers) {\n    this.master = setMaster(numOfWorkers);\n  }\n\n  abstract Master setMaster(int numOfWorkers);\n\n  public Result<?> getResult(Input<?> input) {\n    this.master.doWork(input);\n    return this.master.getFinalResult();\n  }\n}\n"
  },
  {
    "path": "master-worker/src/main/java/com/iluwatar/masterworker/system/systemmaster/ArrayTransposeMaster.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker.system.systemmaster;\n\nimport com.iluwatar.masterworker.ArrayResult;\nimport com.iluwatar.masterworker.system.systemworkers.ArrayTransposeWorker;\nimport com.iluwatar.masterworker.system.systemworkers.Worker;\nimport java.util.ArrayList;\nimport java.util.stream.Collectors;\nimport java.util.stream.IntStream;\n\n/**\n * Class ArrayTransposeMaster extends abstract class {@link Master} and contains definition of\n * aggregateData, which will obtain final result from all data obtained and for setWorkers.\n */\npublic class ArrayTransposeMaster extends Master {\n  public ArrayTransposeMaster(int numOfWorkers) {\n    super(numOfWorkers);\n  }\n\n  @Override\n  ArrayList<Worker> setWorkers(int num) {\n    // i+1 will be id\n    return IntStream.range(0, num)\n        .mapToObj(i -> new ArrayTransposeWorker(this, i + 1))\n        .collect(Collectors.toCollection(() -> new ArrayList<>(num)));\n  }\n\n  @Override\n  ArrayResult aggregateData() {\n    // number of rows in final result is number of rows in any of obtained results from workers\n    var allResultData = this.getAllResultData();\n    var rows = ((ArrayResult) allResultData.elements().nextElement()).data.length;\n    var elements = allResultData.elements();\n    var columns = 0; // columns = sum of number of columns in all results obtained from workers\n    while (elements.hasMoreElements()) {\n      columns += ((ArrayResult) elements.nextElement()).data[0].length;\n    }\n    var resultData = new int[rows][columns];\n    var columnsDone = 0; // columns aggregated so far\n    var workers = this.getWorkers();\n    for (var i = 0; i < this.getExpectedNumResults(); i++) {\n      // result obtained from ith worker\n      var worker = workers.get(i);\n      var workerId = worker.getWorkerId();\n      var work = ((ArrayResult) allResultData.get(workerId)).data;\n      for (var m = 0; m < work.length; m++) {\n        // m = row number, n = columns number\n        System.arraycopy(work[m], 0, resultData[m], columnsDone, work[0].length);\n      }\n      columnsDone += work[0].length;\n    }\n    return new ArrayResult(resultData);\n  }\n}\n"
  },
  {
    "path": "master-worker/src/main/java/com/iluwatar/masterworker/system/systemmaster/Master.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker.system.systemmaster;\n\nimport com.iluwatar.masterworker.Input;\nimport com.iluwatar.masterworker.Result;\nimport com.iluwatar.masterworker.system.systemworkers.Worker;\nimport java.util.Hashtable;\nimport java.util.List;\nimport lombok.Getter;\n\n/**\n * The abstract Master class which contains private fields numOfWorkers (number of workers), workers\n * (arraylist of workers), expectedNumResults (number of divisions of input data, same as expected\n * number of results), allResultData (hashtable of results obtained from workers, mapped by their\n * ids) and finalResult (aggregated from allResultData).\n */\npublic abstract class Master {\n  private final int numOfWorkers;\n  private final List<Worker> workers;\n  private final Hashtable<Integer, Result<?>> allResultData;\n  private int expectedNumResults;\n  @Getter private Result<?> finalResult;\n\n  Master(int numOfWorkers) {\n    this.numOfWorkers = numOfWorkers;\n    this.workers = setWorkers(numOfWorkers);\n    this.expectedNumResults = 0;\n    this.allResultData = new Hashtable<>(numOfWorkers);\n    this.finalResult = null;\n  }\n\n  Hashtable<Integer, Result<?>> getAllResultData() {\n    return this.allResultData;\n  }\n\n  int getExpectedNumResults() {\n    return this.expectedNumResults;\n  }\n\n  List<Worker> getWorkers() {\n    return this.workers;\n  }\n\n  abstract List<Worker> setWorkers(int num);\n\n  public void doWork(Input<?> input) {\n    divideWork(input);\n  }\n\n  private void divideWork(Input<?> input) {\n    var dividedInput = input.divideData(numOfWorkers);\n    if (dividedInput != null) {\n      this.expectedNumResults = dividedInput.size();\n      for (var i = 0; i < this.expectedNumResults; i++) {\n        // ith division given to ith worker in this.workers\n        this.workers.get(i).setReceivedData(this, dividedInput.get(i));\n        this.workers.get(i).start();\n      }\n      for (var i = 0; i < this.expectedNumResults; i++) {\n        try {\n          this.workers.get(i).join();\n        } catch (InterruptedException e) {\n          System.err.println(\"Error while executing thread\");\n        }\n      }\n    }\n  }\n\n  public void receiveData(Result<?> data, Worker w) {\n    // check if we can receive... if yes:\n    collectResult(data, w.getWorkerId());\n  }\n\n  private void collectResult(Result<?> data, int workerId) {\n    this.allResultData.put(workerId, data);\n    if (this.allResultData.size() == this.expectedNumResults) {\n      // all data received\n      this.finalResult = aggregateData();\n    }\n  }\n\n  abstract Result<?> aggregateData();\n}\n"
  },
  {
    "path": "master-worker/src/main/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorker.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker.system.systemworkers;\n\nimport com.iluwatar.masterworker.ArrayInput;\nimport com.iluwatar.masterworker.ArrayResult;\nimport com.iluwatar.masterworker.system.systemmaster.Master;\n\n/**\n * Class ArrayTransposeWorker extends abstract class {@link Worker} and defines method\n * executeOperation(), to be performed on data received from master.\n */\npublic class ArrayTransposeWorker extends Worker {\n\n  public ArrayTransposeWorker(Master master, int id) {\n    super(master, id);\n  }\n\n  @Override\n  ArrayResult executeOperation() {\n    // number of rows in result matrix is equal to number of columns in input matrix and vice versa\n    var arrayInput = (ArrayInput) this.getReceivedData();\n    final var rows = arrayInput.data[0].length;\n    final var cols = arrayInput.data.length;\n    var resultData = new int[rows][cols];\n    for (var i = 0; i < cols; i++) {\n      for (var j = 0; j < rows; j++) {\n        // flipping element positions along diagonal\n        resultData[j][i] = arrayInput.data[i][j];\n      }\n    }\n    return new ArrayResult(resultData);\n  }\n}\n"
  },
  {
    "path": "master-worker/src/main/java/com/iluwatar/masterworker/system/systemworkers/Worker.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker.system.systemworkers;\n\nimport com.iluwatar.masterworker.Input;\nimport com.iluwatar.masterworker.Result;\nimport com.iluwatar.masterworker.system.systemmaster.Master;\nimport lombok.Getter;\n\n/**\n * The abstract Worker class which extends Thread class to enable parallel processing. Contains\n * fields master(holding reference to master), workerId (unique id) and receivedData(from master).\n */\npublic abstract class Worker extends Thread {\n  private final Master master;\n  @Getter private final int workerId;\n  private Input<?> receivedData;\n\n  Worker(Master master, int id) {\n    this.master = master;\n    this.workerId = id;\n    this.receivedData = null;\n  }\n\n  Input<?> getReceivedData() {\n    return this.receivedData;\n  }\n\n  public void setReceivedData(Master m, Input<?> i) {\n    // check if we are ready to receive... if yes:\n    this.receivedData = i;\n  }\n\n  abstract Result<?> executeOperation();\n\n  private void sendToMaster(Result<?> data) {\n    this.master.receiveData(data, this);\n  }\n\n  public void run() { // from Thread class\n    var work = executeOperation();\n    sendToMaster(work);\n  }\n}\n"
  },
  {
    "path": "master-worker/src/test/java/com/iluwatar/masterworker/ArrayInputTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker;\n\nimport static com.iluwatar.masterworker.ArrayUtilityMethods.matricesSame;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.Random;\nimport org.junit.jupiter.api.Test;\n\n/** Testing divideData method in {@link ArrayInput} class. */\nclass ArrayInputTest {\n\n  @Test\n  void divideDataTest() {\n    var rows = 10;\n    var columns = 10;\n    var inputMatrix = new int[rows][columns];\n    var rand = new Random();\n    for (var i = 0; i < rows; i++) {\n      for (var j = 0; j < columns; j++) {\n        inputMatrix[i][j] = rand.nextInt(10);\n      }\n    }\n    var i = new ArrayInput(inputMatrix);\n    var table = i.divideData(4);\n    var division1 = new int[][] {inputMatrix[0], inputMatrix[1], inputMatrix[2]};\n    var division2 = new int[][] {inputMatrix[3], inputMatrix[4], inputMatrix[5]};\n    var division3 = new int[][] {inputMatrix[6], inputMatrix[7]};\n    var division4 = new int[][] {inputMatrix[8], inputMatrix[9]};\n    assertTrue(\n        matricesSame(table.get(0).data, division1)\n            && matricesSame(table.get(1).data, division2)\n            && matricesSame(table.get(2).data, division3)\n            && matricesSame(table.get(3).data, division4));\n  }\n}\n"
  },
  {
    "path": "master-worker/src/test/java/com/iluwatar/masterworker/ArrayUtilityMethodsTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** Testing utility methods in {@link ArrayUtilityMethods} class. */\nclass ArrayUtilityMethodsTest {\n\n  @Test\n  void arraysSameTest() {\n    var arr1 = new int[] {1, 4, 2, 6};\n    var arr2 = new int[] {1, 4, 2, 6};\n    assertTrue(ArrayUtilityMethods.arraysSame(arr1, arr2));\n  }\n\n  @Test\n  void matricesSameTest() {\n    var matrix1 = new int[][] {{1, 4, 2, 6}, {5, 8, 6, 7}};\n    var matrix2 = new int[][] {{1, 4, 2, 6}, {5, 8, 6, 7}};\n    assertTrue(ArrayUtilityMethods.matricesSame(matrix1, matrix2));\n  }\n}\n"
  },
  {
    "path": "master-worker/src/test/java/com/iluwatar/masterworker/system/ArrayTransposeMasterWorkerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker.system;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.masterworker.ArrayInput;\nimport com.iluwatar.masterworker.ArrayResult;\nimport com.iluwatar.masterworker.ArrayUtilityMethods;\nimport org.junit.jupiter.api.Test;\n\n/** Testing getResult method in {@link ArrayTransposeMasterWorker} class. */\nclass ArrayTransposeMasterWorkerTest {\n\n  @Test\n  void getResultTest() {\n    var atmw = new ArrayTransposeMasterWorker();\n    var matrix =\n        new int[][] {\n          {1, 2, 3, 4, 5},\n          {1, 2, 3, 4, 5},\n          {1, 2, 3, 4, 5},\n          {1, 2, 3, 4, 5},\n          {1, 2, 3, 4, 5}\n        };\n    var matrixTranspose =\n        new int[][] {\n          {1, 1, 1, 1, 1},\n          {2, 2, 2, 2, 2},\n          {3, 3, 3, 3, 3},\n          {4, 4, 4, 4, 4},\n          {5, 5, 5, 5, 5}\n        };\n    var i = new ArrayInput(matrix);\n    var r = (ArrayResult) atmw.getResult(i);\n    assertTrue(ArrayUtilityMethods.matricesSame(r.data, matrixTranspose));\n  }\n}\n"
  },
  {
    "path": "master-worker/src/test/java/com/iluwatar/masterworker/system/systemworkers/ArrayTransposeWorkerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.masterworker.system.systemworkers;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.masterworker.ArrayInput;\nimport com.iluwatar.masterworker.ArrayUtilityMethods;\nimport com.iluwatar.masterworker.system.systemmaster.ArrayTransposeMaster;\nimport org.junit.jupiter.api.Test;\n\n/** Testing executeOperation method in {@link ArrayTransposeWorker} class. */\nclass ArrayTransposeWorkerTest {\n\n  @Test\n  void executeOperationTest() {\n    var atm = new ArrayTransposeMaster(1);\n    var atw = new ArrayTransposeWorker(atm, 1);\n    var matrix = new int[][] {{2, 4}, {3, 5}};\n    var matrixTranspose = new int[][] {{2, 3}, {4, 5}};\n    var i = new ArrayInput(matrix);\n    atw.setReceivedData(atm, i);\n    var r = atw.executeOperation();\n    assertTrue(ArrayUtilityMethods.matricesSame(r.data, matrixTranspose));\n  }\n}\n"
  },
  {
    "path": "mediator/README.md",
    "content": "---\ntitle: \"Mediator Pattern in Java: Simplifying Object Communications in Complex Systems\"\nshortTitle: Mediator\ndescription: \"Learn how the Mediator Design Pattern reduces complexity in object communication and improves system maintainability with a centralized mediator in Java. Explore examples and implementation.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Decoupling\n  - Gang of Four\n  - Messaging\n  - Object composition\n---\n\n## Also known as\n\n* Controller\n\n## Intent of Mediator Design Pattern\n\nThe Mediator design pattern is intended to reduce the complexity of communication between multiple objects or classes in a system. It achieves this by providing a centralized mediator class that handles the interactions between different classes, thus reducing their direct dependencies on each other.\n\n## Detailed Explanation of Mediator Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine an air traffic control system at a busy airport, where the air traffic controller acts as a mediator. In this scenario, numerous airplanes wish to take off, land, or navigate around the airport's airspace. Instead of each pilot communicating directly with every other pilot, which could lead to confusion and potential accidents, all communication goes through the air traffic controller. The controller receives requests, processes them, and gives clear, organized instructions to each pilot. This centralized system reduces the complexity of communications and ensures safety and efficiency in managing the airport's operations. This is analogous to the Mediator design pattern in software, where a central mediator class handles and coordinates the interaction between different objects or systems.\n\nIn plain words\n\n> Mediator decouples a set of classes by forcing their communications flow through a mediating object.\n\nWikipedia says\n\n> In software engineering, the mediator pattern defines an object that encapsulates how a set of  objects interact. This pattern is considered to be a behavioral pattern due to the way it can  alter the program's running behavior. In object-oriented programming, programs often consist of  many classes. Business logic and computation are distributed among these classes. However, as  more classes are added to a program, especially during maintenance and/or refactoring, the  problem of communication between these classes may become more complex. This makes the program  harder to read and maintain. Furthermore, it can become difficult to change the program, since  any change may affect code in several other classes. With the mediator pattern, communication  between objects is encapsulated within a mediator object. Objects no longer communicate directly  with each other, but instead communicate through the mediator. This reduces the dependencies  between communicating objects, thereby reducing coupling.\n\nSequence diagram\n\n![Mediator sequence diagram](./etc/mediator-sequence-diagram.png)\n\n## Programmatic Example of Mediator Pattern in Java\n\nIn this example, the mediator encapsulates how a set of objects interact. Instead of referring to each other directly, they use the mediator interface.\n\nThe party members `Rogue`, `Wizard`, `Hobbit`, and `Hunter` all inherit from the `PartyMemberBase`implementing the `PartyMember` interface.\n\n```java\npublic interface PartyMember {\n\n  void joinedParty(Party party);\n\n  void partyAction(Action action);\n\n  void act(Action action);\n}\n\n@Slf4j\npublic abstract class PartyMemberBase implements PartyMember {\n\n  protected Party party;\n\n  @Override\n  public void joinedParty(Party party) {\n    LOGGER.info(\"{} joins the party\", this);\n    this.party = party;\n  }\n\n  @Override\n  public void partyAction(Action action) {\n    LOGGER.info(\"{} {}\", this, action.getDescription());\n  }\n\n  @Override\n  public void act(Action action) {\n    if (party != null) {\n      LOGGER.info(\"{} {}\", this, action);\n      party.act(this, action);\n    }\n  }\n\n  @Override\n  public abstract String toString();\n}\n\npublic class Rogue extends PartyMemberBase {\n\n  @Override\n  public String toString() {\n    return \"Rogue\";\n  }\n}\n\n// Wizard, Hobbit, and Hunter are implemented similarly\n```\n\nOur mediator system consists of `Party` interface and its implementation.\n\n```java\npublic interface Party {\n\n  void addMember(PartyMember member);\n\n  void act(PartyMember actor, Action action);\n}\n\npublic class PartyImpl implements Party {\n\n  private final List<PartyMember> members;\n\n  public PartyImpl() {\n    members = new ArrayList<>();\n  }\n\n  @Override\n  public void act(PartyMember actor, Action action) {\n    for (var member : members) {\n      if (!member.equals(actor)) {\n        member.partyAction(action);\n      }\n    }\n  }\n\n  @Override\n  public void addMember(PartyMember member) {\n    members.add(member);\n    member.joinedParty(this);\n  }\n}\n```\n\nHere's a demo showing the mediator pattern in action.\n\n```java\npublic static void main(String[] args) {\n\n    // create party and members\n    Party party = new PartyImpl();\n    var hobbit = new Hobbit();\n    var wizard = new Wizard();\n    var rogue = new Rogue();\n    var hunter = new Hunter();\n\n    // add party members\n    party.addMember(hobbit);\n    party.addMember(wizard);\n    party.addMember(rogue);\n    party.addMember(hunter);\n\n    // perform actions -> the other party members\n    // are notified by the party\n    hobbit.act(Action.ENEMY);\n    wizard.act(Action.TALE);\n    rogue.act(Action.GOLD);\n    hunter.act(Action.HUNT);\n}\n```\n\nHere's the console output from running the example.\n\n```\n14:05:15.081 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hobbit joins the party\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Wizard joins the party\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Rogue joins the party\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hunter joins the party\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hobbit spotted enemies\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Wizard runs for cover\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Rogue runs for cover\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hunter runs for cover\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Wizard tells a tale\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hobbit comes to listen\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Rogue comes to listen\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hunter comes to listen\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Rogue found gold\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hobbit takes his share of the gold\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Wizard takes his share of the gold\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hunter takes his share of the gold\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hunter hunted a rabbit\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Hobbit arrives for dinner\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Wizard arrives for dinner\n14:05:15.083 [main] INFO com.iluwatar.mediator.PartyMemberBase -- Rogue arrives for dinner\n```\n\n## When to Use the Mediator Pattern in Java\n\nUse the Mediator pattern when\n\n* A set of objects communicate in well-defined but complex ways. The resulting interdependencies are unstructured and difficult to understand\n* Reusing an object is difficult because it refers to and communicates with many other objects\n* A behavior that's distributed between several classes should be customizable without a lot of subclassing\n\n## Real-World Applications of Mediator Pattern in Java\n\n* All scheduleXXX() methods of [java.util.Timer](http://docs.oracle.com/javase/8/docs/api/java/util/Timer.html)\n* [java.util.concurrent.Executor#execute()](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-)\n* submit() and invokeXXX() methods of [java.util.concurrent.ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html)\n* scheduleXXX() methods of [java.util.concurrent.ScheduledExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html)\n* [java.lang.reflect.Method#invoke()](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#invoke-java.lang.Object-java.lang.Object...-)\n* Java Message Service (JMS) uses mediators to handle message exchanges between clients and servers.\n* JavaBeans property change support class (java.beans.PropertyChangeSupport) acts as a mediator by handling communication between beans regarding property changes.\n\n## Benefits and Trade-offs of Mediator Pattern\n\nBenefits:\n\n* Reduces coupling between components of a program, fostering better organization and easier maintenance.\n* Centralizes control. The mediator pattern centralizes the control logic, making it easier to comprehend and manage.\n\nTrade-offs:\n\n* Mediator can become a god object coupled with all classes in the system, gaining too much responsibility and complexity.\n\n## Related Java Design Patterns\n\n* [Observer](https://java-design-patterns.com/patterns/observer/): Often used together, where the mediator pattern can use the observer pattern to notify various objects about state changes. Mediators effectively act as a channel of communication managed by an observer.\n* [Facade](https://java-design-patterns.com/patterns/facade/): Mediator simplifies communication between components, similar to how a facade simplifies a subsystem interface, but a mediator’s colleagues can communicate back to the mediator.\n* [Command](https://java-design-patterns.com/patterns/command/): Commands can be mediated as they are dispatched to their receivers, encapsulating a request as an object.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n"
  },
  {
    "path": "mediator/etc/mediator.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <interface id=\"1\" language=\"java\" name=\"com.iluwatar.mediator.Party\" project=\"mediator\" \n    file=\"/mediator/src/main/java/com/iluwatar/mediator/Party.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"206\" x=\"867\" y=\"467\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.mediator.Rogue\" project=\"mediator\" \n    file=\"/mediator/src/main/java/com/iluwatar/mediator/Rogue.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"131\" x=\"-20\" y=\"467\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <enumeration id=\"3\" language=\"java\" name=\"com.iluwatar.mediator.Action\" project=\"mediator\" \n    file=\"/mediator/src/main/java/com/iluwatar/mediator/Action.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"250\" width=\"155\" x=\"99\" y=\"177\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.mediator.Hobbit\" project=\"mediator\" \n    file=\"/mediator/src/main/java/com/iluwatar/mediator/Hobbit.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"131\" x=\"151\" y=\"467\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"5\" language=\"java\" name=\"com.iluwatar.mediator.PartyMember\" project=\"mediator\" \n    file=\"/mediator/src/main/java/com/iluwatar/mediator/PartyMember.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"163\" x=\"664\" y=\"467\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.mediator.Wizard\" project=\"mediator\" \n    file=\"/mediator/src/main/java/com/iluwatar/mediator/Wizard.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"131\" x=\"322\" y=\"467\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.mediator.PartyMemberBase\" project=\"mediator\" \n    file=\"/mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"159\" width=\"163\" x=\"413\" y=\"177\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.mediator.PartyImpl\" project=\"mediator\" \n    file=\"/mediator/src/main/java/com/iluwatar/mediator/PartyImpl.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"206\" x=\"765\" y=\"177\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"9\" language=\"java\" name=\"com.iluwatar.mediator.Hunter\" project=\"mediator\" \n    file=\"/mediator/src/main/java/com/iluwatar/mediator/Hunter.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"131\" x=\"493\" y=\"467\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <realization id=\"10\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </realization>  \n  <association id=\"11\">    \n    <end type=\"SOURCE\" refId=\"8\" navigable=\"false\">      \n      <attribute id=\"12\" name=\"members\"/>      \n      <multiplicity id=\"13\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"14\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <generalization id=\"15\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <realization id=\"16\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </realization>  \n  <generalization id=\"17\">    \n    <end type=\"SOURCE\" refId=\"9\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <generalization id=\"18\">    \n    <end type=\"SOURCE\" refId=\"6\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <association id=\"19\">    \n    <end type=\"SOURCE\" refId=\"7\" navigable=\"false\">      \n      <attribute id=\"20\" name=\"party\"/>      \n      <multiplicity id=\"21\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "mediator/etc/mediator.urm.puml",
    "content": "@startuml\npackage com.iluwatar.mediator {\n  enum Action {\n    + ENEMY {static}\n    + GOLD {static}\n    + HUNT {static}\n    + NONE {static}\n    + TALE {static}\n    - description : String\n    - title : String\n    + getDescription() : String\n    + toString() : String\n    + valueOf(name : String) : Action {static}\n    + values() : Action[] {static}\n  }\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Hobbit {\n    + Hobbit()\n    + toString() : String\n  }\n  class Hunter {\n    + Hunter()\n    + toString() : String\n  }\n  interface Party {\n    + act(PartyMember, Action) {abstract}\n    + addMember(PartyMember) {abstract}\n  }\n  class PartyImpl {\n    - members : List<PartyMember>\n    + PartyImpl()\n    + act(actor : PartyMember, action : Action)\n    + addMember(member : PartyMember)\n  }\n  interface PartyMember {\n    + act(Action) {abstract}\n    + joinedParty(Party) {abstract}\n    + partyAction(Action) {abstract}\n  }\n  abstract class PartyMemberBase {\n    - LOGGER : Logger {static}\n    # party : Party\n    + PartyMemberBase()\n    + act(action : Action)\n    + joinedParty(party : Party)\n    + partyAction(action : Action)\n    + toString() : String {abstract}\n  }\n  class Rogue {\n    + Rogue()\n    + toString() : String\n  }\n  class Wizard {\n    + Wizard()\n    + toString() : String\n  }\n}\nPartyImpl -->  \"-members\" PartyMember\nPartyMemberBase -->  \"-party\" Party\nHobbit --|> PartyMemberBase \nHunter --|> PartyMemberBase \nPartyImpl ..|> Party \nPartyMemberBase ..|> PartyMember \nRogue --|> PartyMemberBase \nWizard --|> PartyMemberBase \n@enduml"
  },
  {
    "path": "mediator/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>mediator</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-params</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.mediator.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "mediator/src/main/java/com/iluwatar/mediator/Action.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\nimport lombok.Getter;\n\n/** Action enumeration. */\npublic enum Action {\n  HUNT(\"hunted a rabbit\", \"arrives for dinner\"),\n  TALE(\"tells a tale\", \"comes to listen\"),\n  GOLD(\"found gold\", \"takes his share of the gold\"),\n  ENEMY(\"spotted enemies\", \"runs for cover\"),\n  NONE(\"\", \"\");\n\n  private final String title;\n  @Getter private final String description;\n\n  Action(String title, String description) {\n    this.title = title;\n    this.description = description;\n  }\n\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "mediator/src/main/java/com/iluwatar/mediator/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\n/**\n * The Mediator pattern defines an object that encapsulates how a set of objects interact. This\n * pattern is considered to be a behavioral pattern due to the way it can alter the program's\n * running behavior.\n *\n * <p>Usually a program is made up of a large number of classes. So the logic and computation is\n * distributed among these classes. However, as more classes are developed in a program, especially\n * during maintenance and/or refactoring, the problem of communication between these classes may\n * become more complex. This makes the program harder to read and maintain. Furthermore, it can\n * become difficult to change the program, since any change may affect code in several other\n * classes.\n *\n * <p>With the Mediator pattern, communication between objects is encapsulated with a mediator\n * object. Objects no longer communicate directly with each other, but instead communicate through\n * the mediator. This reduces the dependencies between communicating objects, thereby lowering the\n * coupling.\n *\n * <p>In this example the mediator encapsulates how a set of objects ({@link PartyMember}) interact.\n * Instead of referring to each other directly they use the mediator ({@link Party}) interface.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    // create party and members\n    Party party = new PartyImpl();\n    var hobbit = new Hobbit();\n    var wizard = new Wizard();\n    var rogue = new Rogue();\n    var hunter = new Hunter();\n\n    // add party members\n    party.addMember(hobbit);\n    party.addMember(wizard);\n    party.addMember(rogue);\n    party.addMember(hunter);\n\n    // perform actions -> the other party members\n    // are notified by the party\n    hobbit.act(Action.ENEMY);\n    wizard.act(Action.TALE);\n    rogue.act(Action.GOLD);\n    hunter.act(Action.HUNT);\n  }\n}\n"
  },
  {
    "path": "mediator/src/main/java/com/iluwatar/mediator/Hobbit.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\n/** Hobbit party member. */\npublic class Hobbit extends PartyMemberBase {\n\n  @Override\n  public String toString() {\n    return \"Hobbit\";\n  }\n}\n"
  },
  {
    "path": "mediator/src/main/java/com/iluwatar/mediator/Hunter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\n/** Hunter party member. */\npublic class Hunter extends PartyMemberBase {\n\n  @Override\n  public String toString() {\n    return \"Hunter\";\n  }\n}\n"
  },
  {
    "path": "mediator/src/main/java/com/iluwatar/mediator/Party.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\n/** Party interface. */\npublic interface Party {\n\n  void addMember(PartyMember member);\n\n  void act(PartyMember actor, Action action);\n}\n"
  },
  {
    "path": "mediator/src/main/java/com/iluwatar/mediator/PartyImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** Party implementation. */\npublic class PartyImpl implements Party {\n\n  private final List<PartyMember> members;\n\n  public PartyImpl() {\n    members = new ArrayList<>();\n  }\n\n  @Override\n  public void act(PartyMember actor, Action action) {\n    for (var member : members) {\n      if (!member.equals(actor)) {\n        member.partyAction(action);\n      }\n    }\n  }\n\n  @Override\n  public void addMember(PartyMember member) {\n    members.add(member);\n    member.joinedParty(this);\n  }\n}\n"
  },
  {
    "path": "mediator/src/main/java/com/iluwatar/mediator/PartyMember.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\n/** Interface for party members interacting with {@link Party}. */\npublic interface PartyMember {\n\n  void joinedParty(Party party);\n\n  void partyAction(Action action);\n\n  void act(Action action);\n}\n"
  },
  {
    "path": "mediator/src/main/java/com/iluwatar/mediator/PartyMemberBase.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Abstract base class for party members. */\n@Slf4j\npublic abstract class PartyMemberBase implements PartyMember {\n\n  protected Party party;\n\n  @Override\n  public void joinedParty(Party party) {\n    LOGGER.info(\"{} joins the party\", this);\n    this.party = party;\n  }\n\n  @Override\n  public void partyAction(Action action) {\n    LOGGER.info(\"{} {}\", this, action.getDescription());\n  }\n\n  @Override\n  public void act(Action action) {\n    if (party != null) {\n      LOGGER.info(\"{} {}\", this, action);\n      party.act(this, action);\n    }\n  }\n\n  @Override\n  public abstract String toString();\n}\n"
  },
  {
    "path": "mediator/src/main/java/com/iluwatar/mediator/Rogue.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\n/** Rogue party member. */\npublic class Rogue extends PartyMemberBase {\n\n  @Override\n  public String toString() {\n    return \"Rogue\";\n  }\n}\n"
  },
  {
    "path": "mediator/src/main/java/com/iluwatar/mediator/Wizard.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\n/** Wizard party member. */\npublic class Wizard extends PartyMemberBase {\n\n  @Override\n  public String toString() {\n    return \"Wizard\";\n  }\n}\n"
  },
  {
    "path": "mediator/src/test/java/com/iluwatar/mediator/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "mediator/src/test/java/com/iluwatar/mediator/PartyImplTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport org.junit.jupiter.api.Test;\n\n/** PartyImplTest */\nclass PartyImplTest {\n\n  /**\n   * Verify if a member is notified when it's joining a party. Generate an action and see if the\n   * other member gets it. Also check members don't get their own actions.\n   */\n  @Test\n  void testPartyAction() {\n    final var partyMember1 = mock(PartyMember.class);\n    final var partyMember2 = mock(PartyMember.class);\n\n    final var party = new PartyImpl();\n    party.addMember(partyMember1);\n    party.addMember(partyMember2);\n\n    verify(partyMember1).joinedParty(party);\n    verify(partyMember2).joinedParty(party);\n\n    party.act(partyMember1, Action.GOLD);\n    verifyNoMoreInteractions(partyMember1);\n    verify(partyMember2).partyAction(Action.GOLD);\n\n    verifyNoMoreInteractions(partyMember1, partyMember2);\n  }\n}\n"
  },
  {
    "path": "mediator/src/test/java/com/iluwatar/mediator/PartyMemberTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mediator;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.function.Supplier;\nimport java.util.stream.Stream;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.slf4j.LoggerFactory;\n\n/** PartyMemberTest */\nclass PartyMemberTest {\n\n  static Stream<Arguments> dataProvider() {\n    return Stream.of(\n        Arguments.of((Supplier<PartyMember>) Hobbit::new),\n        Arguments.of((Supplier<PartyMember>) Hunter::new),\n        Arguments.of((Supplier<PartyMember>) Rogue::new),\n        Arguments.of((Supplier<PartyMember>) Wizard::new));\n  }\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(PartyMemberBase.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /** Verify if a party action triggers the correct output to the std-Out */\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testPartyAction(Supplier<PartyMember> memberSupplier) {\n    final var member = memberSupplier.get();\n\n    for (final var action : Action.values()) {\n      member.partyAction(action);\n      assertEquals(member + \" \" + action.getDescription(), appender.getLastMessage());\n    }\n\n    assertEquals(Action.values().length, appender.getLogSize());\n  }\n\n  /** Verify if a member action triggers the expected interactions with the party class */\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testAct(Supplier<PartyMember> memberSupplier) {\n    final var member = memberSupplier.get();\n\n    member.act(Action.GOLD);\n    assertEquals(0, appender.getLogSize());\n\n    final var party = mock(Party.class);\n    member.joinedParty(party);\n    assertEquals(member + \" joins the party\", appender.getLastMessage());\n\n    for (final var action : Action.values()) {\n      member.act(action);\n      assertEquals(member + \" \" + action.toString(), appender.getLastMessage());\n      verify(party).act(member, action);\n    }\n\n    assertEquals(Action.values().length + 1, appender.getLogSize());\n  }\n\n  /** Verify if {@link PartyMemberBase#toString()} generate the expected output */\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testToString(Supplier<PartyMember> memberSupplier) {\n    final var member = memberSupplier.get();\n    final var memberClass = member.getClass();\n    assertEquals(memberClass.getSimpleName(), member.toString());\n  }\n\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender(Class<?> clazz) {\n      ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n\n    public String getLastMessage() {\n      return log.get(log.size() - 1).getFormattedMessage();\n    }\n  }\n}\n"
  },
  {
    "path": "memento/README.md",
    "content": "---\ntitle: \"Memento Pattern in Java: Preserving Object State for Undo Operations\"\nshortTitle: Memento\ndescription: \"Learn how to implement the Memento design pattern in Java to capture and restore object state without violating encapsulation. Ideal for undo functionality in applications.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Encapsulation\n  - Gang of Four\n  - Memory management\n  - Object composition\n  - State tracking\n  - Undo\n---\n\n## Also known as\n\n* Snapshot\n* Token\n\n## Intent of Memento Design Pattern\n\nThe Memento design pattern in Java allows developers to capture and restore an object's internal state without violating encapsulation.\n\n## Detailed Explanation of Memento Pattern with Real-World Examples\n\nReal-world example\n\n> A text editor application can utilize the Memento design pattern in Java to enable undo and redo functionalities. By capturing the current state of a document as a memento each time a change is made, the application can easily restore the document to any previous state. The snapshots are stored in a history list. When the user clicks the undo button, the editor restores the document to the state saved in the most recent memento. This process allows users to revert to previous versions of their document without exposing or altering the internal data structures of the editor.\n\nIn plain words\n\n> Memento pattern captures object internal state making it easy to store and restore objects in any point of time.\n\nWikipedia says\n\n> The memento pattern is a software design pattern that provides the ability to restore an object to its previous state (undo via rollback).\n\nSequence diagram\n\n![Memento sequence diagram](./etc/memento-sequence-diagram.png)\n\n## Programmatic Example of Memento Pattern in Java\n\nIn our astrology application, we use the Memento pattern to capture and restore the state of star objects. Each state is saved as a memento, allowing us to revert to previous states as needed.\n\nLet's first define the types of stars we are capable to handle.\n\n```java\npublic enum StarType {\n  SUN(\"sun\"),\n  RED_GIANT(\"red giant\"),\n  WHITE_DWARF(\"white dwarf\"),\n  SUPERNOVA(\"supernova\"),\n  DEAD(\"dead star\");\n  // ...\n}\n```\n\nNext, let's jump straight to the essentials. Here's the `Star` class along with the mementos that we need to manipulate. Especially pay attention to `getMemento` and `setMemento` methods.\n\n```java\npublic interface StarMemento {\n}\n\npublic class Star {\n\n    private StarType type;\n    private int ageYears;\n    private int massTons;\n\n    public Star(StarType startType, int startAge, int startMass) {\n        this.type = startType;\n        this.ageYears = startAge;\n        this.massTons = startMass;\n    }\n\n    public void timePasses() {\n        ageYears *= 2;\n        massTons *= 8;\n        switch (type) {\n            case RED_GIANT -> type = StarType.WHITE_DWARF;\n            case SUN -> type = StarType.RED_GIANT;\n            case SUPERNOVA -> type = StarType.DEAD;\n            case WHITE_DWARF -> type = StarType.SUPERNOVA;\n            case DEAD -> {\n                ageYears *= 2;\n                massTons = 0;\n            }\n            default -> {\n            }\n        }\n    }\n\n    StarMemento getMemento() {\n        var state = new StarMementoInternal();\n        state.setAgeYears(ageYears);\n        state.setMassTons(massTons);\n        state.setType(type);\n        return state;\n    }\n\n    void setMemento(StarMemento memento) {\n        var state = (StarMementoInternal) memento;\n        this.type = state.getType();\n        this.ageYears = state.getAgeYears();\n        this.massTons = state.getMassTons();\n    }\n\n    @Override\n    public String toString() {\n        return String.format(\"%s age: %d years mass: %d tons\", type.toString(), ageYears, massTons);\n    }\n\n    private static class StarMementoInternal implements StarMemento {\n\n        private StarType type;\n        private int ageYears;\n        private int massTons;\n\n        // setters and getters ->\n        // ...\n    }\n}\n```\n\nAnd finally here's how we use the mementos to store and restore star states.\n\n```java\npublic static void main(String[] args) {\n    var states = new Stack<StarMemento>();\n\n    var star = new Star(StarType.SUN, 10000000, 500000);\n    LOGGER.info(star.toString());\n    states.add(star.getMemento());\n    star.timePasses();\n    LOGGER.info(star.toString());\n    states.add(star.getMemento());\n    star.timePasses();\n    LOGGER.info(star.toString());\n    states.add(star.getMemento());\n    star.timePasses();\n    LOGGER.info(star.toString());\n    states.add(star.getMemento());\n    star.timePasses();\n    LOGGER.info(star.toString());\n    while (!states.isEmpty()) {\n        star.setMemento(states.pop());\n        LOGGER.info(star.toString());\n    }\n}\n```\n\nProgram output:\n\n```\n14:09:15.878 [main] INFO com.iluwatar.memento.App -- sun age: 10000000 years mass: 500000 tons\n14:09:15.880 [main] INFO com.iluwatar.memento.App -- red giant age: 20000000 years mass: 4000000 tons\n14:09:15.880 [main] INFO com.iluwatar.memento.App -- white dwarf age: 40000000 years mass: 32000000 tons\n14:09:15.880 [main] INFO com.iluwatar.memento.App -- supernova age: 80000000 years mass: 256000000 tons\n14:09:15.880 [main] INFO com.iluwatar.memento.App -- dead star age: 160000000 years mass: 2048000000 tons\n14:09:15.880 [main] INFO com.iluwatar.memento.App -- supernova age: 80000000 years mass: 256000000 tons\n14:09:15.880 [main] INFO com.iluwatar.memento.App -- white dwarf age: 40000000 years mass: 32000000 tons\n14:09:15.881 [main] INFO com.iluwatar.memento.App -- red giant age: 20000000 years mass: 4000000 tons\n14:09:15.881 [main] INFO com.iluwatar.memento.App -- sun age: 10000000 years mass: 500000 tons\n```\n\n## When to Use the Memento Pattern in Java\n\nUse the Memento pattern when\n\n* You need to capture an object's state in Java and restore it later without exposing its internal structure. This is crucial for maintaining encapsulation and simplifying the management of object states.\n* A direct interface to obtaining the state would expose implementation details and break the object's encapsulation.\n\n## Real-World Applications of Memento Pattern in Java\n\nThe Memento pattern is used in various Java applications, including the java.util.Date and java.util.Calendar classes, which can revert to previous states. It's also common in text editors and graphic editors for undo mechanisms.\n\n## Benefits and Trade-offs of Memento Pattern\n\nBenefits:\n\n* Preserves encapsulation boundaries.\n* Simplifies the originator by removing the need to manage version history or undo functionality directly.\n\nTrade-offs:\n\n* Can be expensive in terms of memory if a large number of states are saved.\n* Care must be taken to manage the lifecycle of mementos to avoid memory leaks.\n\n## Related Java Design Patterns\n\n* [Command](https://java-design-patterns.com/patterns/command/): Often used together; commands store state for undoing operations in mementos.\n* [Prototype](https://java-design-patterns.com/patterns/prototype/): Mementos may use prototyping to store the state.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n"
  },
  {
    "path": "memento/etc/memento.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.Star\" project=\"memento\" \n    file=\"/memento/src/main/java/com/iluwatar/Star.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"301\" y=\"385\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <enumeration id=\"2\" language=\"java\" name=\"com.iluwatar.StarType\" project=\"memento\" \n    file=\"/memento/src/main/java/com/iluwatar/StarType.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"301\" y=\"911\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <interface id=\"3\" language=\"java\" name=\"com.iluwatar.StarMemento\" project=\"memento\" \n    file=\"/memento/src/main/java/com/iluwatar/StarMemento.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"103\" y=\"830\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.Star.StarMementoInternal\" project=\"memento\" \n    file=\"/memento/src/main/java/com/iluwatar/Star.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"103\" y=\"639\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"5\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"6\" name=\"type\"/>      \n      <multiplicity id=\"7\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"8\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"9\" name=\"type\"/>      \n      <multiplicity id=\"10\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <nesting id=\"11\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </nesting>  \n  <realization id=\"12\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "memento/etc/memento.urm.puml",
    "content": "@startuml\npackage com.iluwatar.memento {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Star {\n    - ageYears : int\n    - massTons : int\n    - type : StarType\n    + Star(startType : StarType, startAge : int, startMass : int)\n    ~ getMemento() : StarMemento\n    ~ setMemento(memento : StarMemento)\n    + timePasses()\n    + toString() : String\n  }\n  -class StarMementoInternal {\n    - ageYears : int\n    - massTons : int\n    - type : StarType\n    - StarMementoInternal()\n    + getAgeYears() : int\n    + getMassTons() : int\n    + getType() : StarType\n    + setAgeYears(ageYears : int)\n    + setMassTons(massTons : int)\n    + setType(type : StarType)\n  }\n  interface StarMemento {\n  }\n  enum StarType {\n    + DEAD {static}\n    + RED_GIANT {static}\n    + SUN {static}\n    + SUPERNOVA {static}\n    + UNDEFINED {static}\n    + WHITE_DWARF {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : StarType {static}\n    + values() : StarType[] {static}\n  }\n}\nStarMementoInternal -->  \"-type\" StarType\nStar -->  \"-type\" StarType\nStarMementoInternal ..+ Star\nStarMementoInternal ..|> StarMemento \n@enduml"
  },
  {
    "path": "memento/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>memento</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.memento.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "memento/src/main/java/com/iluwatar/memento/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.memento;\n\nimport java.util.Stack;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Memento pattern is a software design pattern that provides the ability to restore an object\n * to its previous state (undo via rollback).\n *\n * <p>The Memento pattern is implemented with three objects: the originator, a caretaker and a\n * memento. The originator is some object that has an internal state. The caretaker is going to do\n * something to the originator, but wants to be able to undo the change. The caretaker first asks\n * the originator for a memento object. Then it does whatever operation (or sequence of operations)\n * it was going to do. To roll back to the state before the operations, it returns the memento\n * object to the originator. The memento object itself is an opaque object (one which the caretaker\n * cannot, or should not, change). When using this pattern, care should be taken if the originator\n * may change other objects or resources - the memento pattern operates on a single object.\n *\n * <p>In this example the object ({@link Star}) gives out a \"memento\" ({@link StarMemento}) that\n * contains the state of the object. Later on the memento can be set back to the object restoring\n * the state.\n */\n@Slf4j\npublic class App {\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n    var states = new Stack<StarMemento>();\n\n    var star = new Star(StarType.SUN, 10000000, 500000);\n    LOGGER.info(star.toString());\n    states.add(star.getMemento());\n    star.timePasses();\n    LOGGER.info(star.toString());\n    states.add(star.getMemento());\n    star.timePasses();\n    LOGGER.info(star.toString());\n    states.add(star.getMemento());\n    star.timePasses();\n    LOGGER.info(star.toString());\n    states.add(star.getMemento());\n    star.timePasses();\n    LOGGER.info(star.toString());\n    while (!states.isEmpty()) {\n      star.setMemento(states.pop());\n      LOGGER.info(star.toString());\n    }\n  }\n}\n"
  },
  {
    "path": "memento/src/main/java/com/iluwatar/memento/Star.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.memento;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Star uses \"mementos\" to store and restore state. */\npublic class Star {\n\n  private StarType type;\n  private int ageYears;\n  private int massTons;\n\n  /** Constructor. */\n  public Star(StarType startType, int startAge, int startMass) {\n    this.type = startType;\n    this.ageYears = startAge;\n    this.massTons = startMass;\n  }\n\n  /** Makes time pass for the star. */\n  public void timePasses() {\n    ageYears *= 2;\n    massTons *= 8;\n    switch (type) {\n      case RED_GIANT -> type = StarType.WHITE_DWARF;\n      case SUN -> type = StarType.RED_GIANT;\n      case SUPERNOVA -> type = StarType.DEAD;\n      case WHITE_DWARF -> type = StarType.SUPERNOVA;\n      case DEAD -> {\n        ageYears *= 2;\n        massTons = 0;\n      }\n      default -> {}\n    }\n  }\n\n  StarMemento getMemento() {\n    var state = new StarMementoInternal();\n    state.setAgeYears(ageYears);\n    state.setMassTons(massTons);\n    state.setType(type);\n    return state;\n  }\n\n  void setMemento(StarMemento memento) {\n    var state = (StarMementoInternal) memento;\n    this.type = state.getType();\n    this.ageYears = state.getAgeYears();\n    this.massTons = state.getMassTons();\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\"%s age: %d years mass: %d tons\", type.toString(), ageYears, massTons);\n  }\n\n  /** StarMemento implementation. */\n  @Getter\n  @Setter\n  private static class StarMementoInternal implements StarMemento {\n\n    private StarType type;\n    private int ageYears;\n    private int massTons;\n  }\n}\n"
  },
  {
    "path": "memento/src/main/java/com/iluwatar/memento/StarMemento.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.memento;\n\n/** External interface to memento. */\npublic interface StarMemento {}\n"
  },
  {
    "path": "memento/src/main/java/com/iluwatar/memento/StarType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.memento;\n\n/** StarType enumeration. */\npublic enum StarType {\n  SUN(\"sun\"),\n  RED_GIANT(\"red giant\"),\n  WHITE_DWARF(\"white dwarf\"),\n  SUPERNOVA(\"supernova\"),\n  DEAD(\"dead star\");\n\n  private final String title;\n\n  StarType(String title) {\n    this.title = title;\n  }\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "memento/src/test/java/com/iluwatar/memento/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.memento;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "memento/src/test/java/com/iluwatar/memento/StarTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.memento;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** StarTest */\nclass StarTest {\n\n  /** Verify the stages of a dying sun, without going back in time */\n  @Test\n  void testTimePasses() {\n    final var star = new Star(StarType.SUN, 1, 2);\n    assertEquals(\"sun age: 1 years mass: 2 tons\", star.toString());\n\n    star.timePasses();\n    assertEquals(\"red giant age: 2 years mass: 16 tons\", star.toString());\n\n    star.timePasses();\n    assertEquals(\"white dwarf age: 4 years mass: 128 tons\", star.toString());\n\n    star.timePasses();\n    assertEquals(\"supernova age: 8 years mass: 1024 tons\", star.toString());\n\n    star.timePasses();\n    assertEquals(\"dead star age: 16 years mass: 8192 tons\", star.toString());\n\n    star.timePasses();\n    assertEquals(\"dead star age: 64 years mass: 0 tons\", star.toString());\n\n    star.timePasses();\n    assertEquals(\"dead star age: 256 years mass: 0 tons\", star.toString());\n  }\n\n  /** Verify some stage of a dying sun, but go back in time to test the memento */\n  @Test\n  void testSetMemento() {\n    final var star = new Star(StarType.SUN, 1, 2);\n    final var firstMemento = star.getMemento();\n    assertEquals(\"sun age: 1 years mass: 2 tons\", star.toString());\n\n    star.timePasses();\n    final var secondMemento = star.getMemento();\n    assertEquals(\"red giant age: 2 years mass: 16 tons\", star.toString());\n\n    star.timePasses();\n    final var thirdMemento = star.getMemento();\n    assertEquals(\"white dwarf age: 4 years mass: 128 tons\", star.toString());\n\n    star.timePasses();\n    assertEquals(\"supernova age: 8 years mass: 1024 tons\", star.toString());\n\n    star.setMemento(thirdMemento);\n    assertEquals(\"white dwarf age: 4 years mass: 128 tons\", star.toString());\n\n    star.timePasses();\n    assertEquals(\"supernova age: 8 years mass: 1024 tons\", star.toString());\n\n    star.setMemento(secondMemento);\n    assertEquals(\"red giant age: 2 years mass: 16 tons\", star.toString());\n\n    star.setMemento(firstMemento);\n    assertEquals(\"sun age: 1 years mass: 2 tons\", star.toString());\n  }\n}\n"
  },
  {
    "path": "metadata-mapping/README.md",
    "content": "---\ntitle: \"Metadata Mapping Pattern in Java: Bridging Objects and Data Stores Seamlessly\"\nshortTitle: Metadata Mapping\ndescription: \"Explore the Metadata Mapping Design Pattern for managing the mapping between database records and objects in Java applications. Learn implementation with Hibernate, use cases, benefits, and best practices.\"\ncategory: Data access\nlanguage: en\ntag:\n  - Decoupling\n  - Enterprise patterns\n  - Object mapping\n  - Persistence\n---\n\n## Intent of Metadata Mapping Design Pattern\n\nMetadata Mapping Design Pattern is designed to manage the mapping between database records and Java objects in a way that keeps the database schema and object model decoupled and manageable.\n\n## Detailed Explanation of Metadata Mapping Pattern with Real-World Examples\n\nReal-world example\n\n> An analogous real-world example of the Metadata Mapping design pattern can be seen in online retail systems. In such systems, products often have varying attributes depending on their category. For instance, electronics might have attributes like battery life and screen size, while clothing might have attributes like size and fabric type. Using Metadata Mapping, the system can dynamically map these varying attributes to the product objects without modifying the underlying class structure. This flexibility allows for easy updates and management of product attributes as new categories and attributes are introduced, ensuring that the system can evolve with the changing product landscape.\n\nIn plain words\n\n> Metadata Mapping specifies the mapping between classes and tables so that we could treat a table of any database like a Java class.\n\nWikipedia says\n\n> Create a \"virtual [object database](https://en.wikipedia.org/wiki/Object_database)\" that can be used from within the programming language.\n\nFlowchart\n\n![Metadata Mapping flowchart](./etc/metadata-mapping-flowchart.png)\n\n## Programmatic Example of Metadata Mapping Pattern in Java\n\nHibernate ORM Tool uses Metadata Mapping Pattern to specify the mapping between classes and tables either using XML or annotations in code.\n\nWe give an example about visiting the information of `user_account` table in `h2` database. Firstly, we create `user_account` table with `h2`:\n\n```java\n@Slf4j\npublic class DatabaseUtil {\n  private static final String DB_URL = \"jdbc:h2:mem:metamapping\";\n  private static final String CREATE_SCHEMA_SQL = \"DROP TABLE IF EXISTS `user_account`;\"\n      + \"CREATE TABLE `user_account` (\\n\"\n      + \"  `id` int(11) NOT NULL AUTO_INCREMENT,\\n\"\n      + \"  `username` varchar(255) NOT NULL,\\n\"\n      + \"  `password` varchar(255) NOT NULL,\\n\"\n      + \"  PRIMARY KEY (`id`)\\n\"\n      + \");\";\n    \n  static {\n    LOGGER.info(\"create h2 database\");\n    var source = new JdbcDataSource();\n    source.setURL(DB_URL);\n    try (var statement = source.getConnection().createStatement()) {\n      statement.execute(CREATE_SCHEMA_SQL);\n    } catch (SQLException e) {\n      LOGGER.error(\"unable to create h2 data source\", e);\n    }\n  }\n}\n```\n\nCorrespondingly, here's the basic `User` entity.\n\n```java\n@Setter\n@Getter\n@ToString\npublic class User {\n  private Integer id;\n  private String username;\n  private String password;\n    \n  public User(String username, String password) {\n    this.username = username;\n    this.password = password;\n  }\n}\n```\n\nThen we write a `xml` file to show the mapping between the table and the object:\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE hibernate-mapping PUBLIC\n    \"-//Hibernate/Hibernate Mapping DTD//EN\"\n    \"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd\">\n\n<hibernate-mapping>\n  <class name=\"com.iluwatar.metamapping.model.User\" table=\"user_account\">\n    <id name=\"id\" type=\"java.lang.Integer\" column=\"id\">\n      <generator class=\"native\"/>\n    </id>\n    <property name=\"username\" column=\"username\" type=\"java.lang.String\"/>\n    <property name=\"password\" column=\"password\" type=\"java.lang.String\"/>\n  </class>\n</hibernate-mapping>\n```\n\nWe use `Hibernate` to resolve the mapping and connect to our database, here's its configuration:\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE hibernate-configuration PUBLIC\n    \"-//Hibernate/Hibernate Configuration DTD 3.0//EN\"\n    \"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd\">\n<hibernate-configuration>\n  <session-factory>\n    <!-- JDBC Database connection settings -->\n    <property name=\"connection.url\">jdbc:h2:mem:metamapping</property>\n    <property name=\"connection.driver_class\">org.h2.Driver</property>\n    <!-- JDBC connection pool settings ... using built-in test pool -->\n    <property name=\"connection.pool_size\">1</property>\n    <!-- Select our SQL dialect -->\n    <property name=\"dialect\">org.hibernate.dialect.H2Dialect</property>\n    <!-- Echo the SQL to stdout -->\n    <property name=\"show_sql\">false</property>\n    <!-- Drop and re-create the database schema on startup -->\n    <property name=\"hbm2ddl.auto\">create-drop</property>\n    <mapping resource=\"com/iluwatar/metamapping/model/User.hbm.xml\" />\n  </session-factory>\n</hibernate-configuration>\n```\n\nThen we can get access to the table just like an object with `Hibernate`, here's some CRUDs:\n\n```java\n@Slf4j\npublic class UserService {\n  private static final SessionFactory factory = HibernateUtil.getSessionFactory();\n\n  public List<User> listUser() {\n    LOGGER.info(\"list all users.\");\n    List<User> users = new ArrayList<>();\n    try (var session = factory.openSession()) {\n      var tx = session.beginTransaction();\n      List<User> userIter = session.createQuery(\"FROM User\").list();\n      for (var iterator = userIter.iterator(); iterator.hasNext();) {\n        users.add(iterator.next());\n      }\n      tx.commit();\n    } catch (HibernateException e) {\n      LOGGER.debug(\"fail to get users\", e);\n    }\n    return users;\n  }\n  \n  // other CRUDs ->\n  // ...\n    \n  public void close() {\n    HibernateUtil.shutdown();\n  }\n}\n```\n\nHere is our `App` class with `main` function for running the example.\n\n```java\n@Slf4j\npublic class App {\n\n  public static void main(String[] args) {\n    // get service\n    var userService = new UserService();\n    // use create service to add users\n    for (var user : generateSampleUsers()) {\n      var id = userService.createUser(user);\n      LOGGER.info(\"Add user\" + user + \"at\" + id + \".\");\n    }\n    // use list service to get users\n    var users = userService.listUser();\n    LOGGER.info(String.valueOf(users));\n    // use get service to get a user\n    var user = userService.getUser(1);\n    LOGGER.info(String.valueOf(user));\n    // change password of user 1\n    user.setPassword(\"new123\");\n    // use update service to update user 1\n    userService.updateUser(1, user);\n    // use delete service to delete user 2\n    userService.deleteUser(2);\n    // close service\n    userService.close();\n  }\n\n  public static List<User> generateSampleUsers() {\n    final var user1 = new User(\"ZhangSan\", \"zhs123\");\n    final var user2 = new User(\"LiSi\", \"ls123\");\n    final var user3 = new User(\"WangWu\", \"ww123\");\n    return List.of(user1, user2, user3);\n  }\n}\n```\n\nConsole output:\n\n```\n14:44:17.792 [main] INFO  org.hibernate.Version - HHH000412: Hibernate ORM core version 5.6.12.Final\n14:44:17.977 [main] INFO  o.h.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {5.1.2.Final}\n14:44:18.216 [main] WARN  o.hibernate.orm.connections.pooling - HHH10001002: Using Hibernate built-in connection pool (not for production use!)\n14:44:18.217 [main] INFO  o.hibernate.orm.connections.pooling - HHH10001005: using driver [org.h2.Driver] at URL [jdbc:h2:mem:metamapping]\n14:44:18.217 [main] INFO  o.hibernate.orm.connections.pooling - HHH10001001: Connection properties: {}\n14:44:18.217 [main] INFO  o.hibernate.orm.connections.pooling - HHH10001003: Autocommit mode: false\n14:44:18.219 [main] INFO  o.h.e.j.c.i.DriverManagerConnectionProviderImpl - HHH000115: Hibernate connection pool size: 1 (min=1)\n14:44:18.276 [main] INFO  org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.H2Dialect\n14:44:18.463 [main] INFO  o.hibernate.orm.connections.access - HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@73a8e994] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.\n14:44:18.465 [main] INFO  o.hibernate.orm.connections.access - HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@7affc159] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.\n14:44:18.470 [main] INFO  o.h.e.t.j.p.i.JtaPlatformInitiator - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]\n14:44:18.473 [main] INFO  c.i.metamapping.service.UserService - create user: ZhangSan\n14:44:18.508 [main] INFO  c.i.metamapping.service.UserService - create user ZhangSan at 1\n14:44:18.508 [main] INFO  com.iluwatar.metamapping.App - Add userUser(id=1, username=ZhangSan, password=zhs123)at1.\n14:44:18.508 [main] INFO  c.i.metamapping.service.UserService - create user: LiSi\n14:44:18.509 [main] INFO  c.i.metamapping.service.UserService - create user LiSi at 2\n14:44:18.509 [main] INFO  com.iluwatar.metamapping.App - Add userUser(id=2, username=LiSi, password=ls123)at2.\n14:44:18.509 [main] INFO  c.i.metamapping.service.UserService - create user: WangWu\n14:44:18.512 [main] INFO  c.i.metamapping.service.UserService - create user WangWu at 3\n14:44:18.512 [main] INFO  com.iluwatar.metamapping.App - Add userUser(id=3, username=WangWu, password=ww123)at3.\n14:44:18.512 [main] INFO  c.i.metamapping.service.UserService - list all users.\n14:44:18.542 [main] INFO  com.iluwatar.metamapping.App - [User(id=1, username=ZhangSan, password=zhs123), User(id=2, username=LiSi, password=ls123), User(id=3, username=WangWu, password=ww123)]\n14:44:18.542 [main] INFO  c.i.metamapping.service.UserService - get user at: 1\n14:44:18.545 [main] INFO  com.iluwatar.metamapping.App - User(id=1, username=ZhangSan, password=zhs123)\n14:44:18.545 [main] INFO  c.i.metamapping.service.UserService - update user at 1\n14:44:18.548 [main] INFO  c.i.metamapping.service.UserService - delete user at: 2\n14:44:18.550 [main] INFO  o.h.t.s.i.SchemaDropperImpl$DelayedDropActionImpl - HHH000477: Starting delayed evictData of schema as part of SessionFactory shut-down'\n14:44:18.550 [main] INFO  o.hibernate.orm.connections.access - HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@7b5cc918] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.\n14:44:18.551 [main] INFO  o.hibernate.orm.connections.pooling - HHH10001008: Cleaning up connection pool [jdbc:h2:mem:metamapping]\n```\n\n## When to Use the Metadata Mapping Pattern in Java\n\nUse the Metadata Mapping Design Pattern when you need to bridge the gap between an object-oriented domain model and a relational database in Java applications, without hard-coding database queries into the domain logic.\n\n## Real-World Applications of Metadata Mapping Pattern in Java\n\n* Object-Relational Mapping (ORM) frameworks like Hibernate, JPA, EclipseLink, and MyBatis frequently utilize the Metadata Mapping Design Pattern to map Java objects to database tables.\n* Mapping database rows to domain objects in enterprise applications.\n\n## Benefits and Trade-offs of Metadata Mapping Pattern\n\nBenefits:\n\n* Decouples object model and database schema, allowing independent evolution.\n* Reduces boilerplate code associated with data access.\n* Centralizes mapping logic, making changes more manageable.\n\nTrade-offs:\n\n* Adds complexity due to an additional layer of abstraction.\n* Can impact performance if not properly optimized.\n\n## Related Java Design Patterns\n\n* [Data Mapper](https://java-design-patterns.com/patterns/data-mapper/): Metadata Mapping is often used within the broader Data Mapper pattern to facilitate the mapping process.\n* Active Record: Differently from Active Record, Metadata Mapping separates the data access logic from the domain entities.\n* [Repository](https://java-design-patterns.com/patterns/repository/): Works well with the Repository pattern by abstracting data access further, allowing more complex domain logic to be cleanly separated from data mapping.\n\n## References and Credits\n\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Java Persistence with Hibernate](https://amzn.to/44tP1ox)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Pro JPA 2: Mastering the Java Persistence API](https://amzn.to/4b7UoMC)\n"
  },
  {
    "path": "metadata-mapping/etc/metadata-mapping.urm.puml",
    "content": "@startuml\npackage com.iluwatar.metamapping.model {\n  class User {\n    - id : Integer\n    - password : String\n    - username : String\n    + User()\n    + User(username : String, password : String)\n    + getId() : Integer\n    + getPassword() : String\n    + getUsername() : String\n    + setId(id : Integer)\n    + setPassword(password : String)\n    + setUsername(username : String)\n    + toString() : String\n  }\n}\npackage com.iluwatar.metamapping.utils {\n  class DatabaseUtil {\n    - CREATE_SCHEMA_SQL : String {static}\n    - DB_URL : String {static}\n    - LOGGER : Logger {static}\n    - DatabaseUtil()\n  }\n  class HibernateUtil {\n    - LOGGER : Logger {static}\n    - sessionFactory : SessionFactory {static}\n    - HibernateUtil()\n    - buildSessionFactory() : SessionFactory {static}\n    + getSessionFactory() : SessionFactory {static}\n    + shutdown() {static}\n  }\n}\npackage com.iluwatar.metamapping {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + generateSampleUsers() : List<User> {static}\n    + main(args : String[]) {static}\n  }\n}\npackage com.iluwatar.metamapping.service {\n  class UserService {\n    - LOGGER : Logger {static}\n    - factory : SessionFactory {static}\n    + UserService()\n    + close()\n    + createUser(user : User) : int\n    + deleteUser(id : Integer)\n    + getUser(id : Integer) : User\n    + listUser() : List<User>\n    + updateUser(id : Integer, user : User)\n  }\n}\n@enduml"
  },
  {
    "path": "metadata-mapping/etc/metamapping.puml",
    "content": "@startuml\ninterface com.iluwatar.metamapping.service.UserService {\n+ List<User> listUser()\n+ int createUser(User)\n+ void updateUser(Integer,User)\n+ void deleteUser(Integer)\n+ User getUser(Integer)\n+ void close()\n}\nclass com.iluwatar.metamapping.utils.DatabaseUtil {\n+ {static} void createDataSource()\n}\nclass com.iluwatar.metamapping.model.User {\n- Integer id\n- String username\n- String password\n+ User(String username, String password)\n}\nclass com.iluwatar.metamapping.utils.HibernateUtil {\n+ {static} SessionFactory getSessionFactory()\n+ {static} void shutdown()\n}\nclass com.iluwatar.metamapping.App {\n+ {static} void main(String[])\n+ {static} List<User> generateSampleUsers()\n}\n\ncom.iluwatar.metamapping.service.UserService <.. com.iluwatar.metamapping.App\ncom.iluwatar.metamapping.model.User <.. com.iluwatar.metamapping.service.UserService\ncom.iluwatar.metamapping.utils.HibernateUtil <.. com.iluwatar.metamapping.service.UserService\ncom.iluwatar.metamapping.utils.DatabaseUtil <-- com.iluwatar.metamapping.utils.HibernateUtil\n@enduml"
  },
  {
    "path": "metadata-mapping/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n     xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n\n  <artifactId>metadata-mapping</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.hibernate</groupId>\n      <artifactId>hibernate-core</artifactId>\n      <version>6.6.11.Final</version>\n    </dependency>\n    <dependency>\n      <groupId>javax.xml.bind</groupId>\n      <artifactId>jaxb-api</artifactId>\n      <version>2.4.0-b180830.0359</version>\n    </dependency>\n    <dependency>\n      <groupId>org.glassfish.jaxb</groupId>\n      <artifactId>jaxb-runtime</artifactId>\n      <version>4.0.5</version>\n    </dependency>\n    <dependency>\n      <groupId>com.h2database</groupId>\n      <artifactId>h2</artifactId>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.metamapping.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>"
  },
  {
    "path": "metadata-mapping/src/main/java/com/iluwatar/metamapping/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.metamapping;\n\nimport com.iluwatar.metamapping.model.User;\nimport com.iluwatar.metamapping.service.UserService;\nimport com.iluwatar.metamapping.utils.DatabaseUtil;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\nimport org.hibernate.service.ServiceRegistry;\n\n/**\n * Metadata Mapping specifies the mapping between classes and tables so that we could treat a table\n * of any database like a Java class.\n *\n * <p>With hibernate, we achieve list/create/update/delete/get operations: 1)Create the H2 Database\n * in {@link DatabaseUtil}. 2)Hibernate resolve hibernate.cfg.xml and generate service like\n * save/list/get/delete. For learning metadata mapping pattern, we go deeper into Hibernate here:\n * a)read properties from hibernate.cfg.xml and mapping from *.hbm.xml b)create session factory to\n * generate session interacting with database c)generate session with factory pattern d)create query\n * object or use basic api with session, hibernate will convert all query to database query\n * according to metadata 3)We encapsulate hibernate service in {@link UserService} for our use.\n *\n * @see org.hibernate.cfg.Configuration#configure(String)\n * @see org.hibernate.cfg.Configuration#buildSessionFactory(ServiceRegistry)\n * @see org.hibernate.internal.SessionFactoryImpl#openSession()\n */\n@Slf4j\npublic class App {\n  /**\n   * Program entry point.\n   *\n   * @param args command line args.\n   */\n  public static void main(String[] args) {\n    // get service\n    var userService = new UserService();\n    // use create service to add users\n    for (var user : generateSampleUsers()) {\n      var id = userService.createUser(user);\n      LOGGER.info(\"Add user\" + user + \"at\" + id + \".\");\n    }\n    // use list service to get users\n    var users = userService.listUser();\n    LOGGER.info(String.valueOf(users));\n    // use get service to get a user\n    var user = userService.getUser(1);\n    LOGGER.info(String.valueOf(user));\n    // change password of user 1\n    user.setPassword(\"new123\");\n    // use update service to update user 1\n    userService.updateUser(1, user);\n    // use delete service to delete user 2\n    userService.deleteUser(2);\n    // close service\n    userService.close();\n  }\n\n  /**\n   * Generate users.\n   *\n   * @return list of users.\n   */\n  public static List<User> generateSampleUsers() {\n    final var user1 = new User(\"ZhangSan\", \"zhs123\");\n    final var user2 = new User(\"LiSi\", \"ls123\");\n    final var user3 = new User(\"WangWu\", \"ww123\");\n    return List.of(user1, user2, user3);\n  }\n}\n"
  },
  {
    "path": "metadata-mapping/src/main/java/com/iluwatar/metamapping/model/User.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.metamapping.model;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\n/** User Entity. */\n@Setter\n@Getter\n@ToString\npublic class User {\n  private Integer id;\n  private String username;\n  private String password;\n\n  public User() {}\n\n  /**\n   * Get a user.\n   *\n   * @param username user name\n   * @param password user password\n   */\n  public User(String username, String password) {\n    this.username = username;\n    this.password = password;\n  }\n}\n"
  },
  {
    "path": "metadata-mapping/src/main/java/com/iluwatar/metamapping/service/UserService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.metamapping.service;\n\nimport com.iluwatar.metamapping.model.User;\nimport com.iluwatar.metamapping.utils.HibernateUtil;\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\nimport org.hibernate.HibernateException;\nimport org.hibernate.SessionFactory;\n\n/** Service layer for user. */\n@Slf4j\npublic class UserService {\n  private static final SessionFactory factory = HibernateUtil.getSessionFactory();\n\n  /**\n   * List all users.\n   *\n   * @return list of users\n   */\n  public List<User> listUser() {\n    LOGGER.info(\"list all users.\");\n    List<User> users = new ArrayList<>();\n    try (var session = factory.openSession()) {\n      var tx = session.beginTransaction();\n      List<User> userIter = session.createQuery(\"FROM User\").list();\n      for (User user : userIter) {\n        users.add(user);\n      }\n      tx.commit();\n    } catch (HibernateException e) {\n      LOGGER.debug(\"fail to get users\", e);\n    }\n    return users;\n  }\n\n  /**\n   * Add a user.\n   *\n   * @param user user entity\n   * @return user id\n   */\n  public int createUser(User user) {\n    LOGGER.info(\"create user: \" + user.getUsername());\n    var id = -1;\n    try (var session = factory.openSession()) {\n      var tx = session.beginTransaction();\n      id = (Integer) session.save(user);\n      tx.commit();\n    } catch (HibernateException e) {\n      LOGGER.debug(\"fail to create user\", e);\n    }\n    LOGGER.info(\"create user \" + user.getUsername() + \" at \" + id);\n    return id;\n  }\n\n  /**\n   * Update user.\n   *\n   * @param id user id\n   * @param user new user entity\n   */\n  public void updateUser(Integer id, User user) {\n    LOGGER.info(\"update user at \" + id);\n    try (var session = factory.openSession()) {\n      var tx = session.beginTransaction();\n      user.setId(id);\n      session.update(user);\n      tx.commit();\n    } catch (HibernateException e) {\n      LOGGER.debug(\"fail to update user\", e);\n    }\n  }\n\n  /**\n   * Delete user.\n   *\n   * @param id user id\n   */\n  public void deleteUser(Integer id) {\n    LOGGER.info(\"delete user at: \" + id);\n    try (var session = factory.openSession()) {\n      var tx = session.beginTransaction();\n      var user = session.get(User.class, id);\n      session.delete(user);\n      tx.commit();\n    } catch (HibernateException e) {\n      LOGGER.debug(\"fail to delete user\", e);\n    }\n  }\n\n  /**\n   * Get user.\n   *\n   * @param id user id\n   * @return deleted user\n   */\n  public User getUser(Integer id) {\n    LOGGER.info(\"get user at: \" + id);\n    User user = null;\n    try (var session = factory.openSession()) {\n      var tx = session.beginTransaction();\n      user = session.get(User.class, id);\n      tx.commit();\n    } catch (HibernateException e) {\n      LOGGER.debug(\"fail to get user\", e);\n    }\n    return user;\n  }\n\n  /** Close hibernate. */\n  public void close() {\n    HibernateUtil.shutdown();\n  }\n}\n"
  },
  {
    "path": "metadata-mapping/src/main/java/com/iluwatar/metamapping/utils/DatabaseUtil.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.metamapping.utils;\n\nimport java.sql.SQLException;\nimport lombok.extern.slf4j.Slf4j;\nimport org.h2.jdbcx.JdbcDataSource;\n\n/** Create h2 database. */\n@Slf4j\npublic class DatabaseUtil {\n  private static final String DB_URL = \"jdbc:h2:mem:metamapping\";\n  private static final String CREATE_SCHEMA_SQL =\n      \"\"\"\n          DROP TABLE IF EXISTS `user_account`;CREATE TABLE `user_account` (\n            `id` int(11) NOT NULL AUTO_INCREMENT,\n            `username` varchar(255) NOT NULL,\n            `password` varchar(255) NOT NULL,\n            PRIMARY KEY (`id`)\n          );\"\"\";\n\n  /** Hide constructor. */\n  private DatabaseUtil() {}\n\n  static {\n    LOGGER.info(\"create h2 database\");\n    var source = new JdbcDataSource();\n    source.setURL(DB_URL);\n    try (var statement = source.getConnection().createStatement()) {\n      statement.execute(CREATE_SCHEMA_SQL);\n    } catch (SQLException e) {\n      LOGGER.error(\"unable to create h2 data source\", e);\n    }\n  }\n}\n"
  },
  {
    "path": "metadata-mapping/src/main/java/com/iluwatar/metamapping/utils/HibernateUtil.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.metamapping.utils;\n\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\nimport org.hibernate.SessionFactory;\nimport org.hibernate.cfg.Configuration;\n\n/** Manage hibernate. */\n@Slf4j\npublic class HibernateUtil {\n\n  @Getter private static final SessionFactory sessionFactory = buildSessionFactory();\n\n  /** Hide constructor. */\n  private HibernateUtil() {}\n\n  /**\n   * Build session factory.\n   *\n   * @return session factory\n   */\n  private static SessionFactory buildSessionFactory() {\n    // Create the SessionFactory from hibernate.cfg.xml\n    return new Configuration().configure().buildSessionFactory();\n  }\n\n  /** Close session factory. */\n  public static void shutdown() {\n    // Close caches and connection pools\n    getSessionFactory().close();\n  }\n}\n"
  },
  {
    "path": "metadata-mapping/src/main/resources/com/iluwatar/metamapping/model/User.hbm.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE hibernate-mapping PUBLIC\n    \"-//Hibernate/Hibernate Mapping DTD//EN\"\n    \"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd\">\n\n<hibernate-mapping>\n  <class name=\"com.iluwatar.metamapping.model.User\" table=\"user_account\">\n    <id name=\"id\" type=\"java.lang.Integer\" column=\"id\">\n      <generator class=\"native\"/>\n    </id>\n    <property name=\"username\" column=\"username\" type=\"java.lang.String\"/>\n    <property name=\"password\" column=\"password\" type=\"java.lang.String\"/>\n  </class>\n</hibernate-mapping>"
  },
  {
    "path": "metadata-mapping/src/main/resources/hibernate.cfg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE hibernate-configuration PUBLIC\n    \"-//Hibernate/Hibernate Configuration DTD 3.0//EN\"\n    \"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd\">\n<hibernate-configuration>\n  <session-factory>\n    <!-- JDBC Database connection settings -->\n    <property name=\"connection.url\">jdbc:h2:mem:metamapping</property>\n    <property name=\"connection.driver_class\">org.h2.Driver</property>\n    <!-- JDBC connection pool settings ... using built-in test pool -->\n    <property name=\"connection.pool_size\">1</property>\n    <!-- Select our SQL dialect -->\n    <property name=\"dialect\">org.hibernate.dialect.H2Dialect</property>\n    <!-- Echo the SQL to stdout -->\n    <property name=\"show_sql\">false</property>\n    <!-- Drop and re-create the database schema on startup -->\n    <property name=\"hbm2ddl.auto\">create-drop</property>\n    <mapping resource=\"com/iluwatar/metamapping/model/User.hbm.xml\" />\n  </session-factory>\n</hibernate-configuration>"
  },
  {
    "path": "metadata-mapping/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<configuration>\n    <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n        <encoder>\n            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n    <root level=\"info\">\n        <appender-ref ref=\"STDOUT\" />\n    </root>\n</configuration>\n"
  },
  {
    "path": "metadata-mapping/src/test/java/com/iluwatar/metamapping/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.metamapping;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that metadata mapping example runs without errors. */\nclass AppTest {\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteMetaMappingWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "microservices-aggregrator/README.md",
    "content": "---\ntitle: \"Microservices Aggregator Pattern in Java: Building Efficient Composite Services in Java\"\nshortTitle: Microservices Aggregator\ndescription: \"Learn about the Microservices Aggregator Design Pattern with Java examples. Understand its intent, real-world applications, benefits, and trade-offs for scalable system design.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - API design\n  - Client-server\n  - Data processing\n  - Decoupling\n  - Integration\n  - Microservices\n  - Scalability\n---\n\n## Also known as\n\n* API Composition\n\n## Intent of Microservices Aggregator Design Pattern\n\nThe Microservices Aggregator pattern helps aggregate responses from multiple microservices into a single unified response, optimizing client-server interactions in scalable systems.\n\n## Detailed Explanation of Microservices Aggregator Pattern with Real-World Examples\n\nReal-world example\n\n> In a travel booking platform, an Aggregator Microservice consolidates data from flights, hotels, and car rentals microservices, providing a seamless user experience and enhancing scalability. Instead of the user making separate requests to each service, the platform employs an Aggregator Microservice. This microservice calls each of these services, collects their responses, and then consolidates the information into a single, unified response that is sent back to the user. This simplifies the user experience by providing all necessary travel details in one place and reduces the number of direct interactions the user needs to have with the underlying services.\n\nIn plain words\n\n> Microservices Aggregator collects pieces of data from various microservices and returns an aggregate for processing.\n\nStack Overflow says\n\n> Microservices Aggregator invokes multiple services to achieve the functionality required by the application.\n\nArchitecture diagram\n\n![Microservices Aggregator Architecture Diagram](./etc/microservices-aggregator-architecture-diagram.png)\n\n## Programmatic Example of Microservices Aggregator Pattern in Java\n\nOur web marketplace utilizes an Aggregator microservice to fetch combined product and inventory information from separate microservices, ensuring efficient data processing and improved system performance.\n\nLet's start from the data model. Here's our `Product`.\n\n```java\npublic class Product {\n    private String title;\n    private int productInventories;\n    // Other properties and methods...\n}\n```\n\nNext we can introduce our `Aggregator` microservice. It contains clients `ProductInformationClient` and `ProductInventoryClient` for calling respective microservices.\n\n```java\n\n@RestController\npublic class Aggregator {\n\n    @Resource\n    private ProductInformationClient informationClient;\n\n    @Resource\n    private ProductInventoryClient inventoryClient;\n\n    @RequestMapping(path = \"/product\", method = RequestMethod.GET)\n    public Product getProduct() {\n\n        var product = new Product();\n        var productTitle = informationClient.getProductTitle();\n        var productInventory = inventoryClient.getProductInventories();\n\n        //Fallback to error message\n        product.setTitle(requireNonNullElse(productTitle, \"Error: Fetching Product Title Failed\"));\n\n        //Fallback to default error inventory\n        product.setProductInventories(requireNonNullElse(productInventory, -1));\n\n        return product;\n    }\n}\n```\n\nHere's the essence of information microservice implementation. Inventory microservice is similar, it just returns inventory counts.\n\n```java\n\n@RestController\npublic class InformationController {\n    @RequestMapping(value = \"/information\", method = RequestMethod.GET)\n    public String getProductTitle() {\n        return \"The Product Title.\";\n    }\n}\n```\n\nNow calling our `Aggregator` REST API returns the product information.\n\n```bash\n# Example bash call\ncurl http://localhost:50004/product\n\n# Example output\n{\"title\":\"The Product Title.\",\"productInventories\":5}\n```\n\n## When to Use the Microservices Aggregator Pattern in Java\n\nThe Microservices Aggregator pattern is ideal for scenarios requiring composite responses from multiple microservices, such as in e-commerce and dashboard applications where aggregated data enhances user experience and system efficiency.\n\n## Benefits and Trade-offs of Microservices Aggregator Pattern\n\nBenefits:\n\n* Simplified Client: Clients interact with just one service rather than managing calls to multiple microservices, which simplifies client-side logic.\n* Reduced Latency: By aggregating responses, the number of network calls is reduced, which can improve the application's overall latency.\n* Decoupling: Clients are decoupled from the individual microservices, allowing for more flexibility in changing the microservices landscape without impacting clients.\n* Centralized Logic: Aggregation allows for centralized transformation and logic application on the data collected from various services, which can be more efficient than handling it in the client or spreading it across multiple services.\n\nTrade-offs:\n\n* Single Point of Failure: The aggregator service can become a bottleneck or a single point of failure if not designed with high availability and scalability in mind.\n* Complexity: Implementing an aggregator can introduce complexity, especially in terms of data aggregation logic and error handling when dealing with multiple services.\n\n## Related Java Design Patterns\n\n* [API Gateway](https://java-design-patterns.com/patterns/microservices-api-gateway/): The Microservices Aggregator pattern is often used in conjunction with an API Gateway, which provides a single entry point for clients to access multiple microservices.\n* [Composite](https://java-design-patterns.com/patterns/composite/): The Microservices Aggregator pattern can be seen as a form of the Composite pattern, where the composite is the aggregated response from multiple microservices.\n* [Facade](https://java-design-patterns.com/patterns/facade/): The Microservices Aggregator pattern can be seen as a form of the Facade pattern, where the facade is the aggregator service that provides a simplified interface to the client.\n\n## References and Credits\n\n* [Building Microservices: Designing Fine-Grained Systems](https://amzn.to/43aGpSR)\n* [Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems](https://amzn.to/3y6yv1z)\n* [Designing Distributed Systems: Patterns and Paradigms for Scalable, Reliable Services](https://amzn.to/3T9g9Uj)\n* [Microservice Architecture: Aligning Principles, Practices, and Culture](https://amzn.to/3T9jZNi)\n* [Microservices Patterns: With examples in Java](https://amzn.to/4a5LHkP)\n* [Pattern: API Composition](https://microservices.io/patterns/data/api-composition.html)\n* [Production-Ready Microservices: Building Standardized Systems Across an Engineering Organization](https://amzn.to/4a0Vk4c)\n* [Microservice Design Patterns (Arun Gupta)](http://web.archive.org/web/20190705163602/http://blog.arungupta.me/microservice-design-patterns/)\n"
  },
  {
    "path": "microservices-aggregrator/aggregator-service/etc/aggregator-service.urm.puml",
    "content": "@startuml\npackage com.iluwatar.aggregator.microservices {\n  class Aggregator {\n    - informationClient : ProductInformationClient\n    - inventoryClient : ProductInventoryClient\n    + Aggregator()\n    + getProduct() : Product\n  }\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Product {\n    - productInventories : int\n    - title : String\n    + Product()\n    + getProductInventories() : int\n    + getTitle() : String\n    + setProductInventories(productInventories : int)\n    + setTitle(title : String)\n  }\n  interface ProductInformationClient {\n    + getProductTitle() : String {abstract}\n  }\n  class ProductInformationClientImpl {\n    - LOGGER : Logger {static}\n    + ProductInformationClientImpl()\n    + getProductTitle() : String\n  }\n  interface ProductInventoryClient {\n    + getProductInventories() : Integer {abstract}\n  }\n  class ProductInventoryClientImpl {\n    - LOGGER : Logger {static}\n    + ProductInventoryClientImpl()\n    + getProductInventories() : Integer\n  }\n}\nAggregator -->  \"-informationClient\" ProductInformationClient\nAggregator -->  \"-inventoryClient\" ProductInventoryClient\nProductInformationClientImpl ..|> ProductInformationClient \nProductInventoryClientImpl ..|> ProductInventoryClient \n@enduml"
  },
  {
    "path": "microservices-aggregrator/aggregator-service/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>microservices-aggregrator</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>aggregator-service</artifactId>\n  <packaging>jar</packaging>\n  <dependencies>\n    <dependency>\n      <groupId>org.springframework</groupId>\n      <artifactId>spring-webmvc</artifactId>\n      <version>6.2.5</version>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-web</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <!-- Maven assembly plugin is invoked with default setting which we have\n\t\t\t\tin parent pom and specifying the class having main method -->\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.aggregator.microservices.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "microservices-aggregrator/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/Aggregator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.aggregator.microservices;\n\nimport static java.util.Objects.requireNonNullElse;\n\nimport jakarta.annotation.Resource;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * The aggregator aggregates calls on various micro-services, collects data and further publishes\n * them under a REST endpoint.\n */\n@RestController\npublic class Aggregator {\n\n  @Resource private ProductInformationClient informationClient;\n\n  @Resource private ProductInventoryClient inventoryClient;\n\n  /**\n   * Retrieves product data.\n   *\n   * @return a Product.\n   */\n  @GetMapping(\"/product\")\n  public Product getProduct() {\n\n    var product = new Product();\n    var productTitle = informationClient.getProductTitle();\n    var productInventory = inventoryClient.getProductInventories();\n\n    // Fallback to error message\n    product.setTitle(requireNonNullElse(productTitle, \"Error: Fetching Product Title Failed\"));\n\n    // Fallback to default error inventory\n    product.setProductInventories(requireNonNullElse(productInventory, -1));\n\n    return product;\n  }\n}\n"
  },
  {
    "path": "microservices-aggregrator/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.aggregator.microservices;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/** Spring Boot EntryPoint Class. */\n@SpringBootApplication\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    SpringApplication.run(App.class, args);\n  }\n}\n"
  },
  {
    "path": "microservices-aggregrator/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/Product.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.aggregator.microservices;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Encapsulates all the data for a Product that clients will request. */\n@Getter\n@Setter\npublic class Product {\n\n  /** The title of the product. */\n  private String title;\n\n  /** The inventories of the product. */\n  private int productInventories;\n}\n"
  },
  {
    "path": "microservices-aggregrator/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClient.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.aggregator.microservices;\n\n/** Interface for the Information micro-service. */\npublic interface ProductInformationClient {\n\n  String getProductTitle();\n}\n"
  },
  {
    "path": "microservices-aggregrator/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClientImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.aggregator.microservices;\n\nimport java.io.IOException;\nimport java.net.URI;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.stereotype.Component;\n\n/** An adapter to communicate with information micro-service. */\n@Slf4j\n@Component\npublic class ProductInformationClientImpl implements ProductInformationClient {\n\n  @Override\n  public String getProductTitle() {\n    var request =\n        HttpRequest.newBuilder()\n            .GET()\n            .uri(URI.create(\"http://localhost:51515/information\"))\n            .build();\n    var client = HttpClient.newHttpClient();\n    try {\n      var httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString());\n      return httpResponse.body();\n    } catch (IOException ioe) {\n      LOGGER.error(\"IOException Occurred\", ioe);\n    } catch (InterruptedException ie) {\n      LOGGER.error(\"InterruptedException Occurred\", ie);\n      Thread.currentThread().interrupt();\n    }\n    return null;\n  }\n}\n"
  },
  {
    "path": "microservices-aggregrator/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClient.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.aggregator.microservices;\n\n/** Interface to Inventory micro-service. */\npublic interface ProductInventoryClient {\n\n  Integer getProductInventories();\n}\n"
  },
  {
    "path": "microservices-aggregrator/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClientImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.aggregator.microservices;\n\nimport java.io.IOException;\nimport java.net.URI;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.stereotype.Component;\n\n/** An adapter to communicate with inventory micro-service. */\n@Slf4j\n@Component\npublic class ProductInventoryClientImpl implements ProductInventoryClient {\n\n  @Override\n  public Integer getProductInventories() {\n    var response = \"\";\n\n    var request =\n        HttpRequest.newBuilder()\n            .GET()\n            .uri(URI.create(\"http://localhost:51516/inventories\"))\n            .build();\n    var client = HttpClient.newHttpClient();\n    try {\n      var httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString());\n      response = httpResponse.body();\n    } catch (IOException ioe) {\n      LOGGER.error(\"IOException Occurred\", ioe);\n    } catch (InterruptedException ie) {\n      LOGGER.error(\"InterruptedException Occurred\", ie);\n      Thread.currentThread().interrupt();\n    }\n    if (\"\".equalsIgnoreCase(response)) {\n      return null;\n    } else {\n      return Integer.parseInt(response);\n    }\n  }\n}\n"
  },
  {
    "path": "microservices-aggregrator/aggregator-service/src/main/resources/application.properties",
    "content": "#\n# The MIT License\n# Copyright © 2014-2021 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nserver.port=50004"
  },
  {
    "path": "microservices-aggregrator/aggregator-service/src/test/java/com/iluwatar/aggregator/microservices/AggregatorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.aggregator.microservices;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\n\n/** Test Aggregation of domain objects */\nclass AggregatorTest {\n\n  @InjectMocks private Aggregator aggregator;\n\n  @Mock private ProductInformationClient informationClient;\n\n  @Mock private ProductInventoryClient inventoryClient;\n\n  @BeforeEach\n  void setup() {\n    MockitoAnnotations.openMocks(this);\n  }\n\n  /** Tests getting the data for a desktop client */\n  @Test\n  void testGetProduct() {\n    var title = \"The Product Title.\";\n    var inventories = 5;\n\n    when(informationClient.getProductTitle()).thenReturn(title);\n    when(inventoryClient.getProductInventories()).thenReturn(inventories);\n\n    var testProduct = aggregator.getProduct();\n\n    assertEquals(title, testProduct.getTitle());\n    assertEquals(inventories, testProduct.getProductInventories());\n  }\n}\n"
  },
  {
    "path": "microservices-aggregrator/etc/aggregator-microservices.urm.puml",
    "content": "@startuml\n@enduml"
  },
  {
    "path": "microservices-aggregrator/etc/microservices-aggregrator.urm.puml",
    "content": "@startuml\n@enduml"
  },
  {
    "path": "microservices-aggregrator/information-microservice/etc/information-microservice.urm.puml",
    "content": "@startuml\npackage com.iluwatar.information.microservice {\n  class InformationApplication {\n    + InformationApplication()\n    + main(args : String[]) {static}\n  }\n  class InformationController {\n    + InformationController()\n    + getProductTitle() : String\n  }\n}\n@enduml"
  },
  {
    "path": "microservices-aggregrator/information-microservice/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>microservices-aggregrator</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>information-microservice</artifactId>\n  <packaging>jar</packaging>\n  <dependencies>\n    <dependency>\n      <groupId>org.springframework</groupId>\n      <artifactId>spring-webmvc</artifactId>\n      <version>6.2.5</version>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-web</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.information.microservices.InformationApplication</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "microservices-aggregrator/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationApplication.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.information.microservice;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/** Inventory Application starts container (Spring Boot) and exposes the Inventory micro-service. */\n@SpringBootApplication\npublic class InformationApplication {\n\n  public static void main(String[] args) {\n    SpringApplication.run(InformationApplication.class, args);\n  }\n}\n"
  },
  {
    "path": "microservices-aggregrator/information-microservice/src/main/java/com/iluwatar/information/microservice/InformationController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.information.microservice;\n\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/** Controller providing endpoints to retrieve information about products. */\n@RestController\npublic class InformationController {\n\n  /**\n   * Endpoint to retrieve a product's information.\n   *\n   * @return product inventory.\n   */\n  @GetMapping(\"/information\")\n  public String getProductTitle() {\n    return \"The Product Title.\";\n  }\n}\n"
  },
  {
    "path": "microservices-aggregrator/information-microservice/src/main/resources/application.properties",
    "content": "#\n# The MIT License\n# Copyright © 2014-2021 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nserver.port=51515"
  },
  {
    "path": "microservices-aggregrator/information-microservice/src/test/java/com/iluwatar/information/microservice/InformationControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.information.microservice;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test for Information Rest Controller */\nclass InformationControllerTest {\n\n  @Test\n  void shouldGetProductTitle() {\n    var infoController = new InformationController();\n    var title = infoController.getProductTitle();\n    assertEquals(\"The Product Title.\", title);\n  }\n}\n"
  },
  {
    "path": "microservices-aggregrator/inventory-microservice/etc/inventory-microservice.urm.puml",
    "content": "@startuml\npackage com.iluwatar.inventory.microservice {\n  class InventoryApplication {\n    + InventoryApplication()\n    + main(args : String[]) {static}\n  }\n  class InventoryController {\n    + InventoryController()\n    + getProductInventories() : int\n  }\n}\n@enduml"
  },
  {
    "path": "microservices-aggregrator/inventory-microservice/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>microservices-aggregrator</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>inventory-microservice</artifactId>\n  <packaging>jar</packaging>\n  <dependencies>\n    <dependency>\n      <groupId>org.springframework</groupId>\n      <artifactId>spring-webmvc</artifactId>\n      <version>6.2.5</version>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-web</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.inventory.microservices.InventoryApplication</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "microservices-aggregrator/inventory-microservice/src/main/java/com/iluwatar/inventory/microservice/InventoryApplication.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.inventory.microservice;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/** Inventory Application starts container (Spring Boot) and exposes the Inventory micro-service. */\n@SpringBootApplication\npublic class InventoryApplication {\n\n  public static void main(String[] args) {\n    SpringApplication.run(InventoryApplication.class, args);\n  }\n}\n"
  },
  {
    "path": "microservices-aggregrator/inventory-microservice/src/main/java/com/iluwatar/inventory/microservice/InventoryController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.inventory.microservice;\n\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/** Controller providing endpoints to retrieve product inventories. */\n@RestController\npublic class InventoryController {\n\n  /**\n   * Endpoint to retrieve a product's inventories.\n   *\n   * @return product inventory.\n   */\n  @GetMapping(\"/inventories\")\n  public int getProductInventories() {\n    return 5;\n  }\n}\n"
  },
  {
    "path": "microservices-aggregrator/inventory-microservice/src/main/resources/application.properties",
    "content": "#\n# The MIT License\n# Copyright © 2014-2021 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nserver.port=51516"
  },
  {
    "path": "microservices-aggregrator/inventory-microservice/src/test/java/com/iluwatar/inventory/microservice/InventoryControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.inventory.microservice;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test Inventory Rest Controller */\nclass InventoryControllerTest {\n\n  @Test\n  void testGetProductInventories() {\n    var inventoryController = new InventoryController();\n    var numberOfInventories = inventoryController.getProductInventories();\n    assertEquals(5, numberOfInventories);\n  }\n}\n"
  },
  {
    "path": "microservices-aggregrator/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>microservices-aggregrator</artifactId>\n  <packaging>pom</packaging>\n  <modules>\n    <module>information-microservice</module>\n    <module>aggregator-service</module>\n    <module>inventory-microservice</module>\n  </modules>\n</project>\n"
  },
  {
    "path": "microservices-api-gateway/README.md",
    "content": "---\ntitle: \"Microservices API Gateway Pattern in Java: Simplifying Service Access with a Unified Endpoint\"\nshortTitle: Microservices API Gateway\ndescription: \"Learn how the API Gateway pattern simplifies client-side development, enhances security, and optimizes communication in microservices architecture. Explore examples, benefits, and best practices.\"\ncategory: Integration\nlanguage: en\ntag:\n  - API design\n  - Cloud distributed\n  - Decoupling\n  - Enterprise patterns\n  - Integration\n  - Microservices\n  - Scalability\n  - Security\n---\n\n## Intent of Microservices API Gateway Design Pattern\n\nThe API Gateway design pattern aims to provide a unified interface to a set of microservices within a microservices architecture. It acts as a single entry point for clients, routing requests to the appropriate microservices and aggregating results, thereby simplifying the client-side code.\n\n## Also known as\n\n* API Facade\n* Backend for Frontends (BFF)\n\n## Detailed Explanation of Microservices API Gateway Pattern with Real-World Examples\n\nReal-world example\n\n> In a large e-commerce platform, an API Gateway is used as the single entry point for all client requests, simplifying client-side development. When a user visits the site or uses the mobile app, their requests for product information, user authentication, order processing, and payment are all routed through the API Gateway. The API Gateway handles tasks such as user authentication, rate limiting to prevent abuse, and logging for monitoring purposes, enhancing overall security optimization. This setup simplifies the client interface and ensures that all backend microservices can evolve independently without affecting the client directly, thereby enhancing microservices communication. This also enhances security by providing a centralized point to enforce policies and monitor traffic.\n\nIn plain words\n\n> For a system implemented using microservices architecture, API Gateway is the single entry point that aggregates the calls to the individual microservices.\n\nWikipedia says\n\n> API Gateway is a server that acts as an API front-end, receives API requests, enforces throttling and security policies, passes requests to the back-end service and then passes the response back to the requester. A gateway often includes a transformation engine to orchestrate and modify the requests and responses on the fly. A gateway can also provide functionality such as collecting analytics data and providing caching. The gateway can provide functionality to support authentication, authorization, security, audit and regulatory compliance.\n\nSequence diagram\n\n![Microservices API Gateway sequence diagram](./etc/microservices-api-gateway-sequence-diagram.png)\n\n## Programmatic Example of Microservice API Gateway in Java\n\nThis implementation shows what the API Gateway pattern could look like for an e-commerce site. The`ApiGateway` makes calls to the Image and Price microservices using the `ImageClientImpl` and `PriceClientImpl` respectively. Customers viewing the site on a desktop device can see both price information and an image of a product, so the `ApiGateway` calls both of the microservices and aggregates the data in the `DesktopProduct` model. However, mobile users only see price information; they do not see a product image. For mobile users, the `ApiGateway` only retrieves price information, which it uses to populate the `MobileProduct`.\n\nHere's the Image microservice implementation.\n\n```java\npublic interface ImageClient {\n    String getImagePath();\n}\n\npublic class ImageClientImpl implements ImageClient {\n    @Override\n    public String getImagePath() {\n        var httpClient = HttpClient.newHttpClient();\n        var httpGet = HttpRequest.newBuilder()\n                .GET()\n                .uri(URI.create(\"http://localhost:50005/image-path\"))\n                .build();\n\n        try {\n            var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n            return httpResponse.body();\n        } catch (IOException | InterruptedException e) {\n            e.printStackTrace();\n        }\n\n        return null;\n    }\n}\n```\n\nHere's the Price microservice implementation.\n\n```java\npublic interface PriceClient {\n    String getPrice();\n}\n\npublic class PriceClientImpl implements PriceClient {\n\n    @Override\n    public String getPrice() {\n        var httpClient = HttpClient.newHttpClient();\n        var httpGet = HttpRequest.newBuilder()\n                .GET()\n                .uri(URI.create(\"http://localhost:50006/price\"))\n                .build();\n\n        try {\n            var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n            return httpResponse.body();\n        } catch (IOException | InterruptedException e) {\n            e.printStackTrace();\n        }\n\n        return null;\n    }\n}\n```\n\nHere we can see how API Gateway maps the requests to the microservices.\n\n```java\npublic class ApiGateway {\n\n    @Resource\n    private ImageClient imageClient;\n\n    @Resource\n    private PriceClient priceClient;\n\n    @RequestMapping(path = \"/desktop\", method = RequestMethod.GET)\n    public DesktopProduct getProductDesktop() {\n        var desktopProduct = new DesktopProduct();\n        desktopProduct.setImagePath(imageClient.getImagePath());\n        desktopProduct.setPrice(priceClient.getPrice());\n        return desktopProduct;\n    }\n\n    @RequestMapping(path = \"/mobile\", method = RequestMethod.GET)\n    public MobileProduct getProductMobile() {\n        var mobileProduct = new MobileProduct();\n        mobileProduct.setPrice(priceClient.getPrice());\n        return mobileProduct;\n    }\n}\n```\n\n## When to Use the Microservices API Gateway Pattern in Java\n\n* When building a microservices architecture, and there's a need to abstract the complexity of microservices from the client.\n* When multiple microservices need to be consumed in a single request.\n* For authentication, authorization, and security enforcement at a single point.\n* To optimize communication between clients and services, especially in a cloud environment.\n\n## Microservices API Gateway Pattern Java Tutorials\n\n* [Exploring the New Spring Cloud Gateway (Baeldung)](https://www.baeldung.com/spring-cloud-gateway)\n* [Spring Cloud - Gateway(tutorialspoint)](https://www.tutorialspoint.com/spring_cloud/spring_cloud_gateway.htm)\n* [Getting Started With Spring Cloud Gateway (DZone)](https://dzone.com/articles/getting-started-with-spring-cloud-gateway)\n\n## Benefits and Trade-offs of Microservices API Gateway Pattern\n\nBenefits:\n\n* Decouples client from microservices, allowing services to evolve independently.\n* Simplifies client by aggregating requests to multiple services.\n* Centralized location for cross-cutting concerns like security, logging, and rate limiting.\n* Potential for performance optimizations like caching and request compression.\n\nTrade-offs:\n\n* Introduces a single point of failure, although this can be mitigated with high availability setups.\n* Can become a bottleneck if not properly scaled.\n* Adds complexity in terms of deployment and management.\n\n## Real-World Applications of Microservices API Gateway Pattern in Java\n\n* E-commerce platforms where multiple services (product info, pricing, inventory) are aggregated for a single view.\n* Mobile applications that consume various backend services but require a simplified interface for ease of use.\n* Cloud-native applications that leverage multiple microservices architectures.\n\n## Related Java Design Patterns\n\n* [Aggregator Microservice](https://java-design-patterns.com/patterns/microservices-aggregator/) - The API Gateway pattern is often used in conjunction with the Aggregator Microservice pattern to provide a unified interface to a set of microservices.\n* [Circuit Breaker](https://java-design-patterns.com/patterns/circuit-breaker/) - API Gateways can use the Circuit Breaker pattern to prevent cascading failures when calling multiple microservices.\n* [Proxy](https://java-design-patterns.com/patterns/proxy/) - The API Gateway pattern is a specialized form of the Proxy pattern, where the gateway acts as a single entry point for clients, routing requests to the appropriate microservices and aggregating results.\n\n## References and Credits\n\n* [Building Microservices](https://amzn.to/3UACtrU)\n* [Cloud Native Patterns: Designing change-tolerant software](https://amzn.to/3uV12WN)\n* [Designing Data-Intensive Applications](https://amzn.to/3PfRk7Y)\n* [Microservices Patterns: With examples in Java](https://amzn.to/3UyWD5O)\n* [API Gateway (microservices.io)](http://microservices.io/patterns/apigateway.html)\n* [Building Microservices: Using an API Gateway (nginx)](https://www.nginx.com/blog/building-microservices-using-an-api-gateway/)\n"
  },
  {
    "path": "microservices-api-gateway/api-gateway-service/etc/api-gateway-service.urm.puml",
    "content": "@startuml\npackage com.iluwatar.api.gateway {\n  class ApiGateway {\n    - imageClient : ImageClient\n    - priceClient : PriceClient\n    + ApiGateway()\n    + getProductDesktop() : DesktopProduct\n    + getProductMobile() : MobileProduct\n  }\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class DesktopProduct {\n    - imagePath : String\n    - price : String\n    + DesktopProduct()\n    + getImagePath() : String\n    + getPrice() : String\n    + setImagePath(imagePath : String)\n    + setPrice(price : String)\n  }\n  interface ImageClient {\n    + getImagePath() : String {abstract}\n  }\n  class ImageClientImpl {\n    + ImageClientImpl()\n    + getImagePath() : String\n  }\n  class MobileProduct {\n    - price : String\n    + MobileProduct()\n    + getPrice() : String\n    + setPrice(price : String)\n  }\n  interface PriceClient {\n    + getPrice() : String {abstract}\n  }\n  class PriceClientImpl {\n    + PriceClientImpl()\n    + getPrice() : String\n  }\n}\nApiGateway -->  \"-imageClient\" ImageClient\nApiGateway -->  \"-priceClient\" PriceClient\nImageClientImpl ..|> ImageClient \nPriceClientImpl ..|> PriceClient \n@enduml"
  },
  {
    "path": "microservices-api-gateway/api-gateway-service/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>microservices-api-gateway</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>api-gateway-service</artifactId>\n  <packaging>jar</packaging>\n  <dependencies>\n    <dependency>\n      <groupId>org.springframework</groupId>\n      <artifactId>spring-webmvc</artifactId>\n      <version>6.2.5</version>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-web</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.api.gateway.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "microservices-api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ApiGateway.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.api.gateway;\n\nimport jakarta.annotation.Resource;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * The ApiGateway aggregates calls to microservices based on the needs of the individual clients.\n */\n@RestController\npublic class ApiGateway {\n\n  @Resource private ImageClient imageClient;\n\n  @Resource private PriceClient priceClient;\n\n  /**\n   * Retrieves product information that desktop clients need.\n   *\n   * @return Product information for clients on a desktop\n   */\n  @GetMapping(\"/desktop\")\n  public DesktopProduct getProductDesktop() {\n    var desktopProduct = new DesktopProduct();\n    desktopProduct.setImagePath(imageClient.getImagePath());\n    desktopProduct.setPrice(priceClient.getPrice());\n    return desktopProduct;\n  }\n\n  /**\n   * Retrieves product information that mobile clients need.\n   *\n   * @return Product information for clients on a mobile device\n   */\n  @GetMapping(\"/mobile\")\n  public MobileProduct getProductMobile() {\n    var mobileProduct = new MobileProduct();\n    mobileProduct.setPrice(priceClient.getPrice());\n    return mobileProduct;\n  }\n}\n"
  },
  {
    "path": "microservices-api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.api.gateway;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * With the Microservices pattern, a client may need data from multiple different microservices. If\n * the client called each microservice directly, that could contribute to longer load times, since\n * the client would have to make a network request for each microservice called. Moreover, having\n * the client call each microservice directly ties the client to that microservice - if the internal\n * implementations of the microservices change (for example, if two microservices are combined\n * sometime in the future) or if the location (host and port) of a microservice changes, then every\n * client that makes use of those microservices must be updated.\n *\n * <p>The intent of the API Gateway pattern is to alleviate some of these issues. In the API Gateway\n * pattern, an additional entity (the API Gateway) is placed between the client and the\n * microservices. The job of the API Gateway is to aggregate the calls to the microservices. Rather\n * than the client calling each microservice individually, the client calls the API Gateway a single\n * time. The API Gateway then calls each of the microservices that the client needs.\n *\n * <p>This implementation shows what the API Gateway pattern could look like for an e-commerce site.\n * The {@link ApiGateway} makes calls to the Image and Price microservices using the {@link\n * ImageClientImpl} and {@link PriceClientImpl} respectively. Customers viewing the site on a\n * desktop device can see both price information and an image of a product, so the {@link\n * ApiGateway} calls both of the microservices and aggregates the data in the {@link DesktopProduct}\n * model. However, mobile users only see price information; they do not see a product image. For\n * mobile users, the {@link ApiGateway} only retrieves price information, which it uses to populate\n * the {@link MobileProduct}.\n */\n@SpringBootApplication\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    SpringApplication.run(App.class, args);\n  }\n}\n"
  },
  {
    "path": "microservices-api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/DesktopProduct.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.api.gateway;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Encapsulates all of the information that a desktop client needs to display a product. */\n@Getter\n@Setter\npublic class DesktopProduct {\n\n  /** The price of the product. */\n  private String price;\n\n  /** The path to the image of the product. */\n  private String imagePath;\n}\n"
  },
  {
    "path": "microservices-api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClient.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.api.gateway;\n\n/** An interface used to communicate with the Image microservice. */\npublic interface ImageClient {\n  String getImagePath();\n}\n"
  },
  {
    "path": "microservices-api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.api.gateway;\n\nimport java.io.IOException;\nimport java.net.URI;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\nimport java.net.http.HttpResponse.BodyHandlers;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.stereotype.Component;\n\n/** An adapter to communicate with the Image microservice. */\n@Slf4j\n@Component\npublic class ImageClientImpl implements ImageClient {\n\n  /**\n   * Makes a simple HTTP Get request to the Image microservice.\n   *\n   * @return The path to the image\n   */\n  @Override\n  public String getImagePath() {\n\n    var httpClient = HttpClient.newHttpClient();\n    var httpGet =\n        HttpRequest.newBuilder().GET().uri(URI.create(\"http://localhost:50005/image-path\")).build();\n\n    try {\n      LOGGER.info(\"Sending request to fetch image path\");\n      var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n      logResponse(httpResponse);\n      return httpResponse.body();\n    } catch (IOException ioe) {\n      LOGGER.error(\"Failure occurred while getting image path\", ioe);\n    } catch (InterruptedException ie) {\n      LOGGER.error(\"Failure occurred while getting image path\", ie);\n      Thread.currentThread().interrupt();\n    }\n\n    return null;\n  }\n\n  private void logResponse(HttpResponse<String> httpResponse) {\n    if (isSuccessResponse(httpResponse.statusCode())) {\n      LOGGER.info(\"Image path received successfully\");\n    } else {\n      LOGGER.warn(\"Image path request failed\");\n    }\n  }\n\n  private boolean isSuccessResponse(int responseCode) {\n    return responseCode >= 200 && responseCode <= 299;\n  }\n}\n"
  },
  {
    "path": "microservices-api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/MobileProduct.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.api.gateway;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Encapsulates all of the information that mobile client needs to display a product. */\n@Getter\n@Setter\npublic class MobileProduct {\n  /** The price of the product. */\n  private String price;\n}\n"
  },
  {
    "path": "microservices-api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClient.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.api.gateway;\n\n/** An interface used to communicate with the Price microservice. */\npublic interface PriceClient {\n  String getPrice();\n}\n"
  },
  {
    "path": "microservices-api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.api.gateway;\n\nimport java.io.IOException;\nimport java.net.URI;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\nimport java.net.http.HttpResponse.BodyHandlers;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.stereotype.Component;\n\n/** An adapter to communicate with the Price microservice. */\n@Slf4j\n@Component\npublic class PriceClientImpl implements PriceClient {\n\n  /**\n   * Makes a simple HTTP Get request to the Price microservice.\n   *\n   * @return The price of the product\n   */\n  @Override\n  public String getPrice() {\n    var httpClient = HttpClient.newHttpClient();\n    var httpGet =\n        HttpRequest.newBuilder().GET().uri(URI.create(\"http://localhost:50006/price\")).build();\n\n    try {\n      LOGGER.info(\"Sending request to fetch price info\");\n      var httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());\n      logResponse(httpResponse);\n      return httpResponse.body();\n    } catch (IOException e) {\n      LOGGER.error(\"Failure occurred while getting price info\", e);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Failure occurred while getting price info\", e);\n      Thread.currentThread().interrupt();\n    }\n\n    return null;\n  }\n\n  private void logResponse(HttpResponse<String> httpResponse) {\n    if (isSuccessResponse(httpResponse.statusCode())) {\n      LOGGER.info(\"Price info received successfully\");\n    } else {\n      LOGGER.warn(\"Price info request failed\");\n    }\n  }\n\n  private boolean isSuccessResponse(int responseCode) {\n    return responseCode >= 200 && responseCode <= 299;\n  }\n}\n"
  },
  {
    "path": "microservices-api-gateway/api-gateway-service/src/main/resources/application.properties",
    "content": "#\n# The MIT License\n# Copyright © 2014-2021 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nserver.port=50004"
  },
  {
    "path": "microservices-api-gateway/api-gateway-service/src/test/java/com/iluwatar/api/gateway/ApiGatewayTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.api.gateway;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\n\n/** Test API Gateway Pattern */\nclass ApiGatewayTest {\n\n  @InjectMocks private ApiGateway apiGateway;\n\n  @Mock private ImageClient imageClient;\n\n  @Mock private PriceClient priceClient;\n\n  @BeforeEach\n  void setup() {\n    MockitoAnnotations.openMocks(this);\n  }\n\n  /** Tests getting the data for a desktop client */\n  @Test\n  void testGetProductDesktop() {\n    var imagePath = \"/product-image.png\";\n    var price = \"20\";\n    when(imageClient.getImagePath()).thenReturn(imagePath);\n    when(priceClient.getPrice()).thenReturn(price);\n\n    var desktopProduct = apiGateway.getProductDesktop();\n\n    assertEquals(price, desktopProduct.getPrice());\n    assertEquals(imagePath, desktopProduct.getImagePath());\n  }\n\n  /** Tests getting the data for a mobile client */\n  @Test\n  void testGetProductMobile() {\n    var price = \"20\";\n    when(priceClient.getPrice()).thenReturn(price);\n\n    var mobileProduct = apiGateway.getProductMobile();\n\n    assertEquals(price, mobileProduct.getPrice());\n  }\n}\n"
  },
  {
    "path": "microservices-api-gateway/etc/api-gateway.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.9\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.api.gateway.ApiGateway\" project=\"api-gateway\" \n    file=\"/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ApiGateway.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"125\" y=\"87\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.api.gateway.DesktopProduct\" project=\"api-gateway\" \n    file=\"/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/DesktopProduct.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"388\" y=\"109\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"3\" language=\"java\" name=\"com.iluwatar.api.gateway.ImageClient\" project=\"api-gateway\" \n    file=\"/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClient.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"81\" width=\"129\" x=\"13\" y=\"197\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.api.gateway.ImageClientImpl\" project=\"api-gateway\" \n    file=\"/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"99\" width=\"129\" x=\"13\" y=\"325\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.api.gateway.MobileProduct\" project=\"api-gateway\" \n    file=\"/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/MobileProduct.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"376\" y=\"293\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"6\" language=\"java\" name=\"com.iluwatar.api.gateway.PriceClient\" project=\"api-gateway\" \n    file=\"/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClient.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"222\" y=\"231\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.api.gateway.PriceClientImpl\" project=\"api-gateway\" \n    file=\"/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">\n    <position height=\"-1\" width=\"-1\" x=\"223\" y=\"374\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"8\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"9\" name=\"imageClient\"/>      \n      <multiplicity id=\"10\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"11\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </realization>  \n  <association id=\"12\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"13\" name=\"priceClient\"/>      \n      <multiplicity id=\"14\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"6\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"15\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "microservices-api-gateway/etc/api-gateway.urm.puml",
    "content": "@startuml\n@enduml"
  },
  {
    "path": "microservices-api-gateway/etc/microservices-api-gateway.urm.puml",
    "content": "@startuml\n@enduml"
  },
  {
    "path": "microservices-api-gateway/image-microservice/etc/image-microservice.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.9\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.image.microservice.ImageController\" project=\"image-microservice\" \n    file=\"/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageController.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"87\" y=\"61\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "microservices-api-gateway/image-microservice/etc/image-microservice.urm.puml",
    "content": "@startuml\npackage com.iluwatar.image.microservice {\n  class ImageApplication {\n    + ImageApplication()\n    + main(args : String[]) {static}\n  }\n  class ImageController {\n    + ImageController()\n    + getImagePath() : String\n  }\n}\n@enduml"
  },
  {
    "path": "microservices-api-gateway/image-microservice/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>microservices-api-gateway</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>image-microservice</artifactId>\n  <packaging>jar</packaging>\n  <dependencies>\n    <dependency>\n      <groupId>org.springframework</groupId>\n      <artifactId>spring-webmvc</artifactId>\n      <version>6.2.5</version>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-web</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.image.microservice.ImageApplication</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "microservices-api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageApplication.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.image.microservice;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * ImageApplication starts up Spring Boot, exposing endpoints for the Image microservice through the\n * {@link ImageController}.\n */\n@SpringBootApplication\npublic class ImageApplication {\n\n  /**\n   * Microservice entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    SpringApplication.run(ImageApplication.class, args);\n  }\n}\n"
  },
  {
    "path": "microservices-api-gateway/image-microservice/src/main/java/com/iluwatar/image/microservice/ImageController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.image.microservice;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/** Exposes the Image microservice's endpoints. */\n@Slf4j\n@RestController\npublic class ImageController {\n\n  /**\n   * An endpoint for a user to retrieve an image path.\n   *\n   * @return An image path\n   */\n  @GetMapping(\"/image-path\")\n  public String getImagePath() {\n    LOGGER.info(\"Successfully found image path\");\n    return \"/product-image.png\";\n  }\n}\n"
  },
  {
    "path": "microservices-api-gateway/image-microservice/src/main/resources/application.properties",
    "content": "#\n# The MIT License\n# Copyright © 2014-2021 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nserver.port=50005"
  },
  {
    "path": "microservices-api-gateway/image-microservice/src/test/java/com/iluwatar/image/microservice/ImageControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.image.microservice;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test for Image Rest Controller */\nclass ImageControllerTest {\n\n  @Test\n  void testGetImagePath() {\n    var imageController = new ImageController();\n    var imagePath = imageController.getImagePath();\n    assertEquals(\"/product-image.png\", imagePath);\n  }\n}\n"
  },
  {
    "path": "microservices-api-gateway/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>microservices-api-gateway</artifactId>\n  <packaging>pom</packaging>\n  <modules>\n    <module>image-microservice</module>\n    <module>price-microservice</module>\n    <module>api-gateway-service</module>\n  </modules>\n</project>\n"
  },
  {
    "path": "microservices-api-gateway/price-microservice/etc/price-microservice.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.9\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.price.microservice.PriceController\" project=\"price-microservice\" \n    file=\"/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceController.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"82\" y=\"63\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "microservices-api-gateway/price-microservice/etc/price-microservice.urm.puml",
    "content": "@startuml\npackage com.iluwatar.price.microservice {\n  class PriceApplication {\n    + PriceApplication()\n    + main(args : String[]) {static}\n  }\n  class PriceController {\n    + PriceController()\n    + getPrice() : String\n  }\n}\n@enduml"
  },
  {
    "path": "microservices-api-gateway/price-microservice/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>microservices-api-gateway</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>price-microservice</artifactId>\n  <packaging>jar</packaging>\n  <dependencies>\n    <dependency>\n      <groupId>org.springframework</groupId>\n      <artifactId>spring-webmvc</artifactId>\n      <version>6.2.5</version>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-web</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.price.microservices.PriceApplication</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "microservices-api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceApplication.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.price.microservice;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * PriceApplication starts up Spring Boot, exposing endpoints for the Price microservice through the\n * {@link PriceController}.\n */\n@SpringBootApplication\npublic class PriceApplication {\n\n  /**\n   * Microservice entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    SpringApplication.run(PriceApplication.class, args);\n  }\n}\n"
  },
  {
    "path": "microservices-api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.price.microservice;\n\nimport lombok.RequiredArgsConstructor;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/** Exposes the Price microservice's endpoints. */\n@RestController\n@RequiredArgsConstructor\npublic class PriceController {\n\n  private final PriceService priceService;\n\n  /**\n   * An endpoint for a user to retrieve a product's price.\n   *\n   * @return A product's price\n   */\n  @GetMapping(\"/price\")\n  public String getPrice() {\n    return priceService.getPrice();\n  }\n}\n"
  },
  {
    "path": "microservices-api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.price.microservice;\n\n/** Service to get a product's price. */\npublic interface PriceService {\n\n  /**\n   * Getting the price of a product.\n   *\n   * @return A product's price\n   */\n  String getPrice();\n}\n"
  },
  {
    "path": "microservices-api-gateway/price-microservice/src/main/java/com/iluwatar/price/microservice/PriceServiceImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.price.microservice;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.stereotype.Service;\n\n/** {@inheritDoc} */\n@Service\n@Slf4j\npublic class PriceServiceImpl implements PriceService {\n\n  /** {@inheritDoc} */\n  @Override\n  public String getPrice() {\n    LOGGER.info(\"Successfully found price info\");\n    return \"20\";\n  }\n}\n"
  },
  {
    "path": "microservices-api-gateway/price-microservice/src/main/resources/application.properties",
    "content": "#\n# The MIT License\n# Copyright © 2014-2021 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nserver.port=50006"
  },
  {
    "path": "microservices-api-gateway/price-microservice/src/test/java/com/iluwatar/price/microservice/PriceControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.price.microservice;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test for Price Rest Controller */\nclass PriceControllerTest {\n\n  @Test\n  void getPriceTest() {\n    var priceController = new PriceController(new PriceServiceImpl());\n    var price = priceController.getPrice();\n    assertEquals(\"20\", price);\n  }\n}\n"
  },
  {
    "path": "microservices-api-gateway/price-microservice/src/test/java/com/iluwatar/price/microservice/PriceServiceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.price.microservice;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test for Price Service */\nclass PriceServiceTest {\n\n  @Test\n  void getPriceTest() {\n    var priceService = new PriceServiceImpl();\n    var price = priceService.getPrice();\n    assertEquals(\"20\", price);\n  }\n}\n"
  },
  {
    "path": "microservices-client-side-ui-composition/README.md",
    "content": "---\ntitle: \"Microservices Client-Side UI Composition Pattern In Java: Assembling Modular UIs in Microservices Architecture\"\nshortTitle: Microservices Client-Side UI Composition\ndescription: \"Learn how the Client-Side UI Composition pattern allows the assembly of modular UIs on the client side, enabling independent teams to develop, deploy, and scale UI components in a microservices architecture. Discover the benefits, implementation examples, and best practices.\"\ncategory: Architectural\nlanguage: en\ntag:\n    - Client-server\n    - Cloud distributed\n    - Composition\n    - Decoupling\n    - Integration\n    - Microservices\n    - Modularity\n    - Scalability\n    - Web development\n---\n\n## Intent of Client-Side UI Composition Design Pattern\n\nCompose user interface from independently deployable microservices on the client side for greater flexibility and decoupling.\n\n## Also Known As\n\n* UI Aggregator\n* Frontend-Driven Composition\n\n## Detailed Explanation of Client-Side UI Composition Pattern with Real-World Examples\n\nReal-world Example\n\n> In a SaaS dashboard, a client-side composition pattern enables various independent modules like “Billing,” “Reports,” and “Account Settings” to be developed and deployed by separate teams. These modules are composed into a unified interface for the user, with each module independently fetching data from its respective microservice.\n\nIn Plain Words\n\n> The Client-Side UI Composition pattern breaks down the user interface into smaller, independent parts that can be developed, maintained, and scaled separately by different teams.\n\nWikipedia says\n\n> UI composition refers to the practice of building a user interface from modular components, each responsible for fetching its own data and rendering its own content. This approach enables faster development cycles, easier maintenance, and better scalability in large systems.\n\nSequence diagram\n\n![Client-Side UI Composition sequence diagram](./etc/microservices-client-side-ui-composition-sequence-diagram.png)\n\n## Programmatic Example of Client-Side UI Composition in Java\n\nThis example composes an e-commerce frontend by integrating three independent modules. Each module is served by a microservice and fetched on the client side through an API Gateway.\n\n### `ApiGateway` Implementation\n\n```java\npublic class ApiGateway {\n\n    private final Map<String, FrontendComponent> routes = new HashMap<>();\n\n    public void registerRoute(String path, FrontendComponent component) {\n        routes.put(path, component);\n    }\n\n    public String handleRequest(String path, Map<String, String> params) {\n        if (routes.containsKey(path)) {\n            return routes.get(path).fetchData(params);\n        } else {\n            return \"404 Not Found\";\n        }\n    }\n}\n\n```\n\n### `FrontendComponent` Interface\n\n```java\npublic interface FrontendComponent {\n    String fetchData(Map<String, String> params);\n}\n```\n\n### Example Components\n\n```java\npublic class ProductComponent implements FrontendComponent {\n    @Override\n    public String fetchData(Map<String, String> params) {\n        return \"Displaying Products: \" + params.getOrDefault(\"category\", \"all\");\n    }\n}\n\npublic class CartComponent implements FrontendComponent {\n    @Override\n    public String fetchData(Map<String, String> params) {\n        return \"Displaying Cart for User: \" + params.getOrDefault(\"userId\", \"unknown\");\n    }\n}\n```\n\nThis approach dynamically assembles UI components based on the route in the client-side request. Each component fetches its data asynchronously and renders it within the main interface.\n\n## When to Use the Client-Side UI Composition Pattern\n\n* When each microservice must present its own UI components\n* When frequent independent deployments of UI features are required\n* When teams own end-to-end functionality, including front-end modules\n* When Java-based backends provide separate APIs for direct UI consumption\n\n## Client-Side UI Composition Pattern Tutorials\n\n- [Micro Frontends in Action (O'Reilly)](https://www.oreilly.com/library/view/micro-frontends-in/9781617296873/)\n- [Micro Frontends with React (ThoughtWorks)](https://www.thoughtworks.com/insights/articles/building-micro-frontends-using-react)\n- [API Gateway in Microservices (Spring Cloud)](https://spring.io/guides/gs/gateway/)\n\n## Real-World Applications of Client-Side UI Composition Pattern in Java\n\n* Large-scale e-commerce portals with microservices powering modular pages\n* SaaS platforms requiring rapid iteration of front-end features\n* Java-based microservice architectures using frameworks like Spring Boot for modular UI components\n\n## Benefits and Trade-offs of Client-Side UI Composition Pattern\n\nBenefits:\n\n* Facilitates independent deployment cycles for UI features\n* Reduces overall coupling and fosters autonomy among teams\n* Enables polyglot front-end development\n\nTrade-offs:\n\n* Increases client complexity for rendering and data aggregation\n* Can cause performance challenges with multiple service calls\n* Demands consistent UX guidelines across diverse microservices\n\n## Related Design Patterns\n\n* Backend for Frontend (BFF): Provides custom endpoints for specific UIs\n* Micro Frontends: Splits the front-end into smaller, individually deployable fragments\n* [Microservices API Gateway Pattern](https://java-design-patterns.com/patterns/microservices-api-gateway/): API Gateway serves as a routing mechanism for client-side UI requests.\n\n## References and Credits\n\n* [Building Microservices](https://amzn.to/3UACtrU)\n* [Building Microservices with Micro Frontends (Martin Fowler)](https://martinfowler.com/articles/micro-frontends.html)\n* [Client-Side UI Composition (Microservices.io)](https://microservices.io/patterns/client-side-ui-composition.html)\n* [Cloud Native Java: Designing Resilient Systems with Spring Boot, Spring Cloud, and Cloud Foundry](https://amzn.to/44vDTat)\n* [Micro Frontends Architecture (Microfrontends.org)](https://micro-frontends.org/)\n* [Microservices Patterns: With examples in Java](https://amzn.to/3UyWD5O)\n"
  },
  {
    "path": "microservices-client-side-ui-composition/etc/client-side-ui-composition.urm.puml",
    "content": "@startuml client_side_ui_composition_updated\nskinparam classAttributeIconSize 0\n\nclass ApiGateway {\n    +registerRoute(path: String, component: FrontendComponent)\n    +handleRequest(path: String, params: Map<String, String>): String\n}\n\nclass FrontendComponent {\n    +fetchData(params: Map<String, String>): String\n    #getData(params: Map<String, String>): String\n}\n\nclass ProductFrontend {\n    +getData(params: Map<String, String>): String\n}\n\nclass CartFrontend {\n    +getData(params: Map<String, String>): String\n}\n\nclass ClientSideIntegrator {\n    +composeUI(path: String, params: Map<String, String>)\n}\n\nApiGateway --> FrontendComponent\nFrontendComponent <|-- ProductFrontend\nFrontendComponent <|-- CartFrontend\nClientSideIntegrator --> ApiGateway\n\n@enduml\n"
  },
  {
    "path": "microservices-client-side-ui-composition/etc/microservices-client-side-ui-composition.urm.puml",
    "content": "@startuml\npackage com.iluwatar.clientsideuicomposition {\n  class ApiGateway {\n    - routes : Map<String, FrontendComponent>\n    + ApiGateway()\n    + handleRequest(path : String, params : Map<String, String>) : String\n    + registerRoute(path : String, component : FrontendComponent)\n  }\n  class CartFrontend {\n    + CartFrontend()\n    # getData(params : Map<String, String>) : String\n  }\n  class ClientSideIntegrator {\n    - LOGGER : Logger {static}\n    - apiGateway : ApiGateway\n    + ClientSideIntegrator(apiGateway : ApiGateway)\n    + composeUi(path : String, params : Map<String, String>)\n  }\n  abstract class FrontendComponent {\n    + random : Random {static}\n    + FrontendComponent()\n    + fetchData(params : Map<String, String>) : String\n    # getData(Map<String, String>) : String {abstract}\n  }\n  class ProductFrontend {\n    + ProductFrontend()\n    # getData(params : Map<String, String>) : String\n  }\n}\nClientSideIntegrator -->  \"-apiGateway\" ApiGateway\nCartFrontend --|> FrontendComponent \nProductFrontend --|> FrontendComponent \n@enduml"
  },
  {
    "path": "microservices-client-side-ui-composition/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>microservices-client-side-ui-composition</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n    </dependencies>\n\n</project>"
  },
  {
    "path": "microservices-client-side-ui-composition/src/main/java/com/iluwatar/clientsideuicomposition/ApiGateway.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.clientsideuicomposition;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * ApiGateway class acts as a dynamic routing mechanism that forwards client requests to the\n * appropriate frontend components based on dynamically registered routes.\n *\n * <p>This allows for flexible, runtime-defined routing without hardcoding specific paths.\n */\npublic class ApiGateway {\n\n  // A map to store routes dynamically, where the key is the path and the value\n  // is the associated FrontendComponent\n  private final Map<String, FrontendComponent> routes = new HashMap<>();\n\n  /**\n   * Registers a route dynamically at runtime.\n   *\n   * @param path the path to access the component (e.g., \"/products\")\n   * @param component the frontend component to be accessed at the given path\n   */\n  public void registerRoute(String path, FrontendComponent component) {\n    routes.put(path, component);\n  }\n\n  /**\n   * Handles a client request by routing it to the appropriate frontend component.\n   *\n   * <p>This method dynamically handles parameters passed with the request, which allows the\n   * frontend components to respond based on those parameters.\n   *\n   * @param path the path for which the request is made (e.g., \"/products\", \"/cart\")\n   * @param params a map of parameters that might influence the data fetching logic (e.g., filters,\n   *     userId, categories, etc.)\n   * @return the data fetched from the appropriate component or \"404 Not Found\" if the path is not\n   *     registered\n   */\n  public String handleRequest(String path, Map<String, String> params) {\n    if (routes.containsKey(path)) {\n      // Fetch data dynamically based on the provided parameters\n      return routes.get(path).fetchData(params);\n    } else {\n      // Return a 404 error if the path is not registered\n      return \"404 Not Found\";\n    }\n  }\n}\n"
  },
  {
    "path": "microservices-client-side-ui-composition/src/main/java/com/iluwatar/clientsideuicomposition/CartFrontend.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.clientsideuicomposition;\n\nimport java.util.Map;\n\n/**\n * CartFrontend is a concrete implementation of FrontendComponent that simulates fetching shopping\n * cart data based on the user.\n */\npublic class CartFrontend extends FrontendComponent {\n\n  /**\n   * Fetches the current state of the shopping cart based on dynamic parameters like user ID.\n   *\n   * @param params parameters that influence the cart data, e.g., \"userId\"\n   * @return a string representing the items in the shopping cart for a given user\n   */\n  @Override\n  protected String getData(Map<String, String> params) {\n    String userId = params.getOrDefault(\"userId\", \"anonymous\");\n    return \"Shopping Cart for user '\" + userId + \"': [Item 1, Item 2]\";\n  }\n}\n"
  },
  {
    "path": "microservices-client-side-ui-composition/src/main/java/com/iluwatar/clientsideuicomposition/ClientSideIntegrator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.clientsideuicomposition;\n\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * ClientSideIntegrator class simulates the client-side integration layer that dynamically assembles\n * various frontend components into a cohesive user interface.\n */\n@Slf4j\npublic class ClientSideIntegrator {\n\n  private final ApiGateway apiGateway;\n\n  /**\n   * Constructor that accepts an instance of ApiGateway to handle dynamic routing.\n   *\n   * @param apiGateway the gateway that routes requests to different frontend components\n   */\n  public ClientSideIntegrator(ApiGateway apiGateway) {\n    this.apiGateway = apiGateway;\n  }\n\n  /**\n   * Composes the user interface dynamically by fetching data from different frontend components\n   * based on provided parameters.\n   *\n   * @param path the route of the frontend component\n   * @param params a map of dynamic parameters to influence the data fetching\n   */\n  public void composeUi(String path, Map<String, String> params) {\n    // Fetch data dynamically based on the route and parameters\n    String data = apiGateway.handleRequest(path, params);\n    LOGGER.info(\"Composed UI Component for path '\" + path + \"':\");\n    LOGGER.info(data);\n  }\n}\n"
  },
  {
    "path": "microservices-client-side-ui-composition/src/main/java/com/iluwatar/clientsideuicomposition/FrontendComponent.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.clientsideuicomposition;\n\nimport java.util.Map;\nimport java.util.Random;\n\n/**\n * FrontendComponent is an abstract class representing an independent frontend component that\n * fetches data dynamically based on the provided parameters.\n */\npublic abstract class FrontendComponent {\n\n  public static final Random random = new Random();\n\n  /**\n   * Simulates asynchronous data fetching by introducing a random delay and then fetching the data\n   * based on dynamic input.\n   *\n   * @param params a map of parameters that may affect the data fetching logic\n   * @return the data fetched by the frontend component\n   */\n  public String fetchData(Map<String, String> params) {\n    try {\n      // Simulate delay in fetching data (e.g., network latency)\n      Thread.sleep(random.nextInt(1000));\n    } catch (InterruptedException e) {\n      Thread.currentThread().interrupt();\n    }\n    // Fetch and return the data based on the given parameters\n    return getData(params);\n  }\n\n  /**\n   * Abstract method to be implemented by subclasses to return data based on parameters.\n   *\n   * @param params a map of parameters that may affect the data fetching logic\n   * @return the data for this specific component\n   */\n  protected abstract String getData(Map<String, String> params);\n}\n"
  },
  {
    "path": "microservices-client-side-ui-composition/src/main/java/com/iluwatar/clientsideuicomposition/ProductFrontend.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.clientsideuicomposition;\n\nimport java.util.Map;\n\n/**\n * ProductFrontend is a concrete implementation of FrontendComponent that simulates fetching dynamic\n * product data.\n */\npublic class ProductFrontend extends FrontendComponent {\n\n  /**\n   * Fetches a list of products based on dynamic parameters such as category.\n   *\n   * @param params parameters that influence the data fetched, e.g., \"category\"\n   * @return a string representing a filtered list of products\n   */\n  @Override\n  protected String getData(Map<String, String> params) {\n    String category = params.getOrDefault(\"category\", \"all\");\n    return \"Product List for category '\" + category + \"': [Product 1, Product 2, Product 3]\";\n  }\n}\n"
  },
  {
    "path": "microservices-client-side-ui-composition/src/test/java/com/iluwatar/clientsideuicomposition/ClientSideCompositionTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.clientsideuicomposition;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport org.junit.jupiter.api.Test;\n\n/**\n * ClientSideCompositionTest contains unit tests to validate dynamic route registration and UI\n * composition.\n */\nclass ClientSideCompositionTest {\n\n  /** Tests dynamic registration of frontend components and dynamic composition of UI. */\n  @Test\n  void testClientSideUIComposition() {\n    // Create API Gateway and dynamically register frontend components\n    ApiGateway apiGateway = new ApiGateway();\n    apiGateway.registerRoute(\"/products\", new ProductFrontend());\n    apiGateway.registerRoute(\"/cart\", new CartFrontend());\n\n    // Create the Client-Side Integrator\n    ClientSideIntegrator integrator = new ClientSideIntegrator(apiGateway);\n\n    // Dynamically pass parameters for data fetching\n    Map<String, String> productParams = new HashMap<>();\n    productParams.put(\"category\", \"electronics\");\n\n    // Compose UI for products and cart with dynamic params\n    integrator.composeUi(\"/products\", productParams);\n\n    Map<String, String> cartParams = new HashMap<>();\n    cartParams.put(\"userId\", \"user123\");\n    integrator.composeUi(\"/cart\", cartParams);\n\n    // Validate the dynamically fetched data\n    String productData = apiGateway.handleRequest(\"/products\", productParams);\n    String cartData = apiGateway.handleRequest(\"/cart\", cartParams);\n\n    assertTrue(productData.contains(\"Product List for category 'electronics'\"));\n    assertTrue(cartData.contains(\"Shopping Cart for user 'user123'\"));\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/README.md",
    "content": "---\ntitle: \"Microservices Distributed Tracing Pattern In Java: Enhancing Visibility in Service Communication\"\nshortTitle: Microservices Distributed Tracing\ndescription: \"Learn how the Distributed Tracing pattern enhances visibility into service communication across microservices. Discover its benefits, implementation examples, and best practices.\"\ncategory: Architectural\nlanguage: en\ntag:\n    - Cloud distributed\n    - Microservices\n    - Resilience\n    - Observability\n    - Scalability\n    - System health\n---\n\n## Intent of Microservices Distributed Tracing Design Pattern\n\nProvide a mechanism to trace and correlate requests as they traverse multiple microservices in a distributed system, enabling end-to-end visibility and easier troubleshooting.\n\n## Also known as\n\n* Distributed Request Tracing\n* End-to-End Microservice Tracing\n\n## Detailed Explanation of Microservices Distributed Tracing Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine an online food delivery platform where one microservice handles user orders, another manages restaurant menus, and yet another coordinates courier assignments. When a user places an order, the request travels through all three services in sequence. By implementing distributed tracing, each service attaches a trace identifier to its logs. This allows the operations team to follow the journey of a single order across the entire pipeline, identify any delays along the way, and quickly pinpoint which service is causing the bottleneck or experiencing an error.\n\nIn plain words\n\n> Distributed tracing allows you to follow a request's journey through all the services it interacts with, providing insights into system performance and aiding in debugging.\n\nWikipedia says\n\n> Tracing in software engineering refers to the process of capturing and recording information about the execution of a software program. This information is typically used by programmers for debugging purposes, and additionally, depending on the type and detail of information contained in a trace log, by experienced system administrators or technical-support personnel and by software monitoring tools to diagnose common problems with software.\n\nSequence diagram\n\n![Microservices Distributed Tracing Sequence Diagram](./etc/microservices-distributed-tracing-sequence-diagram.png)\n\n## Programmatic Example of Microservices Distributed Tracing in Java\n\nThis implementation shows how an e-commerce platform's `OrderService` interacts with both `PaymentService` and `ProductService`. When a customer places an order, the `OrderService` calls the `PaymentService` to process the payment and the `ProductService` to check the product inventory. By adding distributed trace instrumentation (usually via libraries like Spring Cloud Sleuth or OpenTelemetry), each service attaches trace context to outgoing requests and logs. These logs can then be viewed in the Zipkin interface (or other tracing tools, such as Jaeger) to observe the entire flow of the request and quickly identify any performance bottlenecks or failures across multiple services.\n\nHere's the `Order microservice` implementation.\n\n```java\n@Slf4j\n@RestController\npublic class OrderController {\n\n    private final OrderService orderService;\n\n    public OrderController(final OrderService orderService) {\n        this.orderService = orderService;\n    }\n    \n    @PostMapping(\"/order\")\n    public ResponseEntity<String> processOrder(@RequestBody(required = false) String request) {\n        LOGGER.info(\"Received order request: {}\", request);\n        var result = orderService.processOrder();\n        LOGGER.info(\"Order processed result: {}\", result);\n        return ResponseEntity.ok(result);\n    }\n}\n```\n```java\n@Slf4j\n@Service\npublic class OrderService {\n\n    private final RestTemplateBuilder restTemplateBuilder;\n\n    public OrderService(final RestTemplateBuilder restTemplateBuilder) {\n        this.restTemplateBuilder = restTemplateBuilder;\n    }\n\n    public String processOrder() {\n        if (validateProduct() && processPayment()) {\n            return \"Order processed successfully\";\n        }\n        return \"Order processing failed\";\n    }\n    \n    Boolean validateProduct() {\n        try {\n            ResponseEntity<Boolean> productValidationResult = restTemplateBuilder\n                    .build()\n                    .postForEntity(\"http://localhost:30302/product/validate\", \"validating product\",\n                            Boolean.class);\n            LOGGER.info(\"Product validation result: {}\", productValidationResult.getBody());\n            return productValidationResult.getBody();\n        } catch (ResourceAccessException | HttpClientErrorException e) {\n            LOGGER.error(\"Error communicating with product service: {}\", e.getMessage());\n            return false;\n        }\n    }\n\n    Boolean processPayment() {\n        try {\n            ResponseEntity<Boolean> paymentProcessResult = restTemplateBuilder\n                    .build()\n                    .postForEntity(\"http://localhost:30301/payment/process\", \"processing payment\",\n                            Boolean.class);\n            LOGGER.info(\"Payment processing result: {}\", paymentProcessResult.getBody());\n            return paymentProcessResult.getBody();\n        } catch (ResourceAccessException | HttpClientErrorException e) {\n            LOGGER.error(\"Error communicating with payment service: {}\", e.getMessage());\n            return false;\n        }\n    }\n}\n```\n\nHere's the `Payment microservice` implementation.\n\n```java\n\n@Slf4j\n@RestController\npublic class PaymentController {\n\n    @PostMapping(\"/payment/process\")\n    public ResponseEntity<Boolean> payment(@RequestBody(required = false) String request) {\n        LOGGER.info(\"Received payment request: {}\", request);\n        boolean result = true;\n        LOGGER.info(\"Payment result: {}\", result);\n        return ResponseEntity.ok(result);\n    }\n}\n```\n\nHere's the `Product microservice` implementation.\n\n```java\n/**\n * Controller for handling product validation requests.\n */\n@Slf4j\n@RestController\npublic class ProductController {\n\n    /**\n     * Validates the product based on the request.\n     *\n     * @param request the request body containing product information (can be null)\n     * @return ResponseEntity containing the validation result (true)\n     */\n    @PostMapping(\"/product/validate\")\n    public ResponseEntity<Boolean> validateProduct(@RequestBody(required = false) String request) {\n        LOGGER.info(\"Received product validation request: {}\", request);\n        boolean result = true;\n        LOGGER.info(\"Product validation result: {}\", result);\n        return ResponseEntity.ok(result);\n    }\n}\n```\n\nIn this example, each microservice would typically be configured with tracing libraries (like Sleuth or OpenTelemetry). The trace context is propagated via HTTP headers, enabling the logs and metrics for each service call to be grouped together and visualized in Zipkin or another compatible tool. This ensures complete end-to-end visibility into each request’s journey.\n\n## When to Use the Microservices Distributed Tracing Pattern in Java\n\n* When multiple services form a single user request path and debugging failures requires visibility across service boundaries.\n* When monitoring or diagnosing performance bottlenecks is critical in a multi-service environment.\n* When correlation of logs and metrics from independent services is needed to understand overall system health.\n\n## Microservices Distributed Tracing Pattern Java Tutorials\n\n* [Spring Boot - Tracing (Spring)](https://docs.spring.io/spring-boot/reference/actuator/tracing.html)\n* [Reactive Observability (Spring Academy)](https://spring.academy/guides/microservices-observability-reactive-spring-boot-3)\n* [Spring Cloud – Tracing Services with Zipkin (Baeldung)](https://dzone.com/articles/getting-started-with-spring-cloud-gateway)\n\n## Real-World Applications of Microservices Distributed Tracing Pattern in Java\n\n* OpenTelemetry for tracing instrumentation in Java services.\n* Spring Cloud Sleuth for automatic tracing in Spring Boot microservices.\n* Jaeger and Zipkin for collecting and visualizing distributed traces in Java-based systems.\n\n## Benefits and Trade-offs of Microservices Distributed Tracing Pattern\n\nBenefits:\n\n* Centralized insight into request paths across services, reducing time to diagnose issues.\n* Improved observability enables proactive identification of system bottlenecks.\n* Aids in debugging and troubleshooting complex systems.\n\nTrade-offs:\n\n* Adds overhead to each request due to tracing data.\n* Requires additional infrastructure (e.g., Zipkin, Jaeger) for collecting and visualizing traces.\n* Can become complex to manage in large-scale systems.\n\n## Related Java Design Patterns\n\n* [API Gateway Microservice](https://java-design-patterns.com/patterns/microservices-api-gateway/): Acts as an entry point to microservices and can propagate trace information to downstream services.\n* [Circuit Breaker](https://java-design-patterns.com/patterns/circuit-breaker/): Distributed tracing can be used alongside the Circuit Breaker pattern to monitor and handle failures gracefully, preventing cascading failures in microservices.\n* [Log Aggregation Microservice](https://java-design-patterns.com/patterns/microservices-log-aggregation/): Distributed tracing works well in conjunction with log aggregation to provide comprehensive observability and troubleshooting capabilities.\n* [Saga](https://java-design-patterns.com/patterns/saga/): Orchestrates distributed transactions, which benefit from trace identifiers to correlate steps across services.\n\n## References and Credits\n\n* [Building Microservices](https://amzn.to/3UACtrU)\n* [Distributed tracing (microservices.io)](https://microservices.io/patterns/observability/distributed-tracing.html)\n* [Microservices Patterns: With examples in Java](https://amzn.to/3UyWD5O)\n* [OpenTelemetry Documentation](https://opentelemetry.io/docs/)\n* [Release It! Design and Deploy Production-Ready Software](https://amzn.to/3Uul4kF)\n"
  },
  {
    "path": "microservices-distributed-tracing/etc/microservices-distributed-tracing.puml",
    "content": "@startuml\n!theme vibrant\npackage com.iluwatar.microservices-distributed-tracing {\npackage \"Order Microservice\" {\n    class OrderController {\n        +processOrder()\n    }\n\n    class OrderService {\n        +validateProduct()\n        +processPayment()\n    }\n}\n\npackage \"Payment Microservice\" {\n    class PaymentController {\n        +processPayment()\n    }\n}\n\npackage \"Product Microservice\" {\n    class ProductController {\n        +validateProduct()\n    }\n}\n\nOrderController --> OrderService\nOrderService --> PaymentController : processPayment()\nOrderService --> ProductController : validateProduct()\n}\n@enduml"
  },
  {
    "path": "microservices-distributed-tracing/etc/microservices-distributed-tracing.urm.puml",
    "content": "@startuml\n!theme vibrant\npackage com.iluwatar.microservices-distributed-tracing {\npackage \"Order Microservice\" {\n    class OrderController {\n        +processOrder()\n    }\n\n    class OrderService {\n        +validateProduct()\n        +processPayment()\n    }\n}\n\npackage \"Payment Microservice\" {\n    class PaymentController {\n        +processPayment()\n    }\n}\n\npackage \"Product Microservice\" {\n    class ProductController {\n        +validateProduct()\n    }\n}\n\nOrderController --> OrderService\nOrderService --> PaymentController : processPayment()\nOrderService --> ProductController : validateProduct()\n}\n@enduml"
  },
  {
    "path": "microservices-distributed-tracing/order-microservice/etc/order-microservice.puml",
    "content": "@startuml\n!theme vibrant\npackage com.iluwatar.microservices-distributed-tracing {\npackage \"Order Microservice\" {\n    class OrderController {\n        +processOrder()\n    }\n\n    class OrderService {\n        +validateProduct()\n        +processPayment()\n    }\n}\n}\n@enduml"
  },
  {
    "path": "microservices-distributed-tracing/order-microservice/etc/order-microservice.urm.puml",
    "content": "@startuml\n!theme vibrant\npackage com.iluwatar.microservices-distributed-tracing {\npackage \"Order Microservice\" {\n    class OrderController {\n        +processOrder()\n    }\n\n    class OrderService {\n        +validateProduct()\n        +processPayment()\n    }\n}\n}\n@enduml"
  },
  {
    "path": "microservices-distributed-tracing/order-microservice/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>microservices-distributed-tracing</artifactId>\n        <groupId>com.iluwatar</groupId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>order-microservice</artifactId>\n    <packaging>jar</packaging>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.order.microservice.com.iluwatar.product.microservice.Main</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n    <repositories>\n        <repository>\n            <id>central</id>\n            <name>Maven Central Repository</name>\n            <url>https://repo.maven.apache.org/maven2</url>\n        </repository>\n    </repositories>\n</project>\n"
  },
  {
    "path": "microservices-distributed-tracing/order-microservice/src/main/java/com/iluwatar/order/microservice/Main.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.order.microservice;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * With the Microservices pattern, a request often travels through multiple different microservices.\n * Tracking the entire request flow across these services can be challenging, especially when trying\n * to diagnose performance issues or failures. Distributed tracing addresses this challenge by\n * providing end-to-end visibility into the lifecycle of a request as it passes through various\n * microservices.\n *\n * <p>The intent of the Distributed Tracing pattern is to trace a request across different\n * microservices, collecting detailed timing data and logs that help in understanding the flow,\n * performance bottlenecks, and failure points in a distributed system. Each microservice involved\n * in the request contributes to the tracing data, creating a comprehensive view of the request's\n * journey.\n *\n * <p>This implementation demonstrates distributed tracing in a microservices architecture for an\n * e-commerce platform. When a customer places an order, the {@link OrderService} interacts with\n * both the payment-microservice to process the payment and the product-microservice to check the\n * product inventory. Tracing logs are generated for each interaction, and these logs can be\n * visualized using Zipkin.\n *\n * <p>To run Zipkin and view the tracing logs, you can use the following Docker command:\n *\n * <pre>\n * {@code docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin }\n * </pre>\n *\n * <p>Start Zipkin with the command above. Once Zipkin is running, you can access the Zipkin UI at\n * `<a href=\"http://localhost:9411\">...</a>` to view the tracing logs and analyze the request flows\n * across your microservices.\n *\n * <p>To place an order and generate tracing data, you can use the following curl command:\n *\n * <pre>\n * {@code curl -X POST http://localhost:30300/order -H \"Content-Type: application/json\" -d '{\"orderId\": \"123\"}' }\n * </pre>\n *\n * <p>This command sends a POST request to create an order, which will trigger interactions with the\n * payment and product microservices, generating tracing logs that can be viewed in Zipkin.\n */\n@SpringBootApplication\npublic class Main {\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    SpringApplication.run(Main.class, args);\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/order-microservice/src/main/java/com/iluwatar/order/microservice/OrderController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.order.microservice;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/** This controller handles order processing by calling necessary microservices. */\n@Slf4j\n@RestController\npublic class OrderController {\n\n  private final OrderService orderService;\n\n  /**\n   * Constructor to inject OrderService.\n   *\n   * @param orderService the service to process orders\n   */\n  public OrderController(final OrderService orderService) {\n    this.orderService = orderService;\n  }\n\n  /**\n   * Endpoint to process an order.\n   *\n   * @param request the order request body (can be null)\n   * @return ResponseEntity with a status message\n   */\n  @PostMapping(\"/order\")\n  public ResponseEntity<String> processOrder(@RequestBody(required = false) String request) {\n    LOGGER.info(\"Received order request: {}\", request);\n    var result = orderService.processOrder();\n    LOGGER.info(\"Order processed result: {}\", result);\n    return ResponseEntity.ok(result);\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/order-microservice/src/main/java/com/iluwatar/order/microservice/OrderService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.order.microservice;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.web.client.RestTemplateBuilder;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.client.HttpClientErrorException;\nimport org.springframework.web.client.ResourceAccessException;\n\n/** Service to handle order processing logic. */\n@Slf4j\n@Service\npublic class OrderService {\n\n  private final RestTemplateBuilder restTemplateBuilder;\n\n  /**\n   * Constructor to inject RestTemplateBuilder.\n   *\n   * @param restTemplateBuilder the RestTemplateBuilder to build RestTemplate instances\n   */\n  public OrderService(final RestTemplateBuilder restTemplateBuilder) {\n    this.restTemplateBuilder = restTemplateBuilder;\n  }\n\n  /**\n   * Processes an order by calling {@link OrderService#validateProduct()} and {@link\n   * OrderService#processPayment()}.\n   *\n   * @return A string indicating whether the order was processed successfully or failed.\n   */\n  public String processOrder() {\n    if (validateProduct() && processPayment()) {\n      return \"Order processed successfully\";\n    }\n    return \"Order processing failed\";\n  }\n\n  /**\n   * Validates the product by calling the respective microservice.\n   *\n   * @return true if the product is valid, false otherwise.\n   */\n  Boolean validateProduct() {\n    try {\n      ResponseEntity<Boolean> productValidationResult =\n          restTemplateBuilder\n              .build()\n              .postForEntity(\n                  \"http://localhost:30302/product/validate\", \"validating product\", Boolean.class);\n      LOGGER.info(\"Product validation result: {}\", productValidationResult.getBody());\n      return productValidationResult.getBody();\n    } catch (ResourceAccessException | HttpClientErrorException e) {\n      LOGGER.error(\"Error communicating with product service: {}\", e.getMessage());\n      return false;\n    }\n  }\n\n  /**\n   * Validates the product by calling the respective microservice.\n   *\n   * @return true if the product is valid, false otherwise.\n   */\n  Boolean processPayment() {\n    try {\n      ResponseEntity<Boolean> paymentProcessResult =\n          restTemplateBuilder\n              .build()\n              .postForEntity(\n                  \"http://localhost:30301/payment/process\", \"processing payment\", Boolean.class);\n      LOGGER.info(\"Payment processing result: {}\", paymentProcessResult.getBody());\n      return paymentProcessResult.getBody();\n    } catch (ResourceAccessException | HttpClientErrorException e) {\n      LOGGER.error(\"Error communicating with payment service: {}\", e.getMessage());\n      return false;\n    }\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/order-microservice/src/main/resources/application.properties",
    "content": "#\n# The MIT License\n# Copyright © 2014-2021 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nspring.application.name=order-microservice\nserver.port=30300\n\nmanagement.tracing.sampling.probability=1\nlogging.pattern.level=%5p [${spring.zipkin.service.name:${spring.application.name:}},%X{traceId:-},%X{spanId:-}]\nmanagement.tracing.propagation.type=w3c\nmanagement.tracing.baggage.enabled=true\nmanagement.tracing.enabled=true\nmanagement.zipkin.tracing.endpoint=http://localhost:9411/api/v2/spans\n\n"
  },
  {
    "path": "microservices-distributed-tracing/order-microservice/src/test/java/com/iluwatar/order/microservice/MainTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.order.microservice;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass MainTest {\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> Main.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/order-microservice/src/test/java/com/iluwatar/order/microservice/OrderControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.order.microservice; /*\n                                          * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n                                          *\n                                          * The MIT License\n                                          * Copyright © 2014-2022 Ilkka Seppälä\n                                          *\n                                          * Permission is hereby granted, free of charge, to any person obtaining a copy\n                                          * of this software and associated documentation files (the \"Software\"), to deal\n                                          * in the Software without restriction, including without limitation the rights\n                                          * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n                                          * copies of the Software, and to permit persons to whom the Software is\n                                          * furnished to do so, subject to the following conditions:\n                                          *\n                                          * The above copyright notice and this permission notice shall be included in\n                                          * all copies or substantial portions of the Software.\n                                          *\n                                          * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n                                          * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n                                          * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n                                          * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n                                          * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n                                          * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n                                          * THE SOFTWARE.\n                                          */\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\nimport org.springframework.http.ResponseEntity;\n\n/** OrderControllerTest class to test the OrderController. */\nclass OrderControllerTest {\n\n  @InjectMocks private OrderController orderController;\n\n  @Mock private OrderService orderService;\n\n  @BeforeEach\n  void setup() {\n    MockitoAnnotations.openMocks(this);\n  }\n\n  /** Test to process the order successfully. */\n  @Test\n  void processOrderShouldReturnSuccessStatus() {\n    // Arrange\n    when(orderService.processOrder()).thenReturn(\"Order processed successfully\");\n    // Act\n    ResponseEntity<String> response = orderController.processOrder(\"test order\");\n    // Assert\n    assertEquals(\"Order processed successfully\", response.getBody());\n  }\n\n  /** Test to process the order with failure. */\n  @Test\n  void ProcessOrderShouldReturnFailureStatusWhen() {\n    // Arrange\n    when(orderService.processOrder()).thenReturn(\"Order processing failed\");\n    // Act\n    ResponseEntity<String> response = orderController.processOrder(\"test order\");\n    // Assert\n    assertEquals(\"Order processing failed\", response.getBody());\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/order-microservice/src/test/java/com/iluwatar/order/microservice/OrderServiceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.order.microservice;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\nimport org.springframework.boot.web.client.RestTemplateBuilder;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.client.HttpClientErrorException;\nimport org.springframework.web.client.ResourceAccessException;\nimport org.springframework.web.client.RestTemplate;\n\n/** OrderServiceTest class to test the OrderService. */\nclass OrderServiceTest {\n\n  @InjectMocks private OrderService orderService;\n\n  @Mock private RestTemplateBuilder restTemplateBuilder;\n\n  @Mock private RestTemplate restTemplate;\n\n  @BeforeEach\n  void setup() {\n    MockitoAnnotations.openMocks(this);\n    when(restTemplateBuilder.build()).thenReturn(restTemplate);\n  }\n\n  /** Test to process the order successfully. */\n  @Test\n  void testProcessOrder_Success() {\n    // Arrange\n    when(restTemplate.postForEntity(\n            eq(\"http://localhost:30302/product/validate\"), anyString(), eq(Boolean.class)))\n        .thenReturn(ResponseEntity.ok(true));\n    when(restTemplate.postForEntity(\n            eq(\"http://localhost:30301/payment/process\"), anyString(), eq(Boolean.class)))\n        .thenReturn(ResponseEntity.ok(true));\n    // Act\n    String result = orderService.processOrder();\n    // Assert\n    assertEquals(\"Order processed successfully\", result);\n  }\n\n  /** Test to process the order with failure caused by product validation failure. */\n  @Test\n  void testProcessOrder_FailureWithProductValidationFailure() {\n    // Arrange\n    when(restTemplate.postForEntity(\n            eq(\"http://localhost:30302/product/validate\"), anyString(), eq(Boolean.class)))\n        .thenReturn(ResponseEntity.ok(false));\n    // Act\n    String result = orderService.processOrder();\n    // Assert\n    assertEquals(\"Order processing failed\", result);\n  }\n\n  /** Test to process the order with failure caused by payment processing failure. */\n  @Test\n  void testProcessOrder_FailureWithPaymentProcessingFailure() {\n    // Arrange\n    when(restTemplate.postForEntity(\n            eq(\"http://localhost:30302/product/validate\"), anyString(), eq(Boolean.class)))\n        .thenReturn(ResponseEntity.ok(true));\n    when(restTemplate.postForEntity(\n            eq(\"http://localhost:30301/payment/process\"), anyString(), eq(Boolean.class)))\n        .thenReturn(ResponseEntity.ok(false));\n    // Act\n    String result = orderService.processOrder();\n    // Assert\n    assertEquals(\"Order processing failed\", result);\n  }\n\n  /** Test to validate the product. */\n  @Test\n  void testValidateProduct() {\n    // Arrange\n    when(restTemplate.postForEntity(\n            eq(\"http://localhost:30302/product/validate\"), anyString(), eq(Boolean.class)))\n        .thenReturn(ResponseEntity.ok(true));\n    // Act\n    Boolean result = orderService.validateProduct();\n    // Assert\n    assertEquals(true, result);\n  }\n\n  /** Test to process the payment. */\n  @Test\n  void testProcessPayment() {\n    // Arrange\n    when(restTemplate.postForEntity(\n            eq(\"http://localhost:30301/payment/process\"), anyString(), eq(Boolean.class)))\n        .thenReturn(ResponseEntity.ok(true));\n    // Act\n    Boolean result = orderService.processPayment();\n    // Assert\n    assertEquals(true, result);\n  }\n\n  /** Test to validate the product with ResourceAccessException. */\n  @Test\n  void testValidateProduct_ResourceAccessException() {\n    // Arrange\n    when(restTemplate.postForEntity(\n            eq(\"http://localhost:30302/product/validate\"), anyString(), eq(Boolean.class)))\n        .thenThrow(new ResourceAccessException(\"Service unavailable\"));\n    // Act\n    Boolean result = orderService.validateProduct();\n    // Assert\n    assertEquals(false, result);\n  }\n\n  /** Test to validate the product with HttpClientErrorException. */\n  @Test\n  void testValidateProduct_HttpClientErrorException() {\n    // Arrange\n    when(restTemplate.postForEntity(\n            eq(\"http://localhost:30302/product/validate\"), anyString(), eq(Boolean.class)))\n        .thenThrow(\n            new HttpClientErrorException(\n                org.springframework.http.HttpStatus.BAD_REQUEST, \"Bad request\"));\n    // Act\n    Boolean result = orderService.validateProduct();\n    // Assert\n    assertEquals(false, result);\n  }\n\n  /** Test to process the payment with ResourceAccessException. */\n  @Test\n  void testProcessPayment_ResourceAccessException() {\n    // Arrange\n    when(restTemplate.postForEntity(\n            eq(\"http://localhost:30301/payment/process\"), anyString(), eq(Boolean.class)))\n        .thenThrow(new ResourceAccessException(\"Service unavailable\"));\n    // Act\n    Boolean result = orderService.processPayment();\n    // Assert\n    assertEquals(false, result);\n  }\n\n  /** Test to process the payment with HttpClientErrorException. */\n  @Test\n  void testProcessPayment_HttpClientErrorException() {\n    // Arrange\n    when(restTemplate.postForEntity(\n            eq(\"http://localhost:30301/payment/process\"), anyString(), eq(Boolean.class)))\n        .thenThrow(\n            new HttpClientErrorException(\n                org.springframework.http.HttpStatus.BAD_REQUEST, \"Bad request\"));\n    // Act\n    Boolean result = orderService.processPayment();\n    // Assert\n    assertEquals(false, result);\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/payment-microservice/etc/payment-microservice.puml",
    "content": "@startuml\n!theme vibrant\npackage com.iluwatar.microservices-distributed-tracing {\n\npackage \"Payment Microservice\" {\n    class PaymentController {\n        +processPayment()\n    }\n}\n}\n@enduml"
  },
  {
    "path": "microservices-distributed-tracing/payment-microservice/etc/payment-microservice.urm.puml",
    "content": "@startuml\n!theme vibrant\npackage com.iluwatar.microservices-distributed-tracing {\n\npackage \"Payment Microservice\" {\n    class PaymentController {\n        +processPayment()\n    }\n}\n}\n@enduml"
  },
  {
    "path": "microservices-distributed-tracing/payment-microservice/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>microservices-distributed-tracing</artifactId>\n        <groupId>com.iluwatar</groupId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>payment-microservice</artifactId>\n    <packaging>jar</packaging>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.payment.microservice.com.iluwatar.product.microservice.Main</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "microservices-distributed-tracing/payment-microservice/src/main/java/com/iluwatar/payment/microservice/Main.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.payment.microservice;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * With the Microservices pattern, a request often travels through multiple different microservices.\n * Tracking the entire request flow across these services can be challenging, especially when trying\n * to diagnose performance issues or failures. Distributed tracing addresses this challenge by\n * providing end-to-end visibility into the lifecycle of a request as it passes through various\n * microservices.\n *\n * <p>The intent of the Distributed Tracing pattern is to trace a request across different\n * microservices, collecting detailed timing data and logs that help in understanding the flow,\n * performance bottlenecks, and failure points in a distributed system. Each microservice involved\n * in the request contributes to the tracing data, creating a comprehensive view of the request's\n * journey.\n *\n * <p>This implementation demonstrates distributed tracing in a microservices architecture for an\n * e-commerce platform. When a customer places an order, the OrderService interacts with both the\n * PaymentService to process the payment and the ProductService to check the product inventory.\n * Tracing logs are generated for each interaction, and these logs can be visualized using Zipkin.\n *\n * <p>To run Zipkin and view the tracing logs, you can use the following Docker command:\n *\n * <pre>\n * {@code docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin }\n * </pre>\n *\n * <p>Start Zipkin with the command above. Once Zipkin is running, you can access the Zipkin UI at\n * <a href=\"http://localhost:9411\">http://localhost:9411</a> to view the tracing logs and analyze\n * the request flows across your microservices.\n *\n * <p>To place an order and generate tracing data, you can use the following curl command:\n *\n * <pre>\n * {@code curl -X POST http://localhost:30300/order -H \"Content-Type: application/json\" -d '{\"orderId\": \"123\"}' }\n * </pre>\n *\n * <p>This command sends a POST request to create an order, which will trigger interactions with the\n * payment and product microservices, generating tracing logs that can be viewed in Zipkin.\n */\n@SpringBootApplication\npublic class Main {\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    SpringApplication.run(Main.class, args);\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/payment-microservice/src/main/java/com/iluwatar/payment/microservice/PaymentController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.payment.microservice;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/** Controller for handling payment processing requests. */\n@Slf4j\n@RestController\npublic class PaymentController {\n\n  /**\n   * Processes the payment based on the request.\n   *\n   * @param request the request body containing payment information (can be null)\n   * @return ResponseEntity containing the payment processing result (true)\n   */\n  @PostMapping(\"/payment/process\")\n  public ResponseEntity<Boolean> payment(@RequestBody(required = false) String request) {\n    LOGGER.info(\"Received payment request: {}\", request);\n    boolean result = true;\n    LOGGER.info(\"Payment result: {}\", result);\n    return ResponseEntity.ok(result);\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/payment-microservice/src/main/resources/application.properties",
    "content": "#\n# The MIT License\n# Copyright © 2014-2021 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nspring.application.name=payment-microservice\nserver.port=30301\n\nmanagement.tracing.sampling.probability=1\nlogging.pattern.level=%5p [${spring.zipkin.service.name:${spring.application.name:}},%X{traceId:-},%X{spanId:-}]\nmanagement.tracing.propagation.type=w3c\nmanagement.tracing.baggage.enabled=true\nmanagement.tracing.enabled=true\nmanagement.zipkin.tracing.endpoint=http://localhost:9411/api/v2/spans\n"
  },
  {
    "path": "microservices-distributed-tracing/payment-microservice/src/test/java/com/iluwatar/payment/microservice/MainTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.payment.microservice;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application Context loads test */\nclass MainTest {\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> Main.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/payment-microservice/src/test/java/com/iluwatar/payment/microservice/ProductControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.payment.microservice;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.http.ResponseEntity;\n\n/** Payment controller test. */\nclass ProductControllerTest {\n\n  private PaymentController paymentController;\n\n  @BeforeEach\n  void setUp() {\n    paymentController = new PaymentController();\n  }\n\n  /** Test to process the payment. */\n  @Test\n  void testValidateProduct() {\n    // Arrange\n    String request = \"Sample payment process request\";\n    // Act\n    ResponseEntity<Boolean> response = paymentController.payment(request);\n    // Assert\n    assertEquals(ResponseEntity.ok(true), response);\n  }\n\n  /** Test to process the payment with null request. */\n  @Test\n  void testValidateProductWithNullRequest() {\n    // Arrange\n    // Act\n    ResponseEntity<Boolean> response = paymentController.payment(null);\n    // Assert\n    assertEquals(ResponseEntity.ok(true), response);\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>java-design-patterns</artifactId>\n        <groupId>com.iluwatar</groupId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>microservices-distributed-tracing</artifactId>\n    <packaging>pom</packaging>\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.micrometer</groupId>\n            <artifactId>micrometer-tracing-bridge-brave</artifactId>\n            <version>1.4.5</version>\n            <scope>compile</scope>\n        </dependency>\n        <dependency>\n            <groupId>io.zipkin.reporter2</groupId>\n            <artifactId>zipkin-reporter-brave</artifactId>\n            <version>3.5.0</version>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <modules>\n        <module>order-microservice</module>\n        <module>payment-microservice</module>\n        <module>product-microservice</module>\n    </modules>\n</project>\n"
  },
  {
    "path": "microservices-distributed-tracing/product-microservice/etc/product-microservice.puml",
    "content": "@startuml\n!theme vibrant\npackage com.iluwatar.microservices-distributed-tracing {\npackage \"Product Microservice\" {\n    class ProductController {\n        +validateProduct()\n    }\n}\n}\n@enduml"
  },
  {
    "path": "microservices-distributed-tracing/product-microservice/etc/product-microservice.urm.puml",
    "content": "@startuml\n!theme vibrant\npackage com.iluwatar.microservices-distributed-tracing {\npackage \"Product Microservice\" {\n    class ProductController {\n        +validateProduct()\n    }\n}\n}\n@enduml"
  },
  {
    "path": "microservices-distributed-tracing/product-microservice/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>microservices-distributed-tracing</artifactId>\n        <groupId>com.iluwatar</groupId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>product-microservice</artifactId>\n    <packaging>jar</packaging>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.product.com.iluwatar.product.microservice.microservice.Main</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "microservices-distributed-tracing/product-microservice/src/main/java/com/iluwatar/product/microservice/microservice/Main.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.product.microservice.microservice;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * With the Microservices pattern, a request often travels through multiple different microservices.\n * Tracking the entire request flow across these services can be challenging, especially when trying\n * to diagnose performance issues or failures. Distributed tracing addresses this challenge by\n * providing end-to-end visibility into the lifecycle of a request as it passes through various\n * microservices.\n *\n * <p>The intent of the Distributed Tracing pattern is to trace a request across different\n * microservices, collecting detailed timing data and logs that help in understanding the flow,\n * performance bottlenecks, and failure points in a distributed system. Each microservice involved\n * in the request contributes to the tracing data, creating a comprehensive view of the request's\n * journey.\n *\n * <p>This implementation demonstrates distributed tracing in a microservices architecture for an\n * e-commerce platform. When a customer places an order, the OrderService interacts with both the\n * PaymentService to process the payment and the ProductService to check the product inventory.\n * Tracing logs are generated for each interaction, and these logs can be visualized using Zipkin.\n *\n * <p>To run Zipkin and view the tracing logs, you can use the following Docker command:\n *\n * <pre>\n * {@code docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin }\n * </pre>\n *\n * <p>Start Zipkin with the command above. Once Zipkin is running, you can access the Zipkin UI at\n * <a href=\"http://localhost:9411\">http://localhost:9411</a> to view the tracing logs and analyze\n * the request flows across your microservices.\n *\n * <p>To place an order and generate tracing data, you can use the following curl command:\n *\n * <pre>\n * {@code curl -X POST http://localhost:30300/order -H \"Content-Type: application/json\" -d '{\"orderId\": \"123\"}' }\n * </pre>\n *\n * <p>This command sends a POST request to create an order, which will trigger interactions with the\n * payment and product microservices, generating tracing logs that can be viewed in Zipkin.\n */\n@SpringBootApplication\npublic class Main {\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    SpringApplication.run(Main.class, args);\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/product-microservice/src/main/java/com/iluwatar/product/microservice/microservice/ProductController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.product.microservice.microservice;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RestController;\n\n/** Controller for handling product validation requests. */\n@Slf4j\n@RestController\npublic class ProductController {\n\n  /**\n   * Validates the product based on the request.\n   *\n   * @param request the request body containing product information (can be null)\n   * @return ResponseEntity containing the validation result (true)\n   */\n  @PostMapping(\"/product/validate\")\n  public ResponseEntity<Boolean> validateProduct(@RequestBody(required = false) String request) {\n    LOGGER.info(\"Received product validation request: {}\", request);\n    boolean result = true;\n    LOGGER.info(\"Product validation result: {}\", result);\n    return ResponseEntity.ok(result);\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/product-microservice/src/main/resources/application.properties",
    "content": "#\n# The MIT License\n# Copyright © 2014-2021 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nspring.application.name=product-microservice\nserver.port=30302\n\nmanagement.tracing.sampling.probability=1\nlogging.pattern.level=%5p [${spring.zipkin.service.name:${spring.application.name:}},%X{traceId:-},%X{spanId:-}]\nmanagement.tracing.propagation.type=w3c\nmanagement.tracing.baggage.enabled=true\nmanagement.tracing.enabled=true\nmanagement.zipkin.tracing.endpoint=http://localhost:9411/api/v2/spans\n\n"
  },
  {
    "path": "microservices-distributed-tracing/product-microservice/src/test/java/com/iluwatar/product/microservice/MainTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.product.microservice;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport com.iluwatar.product.microservice.microservice.Main;\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass MainTest {\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> Main.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "microservices-distributed-tracing/product-microservice/src/test/java/com/iluwatar/product/microservice/ProductControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.product.microservice;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.product.microservice.microservice.ProductController;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.http.ResponseEntity;\n\nclass ProductControllerTest {\n\n  private ProductController productController;\n\n  @BeforeEach\n  void setUp() {\n    productController = new ProductController();\n  }\n\n  /** Test to validate the product. */\n  @Test\n  void testValidateProduct() {\n    // Arrange\n    String request = \"Sample product validation request\";\n    // Act\n    ResponseEntity<Boolean> response = productController.validateProduct(request);\n    // Assert\n    assertEquals(ResponseEntity.ok(true), response);\n  }\n\n  /** Test to validate the product with null request. */\n  @Test\n  void testValidateProductWithNullRequest() {\n    // Arrange\n    // Act\n    ResponseEntity<Boolean> response = productController.validateProduct(null);\n    // Assert\n    assertEquals(ResponseEntity.ok(true), response);\n  }\n}\n"
  },
  {
    "path": "microservices-idempotent-consumer/README.md",
    "content": "---\ntitle: \"Microservices Idempotent Consumer Pattern in Java: Ensuring Reliable Message Processing\"\nshortTitle: Microservices Idempotent Consumer\ndescription: \"Learn about the Idempotent Consumer pattern in Java. Discover how it ensures reliable and consistent message processing, even in cases of duplicate messages.\"\ncategory: Messaging\nlanguage: en\ntag:\n    - Asynchronous\n    - Decoupling\n    - Event-driven\n    - Messaging\n    - Microservices\n    - Resilience\n    - Retry\n---\n\n## Also known as\n\n* Idempotent Subscriber\n* Repeatable Message Consumer\n* Safe Consumer\n\n## Intent of Idempotent Consumer Pattern\n\nEnsure that consuming the same message multiple times does not cause unintended side effects in a microservices-based architecture.\n\n## Detailed Explanation of Idempotent Consumer Pattern with Real-World Examples\n\nReal-world example\n\n> In a payment processing system, ensuring that payment messages are idempotent prevents duplicate transactions. For example, if a user’s payment message is accidentally processed twice, the system should recognize the second message as a duplicate and prevent it from executing a second time. By storing unique identifiers for each processed message, such as a transaction ID, the system can skip any duplicate messages. This ensures that a user is not charged twice for the same transaction, maintaining system integrity and customer satisfaction.\n\nIn plain words\n\n> The Idempotent Consumer pattern prevents duplicate messages from causing unintended side effects by ensuring that processing the same message multiple times results in the same outcome. This makes message processing safe in distributed systems where duplicates may occur.\n\n\nWikipedia says\n\n> In computing, idempotence is the property of certain operations in mathematics and computer science whereby they can be applied multiple times without changing the result beyond the initial application.\n\nFlowchart\n\n![Microservices Idempotent Consumer flowchart](./etc/microservices-idempotent-consumer-flowchart.png)\n\n## Programmatic example of Idempotent Consumer Pattern\n\nIn this Java example, we have an idempotent service that creates and updates orders. The `create` method is idempotent, meaning multiple calls with the same order ID return the same result without duplicates. For state changes (like starting or completing an order), the service checks whether the transition is valid and throws an exception if it’s not allowed. The `RequestStateMachine` ensures that order statuses move forward in a valid sequence (e.g., PENDING → STARTED → COMPLETED).\n\n### RequestService - Managing Idempotent Order Operations\n\nThe `RequestService` class provides methods to create and transition an order. The `create` method returns an existing order if it already exists, making it idempotent.\n\n```java\npublic class RequestService {\n    // Idempotent: ensures that the same request is returned if it already exists\n    public Request create(UUID uuid) {\n        Optional<Request> optReq = requestRepository.findById(uuid);\n        if (!optReq.isEmpty()) {\n            return optReq.get();  // Return existing request\n        }\n        return requestRepository.save(new Request(uuid));  // Save and return new request\n    }\n\n    public Request start(UUID uuid) {\n        Optional<Request> optReq = requestRepository.findById(uuid);\n        if (optReq.isEmpty()) {\n            throw new RequestNotFoundException(uuid);\n        }\n        return requestRepository.save(requestStateMachine.next(optReq.get(), Request.Status.STARTED));\n    }\n\n    public Request complete(UUID uuid) {\n        Optional<Request> optReq = requestRepository.findById(uuid);\n        if (optReq.isEmpty()) {\n            throw new RequestNotFoundException(uuid);\n        }\n        return requestRepository.save(requestStateMachine.next(optReq.get(), Request.Status.COMPLETED));\n    }\n}\n```\n\n### RequestStateMachine - Managing Order Transitions\n\nThe `RequestStateMachine` enforces valid state changes. If a requested transition is not allowed based on the current status, an exception is thrown.\n\n```java\npublic class RequestStateMachine {\n\n  public Request next(Request req, Request.Status nextStatus) {\n    String transitionStr = String.format(\"Transition: %s -> %s\", req.getStatus(), nextStatus);\n    switch (nextStatus) {\n      case PENDING -> throw new InvalidNextStateException(transitionStr);\n      case STARTED -> {\n        if (Request.Status.PENDING.equals(req.getStatus())) {\n          return new Request(req.getUuid(), Request.Status.STARTED);  // Valid transition\n        }\n        throw new InvalidNextStateException(transitionStr);  // Invalid transition\n      }\n      case COMPLETED -> {\n        if (Request.Status.STARTED.equals(req.getStatus())) {\n          return new Request(req.getUuid(), Request.Status.COMPLETED);  // Valid transition\n        }\n        throw new InvalidNextStateException(transitionStr);  // Invalid transition\n      }\n      default -> throw new InvalidNextStateException(transitionStr);  // Invalid status\n    }\n  }\n}\n```\n\n### Main Application - Running the Idempotent Consumer Example\n\nHere, we demonstrate how `RequestService` can be called multiple times without creating duplicate orders. We also show how invalid transitions (like trying to start an order twice) result in exceptions, while valid transitions proceed normally.\n\n```java\nRequest req = requestService.create(UUID.randomUUID());\n// Try creating the same Request again with the same UUID (idempotent operation)\nrequestService.create(req.getUuid());\n// Again, try creating the same Request (idempotent operation, no new Request should be created)\nrequestService.create(req.getUuid());\nLOGGER.info(\"Nb of requests : {}\", requestRepository.count()); // 1, processRequest is idempotent\n// Attempt to start the Request (the first valid transition)\nreq = requestService.start(req.getUuid());\n// Try to start the Request again, which should throw an exception since it's already started\ntry {\n  req = requestService.start(req.getUuid());\n} catch (InvalidNextStateException ex) {\n  // Log an error message when trying to start a request twice\n  LOGGER.error(\"Cannot start request twice!\");\n}\n// Complete the Request (valid transition from STARTED to COMPLETED)\nreq = requestService.complete(req.getUuid());\n// Log the final status of the Request to confirm it's been completed\nLOGGER.info(\"Request: {}\", req);\n```\n\nProgram output:\n\n```\n19:01:54.382  INFO [main] com.iluwatar.idempotentconsumer.App      : Nb of requests : 1\n19:01:54.395 ERROR [main] com.iluwatar.idempotentconsumer.App      : Cannot start request twice!\n19:01:54.399  INFO [main] com.iluwatar.idempotentconsumer.App      : Request: Request(uuid=2d5521ef-6b6b-4003-9ade-81e381fe9a63, status=COMPLETED)\n```\n\n## When to Use the Idempotent Consumer Pattern\n\n* When messages can arrive more than once due to network glitches or retries\n* When microservices must guarantee consistent state changes regardless of duplicates\n* When fault-tolerant event-driven communication is critical to system reliability\n* When horizontal scaling requires stateless consumer operations\n\n## Real-World Applications of Idempotent Consumer Pattern\n\n* Payment processing systems that receive duplicate charge events\n* E-commerce order services that handle duplicate purchase requests\n* Notification services that retry failed message deliveries\n* Distributed transaction systems where duplicated events are common\n\n## Benefits and Trade-offs of the Idempotent Consumer Pattern\n\nBenefits\n\n* Prevents duplicate side effects\n* Increases reliability under repeated or delayed messages\n* Simplifies error handling and retry logic\n\nTrade-offs\n\n* Requires careful design to track processed messages\n* Can add overhead for maintaining idempotency tokens or state\n* May require additional storage or database transactions\n\n## Related Patterns in Java\n\n* Outbox Pattern: Uses a dedicated table or storage to reliably publish events and handle deduplication at the source.\n\n## References and Credits\n\n* [Building Microservices](https://amzn.to/3UACtrU)\n* [Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions](https://amzn.to/4dznP2Y)\n* [Microservices Patterns: With examples in Java](https://amzn.to/3UyWD5O)\n"
  },
  {
    "path": "microservices-idempotent-consumer/etc/microservices-idempotent-consumer.urm.puml",
    "content": "@startuml\npackage com.iluwatar.idempotentconsumer {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n    + run(requestService : RequestService, requestRepository : RequestRepository) : CommandLineRunner\n  }\n  class Request {\n    - status : Status\n    - uuid : UUID\n    + Request()\n    + Request(uuid : UUID)\n    + Request(uuid : UUID, status : Status)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getStatus() : Status\n    + getUuid() : UUID\n    + hashCode() : int\n    + setStatus(status : Status)\n    + setUuid(uuid : UUID)\n    + toString() : String\n  }\n  ~enum Status {\n    + COMPLETED {static}\n    + PENDING {static}\n    + STARTED {static}\n    + valueOf(name : String) : Status {static}\n    + values() : Status[] {static}\n  }\n  interface RequestRepository {\n  }\n  class RequestService {\n    ~ requestRepository : RequestRepository\n    ~ requestStateMachine : RequestStateMachine\n    + RequestService(requestRepository : RequestRepository, requestStateMachine : RequestStateMachine)\n    + complete(uuid : UUID) : Request\n    + create(uuid : UUID) : Request\n    + start(uuid : UUID) : Request\n  }\n  class RequestStateMachine {\n    + RequestStateMachine()\n    + next(req : Request, nextStatus : Status) : Request\n  }\n}\nRequestService -->  \"-requestRepository\" RequestRepository\nRequest -->  \"-status\" Status\nRequestService -->  \"-requestStateMachine\" RequestStateMachine\n@enduml"
  },
  {
    "path": "microservices-idempotent-consumer/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>microservices-idempotent-consumer</artifactId>\n    <dependencies>\n        <!-- Spring Boot Dependencies -->\n\n        <!-- Spring Boot Data JPA for database access -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-data-jpa</artifactId>\n        </dependency>\n\n        <!-- Testing Dependencies -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <!-- JUnit Jupiter Engine for testing -->\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <!-- Mockito for mocking in tests -->\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n\n        <!-- H2 for mocking database -->\n        <dependency>\n            <groupId>com.h2database</groupId>\n            <artifactId>h2</artifactId>\n            <scope>runtime</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.hibernate</groupId>\n            <artifactId>hibernate-core</artifactId>\n            <version>6.4.4.Final</version>\n        </dependency>\n\n    </dependencies>\n\n\n    <build>\n        <plugins>\n            <!-- Maven Assembly Plugin for creating a single distributable JAR -->\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <phase>package</phase>\n                        <goals>\n                            <goal>single</goal>\n                        </goals>\n                        <configuration>\n                            <descriptorRefs>\n                                <descriptorRef>jar-with-dependencies</descriptorRef>\n                            </descriptorRefs>\n                            <archive>\n                                <manifest>\n                                    <!-- Define the main class for the executable JAR -->\n                                    <mainClass>com.iluwatar.idempotentconsumer.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n\n            <!-- Other plugins as needed -->\n\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "microservices-idempotent-consumer/src/main/java/com/iluwatar/idempotentconsumer/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.idempotentconsumer;\n\nimport java.util.UUID;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.CommandLineRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Bean;\n\n/**\n * The main entry point for the idempotent-consumer application. This application demonstrates the\n * use of the Idempotent Consumer pattern which ensures that a message is processed exactly once in\n * scenarios where the same message can be delivered multiple times.\n *\n * @see <a href=\"https://en.wikipedia.org/wiki/Idempotence\">Idempotence (Wikipedia)</a>\n * @see <a\n *     href=\"https://camel.apache.org/components/latest/eips/idempotentConsumer-eip.html\">Idempotent\n *     Consumer Pattern (Apache Camel)</a>\n */\n@SpringBootApplication\n@Slf4j\npublic class App {\n  public static void main(String[] args) {\n    SpringApplication.run(App.class, args);\n  }\n\n  /**\n   * The starting point of the CommandLineRunner where the main program is run.\n   *\n   * @param requestService idempotent request service\n   * @param requestRepository request jpa repository\n   */\n  @Bean\n  public CommandLineRunner run(RequestService requestService, RequestRepository requestRepository) {\n    return args -> {\n      Request req = requestService.create(UUID.randomUUID());\n      requestService.create(req.getUuid());\n      requestService.create(req.getUuid());\n      LOGGER.info(\n          \"Nb of requests : {}\", requestRepository.count()); // 1, processRequest is idempotent\n      req = requestService.start(req.getUuid());\n      try {\n        req = requestService.start(req.getUuid());\n      } catch (InvalidNextStateException ex) {\n        LOGGER.error(\"Cannot start request twice!\");\n      }\n      req = requestService.complete(req.getUuid());\n      LOGGER.info(\"Request: {}\", req);\n    };\n  }\n}\n"
  },
  {
    "path": "microservices-idempotent-consumer/src/main/java/com/iluwatar/idempotentconsumer/InvalidNextStateException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.idempotentconsumer;\n\n/**\n * This exception is thrown when an invalid transition is attempted in the Statemachine for the\n * request status. This can occur when attempting to move to a state that is not valid from the\n * current state.\n */\npublic class InvalidNextStateException extends RuntimeException {\n  public InvalidNextStateException(String s) {\n    super(s);\n  }\n}\n"
  },
  {
    "path": "microservices-idempotent-consumer/src/main/java/com/iluwatar/idempotentconsumer/Request.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.idempotentconsumer;\n\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.Id;\nimport java.util.UUID;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * The {@code Request} class represents a request with a unique UUID and a status. The status of a\n * request can be one of four values: PENDING, STARTED, COMPLETED, or INERROR.\n */\n@Entity\n@NoArgsConstructor\n@Data\npublic class Request {\n  enum Status {\n    PENDING,\n    STARTED,\n    COMPLETED\n  }\n\n  @Id private UUID uuid;\n  private Status status;\n\n  public Request(UUID uuid) {\n    this(uuid, Status.PENDING);\n  }\n\n  public Request(UUID uuid, Status status) {\n    this.uuid = uuid;\n    this.status = status;\n  }\n}\n"
  },
  {
    "path": "microservices-idempotent-consumer/src/main/java/com/iluwatar/idempotentconsumer/RequestNotFoundException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.idempotentconsumer;\n\nimport java.util.UUID;\n\n/**\n * This class extends the RuntimeException class to handle scenarios where a Request is not found.\n * It is intended to be used where you would like to have a custom exception that signals that a\n * requested object or action was not found in the system, based on the UUID of the request.\n */\npublic class RequestNotFoundException extends RuntimeException {\n  RequestNotFoundException(UUID uuid) {\n    super(String.format(\"Request %s not found\", uuid));\n  }\n}\n"
  },
  {
    "path": "microservices-idempotent-consumer/src/main/java/com/iluwatar/idempotentconsumer/RequestRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.idempotentconsumer;\n\nimport java.util.UUID;\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.stereotype.Repository;\n\n/**\n * This is a repository interface for the \"Request\" entity. It extends the JpaRepository interface\n * from Spring Data JPA. JpaRepository comes with many operations out of the box, including standard\n * CRUD operations. With JpaRepository, we are also able to leverage the power of Spring Data's\n * query methods. The UUID parameter in JpaRepository refers to the type of the ID in the \"Request\"\n * entity.\n */\n@Repository\npublic interface RequestRepository extends JpaRepository<Request, UUID> {}\n"
  },
  {
    "path": "microservices-idempotent-consumer/src/main/java/com/iluwatar/idempotentconsumer/RequestService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.idempotentconsumer;\n\nimport java.util.Optional;\nimport java.util.UUID;\nimport org.springframework.stereotype.Service;\n\n/**\n * This service is responsible for handling request operations including creation, start, and\n * completion of requests.\n */\n@Service\npublic class RequestService {\n  RequestRepository requestRepository;\n  RequestStateMachine requestStateMachine;\n\n  public RequestService(\n      RequestRepository requestRepository, RequestStateMachine requestStateMachine) {\n    this.requestRepository = requestRepository;\n    this.requestStateMachine = requestStateMachine;\n  }\n\n  /**\n   * Creates a new Request or returns an existing one by its UUID. This operation is idempotent:\n   * performing it once or several times successively leads to an equivalent result.\n   *\n   * @param uuid The unique identifier for the Request.\n   * @return Return existing Request or save and return a new Request.\n   */\n  public Request create(UUID uuid) {\n    Optional<Request> optReq = requestRepository.findById(uuid);\n    return optReq.orElseGet(() -> requestRepository.save(new Request(uuid)));\n  }\n\n  /**\n   * Starts the Request assigned with the given UUID.\n   *\n   * @param uuid The unique identifier for the Request.\n   * @return The started Request.\n   * @throws RequestNotFoundException if a Request with the given UUID is not found.\n   */\n  public Request start(UUID uuid) {\n    Optional<Request> optReq = requestRepository.findById(uuid);\n    if (optReq.isEmpty()) {\n      throw new RequestNotFoundException(uuid);\n    }\n    return requestRepository.save(requestStateMachine.next(optReq.get(), Request.Status.STARTED));\n  }\n\n  /**\n   * Complete the Request assigned with the given UUID.\n   *\n   * @param uuid The unique identifier for the Request.\n   * @return The completed Request.\n   * @throws RequestNotFoundException if a Request with the given UUID is not found.\n   */\n  public Request complete(UUID uuid) {\n    Optional<Request> optReq = requestRepository.findById(uuid);\n    if (optReq.isEmpty()) {\n      throw new RequestNotFoundException(uuid);\n    }\n    return requestRepository.save(requestStateMachine.next(optReq.get(), Request.Status.COMPLETED));\n  }\n}\n"
  },
  {
    "path": "microservices-idempotent-consumer/src/main/java/com/iluwatar/idempotentconsumer/RequestStateMachine.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.idempotentconsumer;\n\nimport org.springframework.stereotype.Component;\n\n/**\n * This class represents a state machine for managing request transitions. It supports transitions\n * to the statuses: PENDING, STARTED, and COMPLETED.\n */\n@Component\npublic class RequestStateMachine {\n\n  /**\n   * Provides the next possible state of the request based on the current and next status.\n   *\n   * @param req The actual request object. This object MUST NOT be null and SHOULD have a valid\n   *     status.\n   * @param nextStatus Represents the next status that the request could transition to. MUST NOT be\n   *     null.\n   * @return A new Request object with updated status if the transition is valid.\n   * @throws InvalidNextStateException If an invalid state transition is attempted.\n   */\n  public Request next(Request req, Request.Status nextStatus) {\n    String transitionStr = String.format(\"Transition: %s -> %s\", req.getStatus(), nextStatus);\n    switch (nextStatus) {\n      case PENDING -> throw new InvalidNextStateException(transitionStr);\n      case STARTED -> {\n        if (Request.Status.PENDING.equals(req.getStatus())) {\n          return new Request(req.getUuid(), Request.Status.STARTED);\n        }\n        throw new InvalidNextStateException(transitionStr);\n      }\n      case COMPLETED -> {\n        if (Request.Status.STARTED.equals(req.getStatus())) {\n          return new Request(req.getUuid(), Request.Status.COMPLETED);\n        }\n        throw new InvalidNextStateException(transitionStr);\n      }\n      default -> throw new InvalidNextStateException(transitionStr);\n    }\n  }\n}\n"
  },
  {
    "path": "microservices-idempotent-consumer/src/test/java/com/iluwatar/idempotentconsumer/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.idempotentconsumer;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport java.util.UUID;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\nimport org.springframework.boot.CommandLineRunner;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void testMain() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n\n  @Test\n  void testRun() throws Exception {\n    RequestService requestService = Mockito.mock(RequestService.class);\n    RequestRepository requestRepository = Mockito.mock(RequestRepository.class);\n    UUID uuid = UUID.randomUUID();\n    Request requestPending = new Request(uuid);\n    Request requestStarted = new Request(uuid, Request.Status.STARTED);\n    Request requestCompleted = new Request(uuid, Request.Status.COMPLETED);\n    when(requestService.create(any())).thenReturn(requestPending);\n    when(requestService.start(any())).thenReturn(requestStarted);\n    when(requestService.complete(any())).thenReturn(requestCompleted);\n\n    CommandLineRunner runner = new App().run(requestService, requestRepository);\n\n    runner.run();\n\n    verify(requestService, times(3)).create(any());\n    verify(requestService, times(2)).start(any());\n    verify(requestService, times(1)).complete(any());\n    verify(requestRepository, times(1)).count();\n  }\n}\n"
  },
  {
    "path": "microservices-idempotent-consumer/src/test/java/com/iluwatar/idempotentconsumer/RequestServiceTests.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.idempotentconsumer;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport java.util.Optional;\nimport java.util.UUID;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\n@ExtendWith(MockitoExtension.class)\nclass RequestServiceTests {\n  private RequestService requestService;\n  @Mock private RequestRepository requestRepository;\n\n  @BeforeEach\n  void setUp() {\n    RequestStateMachine requestStateMachine = new RequestStateMachine();\n    requestService = new RequestService(requestRepository, requestStateMachine);\n  }\n\n  @Test\n  void createRequest_whenNotExists() {\n    UUID uuid = UUID.randomUUID();\n    Request request = new Request(uuid);\n    when(requestRepository.findById(any())).thenReturn(Optional.empty());\n    when(requestRepository.save(request)).thenReturn(request);\n    assertEquals(request, requestService.create(uuid));\n    verify(requestRepository, times(1)).findById(uuid);\n    verify(requestRepository, times(1)).save(any());\n  }\n\n  @Test\n  void createRequest_whenExists() {\n    UUID uuid = UUID.randomUUID();\n    Request request = new Request(uuid);\n    when(requestRepository.findById(any())).thenReturn(Optional.of(request));\n    assertEquals(request, requestService.create(uuid));\n    verify(requestRepository, times(1)).findById(uuid);\n    verify(requestRepository, times(0)).save(any());\n  }\n\n  @Test\n  void startRequest_whenNotExists_shouldThrowError() {\n    UUID uuid = UUID.randomUUID();\n    when(requestRepository.findById(any())).thenReturn(Optional.empty());\n    assertThrows(RequestNotFoundException.class, () -> requestService.start(uuid));\n    verify(requestRepository, times(1)).findById(uuid);\n    verify(requestRepository, times(0)).save(any());\n  }\n\n  @Test\n  void startRequest_whenIsPending() {\n    UUID uuid = UUID.randomUUID();\n    Request request = new Request(uuid);\n    Request startedEntity = new Request(uuid, Request.Status.STARTED);\n    when(requestRepository.findById(any())).thenReturn(Optional.of(request));\n    when(requestRepository.save(any())).thenReturn(startedEntity);\n    assertEquals(startedEntity, requestService.start(uuid));\n    verify(requestRepository, times(1)).findById(uuid);\n    verify(requestRepository, times(1)).save(startedEntity);\n  }\n\n  @Test\n  void startRequest_whenIsStarted_shouldThrowError() {\n    UUID uuid = UUID.randomUUID();\n    Request requestStarted = new Request(uuid, Request.Status.STARTED);\n    when(requestRepository.findById(any())).thenReturn(Optional.of(requestStarted));\n    assertThrows(InvalidNextStateException.class, () -> requestService.start(uuid));\n    verify(requestRepository, times(1)).findById(uuid);\n    verify(requestRepository, times(0)).save(any());\n  }\n\n  @Test\n  void startRequest_whenIsCompleted_shouldThrowError() {\n    UUID uuid = UUID.randomUUID();\n    Request requestStarted = new Request(uuid, Request.Status.COMPLETED);\n    when(requestRepository.findById(any())).thenReturn(Optional.of(requestStarted));\n    assertThrows(InvalidNextStateException.class, () -> requestService.start(uuid));\n    verify(requestRepository, times(1)).findById(uuid);\n    verify(requestRepository, times(0)).save(any());\n  }\n\n  @Test\n  void completeRequest_whenStarted() {\n    UUID uuid = UUID.randomUUID();\n    Request request = new Request(uuid, Request.Status.STARTED);\n    Request completedEntity = new Request(uuid, Request.Status.COMPLETED);\n    when(requestRepository.findById(any())).thenReturn(Optional.of(request));\n    when(requestRepository.save(any())).thenReturn(completedEntity);\n    assertEquals(completedEntity, requestService.complete(uuid));\n    verify(requestRepository, times(1)).findById(uuid);\n    verify(requestRepository, times(1)).save(completedEntity);\n  }\n\n  @Test\n  void completeRequest_whenNotInprogress() {\n    UUID uuid = UUID.randomUUID();\n    Request request = new Request(uuid);\n    when(requestRepository.findById(any())).thenReturn(Optional.of(request));\n    assertThrows(InvalidNextStateException.class, () -> requestService.complete(uuid));\n    verify(requestRepository, times(1)).findById(uuid);\n    verify(requestRepository, times(0)).save(any());\n  }\n}\n"
  },
  {
    "path": "microservices-idempotent-consumer/src/test/java/com/iluwatar/idempotentconsumer/RequestStateMachineTests.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.idempotentconsumer;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nimport java.util.UUID;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass RequestStateMachineTests {\n  private RequestStateMachine requestStateMachine;\n\n  @BeforeEach\n  void setUp() {\n    requestStateMachine = new RequestStateMachine();\n  }\n\n  @Test\n  void transitionPendingToStarted() {\n    Request startedRequest =\n        requestStateMachine.next(\n            new Request(UUID.randomUUID(), Request.Status.PENDING), Request.Status.STARTED);\n    assertEquals(Request.Status.STARTED, startedRequest.getStatus());\n  }\n\n  @Test\n  void transitionAnyToPending_shouldThrowError() {\n    assertThrows(\n        InvalidNextStateException.class,\n        () ->\n            requestStateMachine.next(\n                new Request(UUID.randomUUID(), Request.Status.PENDING), Request.Status.PENDING));\n    assertThrows(\n        InvalidNextStateException.class,\n        () ->\n            requestStateMachine.next(\n                new Request(UUID.randomUUID(), Request.Status.STARTED), Request.Status.PENDING));\n    assertThrows(\n        InvalidNextStateException.class,\n        () ->\n            requestStateMachine.next(\n                new Request(UUID.randomUUID(), Request.Status.COMPLETED), Request.Status.PENDING));\n  }\n\n  @Test\n  void transitionCompletedToAny_shouldThrowError() {\n    assertThrows(\n        InvalidNextStateException.class,\n        () ->\n            requestStateMachine.next(\n                new Request(UUID.randomUUID(), Request.Status.COMPLETED), Request.Status.PENDING));\n    assertThrows(\n        InvalidNextStateException.class,\n        () ->\n            requestStateMachine.next(\n                new Request(UUID.randomUUID(), Request.Status.COMPLETED), Request.Status.STARTED));\n    assertThrows(\n        InvalidNextStateException.class,\n        () ->\n            requestStateMachine.next(\n                new Request(UUID.randomUUID(), Request.Status.COMPLETED),\n                Request.Status.COMPLETED));\n  }\n\n  @Test\n  void transitionStartedToCompleted() {\n    Request completedRequest =\n        requestStateMachine.next(\n            new Request(UUID.randomUUID(), Request.Status.STARTED), Request.Status.COMPLETED);\n    assertEquals(Request.Status.COMPLETED, completedRequest.getStatus());\n  }\n}\n"
  },
  {
    "path": "microservices-log-aggregation/README.md",
    "content": "---\ntitle: \"Microservices Log Aggregation Pattern in Java: Centralizing Logs for Enhanced Monitoring\"\nshortTitle: Microservices Log Aggregation\ndescription: \"Learn about the Microservices Log Aggregation pattern, a method for centralizing log collection and analysis to enhance monitoring, debugging, and operational intelligence in distributed systems.\"\ncategory: Integration\nlanguage: en\ntag:\n  - Data processing\n  - Decoupling\n  - Enterprise patterns\n  - Fault tolerance\n  - Messaging\n  - Microservices\n  - Performance\n  - Scalability\n---\n\n## Also known as\n\n* Centralized Logging\n* Log Management\n\n## Intent of Microservices Log Aggregation Design Pattern\n\nLog Aggregation is a crucial microservices design pattern that centralizes the collection, storage, and analysis of logs from multiple sources, facilitating efficient monitoring, debugging, and operational intelligence.\n\n## Detailed Explanation of Microservices Log Aggregation Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine an e-commerce platform using a microservices architecture, where each service generates logs. A log aggregation system, utilizing tools like the ELK Stack (Elasticsearch, Logstash, Kibana), centralizes these logs. This setup allows administrators to effectively monitor and analyze the entire platform's activity in real-time. By collecting logs from each microservice and centralizing them, the system provides a unified view, enabling quick troubleshooting and comprehensive analysis of user behavior and system performance.\n\nIn plain words\n\n> The Log Aggregation design pattern centralizes the collection and analysis of log data from multiple applications or services to simplify monitoring and troubleshooting.\n\nWikipedia says\n\n> You have applied the Microservice architecture pattern. The application consists of multiple services and service instances that are running on multiple machines. Requests often span multiple service instances. Each service instance generates writes information about what it is doing to a log file in a standardized format. The log file contains errors, warnings, information and debug messages.\n\nFlowchart\n\n![Microservices Log Aggregration flowchart](./etc/microservices-log-aggregation-flowchart.png)\n\n## Programmatic Example of Microservices Log Aggregation Pattern in Java\n\nLog Aggregation is a pattern that centralizes the collection, storage, and analysis of logs from multiple sources to facilitate monitoring, debugging, and operational intelligence. It is particularly useful in distributed systems where logs from various components need to be centralized for better management and analysis.\n\nIn this example, we will demonstrate the Log Aggregation pattern using a simple Java application. The application consists of multiple services that generate logs. These logs are collected by a log aggregator and stored in a central log store.\n\nThe `CentralLogStore` is responsible for storing the logs collected from various services. In this example, we are using an in-memory store for simplicity.\n\n```java\npublic class CentralLogStore {\n\n  private final List<LogEntry> logs = new ArrayList<>();\n\n  public void storeLog(LogEntry logEntry) {\n    logs.add(logEntry);\n  }\n\n  public void displayLogs() {\n    logs.forEach(System.out::println);\n  }\n}\n```\n\nThe `LogAggregator` collects logs from various services and stores them in the `CentralLogStore`. It filters logs based on their log level.\n\n```java\npublic class LogAggregator {\n\n  private final CentralLogStore centralLogStore;\n  private final LogLevel minimumLogLevel;\n\n  public LogAggregator(CentralLogStore centralLogStore, LogLevel minimumLogLevel) {\n    this.centralLogStore = centralLogStore;\n    this.minimumLogLevel = minimumLogLevel;\n  }\n\n  public void collectLog(LogEntry logEntry) {\n    if (logEntry.getLogLevel().compareTo(minimumLogLevel) >= 0) {\n      centralLogStore.storeLog(logEntry);\n    }\n  }\n}\n```\n\nThe `LogProducer` represents a service that generates logs. It sends the logs to the `LogAggregator`.\n\n```java\npublic class LogProducer {\n\n  private final String serviceName;\n  private final LogAggregator logAggregator;\n\n  public LogProducer(String serviceName, LogAggregator logAggregator) {\n    this.serviceName = serviceName;\n    this.logAggregator = logAggregator;\n  }\n\n  public void generateLog(LogLevel logLevel, String message) {\n    LogEntry logEntry = new LogEntry(serviceName, logLevel, message, LocalDateTime.now());\n    logAggregator.collectLog(logEntry);\n  }\n}\n```\n\nThe `main` application creates services, generates logs, aggregates, and finally displays the logs.\n\n```java\npublic class App {\n\n  public static void main(String[] args) throws InterruptedException {\n    final CentralLogStore centralLogStore = new CentralLogStore();\n    final LogAggregator aggregator = new LogAggregator(centralLogStore, LogLevel.INFO);\n\n    final LogProducer serviceA = new LogProducer(\"ServiceA\", aggregator);\n    final LogProducer serviceB = new LogProducer(\"ServiceB\", aggregator);\n\n    serviceA.generateLog(LogLevel.INFO, \"This is an INFO log from ServiceA\");\n    serviceB.generateLog(LogLevel.ERROR, \"This is an ERROR log from ServiceB\");\n    serviceA.generateLog(LogLevel.DEBUG, \"This is a DEBUG log from ServiceA\");\n\n    centralLogStore.displayLogs();\n  }\n}\n```\n\nIn this example, the `LogProducer` services generate logs of different levels. The `LogAggregator` collects these logs and stores them in the `CentralLogStore` if they meet the minimum log level requirement. Finally, the logs are displayed by the `CentralLogStore`.\n\n## When to Use the Microservices Log Aggregation Pattern in Java\n\n* Microservices log aggregation is essential in distributed systems for better management and analysis of log data.\n* Applicable in environments where compliance and auditing require consolidated log data.\n* Beneficial in systems that require high availability and resilience, ensuring that log data is preserved and accessible despite individual component failures.\n\n## Real-World Applications of Microservices Log Aggregation Pattern in Java\n\n* ava applications using frameworks like Log4j2 or SLF4J with centralized log management tools such as the ELK stack or Splunk benefit from microservices log aggregation.\n* Microservices architectures where each service outputs logs that are aggregated into a single system to provide a unified view of the system’s health and behavior.\n\n## Benefits and Trade-offs of Microservices Log Aggregation Pattern\n\nBenefits:\n\n* Centralizing logs in a microservices environment improves debuggability and traceability across multiple services.\n* Enhances monitoring capabilities by providing a centralized platform for log analysis.\n* Facilitates compliance with regulatory requirements for log retention and auditability.\n\nTrade-offs:\n\n* Introduces a potential single point of failure if the log aggregation system is not adequately resilient.\n* Can lead to high data volumes requiring significant storage and processing resources.\n\n## Related Java Design Patterns\n\n* Messaging Patterns: Log Aggregation often utilizes messaging systems to transport log data, facilitating decoupling and asynchronous data processing.\n* Microservices: Often employed in microservice architectures to handle logs from various services efficiently.\n* Publish/Subscribe: Utilizes a pub/sub model for log data collection where components publish logs and the aggregation system subscribes to them.\n\n## References and Credits\n\n* [Cloud Native Java: Designing Resilient Systems with Spring Boot, Spring Cloud, and Cloud Foundry](https://amzn.to/44vDTat)\n* [Logging in Action: With Fluentd, Kubernetes and more](https://amzn.to/3JQLzdT)\n* [Release It! Design and Deploy Production-Ready Software](https://amzn.to/3Uul4kF)\n* [Pattern: Log aggregation (microservices.io)](https://microservices.io/patterns/observability/application-logging.html)\n"
  },
  {
    "path": "microservices-log-aggregation/etc/log-aggregation.puml",
    "content": "@startuml\n\npackage com.iluwatar.logaggregation {\n\n  class App {\n    + main(args: String[]) {static}\n  }\n\n  class CentralLogStore {\n    - logs: ConcurrentLinkedQueue<LogEntry>\n    + storeLog(logEntry: LogEntry)\n    + displayLogs()\n  }\n\n  class LogAggregator {\n    - BUFFER_THRESHOLD: int {static}\n    - centralLogStore: CentralLogStore\n    - buffer: ConcurrentLinkedQueue<LogEntry>\n    - minLogLevel: LogLevel\n    - executorService: ExecutorService\n    - logCount: AtomicInteger\n    + collectLog(logEntry: LogEntry)\n    + stop()\n  }\n\n  class LogEntry {\n    - serviceName: String\n    - level: LogLevel\n    - message: String\n    - timestamp: LocalDateTime\n  }\n\n  enum LogLevel {\n    DEBUG\n    INFO\n    ERROR\n  }\n\n  class LogProducer {\n    - serviceName: String\n    - aggregator: LogAggregator\n    + generateLog(level: LogLevel, message: String)\n  }\n}\n\nLogProducer --> \"-aggregator\" LogAggregator\nLogAggregator --> \"-centralLogStore\" CentralLogStore\nLogAggregator --> \"-buffer\" LogEntry\nCentralLogStore --> \"-logs\" LogEntry\n\n@enduml\n"
  },
  {
    "path": "microservices-log-aggregation/etc/log-aggregation.urm.puml",
    "content": "@startuml\npackage com.iluwatar.logaggregation {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class CentralLogStore {\n    - LOGGER : Logger {static}\n    - logs : ConcurrentLinkedQueue<LogEntry>\n    + CentralLogStore()\n    + displayLogs()\n    + storeLog(logEntry : LogEntry)\n  }\n  class LogAggregator {\n    - BUFFER_THRESHOLD : int {static}\n    - LOGGER : Logger {static}\n    - buffer : ConcurrentLinkedQueue<LogEntry>\n    - centralLogStore : CentralLogStore\n    - executorService : ExecutorService\n    - logCount : AtomicInteger\n    - minLogLevel : LogLevel\n    + LogAggregator(centralLogStore : CentralLogStore, minLogLevel : LogLevel)\n    + collectLog(logEntry : LogEntry)\n    - flushBuffer()\n    - startBufferFlusher()\n    + stop()\n  }\n  class LogEntry {\n    - level : LogLevel\n    - message : String\n    - serviceName : String\n    - timestamp : LocalDateTime\n    + LogEntry(serviceName : String, level : LogLevel, message : String, timestamp : LocalDateTime)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getLevel() : LogLevel\n    + getMessage() : String\n    + getServiceName() : String\n    + getTimestamp() : LocalDateTime\n    + hashCode() : int\n    + setLevel(level : LogLevel)\n    + setMessage(message : String)\n    + setServiceName(serviceName : String)\n    + setTimestamp(timestamp : LocalDateTime)\n    + toString() : String\n  }\n  enum LogLevel {\n    + DEBUG {static}\n    + ERROR {static}\n    + INFO {static}\n    + valueOf(name : String) : LogLevel {static}\n    + values() : LogLevel[] {static}\n  }\n  class LogProducer {\n    - LOGGER : Logger {static}\n    - aggregator : LogAggregator\n    - serviceName : String\n    + LogProducer(serviceName : String, aggregator : LogAggregator)\n    + generateLog(level : LogLevel, message : String)\n  }\n}\nLogAggregator -->  \"-centralLogStore\" CentralLogStore\nLogEntry -->  \"-level\" LogLevel\nCentralLogStore -->  \"-logs\" LogEntry\nLogAggregator -->  \"-buffer\" LogEntry\nLogAggregator -->  \"-minLogLevel\" LogLevel\nLogProducer -->  \"-aggregator\" LogAggregator\n@enduml"
  },
  {
    "path": "microservices-log-aggregation/etc/microservices-log-aggregation.urm.puml",
    "content": "@startuml\npackage com.iluwatar.logaggregation {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class CentralLogStore {\n    - LOGGER : Logger {static}\n    - logs : ConcurrentLinkedQueue<LogEntry>\n    + CentralLogStore()\n    + displayLogs()\n    + storeLog(logEntry : LogEntry)\n  }\n  class LogAggregator {\n    - BUFFER_THRESHOLD : int {static}\n    - LOGGER : Logger {static}\n    - buffer : ConcurrentLinkedQueue<LogEntry>\n    - centralLogStore : CentralLogStore\n    - executorService : ExecutorService\n    - logCount : AtomicInteger\n    - minLogLevel : LogLevel\n    + LogAggregator(centralLogStore : CentralLogStore, minLogLevel : LogLevel)\n    + collectLog(logEntry : LogEntry)\n    - flushBuffer()\n    - startBufferFlusher()\n    + stop()\n  }\n  class LogEntry {\n    - level : LogLevel\n    - message : String\n    - serviceName : String\n    - timestamp : LocalDateTime\n    + LogEntry(serviceName : String, level : LogLevel, message : String, timestamp : LocalDateTime)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getLevel() : LogLevel\n    + getMessage() : String\n    + getServiceName() : String\n    + getTimestamp() : LocalDateTime\n    + hashCode() : int\n    + setLevel(level : LogLevel)\n    + setMessage(message : String)\n    + setServiceName(serviceName : String)\n    + setTimestamp(timestamp : LocalDateTime)\n    + toString() : String\n  }\n  enum LogLevel {\n    + DEBUG {static}\n    + ERROR {static}\n    + INFO {static}\n    + valueOf(name : String) : LogLevel {static}\n    + values() : LogLevel[] {static}\n  }\n  class LogProducer {\n    - LOGGER : Logger {static}\n    - aggregator : LogAggregator\n    - serviceName : String\n    + LogProducer(serviceName : String, aggregator : LogAggregator)\n    + generateLog(level : LogLevel, message : String)\n  }\n}\nLogAggregator -->  \"-centralLogStore\" CentralLogStore\nLogEntry -->  \"-level\" LogLevel\nCentralLogStore -->  \"-logs\" LogEntry\nLogAggregator -->  \"-buffer\" LogEntry\nLogAggregator -->  \"-minLogLevel\" LogLevel\nLogProducer -->  \"-aggregator\" LogAggregator\n@enduml"
  },
  {
    "path": "microservices-log-aggregation/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n\n  <artifactId>microservices-log-aggregation</artifactId>\n\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-junit-jupiter</artifactId>\n      <version>5.16.1</version>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.logaggregation.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "microservices-log-aggregation/src/main/java/com/iluwatar/logaggregation/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.logaggregation;\n\n/**\n * The main application class responsible for demonstrating the log aggregation mechanism. Creates\n * services, generates logs, aggregates, and finally displays the logs.\n */\npublic class App {\n\n  /**\n   * The entry point of the application.\n   *\n   * @param args Command line arguments.\n   * @throws InterruptedException If any thread has interrupted the current thread.\n   */\n  public static void main(String[] args) throws InterruptedException {\n    final CentralLogStore centralLogStore = new CentralLogStore();\n    final LogAggregator aggregator = new LogAggregator(centralLogStore, LogLevel.INFO);\n\n    final LogProducer serviceA = new LogProducer(\"ServiceA\", aggregator);\n    final LogProducer serviceB = new LogProducer(\"ServiceB\", aggregator);\n\n    serviceA.generateLog(LogLevel.INFO, \"This is an INFO log from ServiceA\");\n    serviceB.generateLog(LogLevel.ERROR, \"This is an ERROR log from ServiceB\");\n    serviceA.generateLog(LogLevel.DEBUG, \"This is a DEBUG log from ServiceA\");\n\n    aggregator.stop();\n    centralLogStore.displayLogs();\n  }\n}\n"
  },
  {
    "path": "microservices-log-aggregation/src/main/java/com/iluwatar/logaggregation/CentralLogStore.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.logaggregation;\n\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * A centralized store for logs. It collects logs from various services and stores them. This class\n * is thread-safe, ensuring that logs from different services are safely stored concurrently without\n * data races.\n */\n@Slf4j\npublic class CentralLogStore {\n\n  private final ConcurrentLinkedQueue<LogEntry> logs = new ConcurrentLinkedQueue<>();\n\n  /**\n   * Stores the given log entry into the central log store.\n   *\n   * @param logEntry The log entry to store.\n   */\n  public void storeLog(LogEntry logEntry) {\n    if (logEntry == null) {\n      LOGGER.error(\"Received null log entry. Skipping.\");\n      return;\n    }\n    logs.offer(logEntry);\n  }\n\n  /** Displays all logs currently stored in the central log store. */\n  public void displayLogs() {\n    LOGGER.info(\"----- Centralized Logs -----\");\n    for (LogEntry logEntry : logs) {\n      LOGGER.info(\n          logEntry.getTimestamp() + \" [\" + logEntry.getLevel() + \"] \" + logEntry.getMessage());\n    }\n  }\n}\n"
  },
  {
    "path": "microservices-log-aggregation/src/main/java/com/iluwatar/logaggregation/LogAggregator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.logaggregation;\n\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Responsible for collecting and buffering logs from different services. Once the logs reach a\n * certain threshold or after a certain time interval, they are flushed to the central log store.\n * This class ensures logs are collected and processed asynchronously and efficiently, providing\n * both an immediate collection and periodic flushing.\n */\n@Slf4j\npublic class LogAggregator {\n\n  private static final int BUFFER_THRESHOLD = 3;\n  private final CentralLogStore centralLogStore;\n  private final ConcurrentLinkedQueue<LogEntry> buffer = new ConcurrentLinkedQueue<>();\n  private final LogLevel minLogLevel;\n  private final ExecutorService executorService = Executors.newSingleThreadExecutor();\n  private final AtomicInteger logCount = new AtomicInteger(0);\n\n  /**\n   * constructor of LogAggregator.\n   *\n   * @param centralLogStore central log store implement\n   * @param minLogLevel min log level to store log\n   */\n  public LogAggregator(CentralLogStore centralLogStore, LogLevel minLogLevel) {\n    this.centralLogStore = centralLogStore;\n    this.minLogLevel = minLogLevel;\n    startBufferFlusher();\n  }\n\n  /**\n   * Collects a given log entry, and filters it by the defined log level.\n   *\n   * @param logEntry The log entry to collect.\n   */\n  public void collectLog(LogEntry logEntry) {\n    if (logEntry.getLevel() == null || minLogLevel == null) {\n      LOGGER.warn(\"Log level or threshold level is null. Skipping.\");\n      return;\n    }\n\n    if (logEntry.getLevel().compareTo(minLogLevel) < 0) {\n      LOGGER.debug(\"Log level below threshold. Skipping.\");\n      return;\n    }\n\n    buffer.offer(logEntry);\n\n    if (logCount.incrementAndGet() >= BUFFER_THRESHOLD) {\n      flushBuffer();\n    }\n  }\n\n  /**\n   * Stops the log aggregator service and flushes any remaining logs to the central log store.\n   *\n   * @throws InterruptedException If any thread has interrupted the current thread.\n   */\n  public void stop() throws InterruptedException {\n    executorService.shutdownNow();\n    if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {\n      LOGGER.error(\"Log aggregator did not terminate.\");\n    }\n    flushBuffer();\n  }\n\n  private void flushBuffer() {\n    LogEntry logEntry;\n    while ((logEntry = buffer.poll()) != null) {\n      centralLogStore.storeLog(logEntry);\n      logCount.decrementAndGet();\n    }\n  }\n\n  private void startBufferFlusher() {\n    executorService.execute(\n        () -> {\n          while (!Thread.currentThread().isInterrupted()) {\n            try {\n              Thread.sleep(5000); // Flush every 5 seconds.\n              flushBuffer();\n            } catch (InterruptedException e) {\n              Thread.currentThread().interrupt();\n            }\n          }\n        });\n  }\n}\n"
  },
  {
    "path": "microservices-log-aggregation/src/main/java/com/iluwatar/logaggregation/LogEntry.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.logaggregation;\n\nimport java.time.LocalDateTime;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\n/**\n * Represents a single log entry, capturing essential details like the service name, log level,\n * message, and the timestamp when the log was generated.\n */\n@Data\n@AllArgsConstructor\npublic class LogEntry {\n  private String serviceName;\n  private LogLevel level;\n  private String message;\n  private LocalDateTime timestamp;\n}\n"
  },
  {
    "path": "microservices-log-aggregation/src/main/java/com/iluwatar/logaggregation/LogLevel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.logaggregation;\n\n/**\n * Enum representing different log levels. Defines the severity of a log message, helping in\n * filtering and prioritization.\n *\n * <ul>\n *   <li>DEBUG: Detailed information, typically of interest only when diagnosing problems.\n *   <li>INFO: Confirmation that things are working as expected.\n *   <li>ERROR: Indicates a problem that needs attention.\n * </ul>\n */\npublic enum LogLevel {\n  DEBUG,\n  INFO,\n  ERROR\n}\n"
  },
  {
    "path": "microservices-log-aggregation/src/main/java/com/iluwatar/logaggregation/LogProducer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.logaggregation;\n\nimport java.time.LocalDateTime;\nimport lombok.AllArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Represents a service that produces logs. The logs are generated based on certain activities or\n * events within the service. Once a log is generated, it's passed on to the aggregator for further\n * processing.\n */\n@AllArgsConstructor\n@Slf4j\npublic class LogProducer {\n\n  private String serviceName;\n  private LogAggregator aggregator;\n\n  /**\n   * Generates a log entry with the given log level and message.\n   *\n   * @param level The level of the log.\n   * @param message The message of the log.\n   */\n  public void generateLog(LogLevel level, String message) {\n    final LogEntry logEntry = new LogEntry(serviceName, level, message, LocalDateTime.now());\n    LOGGER.info(\"Producing log: \" + logEntry.getMessage());\n    aggregator.collectLog(logEntry);\n  }\n}\n"
  },
  {
    "path": "microservices-log-aggregation/src/test/java/com/iluwatar/logaggregation/LogAggregatorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.logaggregation;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\nimport java.time.LocalDateTime;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\n@ExtendWith(MockitoExtension.class)\nclass LogAggregatorTest {\n\n  @Mock private CentralLogStore centralLogStore;\n  private LogAggregator logAggregator;\n\n  @BeforeEach\n  void setUp() {\n    logAggregator = new LogAggregator(centralLogStore, LogLevel.INFO);\n  }\n\n  @Test\n  void whenThreeInfoLogsAreCollected_thenCentralLogStoreShouldStoreAllOfThem() {\n    logAggregator.collectLog(createLogEntry(LogLevel.INFO, \"Sample log message 1\"));\n    logAggregator.collectLog(createLogEntry(LogLevel.INFO, \"Sample log message 2\"));\n\n    verifyNoInteractionsWithCentralLogStore();\n\n    logAggregator.collectLog(createLogEntry(LogLevel.INFO, \"Sample log message 3\"));\n\n    verifyCentralLogStoreInvokedTimes(3);\n  }\n\n  @Test\n  void whenDebugLogIsCollected_thenNoLogsShouldBeStored() {\n    logAggregator.collectLog(createLogEntry(LogLevel.DEBUG, \"Sample debug log message\"));\n\n    verifyNoInteractionsWithCentralLogStore();\n  }\n\n  private static LogEntry createLogEntry(LogLevel logLevel, String message) {\n    return new LogEntry(\"ServiceA\", logLevel, message, LocalDateTime.now());\n  }\n\n  private void verifyNoInteractionsWithCentralLogStore() {\n    verify(centralLogStore, times(0)).storeLog(any());\n  }\n\n  private void verifyCentralLogStoreInvokedTimes(int times) {\n    verify(centralLogStore, times(times)).storeLog(any());\n  }\n}\n"
  },
  {
    "path": "microservices-self-registration/README.md",
    "content": "---\ntitle: \"Microservices Self-Registration Pattern in Java with Spring Boot and Eureka\"\nshortTitle: Microservices Pattern - Self-Registration\ndescription: \"Dynamically register and discover Java microservices using Spring Boot and Eureka for resilient, scalable communication.\"\ncategory: Service Discovery\nlanguage: en\ntag:\n    - Microservices\n    - Self-Registration\n    - Service Discovery\n    - Eureka\n    - Spring Boot\n    - Spring Cloud\n    - Java\n    - Dynamic Configuration\n    - Resilience \n---\n\n## Intent of Microservices Self-Registration Pattern\n\nThe intent of the Self-Registration pattern is to enable microservices to automatically announce their presence and location to a central registry (like Eureka) upon startup, simplifying service discovery and allowing other services to find and communicate with them without manual configuration or hardcoded addresses. This promotes dynamic and resilient microservices architectures.\n\n## What's in the Project\n\nThis project demonstrates the Microservices Self-Registration pattern using Java, Spring Boot (version 3.4.4), and Eureka for service discovery. It consists of three main components: a Eureka Server and two simple microservices, a Greeting Service and a Context Service, which discover and communicate with each other.\n\n### Project Structure\n* **`eureka-server`:** The central service registry where microservices register themselves.\n* **`greeting-service`:** A simple microservice that provides a greeting.\n* **`context-service`:** A microservice that consumes the greeting from the Greeting Service and adds context.\n\n The **Eureka Server** acts as the discovery service. Microservices register themselves with the Eureka Server, providing their network location.\n\n    package com.example.eurekaserver;\n    \n    import org.springframework.boot.SpringApplication;\n    import org.springframework.boot.autoconfigure.SpringBootApplication;\n    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;\n    \n    @SpringBootApplication\n    @EnableEurekaServer\n    public class EurekaServerApplication {\n    \n        public static void main(String[] args) {\n            SpringApplication.run(EurekaServerApplication.class, args);\n        }\n    }\n\n The **Greeting Service** is a simple microservice that exposes an endpoint to retrieve a greeting.\n\n    package com.example.greetingservice;\n\n    import org.springframework.boot.SpringApplication;\n    import org.springframework.boot.autoconfigure.SpringBootApplication;\n    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;\n    \n    @SpringBootApplication\n    @EnableDiscoveryClient\n    public class GreetingServiceApplication {\n    \n        public static void main(String[] args) {\n            SpringApplication.run(GreetingServiceApplication.class, args);\n        }\n    }\n\n Greeting Controller \n    \n    package com.example.greetingservice.controller;\n\n    import org.springframework.web.bind.annotation.GetMapping;\n    import org.springframework.web.bind.annotation.RestController;\n    \n    @RestController\n    public class GreetingController {\n    \n        @GetMapping(\"/greeting\")\n        public String getGreeting() {\n            return \"Hello\";\n        }\n    }\n\nThe **Context Service** consumes the greeting from the Greeting Service using OpenFeign and adds contextual information.\n\n    package com.example.contextservice;\n    \n    import org.springframework.boot.SpringApplication;\n    import org.springframework.boot.autoconfigure.SpringBootApplication;\n    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;\n    import org.springframework.cloud.openfeign.EnableFeignClients;\n    \n    @SpringBootApplication\n    @EnableDiscoveryClient\n    @EnableFeignClients\n    public class ContextServiceApplication {\n    \n        public static void main(String[] args) {\n            SpringApplication.run(ContextServiceApplication.class, args);\n        }\n    }\n\n Feign Client : Spring Cloud OpenFeign is a declarative HTTP client that makes it easier to consume RESTful web services in your Spring Cloud applications. Instead of writing the boilerplate code for making HTTP requests, you simply declare interface with annotations that describe the web service you want to consume.\n\n    package com.example.contextservice.client;\n\n    import org.springframework.cloud.openfeign.FeignClient;\n    import org.springframework.web.bind.annotation.GetMapping;\n    \n    @FeignClient(name = \"greeting-service\")\n    public interface GreetingServiceClient {\n    \n        @GetMapping(\"/greeting\")\n        String getGreeting();\n    }\n\n Context Controller\n\n    package com.example.contextservice.controller;\n    \n    import com.example.contextservice.client.GreetingServiceClient;\n    import org.springframework.beans.factory.annotation.Autowired;\n    import org.springframework.beans.factory.annotation.Value;\n    import org.springframework.web.bind.annotation.GetMapping;\n    import org.springframework.web.bind.annotation.RestController;\n    \n    @RestController\n    public class ContextController {\n    \n        @Autowired\n        private GreetingServiceClient greetingServiceClient;\n    \n        @Value(\"${user.region}\")\n        private String userRegion;\n    \n        @GetMapping(\"/context\")\n        public String getContext() {\n            String greeting = greetingServiceClient.getGreeting();\n            return \"The Greeting Service says: \" + greeting + \" from \" + userRegion + \"!\";\n        }\n    }\n\n 1. Both the Greeting Service and the Context Service register themselves with the Eureka Server upon startup using the _@EnableDiscoveryClient_ annotation.\n 2. The Context Service, annotated with _@EnableFeignClients_, uses the GreetingServiceClient interface with _@FeignClient(name = \"greeting-service\")_ to declare its intent to communicate with the service named \"greeting-service\" in Eureka.\n 3. When the /context endpoint of the Context Service is accessed, it calls the _getGreeting()_ method of the GreetingServiceClient.\n 4. OpenFeign, leveraging the service discovery information from Eureka, resolves the network location of an available instance of the Greeting Service and makes an HTTP GET request to its /greeting endpoint.\n 5. The Greeting Service responds with \"Hello\", and the Context Service then adds the configured user.region to the response.\n\n This project utilizes Spring Boot Actuator, which is included as a dependency, to provide health check endpoints for each microservice. These endpoints (e.g., /actuator/health) can be used by Eureka Server to monitor the health of the registered instances.\n\n## Steps to use for this Project\n\nPrerequisites:\n - Java Development Kit (JDK): Make sure you have a compatible JDK installed (ideally Java 17 or later, as Spring Boot 3.x requires it).\n - Maven or Gradle: You'll need either Maven (if you chose Maven during Spring Initializr setup) or Gradle (if you chose Gradle) installed on your system.\n - An IDE (Optional but Recommended): IntelliJ IDEA, Eclipse, or Spring Tool Suite (STS) can make it easier to work with the project.\n - Web Browser: You'll need a web browser to access the Eureka dashboard and the microservice endpoints.\n\nStep :\n - You'll need to build each microservice individually. Navigate to the root directory of each project in your terminal or command prompt and run the appropriate build command:\n   _cd eurekaserver\n   mvn clean install\n   cd ../greetingservice\n   mvn clean install\n   cd ../contextservice\n   mvn clean install_\nStep :\n - Navigate to the root directory of your eurekaserver project in your terminal or command prompt\n   _mvn spring-boot:run_\n - Wait for the Eureka Server application to start. You should see logs in the console indicating that it has started on port 8761 (as configured).\n - Open your web browser and go to http://localhost:8761/. You should see the Eureka Server dashboard. Initially, the list of registered instances will be empty.\nStep :\n - Run the Greeting Service\n   - Open a new terminal or command prompt.\n   - Navigate to the root directory of your greetingservice project. \n   - Run the Spring Boot application: _mvn spring-boot:run_\n   - Wait for the Greeting Service to start. You should see logs indicating that it has registered with the Eureka Server.\n   - Go back to your Eureka Server dashboard in the browser (http://localhost:8761/). You should now see GREETINGSERVICE listed under the \"Instances currently registered with Eureka\". Its status should be \"UP\".\nStep :\n - Run the Context Service\n   - Open a new terminal or command prompt.\n   - Navigate to the root directory of your contextservice project.\n   - Run the Spring Boot application: _mvn spring-boot:run_\n   - Wait for the Context Service to start. You should see logs indicating that it has registered with the Eureka Server.\n   - Go back to your Eureka Server dashboard in the browser (http://localhost:8761/). You should now see CONTEXTSERVICE listed under the \"Instances currently registered with Eureka\". Its status should be \"UP\".\nSTEP :\n   - Test the Greeting Service Directly: Open your web browser and go to http://localhost:8081/greeting. You should see the output: Hello.\n   - Test the Context Service (which calls the Greeting Service): Open your web browser and go to http://localhost:8082/context. You should see the output: The Greeting Service says: Hello from Chennai, Tamil Nadu, India!. This confirms that the Context Service successfully discovered and called the Greeting Service through Eureka.\n\nOptional: Check Health Endpoints\n\nYou can also verify the health status of each service using Spring Boot Actuator:\n - Greeting Service Health: http://localhost:8081/actuator/health (should return {\"status\":\"UP\"})\n - Context Service Health: http://localhost:8082/actuator/health (should return {\"status\":\"UP\"})\n - Eureka Server Health: http://localhost:8761/actuator/health (should return {\"status\":\"UP\"})\n\n## When to use Microservices Self-Registration Pattern\n\n - **Dynamic Environments:** When your microservices are frequently deployed, scaled up or down, or their network locations (IP addresses and ports) change often. This is common in cloud-based or containerized environments (like Docker and Kubernetes).\n - **Large Number of Services:** As the number of microservices in your system grows, manually managing their configurations and dependencies becomes complex and error-prone. Self-registration automates this process.\n - **Need for Automatic Service** Discovery: When services need to find and communicate with each other without hardcoding network locations. This allows for greater flexibility and reduces coupling.\n - **Implementing Load Balancing:** Service registries like Eureka often integrate with load balancers, enabling them to automatically distribute traffic across available instances of a service that have registered themselves.\n - **Improving System Resilience:** If a service instance fails, the registry will eventually be updated (through heartbeats or health checks), and other services can discover and communicate with the remaining healthy instances.\n - **DevOps Automation:** This pattern aligns well with DevOps practices, allowing for more automated deployment and management of microservices.\n\n## Real-World Applications of Self-Registration pattern\n\n - E-Commerce platforms have numerous independent services for product catalogs, order processing, payments, shipping, etc. Self-registration allows these services to dynamically discover and communicate with each other as the system scales during peak loads or as new features are deployed.\n - Streaming services rely on many microservices for user authentication, content delivery networks (CDNs), recommendation engines, billing systems, etc. Self-registration helps these services adapt to varying user demands and infrastructure changes.\n - Social media These platforms use microservices for managing user profiles, timelines, messaging, advertising, and more. Self-registration enables these services to scale independently and handle the massive traffic they experience.\n\n## Advantages \n\n - Microservices can dynamically locate and communicate with each other without needing to know their specific network addresses beforehand. This is crucial in dynamic environments where IP addresses and ports can change frequently.\n - Reduces the need for manual configuration of service locations in each microservice. Services don't need to be updated every time another service's location changes.\n - Scaling microservices up or down becomes easier. New instances automatically register themselves with the service registry, making them immediately discoverable by other services without manual intervention.\n - If a service instance fails, it will eventually stop sending heartbeats to the registry and will be removed. Consumers can then discover and connect to other healthy instances, improving the system's overall resilience.\n - Services are less tightly coupled as they don't have direct dependencies on the physical locations of other services. This makes deployments and updates more flexible.\n - Service registries often integrate with load balancers. When a new service instance registers, the load balancer can automatically include it in the pool of available instances, distributing traffic effectively.\n - Microservices can be deployed across different environments (development, testing, production) without significant changes to their discovery mechanism, as long as they are configured to connect to the appropriate service registry for that environment.\n\n## Trade-offs\n\n - Introducing a service registry adds another component to your system that needs to be set up, managed, and monitored. This increases the overall complexity of the infrastructure.\n - The service registry itself becomes a critical component. If the service registry becomes unavailable, it can disrupt communication between microservices. High availability for the service registry is therefore essential.\n - Microservices need to communicate with the service registry for registration, sending heartbeats, and querying for other services. This can lead to increased network traffic.\n - There might be a slight delay between when a microservice instance starts and when it becomes fully registered and discoverable in the service registry. This needs to be considered, especially during scaling events.\n - You need to consider how your microservices will behave if they fail to register with the service registry upon startup. Robust error handling and retry mechanisms are often necessary.\n - Microservices need to include and configure client libraries (like the Eureka Discovery Client) to interact with the service registry. This adds a dependency to your application code.\n - In distributed service registries, ensuring consistency of the registry data across all nodes can be a challenge. Different registries might have different consistency models (e.g., eventual consistency).\n\n## References\n\n - Microservices Patterns: https://microservices.io/\n - Eureka Documentation: https://github.com/Netflix/eureka | https://spring.io/projects/spring-cloud-netflix \n - Spring Boot Documentation: https://spring.io/projects/spring-boot\n - Spring Cloud OpenFeignDocumentation: https://spring.io/projects/spring-cloud-openfeign\n - Spring Boot Actuator Documentation: https://www.baeldung.com/spring-boot-actuators"
  },
  {
    "path": "microservices-self-registration/contextservice/.gitattributes",
    "content": "/mvnw text eol=lf\n*.cmd text eol=crlf\n"
  },
  {
    "path": "microservices-self-registration/contextservice/.gitignore",
    "content": "HELP.md\ntarget/\n!.mvn/wrapper/maven-wrapper.jar\n!**/src/main/**/target/\n!**/src/test/**/target/\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\nbuild/\n!**/src/main/**/build/\n!**/src/test/**/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "microservices-self-registration/contextservice/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>3.4.4</version>\n        <relativePath/> </parent>\n    <groupId>com.learning</groupId>\n    <artifactId>contextservice</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <name>contextservice</name>\n    <description>contextservice</description>\n\n    <properties>\n        <spring-cloud.version>2024.0.1</spring-cloud.version>\n    </properties>\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <version>1.18.38</version>\n            <scope>provided</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-openfeign</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <dependencyManagement>\n        <dependencies>\n            <dependency>\n                <groupId>org.springframework.cloud</groupId>\n                <artifactId>spring-cloud-dependencies</artifactId>\n                <version>${spring-cloud.version}</version>\n                <type>pom</type>\n                <scope>import</scope>\n            </dependency>\n        </dependencies>\n    </dependencyManagement>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/ContextserviceApplication.java",
    "content": "package com.learning.contextservice;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.cloud.openfeign.EnableFeignClients;\n\n@SpringBootApplication\n@EnableDiscoveryClient\n@EnableFeignClients\npublic class ContextserviceApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(ContextserviceApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/MyCustomHealthCheck.java",
    "content": "package com.learning.contextservice;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.HealthIndicator;\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Component;\n\n\n@Component(\"myCustomHealthCheck\")\npublic class MyCustomHealthCheck implements HealthIndicator {\n\n  private static final Logger log = LoggerFactory.getLogger(MyCustomHealthCheck.class);\n\n  private volatile boolean isHealthy = true;\n\n  @Scheduled(fixedRate = 5000) // Run every 5 seconds\n  public void updateHealthStatus() {\n    // Perform checks here to determine the current health\n    // For example, check database connectivity, external service availability, etc.\n    isHealthy = performHealthCheck();\n    log.info(\"Update health status : {}\", isHealthy);\n  }\n\n  boolean performHealthCheck() {\n    boolean current = System.currentTimeMillis() % 10000 < 5000; // Simulate fluctuating health\n    log.debug(\"Performing health check, current status: {}\", current);\n    return current; // Simulate fluctuating health\n  }\n\n  @Override\n  public Health health() {\n    if (isHealthy) {\n      log.info(\"Health check successful, service is UP\");\n      return Health.up().withDetail(\"message\", \"Service is running and scheduled checks are OK\").build();\n    } else {\n      log.warn(\"Health check failed, service is DOWN\");\n      return Health.down().withDetail(\"error\", \"Scheduled health checks failed\").build();\n    }\n  }\n}\n"
  },
  {
    "path": "microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/client/GreetingServiceClient.java",
    "content": "package com.learning.contextservice.client;\n\nimport org.springframework.cloud.openfeign.FeignClient;\nimport org.springframework.web.bind.annotation.GetMapping;\n\n@FeignClient(name = \"greetingservice\")\npublic interface GreetingServiceClient {\n\n  @GetMapping(\"/greeting\")\n  String getGreeting();\n}\n"
  },
  {
    "path": "microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/controller/ContextController.java",
    "content": "package com.learning.contextservice.controller;\n\nimport com.learning.contextservice.client.GreetingServiceClient;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class ContextController {\n\n  private final GreetingServiceClient greetingServiceClient;\n  private final String userRegion;\n\n  @Autowired\n  public ContextController(GreetingServiceClient greetingServiceClient, @Value(\"${user.region}\") String userRegion) {\n    this.greetingServiceClient = greetingServiceClient;\n    this.userRegion = userRegion;\n  }\n\n  @GetMapping(\"/context\")\n  public String getContext() {\n    String greeting = greetingServiceClient.getGreeting();\n    return \"The Greeting Service says: \"+greeting+\" from \"+userRegion;\n  }\n}\n"
  },
  {
    "path": "microservices-self-registration/contextservice/src/main/resources/application.yml",
    "content": "server:\n    port: 8082\n\nspring:\n    application:\n        name: contextservice\n\neureka:\n    client:\n        service-url.defaultZone: http://localhost:8761/eureka\n\nuser:\n    region: Chennai, Tamil Nadu, India\n\nmanagement:\n  endpoint:\n      health:\n          show-details: always\n      web:\n        exposure:\n            include: health\n\nlogging:\n    file:\n        name: application.log\n"
  },
  {
    "path": "microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/ContextControllerTest.java",
    "content": "package com.learning.contextservice;\n\nimport com.learning.contextservice.client.GreetingServiceClient;\nimport org.hamcrest.Matchers;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;\n\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.context.annotation.Import;\nimport org.springframework.http.MediaType;\nimport org.springframework.test.context.bean.override.mockito.MockitoBean;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.result.MockMvcResultMatchers;\n\n@SpringBootTest(classes = ContextserviceApplication.class)\n@AutoConfigureMockMvc\n@Import(TestConfig.class)\nclass ContextControllerTest {\n\n  @Autowired\n  private MockMvc mockMvc;\n\n  @MockitoBean\n  private GreetingServiceClient greetingServiceClient;\n\n  @Value(\"${user.region}\")\n  private String userRegion;\n\n  @Test\n  void shouldReturnContextGreeting() throws Exception{\n    Mockito.when(greetingServiceClient.getGreeting()).thenReturn(\"Mocked Hello\");\n\n    mockMvc.perform(MockMvcRequestBuilders.get(\"/context\")\n        .accept(MediaType.TEXT_PLAIN))\n        .andExpect(MockMvcResultMatchers.status().isOk())\n        .andExpect(MockMvcResultMatchers.content().string(\"The Greeting Service says: Mocked Hello from Chennai, Tamil Nadu, India\"));\n  }\n\n  @Test\n  void shouldReturnContextServiceHealthStatusUp() throws Exception {\n    mockMvc.perform(MockMvcRequestBuilders.get(\"/actuator/health\"))\n        .andExpect(MockMvcResultMatchers.status().isOk())\n        .andExpect(MockMvcResultMatchers.content().string(Matchers.containsString(\"\\\"status\\\":\\\"UP\\\"\")));\n  }\n}\n"
  },
  {
    "path": "microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/ContextserviceApplicationTests.java",
    "content": "package com.learning.contextservice;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n@SpringBootTest\nclass ContextserviceApplicationTests {\n\n\t@Test\n\tvoid contextLoads() {\n    // This is a basic integration test that checks if the Spring Application Context loads successfully.\n    // If the context loads without any exceptions, the test is considered passing.\n    // It is often left empty as the act of loading the context is the primary verification.\n    // You can add specific assertions here if you want to verify the presence or state of certain beans.\n\t}\n\n}\n"
  },
  {
    "path": "microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/TestConfig.java",
    "content": "package com.learning.contextservice;\n\nimport com.learning.contextservice.client.GreetingServiceClient;\nimport org.mockito.Mockito;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n@Configuration\npublic class TestConfig {\n\n  @Bean\n  public GreetingServiceClient greetingServiceClient() {\n    GreetingServiceClient mockClient = Mockito.mock(GreetingServiceClient.class);\n    Mockito.when(mockClient.getGreeting()).thenReturn(\"Mocked Hello\");\n    return mockClient;\n  }\n}\n"
  },
  {
    "path": "microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/myCustomHealthCheckTest.java",
    "content": "package com.learning.contextservice;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.test.util.ReflectionTestUtils;\nimport org.springframework.boot.actuate.health.Status;\nimport static org.junit.jupiter.api.Assertions.*;\n\nclass MyCustomHealthCheckTest {\n\n  @Test\n  void testHealthUp() {\n    MyCustomHealthCheck healthCheck = new MyCustomHealthCheck();\n    // Simulate a healthy state\n    ReflectionTestUtils.setField(healthCheck, \"isHealthy\", true);\n    Health health = healthCheck.health();\n    assertEquals(Status.UP, health.getStatus());\n    assertTrue(health.getDetails().containsKey(\"message\"));\n    assertEquals(\"Service is running and scheduled checks are OK\", health.getDetails().get(\"message\"));\n  }\n\n  @Test\n  void testHealthDown() {\n    MyCustomHealthCheck healthCheck = new MyCustomHealthCheck();\n    // Simulate an unhealthy state\n    ReflectionTestUtils.setField(healthCheck, \"isHealthy\", false);\n    Health health = healthCheck.health();\n    assertEquals(Status.DOWN, health.getStatus());\n    assertTrue(health.getDetails().containsKey(\"error\"));\n    assertEquals(\"Scheduled health checks failed\", health.getDetails().get(\"error\"));\n  }\n\n}"
  },
  {
    "path": "microservices-self-registration/eurekaserver/.gitattributes",
    "content": "/mvnw text eol=lf\n*.cmd text eol=crlf\n"
  },
  {
    "path": "microservices-self-registration/eurekaserver/.gitignore",
    "content": "HELP.md\ntarget/\n!.mvn/wrapper/maven-wrapper.jar\n!**/src/main/**/target/\n!**/src/test/**/target/\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\nbuild/\n!**/src/main/**/build/\n!**/src/test/**/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "microservices-self-registration/eurekaserver/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>3.4.4</version>\n        <relativePath/> </parent>\n    <groupId>com.learning</groupId>\n    <artifactId>eurekaserver</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <name>eurekaserver</name>\n    <description>eurekaserver</description>\n\n    <properties>\n        <spring-cloud.version>2024.0.1</spring-cloud.version>\n    </properties>\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <dependencyManagement>\n        <dependencies>\n            <dependency>\n                <groupId>org.springframework.cloud</groupId>\n                <artifactId>spring-cloud-dependencies</artifactId>\n                <version>${spring-cloud.version}</version>\n                <type>pom</type>\n                <scope>import</scope>\n            </dependency>\n        </dependencies>\n    </dependencyManagement>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "microservices-self-registration/eurekaserver/src/main/java/com/learning/eurekaserver/EurekaserverApplication.java",
    "content": "package com.learning.eurekaserver;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;\n\n@SpringBootApplication\n@EnableEurekaServer\npublic class EurekaserverApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(EurekaserverApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "microservices-self-registration/eurekaserver/src/main/resources/application.yml",
    "content": "server:\n    port: 8761\n\neureka:\n    client:\n        register-with-eureka: false\n        fetch-registry: false\n    server:\n        enable-self-preservation: true\n\n"
  },
  {
    "path": "microservices-self-registration/eurekaserver/src/test/java/com/learning/eurekaserver/EurekaserverApplicationTests.java",
    "content": "package com.learning.eurekaserver;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n@SpringBootTest\nclass EurekaserverApplicationTests {\n\n\t@Test\n\tvoid contextLoads() {\n    // This is a basic integration test that checks if the Spring Application Context loads successfully.\n    // If the context loads without any exceptions, the test is considered passing.\n    // It is often left empty as the act of loading the context is the primary verification.\n    // You can add specific assertions here if you want to verify the presence or state of certain beans.\n\t}\n\n}\n"
  },
  {
    "path": "microservices-self-registration/greetingservice/.gitattributes",
    "content": "/mvnw text eol=lf\n*.cmd text eol=crlf\n"
  },
  {
    "path": "microservices-self-registration/greetingservice/.gitignore",
    "content": "HELP.md\ntarget/\n!.mvn/wrapper/maven-wrapper.jar\n!**/src/main/**/target/\n!**/src/test/**/target/\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\nbuild/\n!**/src/main/**/build/\n!**/src/test/**/build/\n\n### VS Code ###\n.vscode/\n"
  },
  {
    "path": "microservices-self-registration/greetingservice/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>3.4.4</version>\n        <relativePath/> </parent>\n    <groupId>com.learning</groupId>\n    <artifactId>greetingservice</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <name>greetingservice</name>\n    <description>greetingservice</description>\n\n    <properties>\n        <spring-cloud.version>2024.0.1</spring-cloud.version>\n    </properties>\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <version>1.18.38</version>\n            <scope>provided</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.cloud</groupId>\n            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-actuator</artifactId>\n        </dependency>\n     </dependencies>\n    <dependencyManagement>\n        <dependencies>\n            <dependency>\n                <groupId>org.springframework.cloud</groupId>\n                <artifactId>spring-cloud-dependencies</artifactId>\n                <version>${spring-cloud.version}</version>\n                <type>pom</type>\n                <scope>import</scope>\n            </dependency>\n        </dependencies>\n    </dependencyManagement>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot</groupId>\n                <artifactId>spring-boot-maven-plugin</artifactId>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/GreetingserviceApplication.java",
    "content": "package com.learning.greetingservice;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.cloud.client.discovery.EnableDiscoveryClient;\nimport org.springframework.context.annotation.ComponentScan;\n\n@SpringBootApplication\n@EnableDiscoveryClient\n@ComponentScan(\"com.learning.greetingservice.controller\")\npublic class GreetingserviceApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(GreetingserviceApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/MyCustomHealthCheck.java",
    "content": "package com.learning.greetingservice;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.boot.actuate.health.HealthIndicator;\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Component;\n\n@Component(\"myCustomHealthCheck\")\npublic class MyCustomHealthCheck implements HealthIndicator {\n\n  private static final Logger log = LoggerFactory.getLogger(MyCustomHealthCheck.class);\n\n  private volatile boolean isHealthy = true;\n\n  @Scheduled(fixedRate = 5000) // Run every 5 seconds\n  public void updateHealthStatus() {\n    // Perform checks here to determine the current health\n    // For example, check database connectivity, external service availability, etc.\n    isHealthy = performHealthCheck();\n    log.info(\"Update health status : {}\", isHealthy);\n  }\n\n  boolean performHealthCheck() {\n    boolean current = System.currentTimeMillis() % 10000 < 5000; // Simulate fluctuating health\n    log.debug(\"Performing health check, current status: {}\", current);\n    return current; // Simulate fluctuating health\n  }\n\n  @Override\n  public Health health() {\n    if (isHealthy) {\n      log.info(\"Health check successful, service is UP\");\n      return Health.up().withDetail(\"message\", \"Service is running and scheduled checks are OK\").build();\n    } else {\n      log.warn(\"Health check failed, service is DOWN\");\n      return Health.down().withDetail(\"error\", \"Scheduled health checks failed\").build();\n    }\n  }\n}\n"
  },
  {
    "path": "microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/controller/GreetingsController.java",
    "content": "package com.learning.greetingservice.controller;\n\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class GreetingsController {\n\n  @GetMapping(\"/greeting\")\n  public String getGreeting() {\n    return \"Hello\";\n  }\n}\n"
  },
  {
    "path": "microservices-self-registration/greetingservice/src/main/resources/application.yml",
    "content": "server:\n    port: 8081\n\nspring:\n    application:\n        name: greetingservice\neureka:\n  client:\n      service-url.defaultZone: http://localhost:8761/eureka\n\nmanagement:\n  endpoint:\n    health:\n        show-details: always\n    web:\n      exposure:\n          include: health\n\nlogging:\n    file:\n        name: application.log\n\n"
  },
  {
    "path": "microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/GreetingserviceApplicationTests.java",
    "content": "package com.learning.greetingservice;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.boot.test.context.SpringBootTest;\n\n@SpringBootTest\nclass GreetingserviceApplicationTests {\n\n\t@Test\n\tvoid contextLoads() {\n    // This is a basic integration test that checks if the Spring Application Context loads successfully.\n    // If the context loads without any exceptions, the test is considered passing.\n    // It is often left empty as the act of loading the context is the primary verification.\n    // You can add specific assertions here if you want to verify the presence or state of certain beans.\n\t}\n\n}\n"
  },
  {
    "path": "microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/MyCustomHealthCheckTest.java",
    "content": "package com.learning.greetingservice;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.boot.actuate.health.Health;\nimport org.springframework.test.util.ReflectionTestUtils;\nimport org.springframework.boot.actuate.health.Status;\nimport static org.junit.jupiter.api.Assertions.*;\n\nclass MyCustomHealthCheckTest {\n\n  @Test\n  void testHealthUp() {\n    MyCustomHealthCheck healthCheck = new MyCustomHealthCheck();\n    // Simulate a healthy state\n    ReflectionTestUtils.setField(healthCheck, \"isHealthy\", true);\n    Health health = healthCheck.health();\n    assertEquals(Status.UP, health.getStatus());\n    assertTrue(health.getDetails().containsKey(\"message\"));\n    assertEquals(\"Service is running and scheduled checks are OK\", health.getDetails().get(\"message\"));\n  }\n\n}"
  },
  {
    "path": "microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/controller/GreetingControllerTest.java",
    "content": "package com.learning.greetingservice.controller;\n\nimport com.learning.greetingservice.GreetingserviceApplication;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.http.MediaType;\nimport org.springframework.test.context.ActiveProfiles;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.result.MockMvcResultMatchers;\n\n@SpringBootTest(classes = GreetingserviceApplication.class)\n@AutoConfigureMockMvc\n@ActiveProfiles(\"test\")\nclass GreetingControllerTest {\n\n  @Autowired\n  private MockMvc mockMvc;\n\n  @Test\n  void shouldReturnGreeting() throws Exception{\n    mockMvc.perform(MockMvcRequestBuilders.get(\"/greeting\")\n            .accept(MediaType.TEXT_PLAIN))\n        .andExpect(MockMvcResultMatchers.status().isOk())\n        .andExpect(MockMvcResultMatchers.content().string(\"Hello\"));\n  }\n\n  @Test\n  void shouldReturnHealthStatusUp() throws Exception{\n    mockMvc.perform(MockMvcRequestBuilders.get(\"/actuator/health\"))\n        .andExpect(MockMvcResultMatchers.status().isOk())\n        .andExpect(MockMvcResultMatchers.content().string(org.hamcrest.Matchers.containsString(\"\\\"status\\\":\\\"UP\\\"\")));\n  }\n}\n"
  },
  {
    "path": "microservices-self-registration/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <parent>\n        <artifactId>java-design-patterns</artifactId>\n        <groupId>com.iluwatar</groupId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>microservices-self-registration</artifactId>\n    <packaging>pom</packaging>\n    <modules>\n        <module>eurekaserver</module>\n        <module>greetingservice</module>\n        <module>contextservice</module>\n    </modules>\n\n    <properties>\n        <java.version>21</java.version>\n        <maven.compiler.source>${java.version}</maven.compiler.source>\n        <maven.compiler.target>${java.version}</maven.compiler.target>\n    </properties>\n\n    <build>\n        <pluginManagement>\n            <plugins>\n                <plugin>\n                    <groupId>org.apache.maven.plugins</groupId>\n                    <artifactId>maven-compiler-plugin</artifactId>\n                    <version>3.8.1</version> <configuration>\n                    <source>${maven.compiler.source}</source>\n                    <target>${maven.compiler.target}</target>\n                </configuration>\n                </plugin>\n            </plugins>\n        </pluginManagement>\n    </build>\n</project>"
  },
  {
    "path": "model-view-controller/README.md",
    "content": "---\ntitle: \"Model-View-Controller Pattern in Java: Streamlining Java Web Development\"\nshortTitle: Model-View-Controller (MVC)\ndescription: \"Learn about the Model-View-Controller (MVC) design pattern in Java, including its benefits, real-world examples, use cases, and how to implement it effectively in your applications.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - Architecture\n  - Client-server\n  - Decoupling\n  - Layered architecture\n  - Presentation\n---\n\n## Also known as\n\n* MVC\n\n## Intent of Model-View-Controller Design Pattern\n\nTo separate an application into three interconnected components (Model, View, Controller), enabling modular development of each part independently, enhancing maintainability and scalability. Model-View-Controller (MVC) design pattern is widely used in Java applications for web development and user interface separation.\n\n## Detailed Explanation of Model-View-Controller Pattern with Real-World Examples\n\nReal-world example\n\n> Consider ICU room in a hospital displaying patient health information on devices taking input from sensors. The display shows data received from the controller, which updates from the sensor model. This exemplifies the MVC design pattern in a real-world Java application.\n\nIn plain words\n\n> MVC separates the business logic from user interface by mediating Controller between Model & View.\n\nWikipedia says\n\n> Model–view–controller (MVC) is commonly used for developing user interfaces that divide the related program logic into three interconnected elements. This is done to separate internal representations of information from the ways information is presented to and accepted from the user.\n\nArchitecture diagram\n\n![Model-View-Controller Architecture Diagram](./etc/mvc-architecture-diagram.png)\n\n\n## Programmatic Example of Model-View-Controller Pattern in Java\n\nConsider following `GiantModel` model class that provides the health, fatigue & nourishment information.\n\n```java\n@Getter\n@Setter\n@Builder\n@AllArgsConstructor\n@NoArgsConstructor\npublic class GiantModel {\n\n  private Health health;\n  private Fatigue fatigue;\n  private Nourishment nourishment;\n\n  @Override\n  public String toString() {\n    return String.format(\"The giant looks %s, %s and %s.\", health, fatigue, nourishment);\n  }\n}\n```\n\n`GiantView` class to display received patient data.\n\n```java\npublic class GiantView {\n\n  public void displayGiant(GiantModel giant) {\n    LOGGER.info(giant.toString());\n  }\n}\n```\n\n`GiantController` class takes updates from `GiantModel` and sends to `GiantView` for display.\n\n```java\npublic class GiantController {\n\n  private final GiantModel giant;\n  private final GiantView view;\n\n  public GiantController(GiantModel giant, GiantView view) {\n    this.giant = giant;\n    this.view = view;\n  }\n\n  @SuppressWarnings(\"UnusedReturnValue\")\n  public Health getHealth() {\n    return giant.getHealth();\n  }\n\n  public void setHealth(Health health) {\n    this.giant.setHealth(health);\n  }\n\n  @SuppressWarnings(\"UnusedReturnValue\")\n  public Fatigue getFatigue() {\n    return giant.getFatigue();\n  }\n\n  public void setFatigue(Fatigue fatigue) {\n    this.giant.setFatigue(fatigue);\n  }\n\n  @SuppressWarnings(\"UnusedReturnValue\")\n  public Nourishment getNourishment() {\n    return giant.getNourishment();\n  }\n\n  public void setNourishment(Nourishment nourishment) {\n    this.giant.setNourishment(nourishment);\n  }\n\n  public void updateView() {\n    this.view.displayGiant(giant);\n  }\n}\n```\n\nThis example demonstrates how the MVC pattern separates concerns in a Java application, making it easier to manage and update components independently.\n\n## When to Use the Model-View-Controller Pattern in Java\n\n* Used in web applications to separate data model, user interface, and user input processing.\n* Suitable for applications requiring a clear separation of concerns, ensuring that the business logic, user interface, and user input are loosely coupled and independently managed, following the MVC pattern.\n\n## Model-View-Controller Pattern Java Tutorials\n\n* [Spring Boot Model (ZetCode)](https://zetcode.com/springboot/model/)\n* [Spring MVC Tutorial (Baeldung)](https://www.baeldung.com/spring-mvc-tutorial)\n\n## Real-World Applications of Model-View-Controller Pattern in Java\n\n* Frameworks like Spring MVC in Java for web applications.\n* Desktop applications in Java, such as those using Swing or JavaFX.\n\n## Benefits and Trade-offs of Model-View-Controller Pattern\n\nBenefits:\n\n* Promotes organized code structure by separating concerns.\n* Facilitates parallel development of components.\n* Enhances testability due to decoupled nature.\n* Easier to manage and update individual parts without affecting others.\n\nTrade-offs:\n\n* Increased complexity in initially setting up the architecture.\n* Can lead to excessive boilerplate if not implemented correctly or for very small projects.\n\n## Related Java Design Patterns\n\n* [Observer](https://java-design-patterns.com/patterns/observer/): Often used in MVC where the view observes the model for changes; this is a fundamental relationship for updating the UI when the model state changes.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Controllers may use different strategies for handling user input, related through the ability to switch strategies for user input processing in Java MVC applications.\n* [Composite](https://java-design-patterns.com/patterns/composite/): Views can be structured using the Composite Pattern to manage hierarchies of user interface components.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Pro Spring 5: An In-Depth Guide to the Spring Framework and Its Tools](https://amzn.to/3y9Rrwp)\n* [Model-view-controller (Wikipedia)](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)\n"
  },
  {
    "path": "model-view-controller/etc/model-view-controller.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.GiantView\" project=\"model-view-controller\" \n    file=\"/model-view-controller/src/main/java/com/iluwatar/GiantView.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"198\" x=\"75\" y=\"488\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.GiantModel\" project=\"model-view-controller\" \n    file=\"/model-view-controller/src/main/java/com/iluwatar/GiantModel.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"268\" width=\"261\" x=\"313\" y=\"488\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.GiantController\" project=\"model-view-controller\" \n    file=\"/model-view-controller/src/main/java/com/iluwatar/GiantController.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"214\" width=\"249\" x=\"194\" y=\"234\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"4\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"5\" name=\"view\"/>      \n      <multiplicity id=\"6\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"7\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"8\" name=\"giant\"/>      \n      <multiplicity id=\"9\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "model-view-controller/etc/model-view-controller.urm.puml",
    "content": "@startuml\npackage com.iluwatar.model.view.controller {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  enum Fatigue {\n    + ALERT {static}\n    + SLEEPING {static}\n    + TIRED {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Fatigue {static}\n    + values() : Fatigue[] {static}\n  }\n  class GiantController {\n    - giant : GiantModel\n    - view : GiantView\n    + GiantController(giant : GiantModel, view : GiantView)\n    + getFatigue() : Fatigue\n    + getHealth() : Health\n    + getNourishment() : Nourishment\n    + setFatigue(fatigue : Fatigue)\n    + setHealth(health : Health)\n    + setNourishment(nourishment : Nourishment)\n    + updateView()\n  }\n  class GiantModel {\n    - fatigue : Fatigue\n    - health : Health\n    - nourishment : Nourishment\n    ~ GiantModel(health : Health, fatigue : Fatigue, nourishment : Nourishment)\n    + getFatigue() : Fatigue\n    + getHealth() : Health\n    + getNourishment() : Nourishment\n    + setFatigue(fatigue : Fatigue)\n    + setHealth(health : Health)\n    + setNourishment(nourishment : Nourishment)\n    + toString() : String\n  }\n  class GiantView {\n    - LOGGER : Logger {static}\n    + GiantView()\n    + displayGiant(giant : GiantModel)\n  }\n  enum Health {\n    + DEAD {static}\n    + HEALTHY {static}\n    + WOUNDED {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Health {static}\n    + values() : Health[] {static}\n  }\n  enum Nourishment {\n    + HUNGRY {static}\n    + SATURATED {static}\n    + STARVING {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Nourishment {static}\n    + values() : Nourishment[] {static}\n  }\n}\nGiantModel -->  \"-nourishment\" Nourishment\nGiantController -->  \"-giant\" GiantModel\nGiantModel -->  \"-fatigue\" Fatigue\nGiantModel -->  \"-health\" Health\nGiantController -->  \"-view\" GiantView\n@enduml"
  },
  {
    "path": "model-view-controller/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>model-view-controller</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.model.view.controller.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "model-view-controller/src/main/java/com/iluwatar/model/view/controller/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.controller;\n\n/**\n * Model-View-Controller is a pattern for implementing user interfaces. It divides the application\n * into three interconnected parts namely the model, the view and the controller.\n *\n * <p>The central component of MVC, the model, captures the behavior of the application in terms of\n * its problem domain, independent of the user interface. The model directly manages the data, logic\n * and rules of the application. A view can be any output representation of information, such as a\n * chart or a diagram The third part, the controller, accepts input and converts it to commands for\n * the model or view.\n *\n * <p>In this example we have a giant ({@link GiantModel}) with statuses for health, fatigue and\n * nourishment. {@link GiantView} can display the giant with its current status. {@link\n * GiantController} receives input affecting the model and delegates redrawing the giant to the\n * view.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    // create model, view and controller\n    var giant = new GiantModel(Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    var view = new GiantView();\n    var controller = new GiantController(giant, view);\n    // initial display\n    controller.updateView();\n    // controller receives some interactions that affect the giant\n    controller.setHealth(Health.WOUNDED);\n    controller.setNourishment(Nourishment.HUNGRY);\n    controller.setFatigue(Fatigue.TIRED);\n    // redisplay\n    controller.updateView();\n  }\n}\n"
  },
  {
    "path": "model-view-controller/src/main/java/com/iluwatar/model/view/controller/Fatigue.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.controller;\n\nimport lombok.AllArgsConstructor;\n\n/** Fatigue enumeration. */\n@AllArgsConstructor\npublic enum Fatigue {\n  ALERT(\"alert\"),\n  TIRED(\"tired\"),\n  SLEEPING(\"sleeping\");\n\n  private final String title;\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.controller;\n\n/** GiantController can update the giant data and redraw it using the view. */\npublic class GiantController {\n\n  private final GiantModel giant;\n  private final GiantView view;\n\n  public GiantController(GiantModel giant, GiantView view) {\n    this.giant = giant;\n    this.view = view;\n  }\n\n  @SuppressWarnings(\"UnusedReturnValue\")\n  public Health getHealth() {\n    return giant.getHealth();\n  }\n\n  public void setHealth(Health health) {\n    this.giant.setHealth(health);\n  }\n\n  @SuppressWarnings(\"UnusedReturnValue\")\n  public Fatigue getFatigue() {\n    return giant.getFatigue();\n  }\n\n  public void setFatigue(Fatigue fatigue) {\n    this.giant.setFatigue(fatigue);\n  }\n\n  @SuppressWarnings(\"UnusedReturnValue\")\n  public Nourishment getNourishment() {\n    return giant.getNourishment();\n  }\n\n  public void setNourishment(Nourishment nourishment) {\n    this.giant.setNourishment(nourishment);\n  }\n\n  public void updateView() {\n    this.view.displayGiant(giant);\n  }\n}\n"
  },
  {
    "path": "model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantModel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.controller;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n/** GiantModel contains the giant data. */\n@Getter\n@Setter\n@Builder\n@AllArgsConstructor\n@NoArgsConstructor\npublic class GiantModel {\n\n  private Health health;\n  private Fatigue fatigue;\n  private Nourishment nourishment;\n\n  @Override\n  public String toString() {\n    return String.format(\"The giant looks %s, %s and %s.\", health, fatigue, nourishment);\n  }\n}\n"
  },
  {
    "path": "model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.controller;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** GiantView displays the giant. */\n@Slf4j\npublic class GiantView {\n\n  public void displayGiant(GiantModel giant) {\n    LOGGER.info(giant.toString());\n  }\n}\n"
  },
  {
    "path": "model-view-controller/src/main/java/com/iluwatar/model/view/controller/Health.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.controller;\n\nimport lombok.AllArgsConstructor;\n\n/** Health enumeration. */\n@AllArgsConstructor\npublic enum Health {\n  HEALTHY(\"healthy\"),\n  WOUNDED(\"wounded\"),\n  DEAD(\"dead\");\n\n  private final String title;\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "model-view-controller/src/main/java/com/iluwatar/model/view/controller/Nourishment.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.controller;\n\nimport lombok.AllArgsConstructor;\n\n/** Nourishment enumeration. */\n@AllArgsConstructor\npublic enum Nourishment {\n  SATURATED(\"saturated\"),\n  HUNGRY(\"hungry\"),\n  STARVING(\"starving\");\n\n  private final String title;\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "model-view-controller/src/test/java/com/iluwatar/model/view/controller/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.controller;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.controller;\n\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport org.junit.jupiter.api.Test;\n\n/** GiantControllerTest */\nclass GiantControllerTest {\n\n  /** Verify if the controller passes the health level through to the model and vice versa */\n  @Test\n  void testSetHealth() {\n    final var model = mock(GiantModel.class);\n    final var view = mock(GiantView.class);\n    final var controller = new GiantController(model, view);\n\n    verifyNoMoreInteractions(model, view);\n\n    for (final var health : Health.values()) {\n      controller.setHealth(health);\n      verify(model).setHealth(health);\n      verifyNoMoreInteractions(view);\n    }\n\n    controller.getHealth();\n    //noinspection ResultOfMethodCallIgnored\n    verify(model).getHealth();\n\n    verifyNoMoreInteractions(model, view);\n  }\n\n  /** Verify if the controller passes the fatigue level through to the model and vice versa */\n  @Test\n  void testSetFatigue() {\n    final var model = mock(GiantModel.class);\n    final var view = mock(GiantView.class);\n    final var controller = new GiantController(model, view);\n\n    verifyNoMoreInteractions(model, view);\n\n    for (final var fatigue : Fatigue.values()) {\n      controller.setFatigue(fatigue);\n      verify(model).setFatigue(fatigue);\n      verifyNoMoreInteractions(view);\n    }\n\n    controller.getFatigue();\n    //noinspection ResultOfMethodCallIgnored\n    verify(model).getFatigue();\n\n    verifyNoMoreInteractions(model, view);\n  }\n\n  /** Verify if the controller passes the nourishment level through to the model and vice versa */\n  @Test\n  void testSetNourishment() {\n    final var model = mock(GiantModel.class);\n    final var view = mock(GiantView.class);\n    final var controller = new GiantController(model, view);\n\n    verifyNoMoreInteractions(model, view);\n\n    for (final var nourishment : Nourishment.values()) {\n      controller.setNourishment(nourishment);\n      verify(model).setNourishment(nourishment);\n      verifyNoMoreInteractions(view);\n    }\n\n    controller.getNourishment();\n    //noinspection ResultOfMethodCallIgnored\n    verify(model).getNourishment();\n\n    verifyNoMoreInteractions(model, view);\n  }\n\n  @Test\n  void testUpdateView() {\n    final var model = mock(GiantModel.class);\n    final var view = mock(GiantView.class);\n    final var controller = new GiantController(model, view);\n\n    verifyNoMoreInteractions(model, view);\n\n    controller.updateView();\n    verify(view).displayGiant(model);\n\n    verifyNoMoreInteractions(model, view);\n  }\n}\n"
  },
  {
    "path": "model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantModelTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.controller;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** GiantModelTest */\nclass GiantModelTest {\n\n  /** Verify if the health value is set properly though the constructor and setter */\n  @Test\n  void testSetHealth() {\n    final var model = new GiantModel(Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    assertEquals(Health.HEALTHY, model.getHealth());\n    var messageFormat = \"The giant looks %s, alert and saturated.\";\n    for (final var health : Health.values()) {\n      model.setHealth(health);\n      assertEquals(health, model.getHealth());\n      assertEquals(String.format(messageFormat, health), model.toString());\n    }\n  }\n\n  /** Verify if the fatigue level is set properly though the constructor and setter */\n  @Test\n  void testSetFatigue() {\n    final var model = new GiantModel(Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    assertEquals(Fatigue.ALERT, model.getFatigue());\n    var messageFormat = \"The giant looks healthy, %s and saturated.\";\n    for (final var fatigue : Fatigue.values()) {\n      model.setFatigue(fatigue);\n      assertEquals(fatigue, model.getFatigue());\n      assertEquals(String.format(messageFormat, fatigue), model.toString());\n    }\n  }\n\n  /** Verify if the nourishment level is set properly though the constructor and setter */\n  @Test\n  void testSetNourishment() {\n    final var model = new GiantModel(Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    assertEquals(Nourishment.SATURATED, model.getNourishment());\n    var messageFormat = \"The giant looks healthy, alert and %s.\";\n    for (final var nourishment : Nourishment.values()) {\n      model.setNourishment(nourishment);\n      assertEquals(nourishment, model.getNourishment());\n      assertEquals(String.format(messageFormat, nourishment), model.toString());\n    }\n  }\n}\n"
  },
  {
    "path": "model-view-controller/src/test/java/com/iluwatar/model/view/controller/GiantViewTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.controller;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.mock;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/** GiantViewTest */\nclass GiantViewTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(GiantView.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /**\n   * Verify if the {@link GiantView} does what it has to do: Print the {@link GiantModel} to the\n   * standard out stream, nothing more, nothing less.\n   */\n  @Test\n  void testDisplayGiant() {\n    final var view = new GiantView();\n\n    final var model = mock(GiantModel.class);\n    view.displayGiant(model);\n\n    assertEquals(model.toString(), appender.getLastMessage());\n    assertEquals(1, appender.getLogSize());\n  }\n\n  /** Logging Appender Implementation */\n  public static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender(Class<?> clazz) {\n      ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public String getLastMessage() {\n      return log.get(log.size() - 1).getMessage();\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n  }\n}\n"
  },
  {
    "path": "model-view-intent/README.md",
    "content": "---\ntitle: \"Model-View-Intent Pattern in Java: Building Robust and Scalable Java UIs with MVI\"\nshortTitle: Model-View-Intent (MVI)\ndescription: \"Discover the Model-View-Intent (MVI) pattern for Java applications. Learn how MVI enhances UI predictability, maintainability, and state management through unidirectional data flow. Explore real-world examples and implementation details.\"\ncategory: Architectural\nlanguage: en\ntags:\n  - Abstraction\n  - Decoupling\n  - Presentation\n  - Reactive\n  - State tracking\n---\n\n## Also known as\n\n* MVI\n\n## Intent of Model-View-Intent Design Pattern\n\nThe Model-View-Intent (MVI) pattern for Java applications creates a unidirectional and cyclical data flow between the Model, View, and Intent components, enhancing UI predictability and state management.\n\n## Detailed Explanation of Model-View-Intent Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a real-world analogy of the Model-View-Intent (MVI) pattern in Java using the scenario of ordering at a fast-food restaurant to understand its application in enhancing UI state management.\n>\n> In this analogy:\n> - **Model:** It's like the kitchen of the restaurant, where the current state of your order is managed. As you choose items, the kitchen updates the order status and ingredients used.\n> - **View:** This represents the menu and the digital display board where you see your current order summary. It reflects the current state of your order, showing what items you've added or removed.\n> - **Intent:** Think of this as your decision-making process when you interact with the menu. Each choice you make (like adding a burger or removing a drink) sends a specific intention to the system (kitchen).\n>\n> When you decide to add an item to your order (Intent), the kitchen (Model) processes this request, updates the state of your order, and then the display (View) updates to show the latest status of your order. This cycle continues until you finalize your order, demonstrating the unidirectional and cyclical flow characteristic of MVI. This ensures that every change in the order is predictably and accurately reflected in the customer's view, similar to how UI components update in response to state changes in software using MVI.\n\nIn plain words\n\n> The Model-View-Intent (MVI) pattern is a reactive architectural approach where user actions (Intent) modify the application state (Model), and the updated state is then reflected back in the user interface (View) in a unidirectional and cyclical data flow.\n\nArchitecture diagram\n\n![Model-View-Intent Architecture Diagram](./etc/mvi-architecture-diagram.png)\n\n\n## Programmatic Example of Model-View-Intent Pattern in Java\n\nThe Model-View-Intent (MVI) pattern for Java is a modern approach to structuring your application's logic, ensuring a smooth, unidirectional flow of data and events. It's a variation of the Model-View-Presenter (MVP) and Model-View-ViewModel (MVVM) patterns, but with a more streamlined flow of data and events.\n\nIn MVI, the View sends user events to the Intent. The Intent translates these events into a state change in the Model. The Model then pushes this new state to the View, which updates itself accordingly. This creates a unidirectional data flow, which can make your code easier to understand and debug.\n\nFirst, we have the `App` class, which serves as the entry point for the application. It creates the View and ViewModel, and then simulates a series of user interactions with the calculator.\n\n```java\npublic final class App {\n  private static final double RANDOM_VARIABLE = 10.0;\n\n  public static void main(final String[] args) {\n    var view = new CalculatorView(new CalculatorViewModel());\n    var variable1 = RANDOM_VARIABLE;\n\n    view.setVariable(variable1);\n    view.add();\n    view.displayTotal();\n\n    variable1 = 2.0;\n    view.setVariable(variable1);\n    view.subtract();\n    view.divide();\n    view.multiply();\n    view.displayTotal();\n  }\n\n  private App() {\n  }\n}\n```\n\nThe `CalculatorView` class represents the View in MVI. It receives user events (in this case, simulated by the `App` class), and sends them to the ViewModel. It also updates its display when it receives a new state from the ViewModel.\n\n```java\npublic class CalculatorView {\n  private CalculatorViewModel viewModel;\n\n  public CalculatorView(CalculatorViewModel viewModel) {\n    this.viewModel = viewModel;\n  }\n\n  public void setVariable(double variable) {\n    viewModel.process(new SetVariableEvent(variable));\n  }\n\n  public void add() {\n    viewModel.process(new AddEvent());\n  }\n\n  public void subtract() {\n    viewModel.process(new SubtractEvent());\n  }\n\n  public void divide() {\n    viewModel.process(new DivideEvent());\n  }\n\n  public void multiply() {\n    viewModel.process(new MultiplyEvent());\n  }\n\n  public void displayTotal() {\n    System.out.println(\"Total: \" + viewModel.getState().getTotal());\n  }\n}\n```\n\nThe `CalculatorViewModel` class represents the ViewModel in MVI. It receives events from the View, updates the Model's state accordingly, and then pushes the new state to the View.\n\n```java\npublic class CalculatorViewModel {\n  private CalculatorModel model;\n\n  public CalculatorViewModel() {\n    this.model = new CalculatorModel();\n  }\n\n  public void process(UserEvent event) {\n    event.apply(model);\n  }\n\n  public CalculatorModel getState() {\n    return model;\n  }\n}\n```\n\nThe `CalculatorModel` class represents the Model in MVI. It holds the current state of the calculator, and provides methods for updating that state.\n\n```java\npublic class CalculatorModel {\n  private double total;\n  private double variable;\n\n  public void setVariable(double variable) {\n    this.variable = variable;\n  }\n\n  public void add() {\n    total += variable;\n  }\n\n  public void subtract() {\n    total -= variable;\n  }\n\n  public void divide() {\n    total /= variable;\n  }\n\n  public void multiply() {\n    total *= variable;\n  }\n\n  public double getTotal() {\n    return total;\n  }\n}\n```\n\nFinally, the `UserEvent` interface and its implementations represent the different types of user events that can occur. Each event knows how to apply itself to the Model.\n\n```java\npublic interface UserEvent {\n  void apply(CalculatorModel model);\n}\n\npublic class SetVariableEvent implements UserEvent {\n  private double variable;\n\n  public SetVariableEvent(double variable) {\n    this.variable = variable;\n  }\n\n  @Override\n  public void apply(CalculatorModel model) {\n    model.setVariable(variable);\n  }\n}\n\n// Similar classes would be created for AddEvent, SubtractEvent, DivideEvent, and MultiplyEvent ...\n```\n\nThis example demonstrates the key aspects of the MVI pattern: unidirectional data flow, clear separation of concerns, and the use of events to drive changes in the Model's state.\n\n## When to Use the Model-View-Intent Pattern in Java\n\n* The MVI pattern is useful in Java applications with complex user interfaces that require a clear separation of concerns, predictable state management, and enhanced maintainability.\n* Often applied in reactive programming environments to ensure a smooth data flow and state consistency.\n\n## Model-View-Intent Pattern Java Tutorials\n\n* [Model View Intent: a new Android Architecture Pattern (Apium Academy)](https://apiumacademy.com/blog/model-view-intent-pattern/)\n* [MVI Architecture for Android Tutorial: Getting Started (Kodeco)](https://www.kodeco.com/817602-mvi-architecture-for-android-tutorial-getting-started)\n\n## Real-World Applications of Model-View-Intent Pattern in Java\n\n* Widely adopted in reactive and event-driven Java applications, particularly those using frameworks like RxJava or Project Reactor.\n* Used in Android development, especially with libraries that support reactive programming such as RxJava and LiveData.\n\n## Benefits and Trade-offs of Model-View-Intent Pattern\n\nBenefits:\n\n* Enhances the predictability of the UI by establishing a clear and cyclical data flow.\n* Improves testability due to well-defined separation between components.\n* Supports better state management by centralizing the state within the Model.\n\nTrade-offs:\n\n* Increases complexity for simple UIs due to the structured and cyclical flow.\n* Requires familiarity with reactive programming paradigms.\n* Can lead to boilerplate code if not managed properly.\n\n## Related Java Design Patterns\n\n[Model-View-ViewModel (MVVM)](https://java-design-patterns.com/patterns/model-view-viewmodel/): Shares a similar goal of separating the view from the model but differs as MVI introduces a cyclical data flow.\n[Model-View-Controller (MVC)](https://java-design-patterns.com/patterns/model-view-controller/): MVI can be seen as an evolution of MVC, focusing more on reactive programming and unidirectional data flow.\n[Observer](https://java-design-patterns.com/patterns/observer/): Essential in MVI to observe changes in the Model and update the View accordingly.\n\n## References and Credits\n\n* [Functional and Reactive Domain Modeling](https://amzn.to/4adghJ8)\n* [Reactive Programming with RxJava: Creating Asynchronous, Event-Based Applications](https://amzn.to/4dxwawC)\n"
  },
  {
    "path": "model-view-intent/etc/model-view-intent.urm.puml",
    "content": "@startuml\npackage com.iluwatar.model.view.intent.actions {\n  class AdditionCalculatorAction {\n    + TAG : String {static}\n    + AdditionCalculatorAction()\n    + tag() : String\n  }\n  interface CalculatorAction {\n    + tag() : String {abstract}\n  }\n  class DivisionCalculatorAction {\n    + TAG : String {static}\n    + DivisionCalculatorAction()\n    + tag() : String\n  }\n  class MultiplicationCalculatorAction {\n    + TAG : String {static}\n    + MultiplicationCalculatorAction()\n    + tag() : String\n  }\n  class SetVariableCalculatorAction {\n    + TAG : String {static}\n    + variable : Double\n    + SetVariableCalculatorAction(variable : Double)\n    + tag() : String\n  }\n  class SubtractionCalculatorAction {\n    + TAG : String {static}\n    + SubtractionCalculatorAction()\n    + tag() : String\n  }\n}\npackage com.iluwatar.model.view.intent {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class CalculatorModel {\n    + output : Double\n    + variable : Double\n    + CalculatorModel(output : Double, variable : Double)\n    + copy(output : Double, variable : Double) : CalculatorModel\n  }\n  class CalculatorView {\n    - LOGGER : Logger {static}\n    ~ viewModel : CalculatorViewModel\n    + CalculatorView()\n    ~ add()\n    ~ displayTotal()\n    ~ divide()\n    ~ multiply()\n    ~ setVariable(value : Double)\n    ~ subtract()\n  }\n  class CalculatorViewModel {\n    - model : CalculatorModel\n    + CalculatorViewModel()\n    - add()\n    - divide()\n    + getCalculatorModel() : CalculatorModel\n    ~ handleAction(action : CalculatorAction)\n    - multiply()\n    - setVariable(variable : Double)\n    - subtract()\n  }\n}\nCalculatorView -->  \"-viewModel\" CalculatorViewModel\nCalculatorViewModel -->  \"-model\" CalculatorModel\nAdditionCalculatorAction ..|> CalculatorAction \nDivisionCalculatorAction ..|> CalculatorAction \nMultiplicationCalculatorAction ..|> CalculatorAction \nSetVariableCalculatorAction ..|> CalculatorAction \nSubtractionCalculatorAction ..|> CalculatorAction \n@enduml"
  },
  {
    "path": "model-view-intent/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>model-view-intent</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.model.view.controller.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "model-view-intent/src/main/java/com/iluwatar/model/view/intent/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.intent;\n\n/**\n * Model-View-Intent is a pattern for implementing user interfaces. Its main advantage over MVVM\n * which it closely mirrors is a minimal public api with which user events can be exposed to the\n * ViewModel. In case of the MVI every event is exposed by using a single method with 1 argument\n * which implements UserEvent interface. Specific parameters can be expressed as its parameters. In\n * this case, we'll be using MVI to implement a simple calculator with +, -, /, * operations and the\n * ability to set the variable. It's important to note, that every user action happens through the\n * view, we never interact with the ViewModel directly.\n */\npublic final class App {\n\n  /** To avoid magic value lint error. */\n  private static final double RANDOM_VARIABLE = 10.0;\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(final String[] args) {\n    // create model, view and controller\n\n    // initialize calculator view, output and variable = 0\n    var view = new CalculatorView(new CalculatorViewModel());\n    var variable1 = RANDOM_VARIABLE;\n\n    // calculator variable = RANDOM_VARIABLE -> 10.0\n    view.setVariable(variable1);\n\n    // add calculator variable to output -> calculator output = 10.0\n    view.add();\n    view.displayTotal(); // display output\n\n    variable1 = 2.0;\n    view.setVariable(variable1); // calculator variable = 2.0\n\n    // subtract calculator variable from output -> calculator output = 8\n    view.subtract();\n\n    // divide calculator output by variable -> calculator output = 4.0\n    view.divide();\n\n    // multiply calculator output by variable -> calculator output = 8.0\n    view.multiply();\n    view.displayTotal();\n  }\n\n  /** Avoid default constructor lint error. */\n  private App() {}\n}\n"
  },
  {
    "path": "model-view-intent/src/main/java/com/iluwatar/model/view/intent/CalculatorModel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.intent;\n\nimport lombok.Data;\nimport lombok.Getter;\n\n/** Current state of calculator. */\n@Data\npublic class CalculatorModel {\n\n  /** Current calculator variable used for operations. */\n  @Getter private final Double variable;\n\n  /** Current calculator output -> is affected by operations. */\n  @Getter private final Double output;\n}\n"
  },
  {
    "path": "model-view-intent/src/main/java/com/iluwatar/model/view/intent/CalculatorView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.intent;\n\nimport com.iluwatar.model.view.intent.actions.AdditionCalculatorAction;\nimport com.iluwatar.model.view.intent.actions.DivisionCalculatorAction;\nimport com.iluwatar.model.view.intent.actions.MultiplicationCalculatorAction;\nimport com.iluwatar.model.view.intent.actions.SetVariableCalculatorAction;\nimport com.iluwatar.model.view.intent.actions.SubtractionCalculatorAction;\nimport lombok.Data;\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Exposes changes to the state of calculator to {@link CalculatorViewModel} through {@link\n * com.iluwatar.model.view.intent.actions.CalculatorAction} and displays its updated {@link\n * CalculatorModel}.\n */\n@Slf4j\n@Data\npublic class CalculatorView {\n\n  /** View model param handling the operations. */\n  @Getter private final CalculatorViewModel viewModel;\n\n  /** Display current view model output with logger. */\n  void displayTotal() {\n    LOGGER.info(\"Total value = {}\", viewModel.getCalculatorModel().getOutput().toString());\n  }\n\n  /** Handle addition action. */\n  void add() {\n    viewModel.handleAction(new AdditionCalculatorAction());\n  }\n\n  /** Handle subtraction action. */\n  void subtract() {\n    viewModel.handleAction(new SubtractionCalculatorAction());\n  }\n\n  /** Handle multiplication action. */\n  void multiply() {\n    viewModel.handleAction(new MultiplicationCalculatorAction());\n  }\n\n  /** Handle division action. */\n  void divide() {\n    viewModel.handleAction(new DivisionCalculatorAction());\n  }\n\n  /**\n   * Handle setting new variable action.\n   *\n   * @param value -> new calculator variable.\n   */\n  void setVariable(final Double value) {\n    viewModel.handleAction(new SetVariableCalculatorAction(value));\n  }\n}\n"
  },
  {
    "path": "model-view-intent/src/main/java/com/iluwatar/model/view/intent/CalculatorViewModel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.intent;\n\nimport com.iluwatar.model.view.intent.actions.AdditionCalculatorAction;\nimport com.iluwatar.model.view.intent.actions.CalculatorAction;\nimport com.iluwatar.model.view.intent.actions.DivisionCalculatorAction;\nimport com.iluwatar.model.view.intent.actions.MultiplicationCalculatorAction;\nimport com.iluwatar.model.view.intent.actions.SetVariableCalculatorAction;\nimport com.iluwatar.model.view.intent.actions.SubtractionCalculatorAction;\n\n/**\n * Handle transformations to {@link CalculatorModel} based on intercepted {@link CalculatorAction}.\n */\npublic final class CalculatorViewModel {\n\n  /** Current calculator model (can be changed). */\n  private CalculatorModel model = new CalculatorModel(0.0, 0.0);\n\n  /**\n   * Handle calculator action.\n   *\n   * @param action -> transforms calculator model.\n   */\n  void handleAction(final CalculatorAction action) {\n    switch (action.tag()) {\n      case AdditionCalculatorAction.ADDITION -> add();\n      case SubtractionCalculatorAction.SUBTRACTION -> subtract();\n      case MultiplicationCalculatorAction.MULTIPLICATION -> multiply();\n      case DivisionCalculatorAction.DIVISION -> divide();\n      case SetVariableCalculatorAction.SET_VARIABLE -> {\n        SetVariableCalculatorAction setVariableAction = (SetVariableCalculatorAction) action;\n        setVariable(setVariableAction.getVariable());\n      }\n      default -> throw new IllegalArgumentException(\"Unknown tag\");\n    }\n  }\n\n  /**\n   * Getter.\n   *\n   * @return current calculator model.\n   */\n  public CalculatorModel getCalculatorModel() {\n    return model;\n  }\n\n  /**\n   * Set new calculator model variable.\n   *\n   * @param variable -> value of new calculator model variable.\n   */\n  private void setVariable(final Double variable) {\n    model = new CalculatorModel(variable, model.getOutput());\n  }\n\n  /** Add variable to model output. */\n  private void add() {\n    model = new CalculatorModel(model.getVariable(), model.getOutput() + model.getVariable());\n  }\n\n  /** Subtract variable from model output. */\n  private void subtract() {\n    model = new CalculatorModel(model.getVariable(), model.getOutput() - model.getVariable());\n  }\n\n  /** Multiply model output by variable. */\n  private void multiply() {\n    model = new CalculatorModel(model.getVariable(), model.getOutput() * model.getVariable());\n  }\n\n  /** Divide model output by variable. */\n  private void divide() {\n    model = new CalculatorModel(model.getVariable(), model.getOutput() / model.getVariable());\n  }\n}\n"
  },
  {
    "path": "model-view-intent/src/main/java/com/iluwatar/model/view/intent/actions/AdditionCalculatorAction.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.intent.actions;\n\n/** Addition {@link CalculatorAction}. */\npublic class AdditionCalculatorAction implements CalculatorAction {\n  /** Subclass tag. */\n  public static final String ADDITION = \"ADDITION\";\n\n  /** Makes checking subclass type trivial. */\n  @Override\n  public String tag() {\n    return ADDITION;\n  }\n}\n"
  },
  {
    "path": "model-view-intent/src/main/java/com/iluwatar/model/view/intent/actions/CalculatorAction.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.intent.actions;\n\n/** Defines what outside interactions can be consumed by view model. */\npublic interface CalculatorAction {\n\n  /**\n   * Makes identifying action trivial.\n   *\n   * @return subclass tag.\n   */\n  String tag();\n}\n"
  },
  {
    "path": "model-view-intent/src/main/java/com/iluwatar/model/view/intent/actions/DivisionCalculatorAction.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.intent.actions;\n\n/** Division {@link CalculatorAction}. */\npublic class DivisionCalculatorAction implements CalculatorAction {\n  /** Subclass tag. */\n  public static final String DIVISION = \"DIVISION\";\n\n  /** Makes checking subclass type trivial. */\n  @Override\n  public String tag() {\n    return DIVISION;\n  }\n}\n"
  },
  {
    "path": "model-view-intent/src/main/java/com/iluwatar/model/view/intent/actions/MultiplicationCalculatorAction.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.intent.actions;\n\n/** Multiplication {@link CalculatorAction}. */\npublic class MultiplicationCalculatorAction implements CalculatorAction {\n  /** Subclass tag. */\n  public static final String MULTIPLICATION = \"MULTIPLICATION\";\n\n  /** Makes checking subclass type trivial. */\n  @Override\n  public String tag() {\n    return MULTIPLICATION;\n  }\n}\n"
  },
  {
    "path": "model-view-intent/src/main/java/com/iluwatar/model/view/intent/actions/SetVariableCalculatorAction.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.intent.actions;\n\nimport lombok.Data;\nimport lombok.Getter;\n\n/** SetVariable {@link CalculatorAction}. */\n@Data\npublic final class SetVariableCalculatorAction implements CalculatorAction {\n\n  /** Subclass tag. */\n  public static final String SET_VARIABLE = \"SET_VARIABLE\";\n\n  /** Used by {@link com.iluwatar.model.view.intent.CalculatorViewModel}. */\n  @Getter private final Double variable;\n\n  /** Makes checking subclass type trivial. */\n  @Override\n  public String tag() {\n    return SET_VARIABLE;\n  }\n}\n"
  },
  {
    "path": "model-view-intent/src/main/java/com/iluwatar/model/view/intent/actions/SubtractionCalculatorAction.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.intent.actions;\n\n/** Subtraction {@link CalculatorAction}. */\npublic class SubtractionCalculatorAction implements CalculatorAction {\n  /** Subclass tag. */\n  public static final String SUBTRACTION = \"SUBTRACTION\";\n\n  /** Makes checking subclass type trivial. */\n  @Override\n  public String tag() {\n    return SUBTRACTION;\n  }\n}\n"
  },
  {
    "path": "model-view-intent/src/main/java/com/iluwatar/model/view/intent/actions/package-info.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/**\n * Handle actions for {@link com.iluwatar.model.view.intent.CalculatorModel} defined by {@link\n * com.iluwatar.model.view.intent.actions.CalculatorAction}.\n */\npackage com.iluwatar.model.view.intent.actions;\n"
  },
  {
    "path": "model-view-intent/src/main/java/com/iluwatar/model/view/intent/package-info.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/** Define Model, View and ViewModel. Use them in {@link com.iluwatar.model.view.intent.App} */\npackage com.iluwatar.model.view.intent;\n"
  },
  {
    "path": "model-view-intent/src/test/java/com/iluwatar/model/view/intent/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.intent;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "model-view-intent/src/test/java/com/iluwatar/model/view/intent/CalculatorViewModelTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.intent;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.model.view.intent.actions.*;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\n\nclass CalculatorViewModelTest {\n\n  private CalculatorModel modelAfterExecutingActions(List<CalculatorAction> actions) {\n    CalculatorViewModel viewModel = new CalculatorViewModel();\n    for (CalculatorAction action : actions) {\n      viewModel.handleAction(action);\n    }\n    return viewModel.getCalculatorModel();\n  }\n\n  @Test\n  void testSetup() {\n    CalculatorModel model = modelAfterExecutingActions(new ArrayList<>());\n    assertEquals(0, model.getVariable());\n    assertEquals(0, model.getOutput());\n  }\n\n  @Test\n  void testSetVariable() {\n    List<CalculatorAction> actions = List.of(new SetVariableCalculatorAction(10.0));\n    CalculatorModel model = modelAfterExecutingActions(actions);\n    assertEquals(10.0, model.getVariable());\n    assertEquals(0, model.getOutput());\n  }\n\n  @Test\n  void testAddition() {\n    List<CalculatorAction> actions =\n        List.of(\n            new SetVariableCalculatorAction(2.0),\n            new AdditionCalculatorAction(),\n            new AdditionCalculatorAction(),\n            new SetVariableCalculatorAction(7.0),\n            new AdditionCalculatorAction());\n    CalculatorModel model = modelAfterExecutingActions(actions);\n    assertEquals(7.0, model.getVariable());\n    assertEquals(11.0, model.getOutput());\n  }\n\n  @Test\n  void testSubtraction() {\n    List<CalculatorAction> actions =\n        List.of(\n            new SetVariableCalculatorAction(2.0),\n            new AdditionCalculatorAction(),\n            new AdditionCalculatorAction(),\n            new SubtractionCalculatorAction());\n    CalculatorModel model = modelAfterExecutingActions(actions);\n    assertEquals(2.0, model.getVariable());\n    assertEquals(2.0, model.getOutput());\n  }\n\n  @Test\n  void testMultiplication() {\n    List<CalculatorAction> actions =\n        List.of(\n            new SetVariableCalculatorAction(2.0),\n            new AdditionCalculatorAction(),\n            new AdditionCalculatorAction(),\n            new MultiplicationCalculatorAction());\n    CalculatorModel model = modelAfterExecutingActions(actions);\n    assertEquals(2.0, model.getVariable());\n    assertEquals(8.0, model.getOutput());\n  }\n\n  @Test\n  void testDivision() {\n    List<CalculatorAction> actions =\n        List.of(\n            new SetVariableCalculatorAction(2.0),\n            new AdditionCalculatorAction(),\n            new AdditionCalculatorAction(),\n            new SetVariableCalculatorAction(2.0),\n            new DivisionCalculatorAction());\n    CalculatorModel model = modelAfterExecutingActions(actions);\n    assertEquals(2.0, model.getVariable());\n    assertEquals(2.0, model.getOutput());\n  }\n}\n"
  },
  {
    "path": "model-view-presenter/README.md",
    "content": "---\ntitle: \"Model-View-Presenter Pattern in Java: Enhancing UI Logic Separation for Cleaner Code\"\nshortTitle: Model-View-Presenter (MVP)\ndescription: \"Discover the Model-View-Presenter (MVP) pattern in Java. Learn how it separates user interface, business logic, and data interaction to enhance testability and maintainability.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - Architecture\n  - Client-server\n  - Decoupling\n  - Enterprise patterns\n  - Interface\n  - Presentation\n---\n\n## Also known as\n\n* MVP\n\n## Intent of Model-View-Presenter Design Pattern\n\nMVP aims to separate the user interface (UI) logic from the business logic and model in a software application, enabling easier testing and maintenance.\n\n## Detailed Explanation of Model-View-Presenter Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a real-world analogy of the Model-View-Presenter (MVP) pattern using a restaurant scenario:\n>\n> - **Model:** This is the kitchen in a restaurant, where all the cooking and preparation of dishes happens. It's responsible for managing the food ingredients, cooking processes, and ensuring that recipes are followed correctly.\n>\n> - **View:** This represents the dining area and the menu presented to the customers. It displays the available dishes, takes orders, and shows the final presentation of the food. However, it doesn't decide what's cooked or how it's prepared.\n>\n> - **Presenter:** Acting as the waiter, the presenter takes the customer's order (input) and communicates it to the kitchen (model). The waiter then brings the prepared food (output) back to the customer in the dining area (view). The waiter ensures that what the customer sees (the menu and food presentation) aligns with what the kitchen can provide, and also updates the view based on the kitchen's capabilities (e.g., out-of-stock items).\n>\n> In this analogy, the clear separation of roles allows the restaurant to operate efficiently: the kitchen focuses on food preparation, the dining area on customer interaction, and the waiter bridges the two, ensuring smooth operation and customer satisfaction.\n\nIn plain words\n\n> The Model-View-Presenter (MVP) pattern separates the user interface, business logic, and data interaction in an application, with the presenter mediating between the view and the model to facilitate clear communication and updates. Java developers use MVP to improve application structure.\n\nWikipedia says\n\n> Model–view–presenter (MVP) is a derivation of the model–view–controller (MVC) architectural pattern, and is used mostly for building user interfaces. In MVP, the presenter assumes the functionality of the \"middle-man\". In MVP, all presentation logic is pushed to the presenter.\n\nArchitecture diagram\n\n![Model-View-Presenter Architecture Diagram](./etc/mvp-architecture-diagram.png)\n\n\n## Programmatic Example of Model-View-Presenter Pattern in Java\n\nThe Model-View-Presenter (MVP) design pattern is a derivative of the well-known Model-View-Controller (MVC) pattern. It aims to separate the application's logic (Model), GUIs (View), and the way that the user's actions update the application's logic (Presenter). This separation of concerns makes the application easier to manage, extend, and test.\n\nLet's break down the MVP pattern using the provided code:\n\n1. **Model**: The Model represents the application's logic. In our case, the `FileLoader` class is the Model. It's responsible for handling the file loading process.\n\n```java\n@Getter\npublic class FileLoader implements Serializable {\n  //...\n  public void setFileName(String fileName) {\n    this.fileName = fileName;\n  }\n  \n  public boolean fileExists() {\n    //...\n  }\n\n  public String loadData() {\n    //...\n  }\n}\n```\n\n2. **View**: The View is responsible for displaying the data provided by the Model. Here, the `FileSelectorView` interface and its implementation `FileSelectorJFrame` represent the View. They define how to display data and messages to the user.\n\n```java\npublic interface FileSelectorView {\n  //...\n  void setPresenter(FileSelectorPresenter presenter);\n  void open();\n  void close();\n  void showMessage(String message);\n  void displayData(String data);\n  String getFileName();\n}\n\npublic class FileSelectorJFrame implements FileSelectorView {\n  //...\n  @Override\n  public void displayData(String data) {\n    this.dataDisplayed = true;\n  }\n}\n```\n\n3. **Presenter**: The Presenter acts as a bridge between the Model and the View. It reacts to the user's actions and updates the View accordingly. In our example, the `FileSelectorPresenter` class is the Presenter.\n\n```java\npublic class FileSelectorPresenter implements Serializable {\n  //...\n  public void setLoader(FileLoader loader) {\n    this.loader = loader;\n  }\n\n  public void start() {\n    view.setPresenter(this);\n    view.open();\n  }\n\n  public void fileNameChanged() {\n    loader.setFileName(view.getFileName());\n  }\n\n  public void confirmed() {\n    //...\n  }\n\n  public void cancelled() {\n    view.close();\n  }\n}\n```\n\nFinally, we wire up the Presenter, the View, and the Model in the `App` class:\n\n```java\npublic class App {\n  public static void main(String[] args) {\n    var loader = new FileLoader();\n    var frame = new FileSelectorJFrame();\n    var presenter = new FileSelectorPresenter(frame);\n    presenter.setLoader(loader);\n    presenter.start();\n  }\n}\n```\n\nIn this setup, the `App` class creates instances of the Model, View, and Presenter. It then connects these instances, forming the MVP triad. The Presenter is given a reference to the View, and the Model is set on the Presenter. Finally, the Presenter is started, which in turn opens the View.\n\n## When to Use the Model-View-Presenter Pattern in Java\n\nUse MVP in applications where a clear [separation of concerns](https://java-design-patterns.com/principles/#separation-of-concerns) is needed between the presentation layer and the underlying business logic. It's particularly useful in client-server applications and enterprise-level applications.\n\n## Real-World Applications of Model-View-Presenter Pattern in Java\n\n* Desktop applications like those built using Java Swing or JavaFX.\n* Web applications with complex user interfaces and business logic.\n\n## Benefits and Trade-offs of Model-View-Presenter Pattern\n\nBenefits:\n\n* Enhances testability of UI logic by allowing the presenter to be tested separately from the view.\n* Promotes a clean separation of concerns, making the application easier to manage and extend.\n* Facilitates easier UI updates without affecting the business logic.\n\nTrade-offs:\n\n* Increases complexity with more classes and interfaces.\n* Requires careful design to avoid over-coupling between the presenter and the view.\n\n## Related Java Design Patterns\n\n* [Model-View-Controller (MVC)](https://java-design-patterns.com/patterns/model-view-controller/): MVP is often considered a variant of MVC where the presenter takes over the controller's role in managing user input and updating the model.\n* [Model-View-ViewModel (MVVM)](https://java-design-patterns.com/patterns/model-view-viewmodel/): Similar to MVP but adapted for frameworks like WPF or frameworks that support data binding, making the view update automatically when the model changes.\n\n## References and Credits\n\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Pro JavaFX 8: A Definitive Guide to Building Desktop, Mobile, and Embedded Java Clients](https://amzn.to/4a8qcQ1)\n"
  },
  {
    "path": "model-view-presenter/etc/data/test.txt",
    "content": "====\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n====\n\nTest line 1\nTest line 2"
  },
  {
    "path": "model-view-presenter/etc/model-view-presenter.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.model.view.presenter.FileSelectorJframe\" \n    project=\"model-view-presenter\" \n    file=\"/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJframe.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"430\" width=\"259\" x=\"33\" y=\"149\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.model.view.presenter.FileSelectorStub\" project=\"model-view-presenter\" \n    file=\"/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorStub.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"358\" width=\"259\" x=\"332\" y=\"149\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.model.view.presenter.FileSelectorPresenter\" \n    project=\"model-view-presenter\" \n    file=\"/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"178\" width=\"256\" x=\"73\" y=\"619\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"4\" language=\"java\" name=\"com.iluwatar.model.view.presenter.FileSelectorView\" \n    project=\"model-view-presenter\" \n    file=\"/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorView.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"232\" width=\"259\" x=\"73\" y=\"837\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.model.view.presenter.FileLoader\" project=\"model-view-presenter\" \n    file=\"/model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"214\" width=\"194\" x=\"372\" y=\"837\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"6\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"7\" name=\"loader\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"8\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"9\">    \n    <bendpoint x=\"42\" y=\"619\"/>    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <association id=\"10\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"11\" name=\"presenter\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"12\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"13\">    \n    <bendpoint x=\"359\" y=\"619\"/>    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <association id=\"14\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"15\" name=\"view\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"16\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"17\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"18\" name=\"presenter\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"19\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "model-view-presenter/etc/model-view-presenter.urm.puml",
    "content": "@startuml\npackage com.iluwatar.model.view.presenter {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class FileLoader {\n    - LOGGER : Logger {static}\n    - fileName : String\n    - loaded : boolean\n    - serialVersionUID : long {static}\n    + FileLoader()\n    + fileExists() : boolean\n    + getFileName() : String\n    + isLoaded() : boolean\n    + loadData() : String\n    + setFileName(fileName : String)\n  }\n  class FileSelectorJframe {\n    - area : JTextArea\n    - cancel : JButton\n    - contents : JLabel\n    - fileName : String\n    - info : JLabel\n    - input : JTextField\n    - ok : JButton\n    - panel : JPanel\n    - presenter : FileSelectorPresenter\n    - serialVersionUID : long {static}\n    + FileSelectorJframe()\n    + actionPerformed(e : ActionEvent)\n    + close()\n    + displayData(data : String)\n    + getFileName() : String\n    + getPresenter() : FileSelectorPresenter\n    + isOpened() : boolean\n    + open()\n    + setFileName(name : String)\n    + setPresenter(presenter : FileSelectorPresenter)\n    + showMessage(message : String)\n  }\n  class FileSelectorPresenter {\n    - loader : FileLoader\n    - serialVersionUID : long {static}\n    - view : FileSelectorView\n    + FileSelectorPresenter(view : FileSelectorView)\n    + cancelled()\n    + confirmed()\n    + fileNameChanged()\n    + setLoader(loader : FileLoader)\n    + start()\n  }\n  class FileSelectorStub {\n    - dataDisplayed : boolean\n    - name : String\n    - numOfMessageSent : int\n    - opened : boolean\n    - presenter : FileSelectorPresenter\n    + FileSelectorStub()\n    + close()\n    + dataDisplayed() : boolean\n    + displayData(data : String)\n    + getFileName() : String\n    + getMessagesSent() : int\n    + getPresenter() : FileSelectorPresenter\n    + isOpened() : boolean\n    + open()\n    + setFileName(name : String)\n    + setPresenter(presenter : FileSelectorPresenter)\n    + showMessage(message : String)\n  }\n  interface FileSelectorView {\n    + close() {abstract}\n    + displayData(String) {abstract}\n    + getFileName() : String {abstract}\n    + getPresenter() : FileSelectorPresenter {abstract}\n    + isOpened() : boolean {abstract}\n    + open() {abstract}\n    + setFileName(String) {abstract}\n    + setPresenter(FileSelectorPresenter) {abstract}\n    + showMessage(String) {abstract}\n  }\n}\nFileSelectorJframe -->  \"-presenter\" FileSelectorPresenter\nFileSelectorStub -->  \"-presenter\" FileSelectorPresenter\nFileSelectorPresenter -->  \"-view\" FileSelectorView\nFileSelectorPresenter -->  \"-loader\" FileLoader\nFileSelectorJframe ..|> FileSelectorView \nFileSelectorStub ..|> FileSelectorView \n@enduml"
  },
  {
    "path": "model-view-presenter/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>model-view-presenter</artifactId>\n  <name>model-view-presenter</name>\n  <url>http://maven.apache.org</url>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>net.java.dev.swing-layout</groupId>\n      <artifactId>swing-layout</artifactId>\n      <version>1.0.2</version>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.model.view.presenter.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.presenter;\n\n/**\n * The Model-View-Presenter(MVP) architectural pattern, helps us achieve what is called \"The\n * separation of concerns\" principle. This is accomplished by separating the application's logic\n * (Model), GUIs (View), and finally the way that the user's actions update the application's logic\n * (Presenter).\n *\n * <p>In the following example, The {@link FileLoader} class represents the app's logic, the {@link\n * FileSelectorJframe} is the GUI and the {@link FileSelectorPresenter} is responsible to respond to\n * users' actions.\n *\n * <p>Finally, please notice the wiring between the Presenter and the View and between the Presenter\n * and the Model.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var loader = new FileLoader();\n    var frame = new FileSelectorJframe();\n    var presenter = new FileSelectorPresenter(frame);\n    presenter.setLoader(loader);\n    presenter.start();\n  }\n}\n"
  },
  {
    "path": "model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileLoader.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.presenter;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileReader;\nimport java.io.Serial;\nimport java.io.Serializable;\nimport java.util.stream.Collectors;\nimport lombok.Getter;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Every instance of this class represents the Model component in the Model-View-Presenter\n * architectural pattern.\n *\n * <p>It is responsible for reading and loading the contents of a given file.\n */\n@Getter\npublic class FileLoader implements Serializable {\n\n  /** Generated serial version UID. */\n  @Serial private static final long serialVersionUID = -4745803872902019069L;\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(FileLoader.class);\n\n  /** Indicates if the file is loaded or not. */\n  private boolean loaded;\n\n  /** The name of the file that we want to load. */\n  private String fileName;\n\n  /** Loads the data of the file specified. */\n  public String loadData() {\n    var dataFileName = this.fileName;\n    try (var br = new BufferedReader(new FileReader(dataFileName))) {\n      var result = br.lines().collect(Collectors.joining(\"\\n\"));\n      this.loaded = true;\n      return result;\n    } catch (Exception e) {\n      LOGGER.error(\"File {} does not exist\", dataFileName);\n    }\n\n    return null;\n  }\n\n  /**\n   * Sets the path of the file to be loaded, to the given value.\n   *\n   * @param fileName The path of the file to be loaded.\n   */\n  public void setFileName(String fileName) {\n    this.fileName = fileName;\n  }\n\n  /**\n   * Returns true if the given file exists.\n   *\n   * @return True, if the file given exists, false otherwise.\n   */\n  public boolean fileExists() {\n    return new File(this.fileName).exists();\n  }\n}\n"
  },
  {
    "path": "model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorJframe.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.presenter;\n\nimport static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;\nimport static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;\n\nimport java.awt.Color;\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\nimport java.io.Serial;\nimport javax.swing.JButton;\nimport javax.swing.JFrame;\nimport javax.swing.JLabel;\nimport javax.swing.JOptionPane;\nimport javax.swing.JPanel;\nimport javax.swing.JScrollPane;\nimport javax.swing.JTextArea;\nimport javax.swing.JTextField;\n\n/**\n * This class is the GUI implementation of the View component in the Model-View-Presenter pattern.\n */\npublic class FileSelectorJframe extends JFrame implements FileSelectorView, ActionListener {\n\n  /** Default serial version ID. */\n  @Serial private static final long serialVersionUID = 1L;\n\n  /** The \"OK\" button for loading the file. */\n  private final JButton ok;\n\n  /** The cancel button. */\n  private final JButton cancel;\n\n  /** The text field for giving the name of the file that we want to open. */\n  private final JTextField input;\n\n  /** A text area that will keep the contents of the file opened. */\n  private final JTextArea area;\n\n  /** The Presenter component that the frame will interact with. */\n  private FileSelectorPresenter presenter;\n\n  /** The name of the file that we want to read it's contents. */\n  private String fileName;\n\n  /** Constructor. */\n  public FileSelectorJframe() {\n    super(\"File Loader\");\n    this.setDefaultCloseOperation(EXIT_ON_CLOSE);\n    this.setLayout(null);\n    this.setBounds(100, 100, 500, 200);\n\n    /*\n     * Add the panel.\n     */\n    var panel = new JPanel();\n    panel.setLayout(null);\n    this.add(panel);\n    panel.setBounds(0, 0, 500, 200);\n    panel.setBackground(Color.LIGHT_GRAY);\n\n    /*\n     * Add the info label.\n     */\n    var info = new JLabel(\"File Name :\");\n    panel.add(info);\n    info.setBounds(30, 10, 100, 30);\n\n    /*\n     * Add the contents label.\n     */\n    var contents = new JLabel(\"File contents :\");\n    panel.add(contents);\n    contents.setBounds(30, 100, 120, 30);\n\n    /*\n     * Add the text field.\n     */\n    this.input = new JTextField(100);\n    panel.add(input);\n    this.input.setBounds(150, 15, 200, 20);\n\n    /*\n     * Add the text area.\n     */\n    this.area = new JTextArea(100, 100);\n    var pane = new JScrollPane(area);\n    pane.setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_AS_NEEDED);\n    pane.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_AS_NEEDED);\n    panel.add(pane);\n    this.area.setEditable(false);\n    pane.setBounds(150, 100, 250, 80);\n\n    /*\n     * Add the OK button.\n     */\n    this.ok = new JButton(\"OK\");\n    panel.add(ok);\n    this.ok.setBounds(250, 50, 100, 25);\n    this.ok.addActionListener(this);\n\n    /*\n     * Add the cancel button.\n     */\n    this.cancel = new JButton(\"Cancel\");\n    panel.add(this.cancel);\n    this.cancel.setBounds(380, 50, 100, 25);\n    this.cancel.addActionListener(this);\n\n    this.presenter = null;\n    this.fileName = null;\n  }\n\n  @Override\n  public void actionPerformed(ActionEvent e) {\n    if (this.ok.equals(e.getSource())) {\n      this.fileName = this.input.getText();\n      presenter.fileNameChanged();\n      presenter.confirmed();\n    } else if (this.cancel.equals(e.getSource())) {\n      presenter.cancelled();\n    }\n  }\n\n  @Override\n  public void open() {\n    this.setVisible(true);\n  }\n\n  @Override\n  public void close() {\n    this.dispose();\n  }\n\n  @Override\n  public boolean isOpened() {\n    return this.isVisible();\n  }\n\n  @Override\n  public void setPresenter(FileSelectorPresenter presenter) {\n    this.presenter = presenter;\n  }\n\n  @Override\n  public FileSelectorPresenter getPresenter() {\n    return this.presenter;\n  }\n\n  @Override\n  public void setFileName(String name) {\n    this.fileName = name;\n  }\n\n  @Override\n  public String getFileName() {\n    return this.fileName;\n  }\n\n  @Override\n  public void showMessage(String message) {\n    JOptionPane.showMessageDialog(null, message);\n  }\n\n  @Override\n  public void displayData(String data) {\n    this.area.setText(data);\n  }\n}\n"
  },
  {
    "path": "model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorPresenter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.presenter;\n\nimport java.io.Serial;\nimport java.io.Serializable;\n\n/**\n * Every instance of this class represents the Presenter component in the Model-View-Presenter\n * architectural pattern.\n *\n * <p>It is responsible for reacting to the user's actions and update the View component.\n */\npublic class FileSelectorPresenter implements Serializable {\n\n  /** Generated serial version UID. */\n  @Serial private static final long serialVersionUID = 1210314339075855074L;\n\n  /** The View component that the presenter interacts with. */\n  private final FileSelectorView view;\n\n  /** The Model component that the presenter interacts with. */\n  private FileLoader loader;\n\n  /**\n   * Constructor.\n   *\n   * @param view The view component that the presenter will interact with.\n   */\n  public FileSelectorPresenter(FileSelectorView view) {\n    this.view = view;\n  }\n\n  /**\n   * Sets the {@link FileLoader} object, to the value given as parameter.\n   *\n   * @param loader The new {@link FileLoader} object(the Model component).\n   */\n  public void setLoader(FileLoader loader) {\n    this.loader = loader;\n  }\n\n  /** Starts the presenter. */\n  public void start() {\n    view.setPresenter(this);\n    view.open();\n  }\n\n  /** An \"event\" that fires when the name of the file to be loaded changes. */\n  public void fileNameChanged() {\n    loader.setFileName(view.getFileName());\n  }\n\n  /** Ok button handler. */\n  public void confirmed() {\n    if (loader.getFileName() == null || loader.getFileName().isEmpty()) {\n      view.showMessage(\"Please give the name of the file first!\");\n      return;\n    }\n\n    if (loader.fileExists()) {\n      var data = loader.loadData();\n      view.displayData(data);\n    } else {\n      view.showMessage(\"The file specified does not exist.\");\n    }\n  }\n\n  /** Cancels the file loading process. */\n  public void cancelled() {\n    view.close();\n  }\n}\n"
  },
  {
    "path": "model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorStub.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.presenter;\n\n/**\n * Every instance of this class represents the Stub component in the Model-View-Presenter\n * architectural pattern.\n *\n * <p>The stub implements the View interface and it is useful when we want the test the reaction to\n * user events, such as mouse clicks.\n *\n * <p>Since we can not test the GUI directly, the MVP pattern provides this functionality through\n * the View's dummy implementation, the Stub.\n */\npublic class FileSelectorStub implements FileSelectorView {\n\n  /** Indicates whether or not the view is opened. */\n  private boolean opened;\n\n  /** The presenter Component. */\n  private FileSelectorPresenter presenter;\n\n  /** The current name of the file. */\n  private String name;\n\n  /** Indicates the number of messages that were \"displayed\" to the user. */\n  private int numOfMessageSent;\n\n  /** Indicates if the data of the file where displayed or not. */\n  private boolean dataDisplayed;\n\n  /** Constructor. */\n  public FileSelectorStub() {\n    this.opened = false;\n    this.presenter = null;\n    this.name = \"\";\n    this.numOfMessageSent = 0;\n    this.dataDisplayed = false;\n  }\n\n  @Override\n  public void open() {\n    this.opened = true;\n  }\n\n  @Override\n  public void setPresenter(FileSelectorPresenter presenter) {\n    this.presenter = presenter;\n  }\n\n  @Override\n  public boolean isOpened() {\n    return this.opened;\n  }\n\n  @Override\n  public FileSelectorPresenter getPresenter() {\n    return this.presenter;\n  }\n\n  @Override\n  public String getFileName() {\n    return this.name;\n  }\n\n  @Override\n  public void setFileName(String name) {\n    this.name = name;\n  }\n\n  @Override\n  public void showMessage(String message) {\n    this.numOfMessageSent++;\n  }\n\n  @Override\n  public void close() {\n    this.opened = false;\n  }\n\n  @Override\n  public void displayData(String data) {\n    this.dataDisplayed = true;\n  }\n\n  /** Returns the number of messages that were displayed to the user. */\n  public int getMessagesSent() {\n    return this.numOfMessageSent;\n  }\n\n  /**\n   * Returns true, if the data were displayed.\n   *\n   * @return True if the data where displayed, false otherwise.\n   */\n  public boolean dataDisplayed() {\n    return this.dataDisplayed;\n  }\n}\n"
  },
  {
    "path": "model-view-presenter/src/main/java/com/iluwatar/model/view/presenter/FileSelectorView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.presenter;\n\nimport java.io.Serializable;\n\n/**\n * This interface represents the View component in the Model-View-Presenter pattern. It can be\n * implemented by either the GUI components, or by the Stub.\n */\npublic interface FileSelectorView extends Serializable {\n\n  /** Opens the view. */\n  void open();\n\n  /** Closes the view. */\n  void close();\n\n  /**\n   * Returns true if view is opened.\n   *\n   * @return True, if the view is opened, false otherwise.\n   */\n  boolean isOpened();\n\n  /**\n   * Sets the presenter component, to the one given as parameter.\n   *\n   * @param presenter The new presenter component.\n   */\n  void setPresenter(FileSelectorPresenter presenter);\n\n  /**\n   * Gets presenter component.\n   *\n   * @return The presenter Component.\n   */\n  FileSelectorPresenter getPresenter();\n\n  /**\n   * Sets the file's name, to the value given as parameter.\n   *\n   * @param name The new name of the file.\n   */\n  void setFileName(String name);\n\n  /**\n   * Gets the name of file.\n   *\n   * @return The name of the file.\n   */\n  String getFileName();\n\n  /**\n   * Displays a message to the users.\n   *\n   * @param message The message to be displayed.\n   */\n  void showMessage(String message);\n\n  /**\n   * Displays the data to the view.\n   *\n   * @param data The data to be written.\n   */\n  void displayData(String data);\n}\n"
  },
  {
    "path": "model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.presenter;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileLoaderTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.presenter;\n\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nimport org.junit.jupiter.api.Test;\n\n/** FileLoaderTest */\nclass FileLoaderTest {\n\n  @Test\n  void testLoadData() {\n    final var fileLoader = new FileLoader();\n    fileLoader.setFileName(\"non-existing-file\");\n    assertNull(fileLoader.loadData());\n  }\n}\n"
  },
  {
    "path": "model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileSelectorJframeTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.presenter;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport java.awt.event.ActionEvent;\nimport org.junit.jupiter.api.Test;\n\n/** FileSelectorJframeTest */\nclass FileSelectorJframeTest {\n\n  /** Tests if the jframe action event is triggered without any exception. */\n  @Test\n  void testActionEvent() {\n    assertDoesNotThrow(\n        () -> {\n          FileSelectorJframe jFrame = new FileSelectorJframe();\n          ActionEvent action = new ActionEvent(\"dummy\", 1, \"dummy\");\n          jFrame.actionPerformed(action);\n        });\n  }\n}\n"
  },
  {
    "path": "model-view-presenter/src/test/java/com/iluwatar/model/view/presenter/FileSelectorPresenterTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.presenter;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/**\n * This test case is responsible for testing our application by taking advantage of the\n * Model-View-Controller architectural pattern.\n */\nclass FileSelectorPresenterTest {\n\n  /** The Presenter component. */\n  private FileSelectorPresenter presenter;\n\n  /** The View component, implemented this time as a Stub!!! */\n  private FileSelectorStub stub;\n\n  /** The Model component. */\n  private FileLoader loader;\n\n  /** Initializes the components of the test case. */\n  @BeforeEach\n  void setUp() {\n    this.stub = new FileSelectorStub();\n    this.loader = new FileLoader();\n    presenter = new FileSelectorPresenter(this.stub);\n    presenter.setLoader(loader);\n  }\n\n  /** Tests if the Presenter was successfully connected with the View. */\n  @Test\n  void wiring() {\n    presenter.start();\n\n    assertNotNull(stub.getPresenter());\n    assertTrue(stub.isOpened());\n  }\n\n  /** Tests if the name of the file changes. */\n  @Test\n  void updateFileNameToLoader() {\n    var expectedFile = \"Stamatis\";\n    stub.setFileName(expectedFile);\n\n    presenter.start();\n    presenter.fileNameChanged();\n\n    assertEquals(expectedFile, loader.getFileName());\n  }\n\n  /**\n   * Tests if we receive a confirmation when we attempt to open a file that it's name is null or an\n   * empty string.\n   */\n  @Test\n  void fileConfirmationWhenNameIsNull() {\n    stub.setFileName(null);\n\n    presenter.start();\n    presenter.fileNameChanged();\n    presenter.confirmed();\n\n    assertFalse(loader.isLoaded());\n    assertEquals(1, stub.getMessagesSent());\n  }\n\n  /** Tests if we receive a confirmation when we attempt to open a file that it doesn't exist. */\n  @Test\n  void fileConfirmationWhenFileDoesNotExist() {\n    stub.setFileName(\"RandomName.txt\");\n\n    presenter.start();\n    presenter.fileNameChanged();\n    presenter.confirmed();\n\n    assertFalse(loader.isLoaded());\n    assertEquals(1, stub.getMessagesSent());\n  }\n\n  /** Tests if we can open the file, when it exists. */\n  @Test\n  void fileConfirmationWhenFileExists() {\n    stub.setFileName(\"etc/data/test.txt\");\n    presenter.start();\n    presenter.fileNameChanged();\n    presenter.confirmed();\n\n    assertTrue(loader.isLoaded());\n    assertTrue(stub.dataDisplayed());\n  }\n\n  /** Tests if the view closes after cancellation. */\n  @Test\n  void cancellation() {\n    presenter.start();\n    presenter.cancelled();\n\n    assertFalse(stub.isOpened());\n  }\n\n  @Test\n  void testNullFile() {\n    stub.setFileName(null);\n    presenter.start();\n    presenter.fileNameChanged();\n    presenter.confirmed();\n\n    assertFalse(loader.isLoaded());\n    assertFalse(stub.dataDisplayed());\n  }\n}\n"
  },
  {
    "path": "model-view-viewmodel/README.md",
    "content": "---\ntitle: \"Model-View-ViewModel Pattern in Java: Separating UI and Logic for Cleaner Code\"\nshortTitle: Model-View-ViewModel\ndescription: \"Learn about the Model-View-ViewModel (MVVM) design pattern in Java. Discover its benefits, real-world applications, and how it improves UI and business logic separation for scalable and maintainable code.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - Architecture\n  - Data binding\n  - Decoupling\n  - Presentation\n  - Scalability\n---\n\n## Also known as\n\n* MVVM\n\n## Intent of Model-View-ViewModel Design Pattern\n\nThe intent of the Model-View-ViewModel (MVVM) pattern in Java is to provide a clear [separation of concerns](https://java-design-patterns.com/principles/#separation-of-concerns) between the UI logic, the presentation logic, and the business logic by dividing the application into three interconnected components: Model, View, and ViewModel.\n\n## Detailed Explanation of Model-View-ViewModel Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a real-world analogous example of the MVVM pattern similar to organizing a cooking show. In this scenario:\n>\n> - **Model:** Represents the recipe itself, which includes the ingredients and the steps needed to cook the dish. The model is purely about the data and rules for preparing the dish but does not concern itself with how this information is presented to the audience.\n>\n> - **View:** Is akin to the kitchen set where the cooking show is filmed, including all the visual elements like the layout of the kitchen, the placement of ingredients, and the cookware. The view is responsible for the visual presentation and how the audience sees the cooking process.\n>\n> - **ViewModel:** Acts like the script for the cooking show, where it interprets the recipe (model) and organizes the flow of the show. It tells the chef (view) what to display next, when to add ingredients, and how to respond to changes like substituting an ingredient. The ViewModel bridges the gap between the technical details of the recipe and the chef's presentation, ensuring the audience understands each step without delving into the complexities of the recipe itself.\n>\n> In this example, the ViewModel allows the chef to focus on cooking and interacting with the audience, while the underlying recipe remains unchanged, promoting a clear separation of concerns.\n\nIn plain words\n\n> The MVVM design pattern separates an application into three distinct components: the Model, which holds the data and business logic; the View, which displays the user interface; and the ViewModel, which acts as an intermediary to bind data from the Model to the View.\n\nWikipedia says\n\n> Model–view–viewmodel (MVVM) is a software architectural pattern that facilitates the separation of the development of the graphical user interface (the view) – be it via a markup language or GUI code – from the development of the business logic or back-end logic (the model) so that the view is not dependent on any specific model platform. \n\nArchitecture diagram\n\n![Model-View-ViewModel Architecture Diagram](./etc/mvvm-architecture-diagram.png)\n\n\n## Programmatic Example of Model-View-ViewModel Pattern in Java\n\nViewModel will hold the business logic and expose the data from model to View.\n\n```java\npublic class BookViewModel {\n  @WireVariable\n  private List<Book> bookList;\n  private Book selectedBook;\n  private BookService bookService = new BookServiceImpl();\n  \n  public Book getSelectedBook() {\n    return selectedBook;\n  }\n\n  @NotifyChange(\"selectedBook\")\n  public void setSelectedBook(Book selectedBook) {\n    this.selectedBook = selectedBook;\n  }\n\n  public List<Book> getBookList() {\n    return bookService.load();\n  }\n  \n  /** Deleting a book.\n   */\n  @Command\n  @NotifyChange({\"selectedBook\",\"bookList\"})\n  public void deleteBook() {\n    if (selectedBook != null) {\n      getBookList().remove(selectedBook);\n      selectedBook = null;\n    }\n}\n```\n\nView will have no logic, only UI elements.\n\n```xml\n<zk>\n<window title=\"List of Books\" border=\"normal\" width=\"600px\" apply=\"org.zkoss.bind.BindComposer\" viewModel=\"@id('vm') @init('com.iluwatar.model.view.viewmodel.BookViewModel')\">\n    <vbox hflex=\"true\">\n        <listbox model=\"@bind(vm.bookList)\" selectedItem=\"@bind(vm.selectedBook)\" height=\"400px\" mold=\"paging\">\n            <listhead>\n                <listheader label=\"Book Name\"/>\n                <listheader label=\"Author\"/>               \n            </listhead>\n            <template name=\"model\" var=\"book\">\n                <listitem >\n                    <listcell label=\"@bind(book.name)\"/>\n                    <listcell label=\"@bind(book.author)\"/>\n                </listitem>\n            </template>\n        </listbox>\n    </vbox>\n    <toolbar>\n        <button label=\"Delete\" onClick=\"@command('deleteBook')\" disabled=\"@load(empty vm.selectedBook)\" />\n    </toolbar>\n    <hbox style=\"margin-top:20px\" visible=\"@bind(not empty vm.selectedBook)\">\n\t\t<vbox>\n\t\t\t<hlayout>\n\t\t\t\tBook Name : <label value=\"@bind(vm.selectedBook.name)\" style=\"font-weight:bold\"/>\n\t\t\t</hlayout>\n\t\t\t<hlayout>\n\t\t\t\tBook Author : <label value=\"@bind(vm.selectedBook.author)\" style=\"font-weight:bold\"/>\n\t\t\t</hlayout>\n\t\t\t<hlayout>\n\t\t\t\tBook Description : <label value=\"@bind(vm.selectedBook.description)\" style=\"font-weight:bold\"/>\n\t\t\t</hlayout>\n\t\t</vbox>\n\t</hbox>\n</window>\n</zk>\n```\n\nTo deploy the example, go to model-view-viewmodel folder and run:\n\n* `mvn clean install`\n* `mvn jetty:run -Djetty.http.port=9911`\n* Open browser to address: http://localhost:9911/model-view-viewmodel/\n\n## When to Use the Model-View-ViewModel Pattern in Java\n\nMVVM is applicable in applications requiring a clear separation between the user interface and the underlying business logic, especially in large-scale, data-driven applications where UI and business logic change independently. This makes the Model-View-ViewModel pattern ideal for Java applications.\n\n## Model-View-ViewModel Pattern Java Tutorials\n\n* [Data Binding in Android (developer.android.com)](https://developer.android.com/codelabs/android-databinding#0)\n* [Introduction to Model View View Model (MVVM) (GeeksforGeeks)](https://www.geeksforgeeks.org/introduction-to-model-view-view-model-mvvm/)\n* [Patterns - WPF Apps With The Model-View-ViewModel Design Pattern (Microsoft)](https://docs.microsoft.com/en-us/archive/msdn-magazine/2009/february/patterns-wpf-apps-with-the-model-view-viewmodel-design-pattern)\n\n## Real-World Applications of Model-View-ViewModel Pattern in Java\n\n* Widely used in JavaFX applications for desktop interfaces.\n* Utilized in Android development with libraries like DataBinding and LiveData for reactive UI updates.\n* ZK Framework [zkoss.org](https://www.zkoss.org/)\n* KnockoutJS [knockoutjs.com](https://knockoutjs.com/)\n\n## Benefits and Trade-offs of Model-View-ViewModel Pattern\n\nBenefits:\n\n* Improved testability due to decoupling of business and presentation logic.\n* Easier maintenance and modification of the user interface without affecting the underlying data model.\n* Enhanced reusability of the ViewModel across different views if designed generically.\n\nTrade-offs:\n\n* Increased complexity in small applications where simpler patterns might suffice.\n* Learning curve associated with understanding and applying the pattern correctly.\n\n## Related Java Design Patterns\n\n* [MVC (Model-View-Controller)](https://java-design-patterns.com/patterns/model-view-controller/): MVVM can be seen as a derivative of MVC with a stronger emphasis on binding and decoupling, where the ViewModel acts as an intermediary unlike the controller in MVC.\n* [MVP (Model-View-Presenter)](https://java-design-patterns.com/patterns/model-view-presenter/): Similar to MVVM but with a focus on the presenter handling the UI logic, making MVVM's ViewModel more passive in terms of direct UI manipulation.\n\n## References and Credits\n\n* [Android Programming: The Big Nerd Ranch Guide](https://amzn.to/3wBGG5o)\n* [Pro JavaFX 8: A Definitive Guide to Building Desktop, Mobile, and Embedded Java Clients](https://amzn.to/4a8qcQ1)\n"
  },
  {
    "path": "model-view-viewmodel/etc/model-view-viewmodel.urm.puml",
    "content": "@startuml\npackage com.iluwatar.model.view.viewmodel {\n  class Book {\n    - author : String\n    - description : String\n    - name : String\n    + Book(name : String, author : String, description : String)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getAuthor() : String\n    + getDescription() : String\n    + getName() : String\n    + hashCode() : int\n    + setAuthor(author : String)\n    + setDescription(description : String)\n    + setName(name : String)\n    + toString() : String\n  }\n  interface BookService {\n    + load() : List<Book> {abstract}\n  }\n  class BookServiceImpl {\n    - designPatternBooks : List<Book>\n    + BookServiceImpl()\n    + load() : List<Book>\n  }\n  class BookViewModel {\n    - bookList : List<Book>\n    - bookService : BookService\n    - selectedBook : Book\n    + BookViewModel()\n    + deleteBook()\n    + getBookList() : List<Book>\n    + getSelectedBook() : Book\n    + setSelectedBook(selectedBook : Book)\n  }\n}\nBookViewModel -->  \"-bookService\" BookService\nBookServiceImpl -->  \"-designPatternBooks\" Book\nBookViewModel -->  \"-bookList\" Book\nBookViewModel -->  \"-selectedBook\" Book\nBookServiceImpl ..|> BookService \n@enduml"
  },
  {
    "path": "model-view-viewmodel/lombok.config",
    "content": "config.stopBubbling = true\nlombok.addLombokGeneratedAnnotation = true"
  },
  {
    "path": "model-view-viewmodel/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>model-view-viewmodel</artifactId>\n  <version>1.26.0-SNAPSHOT</version>\n  <properties>\n    <zk.version>10.0.0-jakarta</zk.version>\n    <jetty-maven-plugin.version>11.0.24</jetty-maven-plugin.version>\n    <maven-war-plugin.version>3.4.0</maven-war-plugin.version>\n    <maven.build.timestamp.format>yyyy-MM-dd</maven.build.timestamp.format>\n    <packname>-${project.version}-FL-${maven.build.timestamp}</packname>\n  </properties>\n  <packaging>war</packaging>\n  <name>model-view-viewmodel</name>\n  <description>model-view-viewmodel</description>\n  <licenses>\n    <license>\n      <name>GNU LESSER GENERAL PUBLIC LICENSE, Version 3</name>\n      <url>https://www.gnu.org/licenses/lgpl.html</url>\n      <distribution>repo</distribution>\n    </license>\n  </licenses>\n  <repositories>\n    <repository>\n      <id>ZK CE</id>\n      <name>ZK CE Repository</name>\n      <url>https://mavensync.zkoss.org/maven2</url>\n    </repository>\n    <repository>\n      <id>ZK EVAL</id>\n      <name>ZK Evaluation Repository</name>\n      <url>https://mavensync.zkoss.org/eval</url>\n    </repository>\n  </repositories>\n  <pluginRepositories>\n    <pluginRepository>\n      <id>zkmaven</id>\n      <name>ZK Maven Plugin Repository</name>\n      <url>https://mavensync.zkoss.org/maven2/</url>\n    </pluginRepository>\n  </pluginRepositories>\n  <dependencies>\n    <dependency>\n      <groupId>org.zkoss.zk</groupId>\n      <artifactId>zkbind</artifactId>\n      <version>${zk.version}</version>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <finalName>${project.artifactId}</finalName>\n    <plugins>\n      <!-- Run with Jetty -->\n      <plugin>\n        <groupId>org.eclipse.jetty</groupId>\n        <artifactId>jetty-maven-plugin</artifactId>\n        <version>${jetty-maven-plugin.version}</version>\n        <configuration>\n          <webApp>\n            <contextPath>/${project.artifactId}</contextPath>\n            <allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>\n          </webApp>\n          <scanIntervalSeconds>5</scanIntervalSeconds>\n        </configuration>\n      </plugin>\n      <!-- Build war -->\n      <plugin>\n        <artifactId>maven-war-plugin</artifactId>\n        <groupId>org.apache.maven.plugins</groupId>\n        <version>${maven-war-plugin.version}</version>\n      </plugin>\n      <!-- Pack zips -->\n      <plugin>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <id>webapp</id>\n            <phase>package</phase>\n            <goals>\n              <goal>single</goal>\n            </goals>\n            <configuration>\n              <finalName>model-view-viewmodel${packname}</finalName>\n              <appendAssemblyId>false</appendAssemblyId>\n              <descriptors>\n                <descriptor>src/main/assembly/webapp.xml</descriptor>\n              </descriptors>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "model-view-viewmodel/src/main/assembly/webapp.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<assembly xmlns=\"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd\">\n  <id>webapp</id>\n  <formats>\n    <format>zip</format>\n  </formats>\n  <fileSets>\n    <fileSet>\n      <directory>${project.basedir}/src/main/java</directory>\n      <outputDirectory>/${project.artifactId}/src</outputDirectory>\n    </fileSet>\n    <fileSet>\n      <directory>${project.basedir}/src/main/webapp</directory>\n      <outputDirectory>/${project.artifactId}/WebContent</outputDirectory>\n    </fileSet>\n  </fileSets>\n  <files>\n    <file>\n      <source>${project.build.directory}/${project.artifactId}.war</source>\n      <outputDirectory>/</outputDirectory>\n    </file>\n  </files>\n</assembly>\n"
  },
  {
    "path": "model-view-viewmodel/src/main/java/com/iluwatar/model/view/viewmodel/Book.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.viewmodel;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\n/** Book class. */\n@AllArgsConstructor\n@Data\npublic class Book {\n\n  private String name;\n  private String author;\n  private String description;\n}\n"
  },
  {
    "path": "model-view-viewmodel/src/main/java/com/iluwatar/model/view/viewmodel/BookService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.model.view.viewmodel;\n\nimport java.util.List;\n\n/** Class representing a service to load books. */\npublic interface BookService {\n  /* List all books\n   * @return all books\n   */\n  List<Book> load();\n}\n"
  },
  {
    "path": "model-view-viewmodel/src/main/java/com/iluwatar/model/view/viewmodel/BookServiceImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.viewmodel;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** Class that actually implement the books to load. */\npublic class BookServiceImpl implements BookService {\n  private List<Book> designPatternBooks = new ArrayList<>();\n\n  /**\n   * Initializes Book Data. To be used and passed along in load method In this case, list design\n   * pattern books are initialized to be loaded.\n   */\n  public BookServiceImpl() {\n    designPatternBooks.add(\n        new Book(\n            \"Head First Design Patterns: A Brain-Friendly Guide\",\n            \"Eric Freeman, Bert Bates, Kathy Sierra, Elisabeth Robson\",\n            \"Head First Design Patterns Description\"));\n    designPatternBooks.add(\n        new Book(\n            \"Design Patterns: Elements of Reusable Object-Oriented Software\",\n            \"Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides\",\n            \"Design Patterns Description\"));\n    designPatternBooks.add(\n        new Book(\n            \"Patterns of Enterprise Application Architecture\",\n            \"Martin Fowler\",\n            \"Patterns of Enterprise Application Architecture Description\"));\n    designPatternBooks.add(\n        new Book(\n            \"Design Patterns Explained\",\n            \"Alan Shalloway, James Trott\",\n            \"Design Patterns Explained Description\"));\n    designPatternBooks.add(\n        new Book(\n            \"Applying UML and Patterns: An Introduction to \"\n                + \"Object-Oriented Analysis and Design and Iterative Development\",\n            \"Craig Larman\",\n            \"Applying UML and Patterns Description\"));\n  }\n\n  public List<Book> load() {\n    return designPatternBooks;\n  }\n}\n"
  },
  {
    "path": "model-view-viewmodel/src/main/java/com/iluwatar/model/view/viewmodel/BookViewModel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.viewmodel;\n\nimport java.util.List;\nimport lombok.Getter;\nimport org.zkoss.bind.annotation.Command;\nimport org.zkoss.bind.annotation.NotifyChange;\nimport org.zkoss.zk.ui.select.annotation.WireVariable;\n\n/** BookViewModel class. */\npublic class BookViewModel {\n\n  @WireVariable private List<Book> bookList;\n  @Getter private Book selectedBook;\n  private BookService bookService = new BookServiceImpl();\n\n  @NotifyChange(\"selectedBook\")\n  public void setSelectedBook(Book selectedBook) {\n    this.selectedBook = selectedBook;\n  }\n\n  public List<Book> getBookList() {\n    return bookService.load();\n  }\n\n  /**\n   * Deleting a book. When event is triggered on click of Delete button, this method will be\n   * notified with the selected entry that will be referenced and used to delete the selected book\n   * from the list of books.\n   */\n  @Command\n  @NotifyChange({\"selectedBook\", \"bookList\"})\n  public void deleteBook() {\n    if (selectedBook != null) {\n      getBookList().remove(selectedBook);\n      selectedBook = null;\n    }\n  }\n}\n"
  },
  {
    "path": "model-view-viewmodel/src/main/webapp/META-INF/MANIFEST.MF",
    "content": "Manifest-Version: 1.0\nSpecification-Title: ZK Application\nSpecification-Version: 1.0\nSpecification-Vendor: \nImplementation-Title: \nImplementation-URL: http://your-website/\nImplementation-Version: 1.0\nImplementation-Vendor: \n"
  },
  {
    "path": "model-view-viewmodel/src/main/webapp/WEB-INF/web.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<web-app xmlns=\"http://java.sun.com/xml/ns/j2ee\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"2.4\" xsi:schemaLocation=\"http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd\">\n  <description><![CDATA[My ZK Application]]></description>\n  <display-name>model-view-viewmodel</display-name>\n  <!-- ZK -->\n  <listener>\n    <description>ZK listener for session cleanup</description>\n    <listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>\n  </listener>\n  <servlet>\n    <description>ZK loader for ZUML pages</description>\n    <servlet-name>zkLoader</servlet-name>\n    <servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>\n    <!-- Must. Specifies URI of the update engine (DHtmlUpdateServlet).\n\t\tIt must be the same as <url-pattern> for the update engine.\n\t\t-->\n    <init-param>\n      <param-name>update-uri</param-name>\n      <param-value>/zkau</param-value>\n    </init-param>\n    <load-on-startup>1</load-on-startup>\n    <!-- Must -->\n  </servlet>\n  <servlet-mapping>\n    <servlet-name>zkLoader</servlet-name>\n    <url-pattern>*.zul</url-pattern>\n  </servlet-mapping>\n  <servlet-mapping>\n    <servlet-name>zkLoader</servlet-name>\n    <url-pattern>*.zhtml</url-pattern>\n  </servlet-mapping>\n  <servlet>\n    <description>The asynchronous update engine for ZK</description>\n    <servlet-name>auEngine</servlet-name>\n    <servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class>\n  </servlet>\n  <servlet-mapping>\n    <servlet-name>auEngine</servlet-name>\n    <url-pattern>/zkau/*</url-pattern>\n  </servlet-mapping>\n  <session-config>\n    <session-timeout>60</session-timeout>\n  </session-config>\n  <!-- [Optional] MIME mapping -->\n  <mime-mapping>\n    <extension>doc</extension>\n    <mime-type>application/vnd.ms-word</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>gif</extension>\n    <mime-type>image/gif</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>htm</extension>\n    <mime-type>text/html</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>html</extension>\n    <mime-type>text/html</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>jpeg</extension>\n    <mime-type>image/jpeg</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>jpg</extension>\n    <mime-type>image/jpeg</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>js</extension>\n    <mime-type>text/javascript</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>pdf</extension>\n    <mime-type>application/pdf</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>png</extension>\n    <mime-type>image/png</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>txt</extension>\n    <mime-type>text/plain</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>xls</extension>\n    <mime-type>application/vnd.ms-excel</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>xml</extension>\n    <mime-type>text/xml</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>zhtml</extension>\n    <mime-type>text/html</mime-type>\n  </mime-mapping>\n  <mime-mapping>\n    <extension>zul</extension>\n    <mime-type>text/html</mime-type>\n  </mime-mapping>\n  <welcome-file-list>\n    <welcome-file>index.zul</welcome-file>\n    <welcome-file>index.zhtml</welcome-file>\n    <welcome-file>index.html</welcome-file>\n    <welcome-file>index.htm</welcome-file>\n  </welcome-file-list>\n</web-app>\n"
  },
  {
    "path": "model-view-viewmodel/src/main/webapp/index.zul",
    "content": "<zk>\n<window title=\"List of Books\" border=\"normal\" width=\"600px\" apply=\"org.zkoss.bind.BindComposer\" viewModel=\"@id('vm') @init('com.iluwatar.model.view.viewmodel.BookViewModel')\">\n    <vbox hflex=\"true\">\n        <listbox model=\"@bind(vm.bookList)\" selectedItem=\"@bind(vm.selectedBook)\" height=\"400px\" mold=\"paging\">\n            <listhead>\n                <listheader label=\"Book Name\"/>\n                <listheader label=\"Author\"/>               \n            </listhead>\n            <template name=\"model\" var=\"book\">\n                <listitem >\n                    <listcell label=\"@bind(book.name)\"/>\n                    <listcell label=\"@bind(book.author)\"/>\n                </listitem>\n            </template>\n        </listbox>\n    </vbox>\n    <toolbar>\n        <button label=\"Delete\" onClick=\"@command('deleteBook')\" disabled=\"@load(empty vm.selectedBook)\" />\n    </toolbar>\n    <hbox style=\"margin-top:20px\" visible=\"@bind(not empty vm.selectedBook)\">\n\t\t<vbox>\n\t\t\t<hlayout>\n\t\t\t\tBook Name : <label value=\"@bind(vm.selectedBook.name)\" style=\"font-weight:bold\"/>\n\t\t\t</hlayout>\n\t\t\t<hlayout>\n\t\t\t\tBook Author : <label value=\"@bind(vm.selectedBook.author)\" style=\"font-weight:bold\"/>\n\t\t\t</hlayout>\n\t\t\t<hlayout>\n\t\t\t\tBook Description : <label value=\"@bind(vm.selectedBook.description)\" style=\"font-weight:bold\"/>\n\t\t\t</hlayout>\n\t\t</vbox>\n\t</hbox>\n</window>\n</zk>"
  },
  {
    "path": "model-view-viewmodel/src/test/java/com/iluwatar/model/view/viewmodel/BookTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model.view.viewmodel;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.List;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass BookTest {\n\n  BookViewModel bvm;\n  Book testBook;\n  List<Book> testBookList;\n  Book testBookTwo;\n  Book testBookThree;\n\n  @BeforeEach\n  void setUp() {\n    bvm = new BookViewModel();\n    testBook =\n        new Book(\n            \"Head First Design Patterns: A Brain-Friendly Guide\",\n            \"Eric Freeman, Bert Bates, Kathy Sierra, Elisabeth Robson\",\n            \"Head First Design Patterns Description\");\n    testBookList = bvm.getBookList();\n    testBookTwo =\n        new Book(\n            \"Head First Design Patterns: A Brain-Friendly Guide\",\n            \"Eric Freeman, Bert Bates, Kathy Sierra, Elisabeth Robson\",\n            \"Head First Design Patterns Description\");\n    testBookThree =\n        new Book(\n            \"Design Patterns: Elements of Reusable Object-Oriented Software\",\n            \"Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides\",\n            \"Design Patterns Description\");\n  }\n\n  @Test\n  void testBookModel() {\n    assertNotNull(testBook);\n  }\n\n  @Test\n  void testEquals() {\n    assertEquals(testBook, testBookTwo);\n  }\n\n  @Test\n  void testToString() {\n    assertEquals(testBook.toString(), testBookTwo.toString());\n    assertNotEquals(testBook.toString(), testBookThree.toString());\n  }\n\n  @Test\n  void testHashCode() {\n    assertTrue(testBook.equals(testBookTwo) && testBookTwo.equals(testBook));\n    assertEquals(testBook.hashCode(), testBookTwo.hashCode());\n  }\n\n  @Test\n  void testLoadData() {\n    assertNotNull(testBookList);\n    assertTrue(testBookList.get(0).toString().contains(\"Head First Design Patterns\"));\n  }\n\n  @Test\n  void testSelectedData() {\n    bvm.setSelectedBook(testBook);\n    assertNotNull(bvm.getSelectedBook());\n    assertEquals(testBook.toString(), bvm.getSelectedBook().toString());\n    assertTrue(true, bvm.getSelectedBook().toString());\n  }\n\n  @Test\n  void testDeleteData() {\n    bvm.setSelectedBook(testBook);\n    assertNotNull(bvm.getSelectedBook());\n    assertTrue(testBookList.get(0).toString().contains(\"Head First Design Patterns\"));\n    bvm.deleteBook();\n    assertNull(bvm.getSelectedBook());\n    assertFalse(testBookList.get(0).toString().contains(\"Head First Design Patterns\"));\n  }\n}\n"
  },
  {
    "path": "monad/README.md",
    "content": "---\ntitle: \"Monad Pattern in Java: Mastering Functional Programming Paradigms\"\nshortTitle: Monad\ndescription: \"Learn how to implement the Monad design pattern in Java for functional programming. Discover its benefits, real-world examples, and best practices to enhance code readability and error handling.\"\ncategory: Functional\nlanguage: en\ntag:\n  - Abstraction\n  - Accumulation\n  - Decoupling\n  - Encapsulation\n  - Functional decomposition\n  - Generic\n  - Idiom\n  - Instantiation\n  - Interface\n  - Layered architecture\n  - Object composition\n---\n\n## Also known as\n\n* Computation Wrapper\n* Monadic Interface\n\n## Intent of Monad Design Pattern\n\nThe Monad design pattern in Java provides a mechanism for encapsulating computations or side effects, enabling the chaining of operations while managing context and data flow in a side-effect-free manner.\n\n## Detailed Explanation of Monad Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a real-world example of a monad in Java with a restaurant meal ordering process. This encapsulation and chaining allow for a clean, error-managed progression, similar to how monads handle data and operations in functional programming. In this scenario, each step of selecting a dish, adding sides, and choosing a drink can be thought of as a monadic operation. Each operation encapsulates the current state of the order (e.g., main dish chosen) and allows for the next choice (e.g., selecting a side) without exposing the complexity of the entire order's details to the customer.\n>\n> Just like in a functional monad, if any step fails (like an unavailable dish), the entire process can be halted or redirected without throwing exceptions, maintaining a smooth flow. This encapsulation and chaining allow for a clean, error-managed progression from choosing the main dish to completing the full meal order, akin to how monads handle data and operations in functional programming. This approach ensures a consistent experience, where every choice builds on the previous one in a controlled manner.\n\nIn plain words\n\n> Monad pattern ensures that each operation is executed regardless of the success or failure of previous ones.\n\nWikipedia says\n\n> In functional programming, a monad is a structure that combines program fragments (functions) and wraps their return values in a type with additional computation. In addition to defining a wrapping monadic type, monads define two operators: one to wrap a value in the monad type, and another to compose together functions that output values of the monad type (these are known as monadic functions). General-purpose languages use monads to reduce boilerplate code needed for common operations (such as dealing with undefined values or fallible functions, or encapsulating bookkeeping code). Functional languages use monads to turn complicated sequences of functions into succinct pipelines that abstract away control flow, and side effects.\n\nFlowchart\n\n![Monad flowchart](./etc/monad-flowchart.png)\n\n## Programmatic Example of Monad Pattern in Java\n\nHere’s the Monad implementation in Java. The `Validator` class encapsulates an object and performs validation steps in a monadic fashion, showcasing the benefits of using the Monad pattern for error handling and state management.\n\n```java\npublic class Validator<T> {\n  private final T obj;\n  private final List<Throwable> exceptions = new ArrayList<>();\n\n   private Validator(T obj) {\n    this.obj = obj;\n  }\n  public static <T> Validator<T> of(T t) {\n    return new Validator<>(Objects.requireNonNull(t));\n  }\n\n  public Validator<T> validate(Predicate<? super T> validation, String message) {\n    if (!validation.test(obj)) {\n      exceptions.add(new IllegalStateException(message));\n    }\n    return this;\n  }\n\n  public <U> Validator<T> validate(\n      Function<? super T, ? extends U> projection,\n      Predicate<? super U> validation,\n      String message\n  ) {\n    return validate(projection.andThen(validation::test)::apply, message);\n  }\n\n  public T get() throws IllegalStateException {\n    if (exceptions.isEmpty()) {\n      return obj;\n    }\n    var e = new IllegalStateException();\n    exceptions.forEach(e::addSuppressed);\n    throw e;\n  }\n}\n```\n\nNext we define an enum `Sex`.\n\n```java\npublic enum Sex {\n  MALE, FEMALE\n}\n```\n\nNow we can introduce the `User`.\n\n```java\npublic record User(String name, int age, Sex sex, String email) {\n}\n```\n\nAnd finally, a `User` object is validated for its name, email, and age using the `Validator` monad.\n\n```java\npublic static void main(String[] args) {\n    var user = new User(\"user\", 24, Sex.FEMALE, \"foobar.com\");\n    LOGGER.info(Validator.of(user).validate(User::name, Objects::nonNull, \"name is null\")\n        .validate(User::name, name -> !name.isEmpty(), \"name is empty\")\n        .validate(User::email, email -> !email.contains(\"@\"), \"email doesn't contains '@'\")\n        .validate(User::age, age -> age > 20 && age < 30, \"age isn't between...\").get()\n        .toString());\n}\n```\n\nConsole output:\n\n```\n15:06:17.679 [main] INFO com.iluwatar.monad.App -- User[name=user, age=24, sex=FEMALE, email=foobar.com]\n```\n\n## When to Use the Monad Pattern in Java\n\nThe Monad design pattern is applicable when\n\n* Consistent and unified error handling is required without relying on exceptions, particularly in functional programming paradigms.\n* Asynchronous computations need clear and maintainable chaining.\n* State needs to be managed and encapsulated within functional flows.\n* Dependencies and lazy evaluations are to be handled cleanly and efficiently.\n\n## Monad Pattern Java Tutorials\n\n* [Design Pattern Reloaded (Remi Forax)](https://youtu.be/-k2X7guaArU)\n\n## Real-World Applications of Monad Pattern in Java\n\n* Optional in Java's standard library for handling potential absence of values.\n* Stream for constructing functional pipelines to operate on collections.\n* Frameworks like Vavr enhance functional programming in Java by providing monadic constructs for better code maintainability.\n\n## Benefits and Trade-offs of Monad Pattern\n\nBenefits:\n\n* Increases code readability and reduces boilerplate.\n* Encourages a declarative programming style.\n* Promotes immutability and thread safety.\n* Simplifies complex error handling and state management.\n\nTrade-offs:\n\n* Can be challenging for developers new to functional programming.\n* May introduce performance overhead due to additional abstraction layers.\n* Debugging can be difficult due to less transparent operational flow.\n\n## Related Java Design Patterns\n\nRelated design patterns to monads in Java include\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Similar in that it helps instantiate monads, encapsulating object creation logic.\n* [Command](https://java-design-patterns.com/patterns/command/): Also encapsulates operations, but monads add context management to the mix.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Dynamically enhances functionalities, whereas monads use static typing for consistent composability.\n\n## References and Credits\n\n* [Functional Programming in Java](https://amzn.to/3JUIc5Q)\n* [Java 8 in Action: Lambdas, Streams, and functional-style programming](https://amzn.to/3QCmGXs)\n* [Real-World Software Development: A Project-Driven Guide to Fundamentals in Java](https://amzn.to/4btoN7U)\n* [Monad (functional programming) (Wikipedia)](https://en.wikipedia.org/wiki/Monad_(functional_programming))\n"
  },
  {
    "path": "monad/etc/monad.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.9\" icons=\"true\" always-add-relationships=\"false\" generalizations=\"true\" realizations=\"true\" \n  associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.monad.App\" project=\"monad\" \n    file=\"/monad/src/main/java/com/iluwatar/monad/App.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"101\" width=\"125\" x=\"631\" y=\"37\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <enumeration id=\"2\" language=\"java\" name=\"com.iluwatar.monad.Sex\" project=\"monad\" \n    file=\"/monad/src/main/java/com/iluwatar/monad/Sex.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"119\" width=\"137\" x=\"424\" y=\"286\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.monad.User\" project=\"monad\" \n    file=\"/monad/src/main/java/com/iluwatar/monad/User.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"209\" width=\"167\" x=\"424\" y=\"37\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.monad.Validator\" project=\"monad\" \n    file=\"/monad/src/main/java/com/iluwatar/monad/Validator.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"191\" width=\"343\" x=\"41\" y=\"37\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"5\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"6\" name=\"sex\"/>      \n      <multiplicity id=\"7\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "monad/etc/monad.urm.puml",
    "content": "@startuml\npackage com.iluwatar.monad {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  enum Sex {\n    + FEMALE {static}\n    + MALE {static}\n    + valueOf(name : String) : Sex {static}\n    + values() : Sex[] {static}\n  }\n  class User {\n    - age : int\n    - email : String\n    - name : String\n    - sex : Sex\n    + User(name : String, age : int, sex : Sex, email : String)\n    + getAge() : int\n    + getEmail() : String\n    + getName() : String\n    + getSex() : Sex\n  }\n  class Validator<T> {\n    - exceptions : List<Throwable>\n    - obj : T\n    - Validator<T>(obj : T)\n    + get() : T\n    + of(t : T) : Validator<T> {static}\n    + validate(projection : Function<T, U>, validation : Predicate<U>, message : String) : Validator<T>\n    + validate(validation : Predicate<T>, message : String) : Validator<T>\n  }\n}\nUser -->  \"-sex\" Sex\n@enduml"
  },
  {
    "path": "monad/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>monad</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.monostate.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "monad/src/main/java/com/iluwatar/monad/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monad;\n\nimport java.util.Objects;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Monad pattern defines a monad structure, that enables chaining operations in pipelines and\n * processing data step by step. Formally, monad consists of a type constructor M and two\n * operations: <br>\n * bind - that takes monadic object and a function from plain object to the monadic value and\n * returns monadic value. <br>\n * return - that takes plain type object and returns this object wrapped in a monadic value.\n *\n * <p>In the given example, the Monad pattern is represented as a {@link Validator} that takes an\n * instance of a plain object with {@link Validator#of(Object)} and validates it {@link\n * Validator#validate(Function, Predicate, String)} against given predicates.\n *\n * <p>As a validation result {@link Validator#get()} either returns valid object or throws {@link\n * IllegalStateException} with list of exceptions collected during validation.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var user = new User(\"user\", 24, Sex.FEMALE, \"foobar.com\");\n    LOGGER.info(\n        Validator.of(user)\n            .validate(User::name, Objects::nonNull, \"name is null\")\n            .validate(User::name, name -> !name.isEmpty(), \"name is empty\")\n            .validate(User::email, email -> !email.contains(\"@\"), \"email doesn't contains '@'\")\n            .validate(User::age, age -> age > 20 && age < 30, \"age isn't between...\")\n            .get()\n            .toString());\n  }\n}\n"
  },
  {
    "path": "monad/src/main/java/com/iluwatar/monad/Sex.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monad;\n\n/** Enumeration of Types of Sex. */\npublic enum Sex {\n  MALE,\n  FEMALE\n}\n"
  },
  {
    "path": "monad/src/main/java/com/iluwatar/monad/User.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monad;\n\n/**\n * Record class.\n *\n * @param name - name\n * @param age - age\n * @param sex - sex\n * @param email - email address\n */\npublic record User(String name, int age, Sex sex, String email) {}\n"
  },
  {
    "path": "monad/src/main/java/com/iluwatar/monad/Validator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monad;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.function.Function;\nimport java.util.function.Predicate;\n\n/**\n * Class representing Monad design pattern. Monad is a way of chaining operations on the given\n * object together step by step. In Validator each step results in either success or failure\n * indicator, giving a way of receiving each of them easily and finally getting validated object or\n * list of exceptions.\n *\n * @param <T> Placeholder for an object.\n */\npublic class Validator<T> {\n  /** Object that is validated. */\n  private final T obj;\n\n  /** List of exception thrown during validation. */\n  private final List<Throwable> exceptions = new ArrayList<>();\n\n  /**\n   * Creates a monadic value of given object.\n   *\n   * @param obj object to be validated\n   */\n  private Validator(T obj) {\n    this.obj = obj;\n  }\n\n  /**\n   * Creates validator against given object.\n   *\n   * @param t object to be validated\n   * @param <T> object's type\n   * @return new instance of a validator\n   */\n  public static <T> Validator<T> of(T t) {\n    return new Validator<>(Objects.requireNonNull(t));\n  }\n\n  /**\n   * Checks if the validation is successful.\n   *\n   * @param validation one argument boolean-valued function that represents one step of validation.\n   *     Adds exception to main validation exception list when single step validation ends with\n   *     failure.\n   * @param message error message when object is invalid\n   * @return this\n   */\n  public Validator<T> validate(Predicate<? super T> validation, String message) {\n    if (!validation.test(obj)) {\n      exceptions.add(new IllegalStateException(message));\n    }\n    return this;\n  }\n\n  /**\n   * Extension for the {@link Validator#validate(Predicate, String)} method, dedicated for objects,\n   * that need to be projected before requested validation.\n   *\n   * @param projection function that gets an objects, and returns projection representing element to\n   *     be validated.\n   * @param validation see {@link Validator#validate(Predicate, String)}\n   * @param message see {@link Validator#validate(Predicate, String)}\n   * @param <U> see {@link Validator#validate(Predicate, String)}\n   * @return this\n   */\n  public <U> Validator<T> validate(\n      Function<? super T, ? extends U> projection,\n      Predicate<? super U> validation,\n      String message) {\n    return validate(projection.andThen(validation::test)::apply, message);\n  }\n\n  /**\n   * Receives validated object or throws exception when invalid.\n   *\n   * @return object that was validated\n   * @throws IllegalStateException when any validation step results with failure\n   */\n  public T get() throws IllegalStateException {\n    if (exceptions.isEmpty()) {\n      return obj;\n    }\n    var e = new IllegalStateException();\n    exceptions.forEach(e::addSuppressed);\n    throw e;\n  }\n}\n"
  },
  {
    "path": "monad/src/test/java/com/iluwatar/monad/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monad;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application Test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "monad/src/test/java/com/iluwatar/monad/MonadTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monad;\n\nimport static org.junit.jupiter.api.Assertions.assertSame;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nimport java.util.Objects;\nimport org.junit.jupiter.api.Test;\n\n/** Test for Monad Pattern */\nclass MonadTest {\n\n  @Test\n  void testForInvalidName() {\n    var tom = new User(null, 21, Sex.MALE, \"tom@foo.bar\");\n    assertThrows(\n        IllegalStateException.class,\n        () ->\n            Validator.of(tom).validate(User::name, Objects::nonNull, \"name cannot be null\").get());\n  }\n\n  @Test\n  void testForInvalidAge() {\n    var john = new User(\"John\", 17, Sex.MALE, \"john@qwe.bar\");\n    assertThrows(\n        IllegalStateException.class,\n        () ->\n            Validator.of(john)\n                .validate(User::name, Objects::nonNull, \"name cannot be null\")\n                .validate(User::age, age -> age > 21, \"user is underage\")\n                .get());\n  }\n\n  @Test\n  void testForValid() {\n    var sarah = new User(\"Sarah\", 42, Sex.FEMALE, \"sarah@det.org\");\n    var validated =\n        Validator.of(sarah)\n            .validate(User::name, Objects::nonNull, \"name cannot be null\")\n            .validate(User::age, age -> age > 21, \"user is underage\")\n            .validate(User::sex, sex -> sex == Sex.FEMALE, \"user is not female\")\n            .validate(User::email, email -> email.contains(\"@\"), \"email does not contain @ sign\")\n            .get();\n    assertSame(validated, sarah);\n  }\n}\n"
  },
  {
    "path": "money/README.md",
    "content": "---\ntitle: \"Money Pattern in Java: Encapsulating Monetary Values with Currency Consistency\"\nshortTitle: Money\ndescription: \"Learn how the Money design pattern in Java ensures currency safety, precision handling, and maintainable financial operations. Explore examples, applicability, and benefits of the pattern.\"\ncategory: Structural\nlanguage: en\ntag:\n    - Business\n    - Domain\n    - Encapsulation\n    - Immutable\n---\n\n## Also known as\n\n* Monetary Value Object\n\n## Intent of Money Design Pattern\n\nEncapsulate monetary values and their associated currency in a domain-specific object.\n\n## Detailed Explanation of Money Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine an online gift card system, where each gift card holds a specific balance in a particular currency. Instead of just using a floating-point value for the balance, the system uses a Money object to precisely track the amount and currency. Whenever someone uses the gift card, it updates the balance with accurate calculations that avoid floating-point rounding errors, ensuring the domain logic stays consistent and accurate.\n\nIn plain words\n\n> The Money pattern encapsulates both an amount and its currency, ensuring financial operations are precise, consistent, and maintainable.\n\nWikipedia says\n\n> The Money design pattern encapsulates a monetary value and its currency, allowing for safe arithmetic operations and conversions while preserving accuracy and consistency in financial calculations.\n\nMind map\n\n![Money Pattern Mind Map](./etc/money-mind-map.png)\n\nFlowchart\n\n![Money Pattern Flowchart](./etc/money-flowchart.png)\n\n## Programmatic Example of Money Pattern in Java\n\nIn this example, we're creating a `Money` class to demonstrate how monetary values can be encapsulated along with their currency. This approach helps avoid floating-point inaccuracies, ensures arithmetic operations are handled consistently, and provides a clear domain-centric way of working with money.\n\n```java\n@AllArgsConstructor\n@Getter\npublic class Money {\n    private double amount;\n    private String currency;\n\n    public Money(double amnt, String curr) {\n        this.amount = amnt;\n        this.currency = curr;\n    }\n\n    private double roundToTwoDecimals(double value) {\n        return Math.round(value * 100.0) / 100.0;\n    }\n\n    public void addMoney(Money moneyToBeAdded) throws CannotAddTwoCurrienciesException {\n        if (!moneyToBeAdded.getCurrency().equals(this.currency)) {\n            throw new CannotAddTwoCurrienciesException(\"You are trying to add two different currencies\");\n        }\n        this.amount = roundToTwoDecimals(this.amount + moneyToBeAdded.getAmount());\n    }\n\n    public void subtractMoney(Money moneyToBeSubtracted) throws CannotSubtractException {\n        if (!moneyToBeSubtracted.getCurrency().equals(this.currency)) {\n            throw new CannotSubtractException(\"You are trying to subtract two different currencies\");\n        } else if (moneyToBeSubtracted.getAmount() > this.amount) {\n            throw new CannotSubtractException(\"The amount you are trying to subtract is larger than the amount you have\");\n        }\n        this.amount = roundToTwoDecimals(this.amount - moneyToBeSubtracted.getAmount());\n    }\n\n    public void multiply(int factor) {\n        if (factor < 0) {\n            throw new IllegalArgumentException(\"Factor must be non-negative\");\n        }\n        this.amount = roundToTwoDecimals(this.amount * factor);\n    }\n\n    public void exchangeCurrency(String currencyToChangeTo, double exchangeRate) {\n        if (exchangeRate < 0) {\n            throw new IllegalArgumentException(\"Exchange rate must be non-negative\");\n        }\n        this.amount = roundToTwoDecimals(this.amount * exchangeRate);\n        this.currency = currencyToChangeTo;\n    }\n}\n```\n\nBy encapsulating all money-related logic in a single class, we reduce the risk of mixing different currencies, improve clarity of the codebase, and facilitate future modifications such as adding new currencies or refining rounding rules. This pattern ultimately strengthens the domain model by treating money as a distinct concept rather than just another numeric value.\n\n## When to Use the Money Pattern\n\n* When financial calculations or money manipulations are part of the business logic\n* When precise handling of currency amounts is required to avoid floating-point inaccuracies\n* When domain-driven design principles and strong typing are desired\n\n## Real-World Applications of Monad Pattern in Java\n\n* JSR 354 (Java Money and Currency) library in Java\n* Custom domain models in e-commerce and accounting systems\n\n## Benefits and Trade-offs of Money Pattern\n\nBenefits\n\n* Provides a single, type-safe representation of monetary amounts and currency\n* Encourages encapsulation of related operations such as addition, subtraction, and formatting\n* Avoids floating-point errors by using integers or specialized decimal libraries\n\nTrade-offs\n\n* Requires additional classes and infrastructure to handle currency conversions and formatting\n* Might introduce performance overhead when performing large numbers of money operations\n\n## Related Design Patterns\n\n* [Value Object](https://java-design-patterns.com/patterns/value-object/): Money is typically a prime example of a domain-driven design value object.\n\n## References and Credits\n\n* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3wlDrze)\n* [Implementing Domain-Driven Design](https://amzn.to/4dmBjrB)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "money/etc/money.urm.puml",
    "content": "@startuml\npackage com.iluwatar {\n  class App {\n    - logger : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Money {\n    - amount : double\n    - currency : String\n    + Money(amnt : double, curr : String)\n    + addMoney(moneyToBeAdded : Money)\n    + exchangeCurrency(currencyToChangeTo : String, exchangeRate : double)\n    + getAmount() : double\n    + getCurrency() : String\n    + multiply(factor : int)\n    - roundToTwoDecimals(value : double) : double\n    + subtractMoney(moneyToBeSubtracted : Money)\n  }\n}\n@enduml"
  },
  {
    "path": "money/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>money</artifactId>\n\n\n    <dependencies>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "money/src/main/java/com/iluwatar/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\n\n/**\n * The `App` class demonstrates the functionality of the {@link Money} class, which encapsulates\n * monetary values and their associated currencies. It showcases operations like addition,\n * subtraction, multiplication, and currency conversion, while ensuring validation and immutability.\n *\n * <p>Through this example, the handling of invalid operations (e.g., mismatched currencies or\n * invalid inputs) is demonstrated using custom exceptions. Logging is used for transparency.\n *\n * <p>This highlights the practical application of object-oriented principles such as encapsulation\n * and validation in a financial context.\n */\npublic class App {\n\n  // Initialize the logger\n  private static final Logger logger = Logger.getLogger(App.class.getName());\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    // Create instances of Money\n    Money usdAmount1 = new Money(50.00, \"USD\");\n    Money usdAmount2 = new Money(20.00, \"USD\");\n\n    // Demonstrate addition\n    try {\n      usdAmount1.addMoney(usdAmount2);\n      logger.log(Level.INFO, \"Sum in USD: {0}\", usdAmount1.getAmount());\n    } catch (CannotAddTwoCurrienciesException e) {\n      logger.log(Level.SEVERE, \"Error adding money: {0}\", e.getMessage());\n    }\n\n    // Demonstrate subtraction\n    try {\n      usdAmount1.subtractMoney(usdAmount2);\n      logger.log(Level.INFO, \"Difference in USD: {0}\", usdAmount1.getAmount());\n    } catch (CannotSubtractException e) {\n      logger.log(Level.SEVERE, \"Error subtracting money: {0}\", e.getMessage());\n    }\n\n    // Demonstrate multiplication\n    try {\n      usdAmount1.multiply(2);\n      logger.log(Level.INFO, \"Multiplied Amount in USD: {0}\", usdAmount1.getAmount());\n    } catch (IllegalArgumentException e) {\n      logger.log(Level.SEVERE, \"Error multiplying money: {0}\", e.getMessage());\n    }\n\n    // Demonstrate currency conversion\n    try {\n      double exchangeRateUsdToEur = 0.85; // Example exchange rate\n      usdAmount1.exchangeCurrency(\"EUR\", exchangeRateUsdToEur);\n      logger.log(\n          Level.INFO,\n          \"USD converted to EUR: {0} {1}\",\n          new Object[] {usdAmount1.getAmount(), usdAmount1.getCurrency()});\n    } catch (IllegalArgumentException e) {\n      logger.log(Level.SEVERE, \"Error converting currency: {0}\", e.getMessage());\n    }\n  }\n}\n"
  },
  {
    "path": "money/src/main/java/com/iluwatar/CannotAddTwoCurrienciesException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\n/** An exception for when the user tries to add two diffrent currencies. */\npublic class CannotAddTwoCurrienciesException extends Exception {\n  /**\n   * Constructs an exception with the specified message.\n   *\n   * @param message the message shown in the terminal (as a String).\n   */\n  public CannotAddTwoCurrienciesException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "money/src/main/java/com/iluwatar/CannotSubtractException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\n/**\n * An exception for when the user tries to subtract two different currencies or subtract an amount\n * he doesn't have.\n */\npublic class CannotSubtractException extends Exception {\n  /**\n   * Constructs an exception with the specified message.\n   *\n   * @param message the message shown in the terminal (as a String).\n   */\n  public CannotSubtractException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "money/src/main/java/com/iluwatar/Money.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\n/**\n * Represents a monetary value with an associated currency. Provides operations for basic arithmetic\n * (addition, subtraction, multiplication), as well as currency conversion while ensuring proper\n * rounding.\n */\n@AllArgsConstructor\n@Getter\npublic class Money {\n  private double amount;\n  private String currency;\n\n  /**\n   * Rounds the given value to two decimal places.\n   *\n   * @param value the value to round.\n   * @return the rounded value, up to two decimal places.\n   */\n  private double roundToTwoDecimals(double value) {\n    return Math.round(value * 100.0) / 100.0;\n  }\n\n  /**\n   * Adds another Money object to the current instance.\n   *\n   * @param moneyToBeAdded the Money object to add.\n   * @throws CannotAddTwoCurrienciesException if the currencies do not match.\n   */\n  public void addMoney(Money moneyToBeAdded) throws CannotAddTwoCurrienciesException {\n    if (!moneyToBeAdded.getCurrency().equals(this.currency)) {\n      throw new CannotAddTwoCurrienciesException(\"You are trying to add two different currencies\");\n    }\n    this.amount = roundToTwoDecimals(this.amount + moneyToBeAdded.getAmount());\n  }\n\n  /**\n   * Subtracts another Money object from the current instance.\n   *\n   * @param moneyToBeSubtracted the Money object to subtract.\n   * @throws CannotSubtractException if the currencies do not match or if the amount to subtract is\n   *     larger than the current amount.\n   */\n  public void subtractMoney(Money moneyToBeSubtracted) throws CannotSubtractException {\n    if (!moneyToBeSubtracted.getCurrency().equals(this.currency)) {\n      throw new CannotSubtractException(\"You are trying to subtract two different currencies\");\n    } else if (moneyToBeSubtracted.getAmount() > this.amount) {\n      throw new CannotSubtractException(\n          \"The amount you are trying to subtract is larger than the amount you have\");\n    }\n    this.amount = roundToTwoDecimals(this.amount - moneyToBeSubtracted.getAmount());\n  }\n\n  /**\n   * Multiplies the current amount of money by a factor.\n   *\n   * @param factor the factor to multiply by.\n   * @throws IllegalArgumentException if the factor is negative.\n   */\n  public void multiply(int factor) {\n    if (factor < 0) {\n      throw new IllegalArgumentException(\"Factor must be non-negative\");\n    }\n    this.amount = roundToTwoDecimals(this.amount * factor);\n  }\n\n  /**\n   * Converts the current amount of money to another currency using the provided exchange rate.\n   *\n   * @param currencyToChangeTo the new currency to convert to.\n   * @param exchangeRate the exchange rate to convert from the current currency to the new currency.\n   * @throws IllegalArgumentException if the exchange rate is negative.\n   */\n  public void exchangeCurrency(String currencyToChangeTo, double exchangeRate) {\n    if (exchangeRate < 0) {\n      throw new IllegalArgumentException(\"Exchange rate must be non-negative\");\n    }\n    this.amount = roundToTwoDecimals(this.amount * exchangeRate);\n    this.currency = currencyToChangeTo;\n  }\n}\n"
  },
  {
    "path": "money/src/test/java/com/iluwater/money/MoneyTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwater.money;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport com.iluwatar.App;\nimport com.iluwatar.CannotAddTwoCurrienciesException;\nimport com.iluwatar.CannotSubtractException;\nimport com.iluwatar.Money;\nimport org.junit.jupiter.api.Test;\n\nclass MoneyTest {\n\n  @Test\n  void testConstructor() {\n    // Test the constructor\n    Money money = new Money(100.00, \"USD\");\n    assertEquals(100.00, money.getAmount());\n    assertEquals(\"USD\", money.getCurrency());\n  }\n\n  @Test\n  void testAddMoney_SameCurrency() throws CannotAddTwoCurrienciesException {\n    // Test adding two Money objects with the same currency\n    Money money1 = new Money(100.00, \"USD\");\n    Money money2 = new Money(50.25, \"USD\");\n\n    money1.addMoney(money2);\n\n    assertEquals(150.25, money1.getAmount(), \"Amount after addition should be 150.25\");\n  }\n\n  @Test\n  void testAddMoney_DifferentCurrency() {\n    // Test adding two Money objects with different currencies\n    Money money1 = new Money(100.00, \"USD\");\n    Money money2 = new Money(50.25, \"EUR\");\n\n    assertThrows(CannotAddTwoCurrienciesException.class, () -> money1.addMoney(money2));\n  }\n\n  @Test\n  void testSubtractMoney_SameCurrency() throws CannotSubtractException {\n    // Test subtracting two Money objects with the same currency\n    Money money1 = new Money(100.00, \"USD\");\n    Money money2 = new Money(50.25, \"USD\");\n\n    money1.subtractMoney(money2);\n\n    assertEquals(49.75, money1.getAmount(), \"Amount after subtraction should be 49.75\");\n  }\n\n  @Test\n  void testSubtractMoney_DifferentCurrency() {\n    // Test subtracting two Money objects with different currencies\n    Money money1 = new Money(100.00, \"USD\");\n    Money money2 = new Money(50.25, \"EUR\");\n\n    assertThrows(CannotSubtractException.class, () -> money1.subtractMoney(money2));\n  }\n\n  @Test\n  void testSubtractMoney_AmountTooLarge() {\n    // Test subtracting an amount larger than the current amount\n    Money money1 = new Money(50.00, \"USD\");\n    Money money2 = new Money(60.00, \"USD\");\n\n    assertThrows(CannotSubtractException.class, () -> money1.subtractMoney(money2));\n  }\n\n  @Test\n  void testMultiply() {\n    // Test multiplying the money amount by a factor\n    Money money = new Money(100.00, \"USD\");\n\n    money.multiply(3);\n\n    assertEquals(300.00, money.getAmount(), \"Amount after multiplication should be 300.00\");\n  }\n\n  @Test\n  void testMultiply_NegativeFactor() {\n    // Test multiplying by a negative factor\n    Money money = new Money(100.00, \"USD\");\n\n    assertThrows(IllegalArgumentException.class, () -> money.multiply(-2));\n  }\n\n  @Test\n  void testExchangeCurrency() {\n    // Test converting currency using an exchange rate\n    Money money = new Money(100.00, \"USD\");\n\n    money.exchangeCurrency(\"EUR\", 0.85);\n\n    assertEquals(\"EUR\", money.getCurrency(), \"Currency after conversion should be EUR\");\n    assertEquals(85.00, money.getAmount(), \"Amount after conversion should be 85.00\");\n  }\n\n  @Test\n  void testExchangeCurrency_NegativeExchangeRate() {\n    // Test converting currency with a negative exchange rate\n    Money money = new Money(100.00, \"USD\");\n\n    assertThrows(IllegalArgumentException.class, () -> money.exchangeCurrency(\"EUR\", -0.85));\n  }\n\n  @Test\n  void testAppExecution() {\n    assertDoesNotThrow(\n        () -> App.main(new String[] {}), \"App execution should not throw any exceptions\");\n  }\n}\n"
  },
  {
    "path": "monitor/README.md",
    "content": "---\ntitle: \"Monitor Pattern in Java: Implementing Robust Locking Mechanisms with Monitors\"\nshortTitle: Monitor\ndescription: \"Learn how the Monitor design pattern in Java ensures thread safety and synchronization. Explore examples, applicability, and benefits of using monitors in concurrent programming.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Encapsulation\n  - Fault tolerance\n  - Isolation\n  - Synchronization\n  - Thread management\n---\n\n## Also known as\n\n* Synchronized Block\n\n## Intent of Monitor Design Pattern\n\nThe Monitor design pattern in Java is essential for synchronizing concurrent operations, ensuring thread safety and preventing race conditions.\n\n## Detailed Explanation of Monitor Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a shared office printer that several employees need to use. The printer can only handle one print job at a time to avoid mixing up pages from different documents. This scenario is analogous to the Monitor design pattern in programming.\n>\n> In this example, the printer represents the shared resource, and the employees are analogous to threads. A system is set up where each employee must request access to the printer before starting their print job. This system ensures that only one employee (or \"thread\") can use the printer at a time, preventing any overlap or interference between jobs. Once a print job is complete, the next employee in the queue can access the printer. This mechanism mirrors the Monitor pattern's way of controlling access to a shared resource, ensuring orderly and safe use by multiple \"threads\" (employees).\n\nIn plain words\n\n> Monitor pattern is used to enforce single-threaded access to data. Only one thread at a time is allowed to execute code within the monitor object.\n\nWikipedia says\n\n> In concurrent programming (also known as parallel programming), a monitor is a synchronization construct that allows threads to have both mutual exclusion and the ability to wait (block) for a certain condition to become false. Monitors also have a mechanism for signaling other threads that their condition has been met.\n\nSequence diagram\n\n![Monitor sequence diagram](./etc/monitor-sequence-diagram.png)\n\n## Programmatic Example of Monitor Pattern in Java\n\nThe Monitor design pattern is a synchronization technique used in concurrent programming to ensure that only one thread can execute a particular section of code at a time. It is a method of wrapping and hiding the synchronization primitives (like semaphores or locks) within the methods of an object. This pattern is useful in situations where race conditions could occur.\n\nThe Java Monitor design pattern can be seen in the `Bank` class example. By using synchronized methods, the `Bank` class ensures that only one thread can perform transactions at any given time, illustrating effective use of the Monitor pattern in real-world applications.\n\nHere is a simplified version of the `Bank` class with additional comments:\n\n```java\npublic class Bank {\n\n    @Getter\n    private final int[] accounts;\n\n    public Bank(int accountNum, int baseAmount) {\n        accounts = new int[accountNum];\n        Arrays.fill(accounts, baseAmount);\n    }\n\n    public synchronized void transfer(int accountA, int accountB, int amount) {\n        // Only one thread can execute this method at a time due to the 'synchronized' keyword.\n        if (accounts[accountA] >= amount && accountA != accountB) {\n            accounts[accountB] += amount;\n            accounts[accountA] -= amount;\n        }\n    }\n\n    public synchronized int getBalance() {\n        // Only one thread can execute this method at a time due to the 'synchronized' keyword.\n        int balance = 0;\n        for (int account : accounts) {\n            balance += account;\n        }\n        return balance;\n    }\n\n    public synchronized int getBalance(int accountNumber) {\n        // Only one thread can execute this method at a time due to the 'synchronized' keyword.\n        return accounts[accountNumber];\n    }\n}\n```\n\nIn the `Main` class, multiple threads are created to perform transactions on the bank accounts. The `Bank` class, acting as a monitor, ensures that these transactions are performed in a thread-safe manner.\n\n```java\npublic class Main {\n\n    private static final int NUMBER_OF_THREADS = 5;\n    private static final int BASE_AMOUNT = 1000;\n    private static final int ACCOUNT_NUM = 4;\n\n    public static void runner(Bank bank, CountDownLatch latch) {\n        try {\n            SecureRandom random = new SecureRandom();\n            Thread.sleep(random.nextInt(1000));\n            for (int i = 0; i < 1000000; i++) {\n                bank.transfer(random.nextInt(4), random.nextInt(4), random.nextInt(0, BASE_AMOUNT));\n            }\n            latch.countDown();\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n        }\n    }\n\n    public static void main(String[] args) throws InterruptedException {\n        var bank = new Bank(ACCOUNT_NUM, BASE_AMOUNT);\n        var latch = new CountDownLatch(NUMBER_OF_THREADS);\n        var executorService = Executors.newFixedThreadPool(NUMBER_OF_THREADS);\n\n        for (int i = 0; i < NUMBER_OF_THREADS; i++) {\n            executorService.execute(() -> runner(bank, latch));\n        }\n\n        latch.await();\n    }\n}\n```\n\nIn this example, the `Bank` class is the monitor, and the `transfer` method is the critical section that needs to be executed in a mutually exclusive manner. The `synchronized` keyword in Java is used to implement the Monitor pattern, ensuring that only one thread can execute the `transfer` method at a time.\n\n## When to Use the Monitor Pattern in Java\n\nThe Monitor design pattern should be used in situations where you have shared resources that need to be accessed and manipulated by multiple threads or processes concurrently. This pattern is particularly useful in scenarios where synchronization is necessary to prevent race conditions, data corruption, and inconsistent states. Here are some situations where you should consider using the Monitor pattern:\n\n1. **Shared Data**: When your application involves shared data structures, variables, or resources that need to be accessed and updated by multiple threads. Monitors ensure that only one thread can access the shared resource at a time, preventing conflicts and ensuring data consistency.\n\n2. **Critical Sections**: When you have critical sections of code that need to be executed by only one thread at a time. Critical sections are portions of code where shared resources are manipulated, and concurrent access could lead to problems. Monitors help ensure that only one thread can execute the critical section at any given time.\n\n3. **Thread Safety**: When you need to ensure thread safety without relying solely on low-level synchronization mechanisms like locks and semaphores. Monitors provide a higher-level abstraction that encapsulates synchronization and resource management.\n\n4. **Waiting and Signaling**: When you have scenarios where threads need to wait for certain conditions to be met before proceeding. Monitors often include mechanisms for threads to wait for specific conditions and for other threads to notify them when the conditions are satisfied.\n\n5. **Deadlock Prevention**: When you want to prevent deadlocks by providing a structured way to acquire and release locks on shared resources. Monitors help avoid common deadlock scenarios by ensuring that resource access is well-managed.\n\n6. **Concurrent Data Structures**: When you're implementing concurrent data structures, such as queues, stacks, or hash tables, where multiple threads need to manipulate the structure while maintaining its integrity.\n\n7. **Resource Sharing**: When multiple threads need to share limited resources, like connections to a database or access to a network socket. Monitors can help manage the allocation and release of these resources in a controlled manner.\n\n8. **Improved Maintainability**: When you want to encapsulate synchronization logic and shared resource management within a single object, improving code organization and making it easier to reason about concurrency-related code.\n\nHowever, it's important to note that the Monitor pattern might not be the best fit for all concurrency scenarios. In some cases, other synchronization mechanisms like locks, semaphores, or concurrent data structures might be more suitable. Additionally, modern programming languages and frameworks often provide higher-level concurrency constructs that abstract away the complexities of low-level synchronization.\n\nBefore applying the Monitor pattern, it's recommended to thoroughly analyze your application's concurrency requirements and choose the synchronization approach that best suits your needs, taking into consideration factors like performance, complexity, and available language features.\n\n## Real-World Applications of Monitor Pattern in Java\n\nCommon implementations of the Monitor design pattern in Java include synchronized methods and blocks, as well as concurrent data structures like `Vector` and `Hashtable`.\n\n## Benefits and Trade-offs of Monitor Pattern\n\nBenefits:\n\n* Ensures mutual exclusion, preventing race conditions.\n* Simplifies the complexity of thread management by providing a clear structure for resource access.\n\nTrade-offs:\n\n* Can lead to decreased performance due to locking overhead.\n* Potential for deadlocks if not carefully designed.\n\n## Related Java Design Patterns\n\nSemaphore: Used to control access to a common resource by multiple threads; Monitor uses a binary semaphore concept at its core.\nMutex: Another mechanism for ensuring mutual exclusion; Monitor is a higher-level construct often implemented using mutexes.\n\n## References and Credits\n\n* [Concurrency: State Models & Java Programs](https://amzn.to/4dxxjUX)\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n"
  },
  {
    "path": "monitor/etc/monitor.urm.puml",
    "content": "@startuml\nMain - Bank : use\nclass Main{\n    + main(args : String[]) : void\n}\nclass Bank{\n    - accounts : int[]\n    + Bank (accountNum : int , baseAccount : int)\n    + transfer(accountA : int , accountB : int , amount : int) : void {synchronized}\n    - getBalance() : void {synchronized}\n}\n@enduml\n"
  },
  {
    "path": "monitor/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>monitor</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <!-- Maven assembly plugin is invoked with default setting which we have\n                in parent pom and specifying the class having main method -->\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.monitor.Main</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "monitor/src/main/java/com/iluwatar/monitor/Bank.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n/*\n *The MIT License\n *Copyright © 2014-2021 Ilkka Seppälä\n *\n *Permission is hereby granted, free of charge, to any person obtaining a copy\n *of this software and associated documentation files (the \"Software\"), to deal\n *in the Software without restriction, including without limitation the rights\n *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n *copies of the Software, and to permit persons to whom the Software is\n *furnished to do so, subject to the following conditions:\n *\n *The above copyright notice and this permission notice shall be included in\n *all copies or substantial portions of the Software.\n *\n *THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n *THE SOFTWARE.\n */\n\npackage com.iluwatar.monitor;\n\nimport java.util.Arrays;\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Bank Definition. */\n@Slf4j\npublic class Bank {\n\n  @Getter private final int[] accounts;\n\n  /**\n   * Constructor.\n   *\n   * @param accountNum - account number\n   * @param baseAmount - base amount\n   */\n  public Bank(int accountNum, int baseAmount) {\n    accounts = new int[accountNum];\n    Arrays.fill(accounts, baseAmount);\n  }\n\n  /**\n   * Transfer amounts from one account to another.\n   *\n   * @param accountA - source account\n   * @param accountB - destination account\n   * @param amount - amount to be transferred\n   */\n  public synchronized void transfer(int accountA, int accountB, int amount) {\n    if (accounts[accountA] >= amount && accountA != accountB) {\n      accounts[accountB] += amount;\n      accounts[accountA] -= amount;\n      if (LOGGER.isDebugEnabled()) {\n        LOGGER.debug(\n            \"Transferred from account: {} to account: {} , amount: {} , bank balance at: {}, source account balance: {}, destination account balance: {}\",\n            accountA,\n            accountB,\n            amount,\n            getBalance(),\n            getBalance(accountA),\n            getBalance(accountB));\n      }\n    }\n  }\n\n  /**\n   * Calculates the total balance.\n   *\n   * @return balance\n   */\n  public synchronized int getBalance() {\n    int balance = 0;\n    for (int account : accounts) {\n      balance += account;\n    }\n    return balance;\n  }\n\n  /**\n   * Get the accountNumber balance.\n   *\n   * @param accountNumber - accountNumber number\n   * @return accounts[accountNumber]\n   */\n  public synchronized int getBalance(int accountNumber) {\n    return accounts[accountNumber];\n  }\n}\n"
  },
  {
    "path": "monitor/src/main/java/com/iluwatar/monitor/Main.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monitor;\n\nimport java.security.SecureRandom;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.Executors;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Monitor pattern is used in concurrent algorithms to achieve mutual exclusion.\n *\n * <p>Bank is a simple class that transfers money from an account to another account using {@link\n * Bank#transfer}. It can also return the balance of the bank account stored in the bank.\n *\n * <p>Main class uses ThreadPool to run threads that do transactions on the bank accounts.\n */\n@Slf4j\npublic class Main {\n\n  private static final int NUMBER_OF_THREADS = 5;\n  private static final int BASE_AMOUNT = 1000;\n  private static final int ACCOUNT_NUM = 4;\n\n  /**\n   * Runner to perform a bunch of transfers and handle exception.\n   *\n   * @param bank bank object\n   * @param latch signal finished execution\n   */\n  public static void runner(Bank bank, CountDownLatch latch) {\n    try {\n      SecureRandom random = new SecureRandom();\n      Thread.sleep(random.nextInt(1000));\n      LOGGER.info(\"Start transferring...\");\n      for (int i = 0; i < 1000000; i++) {\n        bank.transfer(random.nextInt(4), random.nextInt(4), random.nextInt(0, BASE_AMOUNT));\n      }\n      LOGGER.info(\"Finished transferring.\");\n      latch.countDown();\n    } catch (InterruptedException e) {\n      LOGGER.error(e.getMessage());\n      Thread.currentThread().interrupt();\n    }\n  }\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) throws InterruptedException {\n    var bank = new Bank(ACCOUNT_NUM, BASE_AMOUNT);\n    var latch = new CountDownLatch(NUMBER_OF_THREADS);\n    var executorService = Executors.newFixedThreadPool(NUMBER_OF_THREADS);\n\n    for (int i = 0; i < NUMBER_OF_THREADS; i++) {\n      executorService.execute(() -> runner(bank, latch));\n    }\n\n    latch.await();\n  }\n}\n"
  },
  {
    "path": "monitor/src/test/java/com/iluwatar/monitor/BankTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monitor;\n\nimport static org.junit.jupiter.api.Assertions.*;\nimport static org.junit.jupiter.api.Assumptions.*;\n\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nclass BankTest {\n\n  private static final int ACCOUNT_NUM = 4;\n  private static final int BASE_AMOUNT = 1000;\n  private static Bank bank;\n\n  @BeforeAll\n  public static void Setup() {\n    bank = new Bank(ACCOUNT_NUM, BASE_AMOUNT);\n  }\n\n  @AfterAll\n  public static void TearDown() {\n    bank = null;\n  }\n\n  @Test\n  void GetAccountHaveNotBeNull() {\n    assertNotNull(bank.getAccounts());\n  }\n\n  @Test\n  void LengthOfAccountsHaveToEqualsToAccountNumConstant() {\n    assumeTrue(bank.getAccounts() != null);\n    assertEquals(ACCOUNT_NUM, bank.getAccounts().length);\n  }\n\n  @Test\n  void TransferMethodHaveToTransferAmountFromAnAccountToOtherAccount() {\n    bank.transfer(0, 1, 1000);\n    int[] accounts = bank.getAccounts();\n    assertEquals(0, accounts[0]);\n    assertEquals(2000, accounts[1]);\n  }\n\n  @Test\n  void BalanceHaveToBeOK() {\n    assertEquals(4000, bank.getBalance());\n  }\n\n  @Test\n  void ReturnBalanceWhenGivenAccountNumber() {\n    bank.transfer(0, 1, 1000);\n    assertEquals(0, bank.getBalance(0));\n    assertEquals(2000, bank.getBalance(1));\n  }\n}\n"
  },
  {
    "path": "monitor/src/test/java/com/iluwatar/monitor/MainTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monitor;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.concurrent.CountDownLatch;\nimport org.junit.jupiter.api.Test;\n\n/** Test if the application starts without throwing an exception. */\nclass MainTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> Main.main(new String[] {}));\n  }\n\n  @Test\n  void runnerShouldExecuteWithoutException() {\n    var bank = new Bank(4, 1000);\n    var latch = new CountDownLatch(1);\n\n    assertDoesNotThrow(() -> Main.runner(bank, latch));\n    assertEquals(0, latch.getCount());\n  }\n}\n"
  },
  {
    "path": "monitor/src/test/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<configuration>\n    <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n        <encoder>\n            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n    <root level=\"info\">\n        <appender-ref ref=\"STDOUT\" />\n    </root>\n</configuration>\n"
  },
  {
    "path": "monolithic-architecture/README.md",
    "content": "---\ntitle: \"Monolithic Architecture in Java: A Cohesive Application Model\"\nshortTitle: Monolithic Architecture\ndescription: \"Explore the Monolithic Architecture application structure, its design intent, benefits, limitations, and real-world applications. Understand its simplicity and practical use cases.\"\ncategory: Architectural\nlanguage: en\ntag:\n    - Architecture\n    - Cohesion\n    - Encapsulation\n    - Layered architecture\n    - Modularity\n---\n\n## Also known as\n\n* Single-tier architecture\n* Monolith\n\n## The Intent of Monolithic Design pattern\n\nEncapsulate all the functionality of an application within a single, cohesive codebase.\n\n## Detailed Explanation of the Monolithic Architecture\n\nReal-world example\n\n> An analogous real-world example of the Monolithic Architecture pattern is a department store. Just like a monolithic Java application, a department store hosts all product categories, sales, storage, and customer services within a single, large building. It simplifies shopping by consolidating everything under one roof, making operations straightforward and easy to manage. However, expanding or rearranging specific departments becomes increasingly challenging over time, similar to how scaling individual functionalities within a monolithic system can become complex and cumbersome.\n\nIn plain words\n\n> The monolithic design pattern structures an application as a single unified unit, where all components are tightly coupled and run within a single process.\n\nWikipedia says\n\n> In software engineering, a monolithic application is a single unified software application that is self-contained and independent of other applications, but typically lacks flexibility. There are advantages and disadvantages of building applications in a monolithic style of software architecture, depending on requirements. Monolith applications are relatively simple and have a low cost but their shortcomings are lack of elasticity, fault tolerance and scalability.\n\nMind map\n\n![Monolithic Architecture Mind Map](./etc/monolithic-architecture-mind-map.png)\n\nFlowchart\n\n![Monolithic Architecture Flowchart](./etc/monolithic-architecture-flowchart.png)\n\n## Programmatic Example of Monolithic Architecture in Java\n\nThis is a simplified version of the main application, demonstrating how a monolithic architecture can be implemented. Here, all the essential services—such as user management (`UserCon`), product management (`ProductCon`), and order processing (`OrderCon`) — are tightly integrated within a single executable Java application. The CLI provides a straightforward user interaction point where operations like user registration, adding products, and placing orders are handled.\n\n```java\n@SpringBootApplication\npublic class EcommerceApp implements CommandLineRunner {\n\n  private static final Logger log = LogManager.getLogger(EcommerceApp.class);\n  private final UserCon userService;\n  private final ProductCon productService;\n  private final OrderCon orderService;\n  public EcommerceApp(UserCon userService, ProductCon productService, OrderCon orderService) {\n    this.userService = userService;\n    this.productService = productService;\n    this.orderService = orderService;\n  }\n  public static void main(String... args) {\n    SpringApplication.run(EcommerceApp.class, args);\n  }\n  @Override\n  public void run(String... args) {\n    Scanner scanner = new Scanner(System.in, StandardCharsets.UTF_8);\n\n    log.info(\"Welcome to the Monolithic E-commerce CLI!\");\n    while (true) {\n      log.info(\"\\nChoose an option:\");\n      log.info(\"1. Register User\");\n      log.info(\"2. Add Product\");\n      log.info(\"3. Place Order\");\n      log.info(\"4. Exit\");\n      log.info(\"Enter your choice: \");\n\n      int userInput = scanner.nextInt();\n      scanner.nextLine();\n\n      switch (userInput) {\n        case 1 -> registerUser(scanner);\n        case 2 -> addProduct(scanner);\n        case 3 -> placeOrder(scanner);\n        case 4 -> {\n          log.info(\"Exiting the application. Goodbye!\");\n          return;\n        }\n        default -> log.info(\"Invalid choice! Please try again.\");\n      }\n    }\n  }\n  protected void registerUser(Scanner scanner) {\n    log.info(\"Enter user details:\");\n    log.info(\"Name: \");\n    String name = scanner.nextLine();\n    log.info(\"Email: \");\n    String email = scanner.nextLine();\n    log.info(\"Password: \");\n    String password = scanner.nextLine();\n\n    User user = new User(null, name, email, password);\n    userService.registerUser(user);\n    log.info(\"User registered successfully!\");\n  }\n\n}\n```\n\nIn this example, the core business functionalities are closely interconnected, sharing common resources and residing within the same codebase. This approach simplifies initial application development, testing, and deployment, as each component can easily access the others directly without the overhead of inter-service communication. However, as the application grows, scaling individual components independently becomes more challenging, highlighting the key trade-off inherent in the monolithic architecture.\n\n## When to Use the Monolithic Architecture in Java\n\n* Suitable for small to medium-sized applications where simplicity, cohesive development, and ease of deployment outweigh scalability and flexibility requirements.\n* Applicable in contexts where initial rapid development and ease of testing are prioritized.\n\n## Real-World Applications of Monolithic Architecture in Java\n\n* Early-stage Java web applications developed using frameworks like Spring MVC, Java EE (Servlets/JSP), or frameworks like Play.\n* Traditional Java enterprise applications packaged and deployed as WAR or EAR files on application servers such as Apache Tomcat, Jetty, or WildFly.\n* Standalone Java applications and desktop applications packaged as single executable JAR files.\n\n## Benefits and Trade-offs of Monolithic Architecture\n\nBenefits:\n\n* Simpler to develop, test, and deploy as the application is a single unit.\n* Easier debugging and performance monitoring due to the single unified runtime.\n* Typically faster initial development and straightforward management of dependencies.\n\nTrade-offs:\n\n* Poor scalability and potential performance bottlenecks as the application grows.\n* Limited modularity, leading to increased complexity and harder maintainability over time.\n* Slow deployments and updates due to a single large codebase.\n* Difficult to scale individual functionalities independently.\n\n## Related Patterns\n\n* Microservices Architecture: Breaks down a monolithic application into independently deployable services, directly addressing the scalability and maintainability limitations of monoliths.\n* [Layered Architecture](https://java-design-patterns.com/patterns/layered-architecture/): Often used internally within monoliths to provide clear separation between presentation, business logic, and persistence layers.\n\n## References\n\n* [Building Microservices](https://amzn.to/3UACtrU)\n* [Fundamentals of Software Architecture: An Engineering Approach](https://amzn.to/4cx4A2N)\n* [Monolithic Architecture - System Design (GeeksforGeeks)](https://www.geeksforgeeks.org/monolithic-architecture-system-design/)\n* [Monolithic Application (Wikipedia)](https://en.wikipedia.org/wiki/Monolithic_application)\n* [Pattern: Monolithic Architecture (Microservices.io)](https://microservices.io/patterns/monolithic.html)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [What Is Monolithic Architecture? (IBM)](https://www.ibm.com/think/topics/monolithic-architecture)\n"
  },
  {
    "path": "monolithic-architecture/etc/Monolithic-Ecommerce.urm.puml",
    "content": "@startuml\npackage com.iluwatar.monolithic.model {\n  class Orders {\n    - id : Long\n    - product : Products\n    - quantity : Integer\n    - totalPrice : Double\n    - user : User\n    + Orders()\n    + Orders(id : Long, user : User, product : Products, quantity : Integer, totalPrice : Double)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getId() : Long\n    + getProduct() : Products\n    + getQuantity() : Integer\n    + getTotalPrice() : Double\n    + getUser() : User\n    + hashCode() : int\n    + setId(id : Long)\n    + setProduct(product : Products)\n    + setQuantity(quantity : Integer)\n    + setTotalPrice(totalPrice : Double)\n    + setUser(user : User)\n    + toString() : String\n  }\n  class Products {\n    - description : String\n    - id : Long\n    - name : String\n    - price : Double\n    - stock : Integer\n    + Products()\n    + Products(id : Long, name : String, description : String, price : Double, stock : Integer)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getDescription() : String\n    + getId() : Long\n    + getName() : String\n    + getPrice() : Double\n    + getStock() : Integer\n    + hashCode() : int\n    + setDescription(description : String)\n    + setId(id : Long)\n    + setName(name : String)\n    + setPrice(price : Double)\n    + setStock(stock : Integer)\n    + toString() : String\n  }\n  class User {\n    - email : String\n    - id : Long\n    - name : String\n    - password : String\n    + User()\n    + User(id : Long, name : String, email : String, password : String)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getEmail() : String\n    + getId() : Long\n    + getName() : String\n    + getPassword() : String\n    + hashCode() : int\n    + setEmail(email : String)\n    + setId(id : Long)\n    + setName(name : String)\n    + setPassword(password : String)\n    + toString() : String\n  }\n}\npackage com.iluwatar.monolithic.repository {\n  interface OrderRepo {\n  }\n  interface ProductRepo {\n  }\n  interface UserRepo {\n    + findByEmail(String) : User {abstract}\n  }\n}\npackage com.iluwatar.monolithic.controller {\n  class OrderCon {\n    - orderRepository : OrderRepo\n    - productRepository : ProductRepo\n    - userRepository : UserRepo\n    + OrderCon(orderRepository : OrderRepo, userRepository : UserRepo, productRepository : ProductRepo)\n    + placeOrder(userId : Long, productId : Long, quantity : Integer) : Orders\n  }\n  class ProductCon {\n    - productRepository : ProductRepo\n    + ProductCon(productRepository : ProductRepo)\n    + addProduct(product : Products) : Products\n    + getAllProducts() : List<Products>\n  }\n  class UserCon {\n    - userRepository : UserRepo\n    + UserCon(userRepository : UserRepo)\n    + registerUser(user : User) : User\n  }\n}\npackage com.iluwatar.monolithic {\n  class EcommerceApp {\n    - log : Logger {static}\n    - orderService : OrderCon\n    - productService : ProductCon\n    - userService : UserCon\n    + EcommerceApp(userService : UserCon, productService : ProductCon, orderService : OrderCon)\n    # addProduct(scanner : Scanner)\n    + main(args : String[]) {static}\n    # placeOrder(scanner : Scanner)\n    # registerUser(scanner : Scanner)\n    + run(args : String[])\n  }\n}\nUserCon -->  \"-userRepository\" UserRepo\nOrders -->  \"-user\" User\nOrderCon -->  \"-productRepository\" ProductRepo\nOrderCon -->  \"-userRepository\" UserRepo\nOrderCon -->  \"-orderRepository\" OrderRepo\nEcommerceApp -->  \"-userService\" UserCon\nEcommerceApp -->  \"-productService\" ProductCon\nProductCon -->  \"-productRepository\" ProductRepo\nOrders -->  \"-product\" Products\nEcommerceApp -->  \"-orderService\" OrderCon\n@enduml"
  },
  {
    "path": "monolithic-architecture/etc/monolithic-architecture.urm.puml",
    "content": "@startuml\npackage com.iluwatar.monolithic.model {\n  class Orders {\n    - id : Long\n    - product : Products\n    - quantity : Integer\n    - totalPrice : Double\n    - user : User\n    + Orders()\n    + Orders(id : Long, user : User, product : Products, quantity : Integer, totalPrice : Double)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getId() : Long\n    + getProduct() : Products\n    + getQuantity() : Integer\n    + getTotalPrice() : Double\n    + getUser() : User\n    + hashCode() : int\n    + setId(id : Long)\n    + setProduct(product : Products)\n    + setQuantity(quantity : Integer)\n    + setTotalPrice(totalPrice : Double)\n    + setUser(user : User)\n    + toString() : String\n  }\n  class Products {\n    - description : String\n    - id : Long\n    - name : String\n    - price : Double\n    - stock : Integer\n    + Products()\n    + Products(id : Long, name : String, description : String, price : Double, stock : Integer)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getDescription() : String\n    + getId() : Long\n    + getName() : String\n    + getPrice() : Double\n    + getStock() : Integer\n    + hashCode() : int\n    + setDescription(description : String)\n    + setId(id : Long)\n    + setName(name : String)\n    + setPrice(price : Double)\n    + setStock(stock : Integer)\n    + toString() : String\n  }\n  class User {\n    - email : String\n    - id : Long\n    - name : String\n    - password : String\n    + User()\n    + User(id : Long, name : String, email : String, password : String)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getEmail() : String\n    + getId() : Long\n    + getName() : String\n    + getPassword() : String\n    + hashCode() : int\n    + setEmail(email : String)\n    + setId(id : Long)\n    + setName(name : String)\n    + setPassword(password : String)\n    + toString() : String\n  }\n}\npackage com.iluwatar.monolithic.repository {\n  interface OrderRepo {\n  }\n  interface ProductRepo {\n  }\n  interface UserRepo {\n    + findByEmail(String) : User {abstract}\n  }\n}\npackage com.iluwatar.monolithic.controller {\n  class OrderCon {\n    - orderRepository : OrderRepo\n    - productRepository : ProductRepo\n    - userRepository : UserRepo\n    + OrderCon(orderRepository : OrderRepo, userRepository : UserRepo, productRepository : ProductRepo)\n    + placeOrder(userId : Long, productId : Long, quantity : Integer) : Orders\n  }\n  class ProductCon {\n    - productRepository : ProductRepo\n    + ProductCon(productRepository : ProductRepo)\n    + addProduct(product : Products) : Products\n    + getAllProducts() : List<Products>\n  }\n  class UserCon {\n    - userRepository : UserRepo\n    + UserCon(userRepository : UserRepo)\n    + registerUser(user : User) : User\n  }\n}\npackage com.iluwatar.monolithic {\n  class EcommerceApp {\n    - log : Logger {static}\n    - orderService : OrderCon\n    - productService : ProductCon\n    - userService : UserCon\n    + EcommerceApp(userService : UserCon, productService : ProductCon, orderService : OrderCon)\n    # addProduct(scanner : Scanner)\n    + main(args : String[]) {static}\n    # placeOrder(scanner : Scanner)\n    # registerUser(scanner : Scanner)\n    + run(args : String[])\n  }\n}\nUserCon -->  \"-userRepository\" UserRepo\nOrders -->  \"-user\" User\nOrderCon -->  \"-productRepository\" ProductRepo\nOrderCon -->  \"-userRepository\" UserRepo\nOrderCon -->  \"-orderRepository\" OrderRepo\nEcommerceApp -->  \"-userService\" UserCon\nOrders -->  \"-product\" Products\nProductCon -->  \"-productRepository\" ProductRepo\nEcommerceApp -->  \"-productService\" ProductCon\nEcommerceApp -->  \"-orderService\" OrderCon\n@enduml"
  },
  {
    "path": "monolithic-architecture/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n\n  <artifactId>monolithic-architecture</artifactId>\n\n  <dependencies>\n    <!-- Spring Boot Starter Web -->\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-web</artifactId>\n    </dependency>\n\n    <!-- Spring Boot Starter Data JPA -->\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-data-jpa</artifactId>\n    </dependency>\n\n    <!-- H2 Database -->\n    <dependency>\n      <groupId>com.h2database</groupId>\n      <artifactId>h2</artifactId>\n      <scope>runtime</scope>\n    </dependency>\n\n    <!-- Jakarta Persistence API -->\n    <dependency>\n      <groupId>jakarta.persistence</groupId>\n      <artifactId>jakarta.persistence-api</artifactId>\n      <version>3.2.0</version>\n    </dependency>\n\n    <!-- JUnit for Testing -->\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n\n    <!-- Mockito for Unit Testing -->\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.monolithic.EcommerceApp</mainClass>\n                </manifest>\n              </archive>\n              <descriptorRefs>\n                <descriptorRef>jar-with-dependencies</descriptorRef>\n              </descriptorRefs>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n\n\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/EcommerceApp.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic;\n\nimport com.iluwatar.monolithic.controller.OrderController;\nimport com.iluwatar.monolithic.controller.ProductController;\nimport com.iluwatar.monolithic.controller.UserController;\nimport com.iluwatar.monolithic.model.Product;\nimport com.iluwatar.monolithic.model.User;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Scanner;\nimport org.apache.logging.log4j.LogManager;\nimport org.apache.logging.log4j.Logger;\nimport org.springframework.boot.CommandLineRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * Main entry point for the Monolithic E-commerce application.\n * ------------------------------------------------------------------------ Monolithic architecture\n * is a software design pattern where all components of the application (presentation, business\n * logic, and data access layers) are part of a single unified codebase and deployable unit.\n * ------------------------------------------------------------------------ This example implements\n * a monolithic architecture by integrating user management, product management, and order placement\n * within the same application, sharing common resources and a single database.\n */\n@SpringBootApplication\npublic class EcommerceApp implements CommandLineRunner {\n\n  private static final Logger log = LogManager.getLogger(EcommerceApp.class);\n  private final UserController userService;\n  private final ProductController productService;\n  private final OrderController orderService;\n\n  /** Initilizing controllers as services. */\n  public EcommerceApp(\n      UserController userService, ProductController productService, OrderController orderService) {\n    this.userService = userService;\n    this.productService = productService;\n    this.orderService = orderService;\n  }\n\n  /**\n   * The main entry point for the Monolithic E-commerce application. Initializes the Spring Boot\n   * application and starts the embedded server.\n   */\n  public static void main(String... args) {\n    SpringApplication.run(EcommerceApp.class, args);\n  }\n\n  @Override\n  public void run(String... args) {\n    Scanner scanner = new Scanner(System.in, StandardCharsets.UTF_8);\n\n    log.info(\"Welcome to the Monolithic E-commerce CLI!\");\n    while (true) {\n      log.info(\"\\nChoose an option:\");\n      log.info(\"1. Register User\");\n      log.info(\"2. Add Product\");\n      log.info(\"3. Place Order\");\n      log.info(\"4. Exit\");\n      log.info(\"Enter your choice: \");\n\n      int userInput = scanner.nextInt();\n      scanner.nextLine();\n\n      switch (userInput) {\n        case 1 -> registerUser(scanner);\n        case 2 -> addProduct(scanner);\n        case 3 -> placeOrder(scanner);\n        case 4 -> {\n          log.info(\"Exiting the application. Goodbye!\");\n          return;\n        }\n        default -> log.info(\"Invalid choice! Please try again.\");\n      }\n    }\n  }\n\n  /** Handles User Registration through user CLI inputs. */\n  protected void registerUser(Scanner scanner) {\n    log.info(\"Enter user details:\");\n    log.info(\"Name: \");\n    String name = scanner.nextLine();\n    log.info(\"Email: \");\n    String email = scanner.nextLine();\n    log.info(\"Password: \");\n    String password = scanner.nextLine();\n\n    User user = new User(null, name, email, password);\n    userService.registerUser(user);\n    log.info(\"User registered successfully!\");\n  }\n\n  /** Handles the addition of products. */\n  protected void addProduct(Scanner scanner) {\n    log.info(\"Enter product details:\");\n    log.info(\"Name: \");\n    String name = scanner.nextLine();\n    log.info(\"Description: \");\n    String description = scanner.nextLine();\n    log.info(\"Price: \");\n    double price = scanner.nextDouble();\n    log.info(\"Stock: \");\n    int stock = scanner.nextInt();\n    Product product = new Product(null, name, description, price, stock);\n    scanner.nextLine();\n    productService.addProduct(product);\n    log.info(\"Product added successfully!\");\n  }\n\n  /** Handles Order Placement through user CLI inputs. */\n  protected void placeOrder(Scanner scanner) {\n    log.info(\"Enter order details:\");\n    log.info(\"User ID: \");\n    long userId = scanner.nextLong();\n    log.info(\"Product ID: \");\n    long productId = scanner.nextLong();\n    log.info(\"Quantity: \");\n    int quantity = scanner.nextInt();\n    scanner.nextLine();\n\n    try {\n      orderService.placeOrder(userId, productId, quantity);\n      log.info(\"Order placed successfully!\");\n    } catch (Exception e) {\n      log.info(\"Error placing order: {}\", e.getMessage());\n    }\n  }\n}\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/controller/OrderController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic.controller;\n\nimport com.iluwatar.monolithic.exceptions.InsufficientStockException;\nimport com.iluwatar.monolithic.exceptions.NonExistentProductException;\nimport com.iluwatar.monolithic.exceptions.NonExistentUserException;\nimport com.iluwatar.monolithic.model.Order;\nimport com.iluwatar.monolithic.model.Product;\nimport com.iluwatar.monolithic.model.User;\nimport com.iluwatar.monolithic.repository.OrderRepository;\nimport com.iluwatar.monolithic.repository.ProductRepository;\nimport com.iluwatar.monolithic.repository.UserRepository;\nimport org.springframework.stereotype.Service;\n\n/** OrderController is a controller class for managing Order operations. */\n@Service\npublic class OrderController {\n  private final OrderRepository orderRepository;\n  private final UserRepository userRepository;\n  private final ProductRepository productRepository;\n\n  /** This function handles the initializing of the controller. */\n  public OrderController(\n      OrderRepository orderRepository,\n      UserRepository userRepository,\n      ProductRepository productRepository) {\n    this.orderRepository = orderRepository;\n    this.userRepository = userRepository;\n    this.productRepository = productRepository;\n  }\n\n  /** This function handles placing orders with all of its cases. */\n  public Order placeOrder(Long userId, Long productId, Integer quantity) {\n    final User user =\n        userRepository\n            .findById(userId)\n            .orElseThrow(\n                () -> new NonExistentUserException(\"User with ID \" + userId + \" not found\"));\n\n    final Product product =\n        productRepository\n            .findById(productId)\n            .orElseThrow(\n                () ->\n                    new NonExistentProductException(\"Product with ID \" + productId + \" not found\"));\n\n    if (product.getStock() < quantity) {\n      throw new InsufficientStockException(\"Not enough stock for product \" + productId);\n    }\n\n    product.setStock(product.getStock() - quantity);\n    productRepository.save(product);\n\n    final Order order = new Order(null, user, product, quantity, product.getPrice() * quantity);\n    return orderRepository.save(order);\n  }\n}\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/controller/ProductController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic.controller;\n\nimport com.iluwatar.monolithic.model.Product;\nimport com.iluwatar.monolithic.repository.ProductRepository;\nimport java.util.List;\nimport org.springframework.stereotype.Service;\n\n/** ProductCon is a controller class for managing Product operations. */\n@Service\npublic class ProductController {\n  private final ProductRepository productRepository;\n\n  /** Linking Controller to DB. */\n  public ProductController(ProductRepository productRepository) {\n    this.productRepository = productRepository;\n  }\n\n  /** Adds a product to the DB. */\n  public Product addProduct(Product product) {\n    return productRepository.save(product);\n  }\n\n  /** Returns all relevant Product. */\n  public List<Product> getAllProducts() {\n    return productRepository.findAll();\n  }\n}\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/controller/UserController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic.controller;\n\nimport com.iluwatar.monolithic.model.User;\nimport com.iluwatar.monolithic.repository.UserRepository;\nimport org.springframework.stereotype.Service;\n\n/** UserController is a controller class for managing user operations. */\n@Service\npublic class UserController {\n  private final UserRepository userRepository;\n\n  /** Linking Controller to DB. */\n  public UserController(UserRepository userRepository) {\n    this.userRepository = userRepository;\n  }\n\n  /** Adds a user to the DB. */\n  public User registerUser(User user) {\n    return userRepository.save(user);\n  }\n}\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/exceptions/InsufficientStockException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic.exceptions;\n\nimport java.io.Serial;\n\n/** Custom Exception class for enhanced readability. */\npublic class InsufficientStockException extends RuntimeException {\n  @Serial private static final long serialVersionUID = 1005208208127745099L;\n\n  /**\n   * Exception Constructor that is readable through code and provides the message inputted into it.\n   */\n  public InsufficientStockException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/exceptions/NonExistentProductException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic.exceptions;\n\nimport java.io.Serial;\n\n/** Custom Exception class for enhanced readability. */\npublic class NonExistentProductException extends RuntimeException {\n  @Serial private static final long serialVersionUID = -593425162052345565L;\n\n  /**\n   * Exception Constructor that is readable through code and provides the message inputted into it.\n   */\n  public NonExistentProductException(String msg) {\n    super(msg);\n  }\n}\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/exceptions/NonExistentUserException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic.exceptions;\n\nimport java.io.Serial;\n\n/** Custom Exception class for enhanced readability. */\npublic class NonExistentUserException extends RuntimeException {\n  @Serial private static final long serialVersionUID = -7660909426227843633L;\n\n  /**\n   * Exception Constructor that is readable through code and provides the message inputted into it.\n   */\n  public NonExistentUserException(String msg) {\n    super(msg);\n  }\n}\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/model/Order.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic.model;\n\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.GenerationType;\nimport jakarta.persistence.Id;\nimport jakarta.persistence.ManyToOne;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/** Represents a Database in which Order are stored. */\n@Entity\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class Order {\n  @Id\n  @GeneratedValue(strategy = GenerationType.IDENTITY)\n  private Long id;\n\n  @ManyToOne private User user;\n\n  @ManyToOne private Product product;\n\n  private Integer quantity;\n\n  private Double totalPrice;\n}\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/model/Product.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic.model;\n\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.GenerationType;\nimport jakarta.persistence.Id;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/** Represents a database of products. */\n@Entity\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class Product {\n  @Id\n  @GeneratedValue(strategy = GenerationType.IDENTITY)\n  private Long id;\n\n  private String name;\n\n  private String description;\n\n  private Double price;\n\n  private Integer stock;\n}\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/model/User.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic.model;\n\nimport jakarta.persistence.Column;\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.GenerationType;\nimport jakarta.persistence.Id;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/** Represents a Product entity for the database. */\n@Entity\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class User {\n  @Id\n  @GeneratedValue(strategy = GenerationType.IDENTITY)\n  private Long id;\n\n  private String name;\n\n  @Column(unique = true)\n  private String email;\n\n  private String password;\n}\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/repository/OrderRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic.repository;\n\nimport com.iluwatar.monolithic.model.Order;\nimport org.springframework.data.jpa.repository.JpaRepository;\n\n/** This interface allows JpaRepository to generate queries for the required tables. */\npublic interface OrderRepository extends JpaRepository<Order, Long> {}\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/repository/ProductRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic.repository;\n\nimport com.iluwatar.monolithic.model.Product;\nimport org.springframework.data.jpa.repository.JpaRepository;\n\n/** This interface allows JpaRepository to generate queries for the required tables. */\npublic interface ProductRepository extends JpaRepository<Product, Long> {}\n"
  },
  {
    "path": "monolithic-architecture/src/main/java/com/iluwatar/monolithic/repository/UserRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic.repository;\n\nimport com.iluwatar.monolithic.model.User;\nimport org.springframework.data.jpa.repository.JpaRepository;\n\n/** This interface allows JpaRepository to generate queries for the required tables. */\npublic interface UserRepository extends JpaRepository<User, Long> {\n  /**\n   * Utilizes JpaRepository functionalities to generate a function which looks up in the User table\n   * using emails.\n   */\n  User findByEmail(String email);\n}\n"
  },
  {
    "path": "monolithic-architecture/src/main/resources/application.properties",
    "content": "spring.datasource.driver-class-name=org.h2.Driver\nspring.datasource.password=password\nspring.datasource.url=jdbc:h2:mem:testdb\nspring.datasource.username=admin\nspring.h2.console.enabled=true\nspring.jpa.hibernate.ddl-auto=update\nspring.jpa.show-sql=true\n"
  },
  {
    "path": "monolithic-architecture/src/test/java/com/iluwatar/monolithic/MonolithicAppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monolithic;\n\nimport static org.junit.jupiter.api.Assertions.*;\nimport static org.mockito.Mockito.*;\n\nimport com.iluwatar.monolithic.controller.OrderController;\nimport com.iluwatar.monolithic.controller.ProductController;\nimport com.iluwatar.monolithic.controller.UserController;\nimport com.iluwatar.monolithic.exceptions.InsufficientStockException;\nimport com.iluwatar.monolithic.exceptions.NonExistentProductException;\nimport com.iluwatar.monolithic.exceptions.NonExistentUserException;\nimport com.iluwatar.monolithic.model.Order;\nimport com.iluwatar.monolithic.model.Product;\nimport com.iluwatar.monolithic.model.User;\nimport com.iluwatar.monolithic.repository.OrderRepository;\nimport com.iluwatar.monolithic.repository.ProductRepository;\nimport com.iluwatar.monolithic.repository.UserRepository;\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.PrintStream;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Locale;\nimport java.util.Optional;\nimport java.util.Scanner;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\n\nclass MonolithicAppTest {\n\n  @Mock private UserController userService;\n\n  @Mock private ProductController productService;\n\n  @Mock private OrderController orderService;\n\n  private EcommerceApp ecommerceApp;\n\n  private ByteArrayOutputStream outputStream;\n\n  @BeforeEach\n  void setUp() {\n    MockitoAnnotations.openMocks(this);\n    ecommerceApp = new EcommerceApp(userService, productService, orderService);\n    outputStream = new ByteArrayOutputStream();\n    System.setOut(new PrintStream(outputStream, true, StandardCharsets.UTF_8));\n    Locale.setDefault(Locale.US);\n  }\n\n  @Test\n  void testRegisterUser() {\n    String simulatedInput = \"John Doe\\njohn@example.com\\npassword123\\n\";\n    System.setIn(new ByteArrayInputStream(simulatedInput.getBytes(StandardCharsets.UTF_8)));\n\n    ecommerceApp.registerUser(new Scanner(System.in, StandardCharsets.UTF_8));\n\n    verify(userService, times(1)).registerUser(any(User.class));\n    assertTrue(outputStream.toString().contains(\"User registered successfully!\"));\n  }\n\n  @Test\n  void testPlaceOrderUserNotFound() {\n    UserRepository mockUserRepository = mock(UserRepository.class);\n    ProductRepository mockProductRepository = mock(ProductRepository.class);\n    OrderRepository mockOrderRepo = mock(OrderRepository.class);\n\n    when(mockUserRepository.findById(1L)).thenReturn(Optional.empty());\n\n    OrderController orderCon =\n        new OrderController(mockOrderRepo, mockUserRepository, mockProductRepository);\n\n    Exception exception =\n        assertThrows(NonExistentUserException.class, () -> orderCon.placeOrder(1L, 1L, 5));\n\n    assertEquals(\"User with ID 1 not found\", exception.getMessage());\n  }\n\n  @Test\n  void testPlaceOrderProductNotFound() {\n    UserRepository mockUserRepository = mock(UserRepository.class);\n    ProductRepository mockProductRepository = mock(ProductRepository.class);\n    OrderRepository mockOrderRepository = mock(OrderRepository.class);\n\n    User mockUser = new User(1L, \"John Doe\", \"john@example.com\", \"password123\");\n    when(mockUserRepository.findById(1L)).thenReturn(Optional.of(mockUser));\n\n    when(mockProductRepository.findById(1L)).thenReturn(Optional.empty());\n\n    OrderController orderCon =\n        new OrderController(mockOrderRepository, mockUserRepository, mockProductRepository);\n\n    Exception exception =\n        assertThrows(NonExistentProductException.class, () -> orderCon.placeOrder(1L, 1L, 5));\n\n    assertEquals(\"Product with ID 1 not found\", exception.getMessage());\n  }\n\n  @Test\n  void testOrderConstructor() {\n    OrderRepository mockOrderRepository = mock(OrderRepository.class);\n    UserRepository mockUserRepository = mock(UserRepository.class);\n    ProductRepository mockProductRepository = mock(ProductRepository.class);\n\n    OrderController orderCon =\n        new OrderController(mockOrderRepository, mockUserRepository, mockProductRepository);\n\n    assertNotNull(orderCon);\n  }\n\n  @Test\n  void testAddProduct() {\n    String simulatedInput = \"Laptop\\nGaming Laptop\\n1200.50\\n10\\n\";\n    System.setIn(new ByteArrayInputStream(simulatedInput.getBytes(StandardCharsets.UTF_8)));\n\n    ecommerceApp.addProduct(new Scanner(System.in, StandardCharsets.UTF_8));\n\n    verify(productService, times(1)).addProduct(any(Product.class));\n    assertTrue(outputStream.toString().contains(\"Product added successfully!\"));\n  }\n\n  @Test\n  void testPlaceOrderSuccess() {\n    String simulatedInput = \"1\\n2\\n3\\n\";\n    System.setIn(new ByteArrayInputStream(simulatedInput.getBytes(StandardCharsets.UTF_8)));\n\n    Order mockOrder = new Order();\n    doReturn(mockOrder).when(orderService).placeOrder(anyLong(), anyLong(), anyInt());\n\n    ecommerceApp.placeOrder(new Scanner(System.in, StandardCharsets.UTF_8));\n\n    verify(orderService, times(1)).placeOrder(anyLong(), anyLong(), anyInt());\n    assertTrue(outputStream.toString().contains(\"Order placed successfully!\"));\n  }\n\n  @Test\n  void testPlaceOrderFailure() {\n    String simulatedInput = \"1\\n2\\n3\\n\";\n    System.setIn(new ByteArrayInputStream(simulatedInput.getBytes(StandardCharsets.UTF_8)));\n\n    doThrow(new RuntimeException(\"Product out of stock\"))\n        .when(orderService)\n        .placeOrder(anyLong(), anyLong(), anyInt());\n\n    ecommerceApp.placeOrder(new Scanner(System.in, StandardCharsets.UTF_8));\n\n    verify(orderService, times(1)).placeOrder(anyLong(), anyLong(), anyInt());\n    assertTrue(outputStream.toString().contains(\"Error placing order: Product out of stock\"));\n  }\n\n  @Test\n  void testPlaceOrderInsufficientStock() {\n    UserRepository mockUserRepository = mock(UserRepository.class);\n    ProductRepository mockProductRepository = mock(ProductRepository.class);\n    OrderRepository mockOrderRepository = mock(OrderRepository.class);\n\n    User mockUser = new User(1L, \"John Doe\", \"john@example.com\", \"password123\");\n    when(mockUserRepository.findById(1L)).thenReturn(Optional.of(mockUser));\n    Product mockProduct =\n        new Product(1L, \"Laptop\", \"High-end gaming laptop\", 1500.00, 2); // Only 2 in stock\n    when(mockProductRepository.findById(1L)).thenReturn(Optional.of(mockProduct));\n\n    OrderController orderCon =\n        new OrderController(mockOrderRepository, mockUserRepository, mockProductRepository);\n\n    Exception exception =\n        assertThrows(InsufficientStockException.class, () -> orderCon.placeOrder(1L, 1L, 5));\n    assertEquals(\"Not enough stock for product 1\", exception.getMessage());\n  }\n\n  @Test\n  void testProductConAddProduct() {\n    ProductRepository mockProductRepository = mock(ProductRepository.class);\n\n    Product mockProduct = new Product(1L, \"Smartphone\", \"High-end smartphone\", 1000.00, 20);\n\n    when(mockProductRepository.save(any(Product.class))).thenReturn(mockProduct);\n\n    ProductController productController = new ProductController(mockProductRepository);\n\n    Product savedProduct = productController.addProduct(mockProduct);\n\n    verify(mockProductRepository, times(1)).save(any(Product.class));\n\n    assertNotNull(savedProduct);\n    assertEquals(\"Smartphone\", savedProduct.getName());\n    assertEquals(\"High-end smartphone\", savedProduct.getDescription());\n    assertEquals(1000.00, savedProduct.getPrice());\n    assertEquals(20, savedProduct.getStock());\n  }\n\n  @Test\n  void testRun() {\n    String simulatedInput =\n        \"\"\"\n        1\n        John Doe\n        john@example.com\n        password123\n        2\n        Laptop\n        Gaming Laptop\n        1200.50\n        10\n        3\n        1\n        1\n        2\n        4\n        \"\"\"; // Exit\n    System.setIn(new ByteArrayInputStream(simulatedInput.getBytes(StandardCharsets.UTF_8)));\n\n    ByteArrayOutputStream outputTest = new ByteArrayOutputStream();\n    System.setOut(new PrintStream(outputTest, true, StandardCharsets.UTF_8));\n\n    when(userService.registerUser(any(User.class)))\n        .thenReturn(new User(1L, \"John Doe\", \"john@example.com\", \"password123\"));\n    when(productService.addProduct(any(Product.class)))\n        .thenReturn(new Product(1L, \"Laptop\", \"Gaming Laptop\", 1200.50, 10));\n    when(orderService.placeOrder(anyLong(), anyLong(), anyInt()))\n        .thenReturn(\n            new Order(\n                1L,\n                new User(1L, \"John Doe\", \"john@example.com\", \"password123\"),\n                new Product(1L, \"Laptop\", \"Gaming Laptop\", 1200.50, 10),\n                5,\n                6002.50));\n\n    ecommerceApp.run();\n\n    verify(userService, times(1)).registerUser(any(User.class));\n    verify(productService, times(1)).addProduct(any(Product.class));\n    verify(orderService, times(1)).placeOrder(anyLong(), anyLong(), anyInt());\n\n    String output = outputTest.toString(StandardCharsets.UTF_8);\n    assertTrue(output.contains(\"Welcome to the Monolithic E-commerce CLI!\"));\n    assertTrue(output.contains(\"Choose an option:\"));\n    assertTrue(output.contains(\"Register User\"));\n    assertTrue(output.contains(\"Add Product\"));\n    assertTrue(output.contains(\"Place Order\"));\n    assertTrue(output.contains(\"Exiting the application. Goodbye!\"));\n  }\n}\n"
  },
  {
    "path": "monostate/README.md",
    "content": "---\ntitle: \"Monostate Pattern in Java: Achieving Singleton Behavior with Class-Level State\"\nshortTitle: Monostate\ndescription: \"Learn how the Monostate design pattern works in Java. Discover its benefits, implementation details, and use cases. Perfect for ensuring shared state across multiple class instances.\"\ncategory: Creational\nlanguage: en\ntag:\n  - Encapsulation\n  - Instantiation\n  - Object composition\n  - Persistence\n  - Polymorphism\n---\n\n## Also known as\n\n* Borg\n\n## Intent of Monostate Design Pattern\n\nThe Monostate pattern is an alternative approach to achieving a singleton-like behavior in object-oriented design, ensuring a shared state in Java applications. It enforces a unique behavior where all instances of a class share the same state. Unlike the Singleton pattern, which restricts a class to a single instance, Monostate allows for multiple instances but ensures they all have a shared state.\n\n## Detailed Explanation of Monostate Pattern with Real-World Examples\n\nReal-word example\n\n> Imagine a library with multiple desks where patrons can access the library's catalog. While each desk appears to be independent, any changes made to the catalog (like adding or removing a book) are immediately reflected at all desks. This setup ensures that no matter which desk a patron uses, they see the exact same, up-to-date catalog, similar to how the Monostate pattern maintains a shared state across all instances in Java. This is analogous to the Monostate pattern, where multiple instances of a class share the same state, ensuring consistent data across all instances.\n\nIn plain words\n\n> Monostate allows multiple instances of a class to share the same state by channeling their state management through a common shared structure. This ensures consistent state across all instances while maintaining the facade of independent objects.\n\nwiki.c2.com says\n\n> A monostate is a \"conceptual singleton\" - all data members of a monostate are static, so all instances of the monostate use the same (static) data. Applications using a monostate can create any number of instances that they desire, as each instance uses the same data.\n\nFlowchart\n\n![Monostate flowchart](./etc/monostate-flowchart.png)\n\n## Programmatic Example of Monostate Pattern in Java\n\nThe Monostate pattern in Java ensures that all instances of a class share the same state, making it a great Singleton alternative for maintaining consistent data. This is achieved by using static fields in the class. Any changes to these fields will be reflected across all instances of the class. This pattern is useful when you want to avoid global variables but still need a shared state across multiple instances.\n\nLet's take a look at the `LoadBalancer` class from the `monostate` module:\n\n```java\npublic class LoadBalancer {\n    private static List<Server> servers = new ArrayList<>();\n    private static int nextServerIndex = 0;\n\n    public LoadBalancer() {\n        // Initialize servers\n        servers.add(new Server(\"192.168.0.1\", 8080, 1));\n        servers.add(new Server(\"192.168.0.2\", 8080, 2));\n        servers.add(new Server(\"192.168.0.3\", 8080, 3));\n    }\n\n    public void serverRequest(Request request) {\n        Server server = servers.get(nextServerIndex);\n        server.serve(request);\n        nextServerIndex = (nextServerIndex + 1) % servers.size();\n    }\n}\n```\n\nIn this class, `servers` and `nextServerIndex` are static fields. This means that they are shared across all instances of `LoadBalancer`. The method `serverRequest` is used to serve a request and then update the `nextServerIndex` to the next server in the list.\n\nNow, let's see how this works in practice:\n\n```java\npublic class App {\n    public static void main(String[] args) {\n        LoadBalancer loadBalancer1 = new LoadBalancer();\n        LoadBalancer loadBalancer2 = new LoadBalancer();\n\n        // Both instances share the same state\n        loadBalancer1.serverRequest(new Request(\"Hello\"));  // Server 1 serves the request\n        loadBalancer2.serverRequest(new Request(\"Hello World\"));  // Server 2 serves the request\n    }\n}\n```\n\nIn this example, we create two instances of `LoadBalancer`: `loadBalancer1` and `loadBalancer2`. They share the same state. When we make a request via `loadBalancer1`, the request is served by the first server. When we make a request via `loadBalancer2`, the request is served by the second server, not the first one, because the `nextServerIndex` has been updated by `loadBalancer1`. This demonstrates the Monostate pattern in action.\n\n## When to Use the Monostate Pattern in Java\n\nUse the Monostate pattern in Java design patterns when\n\n1. **Shared State Across Instances:** All instances of a class must share the same state. Changes in one instance should be reflected across all instances. Monostate offers more flexibility compared to the traditional Singleton pattern.\n\n2. **Transparent Usage:** Unlike Singleton, which can be less transparent in its usage, Monostate allows for a more transparent way of sharing state across instances. Clients interact with instances of the Monostate class as if they were regular instances, unaware of the shared state.\n\n3. **Subclass Flexibility:** Monostate provides an advantage over Singleton when it comes to extending behavior through subclasses. Subclasses of a Monostate class can introduce additional behavior or modify existing behavior while still sharing the same state as instances of the base class. This allows for dynamic and diverse behaviors across different parts of an application, all while maintaining a shared state.\n\n4. **Avoiding Global Variables:** The pattern is applicable when you want to avoid global variables but still need a shared state across multiple instances.\n\n5. **Integration with Existing Systems:** Monostate can be more easily integrated into existing systems that expect to work with instances rather than a single global instance. This can lead to a smoother transition when refactoring code to use shared state.\n\n6. **Consistent Configuration or State Management:** In scenarios where you need consistent configuration management or state management across different parts of an application, Monostate provides a pattern to ensure all parts of the system are in sync.\n\n## Real-World Applications of Monostate Pattern in Java\n\n* Configuration settings that need to be shared and accessible by various parts of an application.\n* Resource pools where the state needs to be consistent across different consumers.\n\n## Benefits and Trade-offs of Monostate Pattern\n\nBenefits:\n\n* Provides a shared state without restricting the creation of multiple instances.\n* Ensures consistency of data across instances.\n\nTrade-offs:\n\n* Can lead to hidden dependencies due to shared state, making the system harder to understand and debug.\n* Reduces the flexibility to have instances with independent states.\n\n## Related Java Design Patterns\n\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Both Singleton and Monostate patterns ensure a single shared state, but the Monostate pattern in Java allows for multiple instances with the same state, making it a unique object-oriented design approach.\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Flyweight shares state to reduce memory usage, similar to how Monostate shares state among instances.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "monostate/etc/MonoState.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" always-add-relationships=\"false\" generalizations=\"true\" realizations=\"true\" \n  associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.monostate.LoadBalancer\" project=\"monostate\" \n    file=\"/monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"187\" width=\"158\" x=\"100\" y=\"66\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.monostate.Server\" project=\"monostate\" \n    file=\"/monostate/src/main/java/com/iluwatar/monostate/Server.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"176\" y=\"372\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.monostate.Request\" project=\"monostate\" \n    file=\"/monostate/src/main/java/com/iluwatar/monostate/Request.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"329\" y=\"352\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <dependency id=\"4\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </dependency>  \n  <dependency id=\"5\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </dependency>  \n  <association id=\"6\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"7\" name=\"servers\"/>      \n      <multiplicity id=\"8\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "monostate/etc/monostate.urm.puml",
    "content": "@startuml\npackage com.iluwatar.monostate {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class LoadBalancer {\n    - SERVERS : List<Server> {static}\n    - lastServedId : int {static}\n    + LoadBalancer()\n    + addServer(server : Server)\n    + getLastServedId() : int\n    + getNoOfServers() : int\n    + serverRequest(request : Request)\n  }\n  class Request {\n    + value : String\n    + Request(value : String)\n  }\n  class Server {\n    - LOGGER : Logger {static}\n    + host : String\n    + id : int\n    + port : int\n    + Server(host : String, port : int, id : int)\n    + getHost() : String\n    + getPort() : int\n    + serve(request : Request)\n  }\n}\nLoadBalancer -->  \"-SERVERS\" Server\n@enduml"
  },
  {
    "path": "monostate/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>monostate</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.monostate.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "monostate/src/main/java/com/iluwatar/monostate/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monostate;\n\n/**\n * The MonoState pattern ensures that all instances of the class will have the same state. This can\n * be used a direct replacement of the Singleton pattern.\n *\n * <p>In the following example, The {@link LoadBalancer} class represents the app's logic. It\n * contains a series of Servers, which can handle requests of type {@link Request}. Two instances of\n * LoadBalancer are created. When a request is made to a server via the first LoadBalancer the state\n * change in the first load balancer affects the second. So if the first LoadBalancer selects the\n * Server 1, the second LoadBalancer on a new request will select the Second server. If a third\n * LoadBalancer is created and a new request is made to it, then it will select the third server as\n * the second load balancer has already selected the second server.\n */\npublic class App {\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var loadBalancer1 = new LoadBalancer();\n    var loadBalancer2 = new LoadBalancer();\n    loadBalancer1.serverRequest(new Request(\"Hello\"));\n    loadBalancer2.serverRequest(new Request(\"Hello World\"));\n  }\n}\n"
  },
  {
    "path": "monostate/src/main/java/com/iluwatar/monostate/LoadBalancer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monostate;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * The LoadBalancer class. This implements the MonoState pattern. It holds a series of servers. Upon\n * receiving a new Request, it delegates the call to the servers in a Round Robin Fashion. Since all\n * instances of the class share the same state, all instances will delegate to the same server on\n * receiving a new Request.\n */\npublic class LoadBalancer {\n  private static final List<Server> SERVERS = new ArrayList<>();\n  private static int lastServedId;\n\n  static {\n    var id = 0;\n    for (var port : new int[] {8080, 8081, 8082, 8083, 8084}) {\n      SERVERS.add(new Server(\"localhost\", port, ++id));\n    }\n  }\n\n  /** Add new server. */\n  public final void addServer(Server server) {\n    synchronized (SERVERS) {\n      SERVERS.add(server);\n    }\n  }\n\n  public final int getNoOfServers() {\n    return SERVERS.size();\n  }\n\n  public int getLastServedId() {\n    return lastServedId;\n  }\n\n  /** Handle request. */\n  public synchronized void serverRequest(Request request) {\n    if (lastServedId >= SERVERS.size()) {\n      lastServedId = 0;\n    }\n    var server = SERVERS.get(lastServedId++);\n    server.serve(request);\n  }\n}\n"
  },
  {
    "path": "monostate/src/main/java/com/iluwatar/monostate/Request.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monostate;\n\n/** The Request record. A {@link Server} can handle an instance of a Request. */\npublic record Request(String value) {}\n"
  },
  {
    "path": "monostate/src/main/java/com/iluwatar/monostate/Server.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monostate;\n\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Server class. Each Server sits behind a LoadBalancer which delegates the call to the servers\n * in a simplistic Round Robin fashion.\n */\n@Slf4j\n@Getter\npublic class Server {\n\n  public final String host;\n  public final int port;\n  public final int id;\n\n  /** Constructor. */\n  public Server(String host, int port, int id) {\n    this.host = host;\n    this.port = port;\n    this.id = id;\n  }\n\n  public void serve(Request request) {\n    LOGGER.info(\n        \"Server ID {} associated to host : {} and port {}. Processed request with value {}\",\n        id,\n        host,\n        port,\n        request.value());\n  }\n}\n"
  },
  {
    "path": "monostate/src/test/java/com/iluwatar/monostate/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monostate;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application Test Entry */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "monostate/src/test/java/com/iluwatar/monostate/LoadBalancerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.monostate;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.doNothing;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\nimport static org.mockito.Mockito.when;\n\nimport org.junit.jupiter.api.Test;\n\n/** LoadBalancerTest */\nclass LoadBalancerTest {\n\n  @Test\n  void testSameStateAmongstAllInstances() {\n    final var firstBalancer = new LoadBalancer();\n    final var secondBalancer = new LoadBalancer();\n    firstBalancer.addServer(new Server(\"localhost\", 8085, 6));\n    // Both should have the same number of servers.\n    assertEquals(firstBalancer.getNoOfServers(), secondBalancer.getNoOfServers());\n    // Both Should have the same LastServedId\n    assertEquals(firstBalancer.getLastServedId(), secondBalancer.getLastServedId());\n  }\n\n  @Test\n  void testServe() {\n    final var server = mock(Server.class);\n    when(server.getHost()).thenReturn(\"testhost\");\n    when(server.getPort()).thenReturn(1234);\n    doNothing().when(server).serve(any(Request.class));\n\n    final var loadBalancer = new LoadBalancer();\n    loadBalancer.addServer(server);\n\n    verifyNoMoreInteractions(server);\n\n    final var request = new Request(\"test\");\n    for (var i = 0; i < loadBalancer.getNoOfServers() * 2; i++) {\n      loadBalancer.serverRequest(request);\n    }\n\n    verify(server, times(2)).serve(request);\n    verifyNoMoreInteractions(server);\n  }\n}\n"
  },
  {
    "path": "multiton/README.md",
    "content": "---\ntitle: \"Multiton Pattern in Java: Mastering Advanced Singleton Variants\"\nshortTitle: Multiton\ndescription: \"Learn how the Multiton pattern in Java ensures unique named instances and provides a global access point. Discover implementation tips and code examples.\"\ncategory: Creational\nlanguage: en\ntag:\n  - Decoupling\n  - Instantiation\n  - Object composition\n---\n\n## Also known as\n\n* Registry of Singletons\n\n## Intent of Multiton Design Pattern\n\nThe Multiton pattern in Java ensures a class has only unique named instances, providing a global point of access to them. Each named instance is accessed through a unique key, making it an essential part of Java design patterns.\n\n## Detailed Explanation of Multiton Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world example of the Multiton pattern is a printer management system in a large office. In this scenario, the office has several printers, each serving a different department. Instead of creating a new printer object every time a printing request is made, the system uses the Multiton pattern to ensure that each department has exactly one printer instance. When a printing request comes from a specific department, the system checks the registry of printer instances and retrieves the existing printer for that department. If no printer exists for that department, it creates one, registers it, and then returns it. This ensures efficient management of printer resources and prevents unnecessary creation of multiple printer instances for the same department.       \n\nIn plain words\n\n> The Multiton pattern is an extension of the Singleton pattern, offering a way to have a map of unique named instances instead of a single instance. This makes it a valuable Java design pattern for managing named instances efficiently.\n\nWikipedia says\n\n> In software engineering, the multiton pattern is a design pattern which generalizes the singleton pattern. Whereas the singleton allows only one instance of a class to be created, the multiton pattern allows for the controlled creation of multiple instances, which it manages through the use of a map.\n\nFlowchart\n\n![Multiton flowchart](./etc/multiton-flowchart.png)\n\n## Programmatic Example of Multiton Pattern in Java\n\nIn this tutorial, we’ll explore how to implement the Multiton pattern in Java, covering its structure, benefits, and providing code examples. By following these implementation tips, you’ll be able to effectively utilize this Java design pattern.\n\nThe Nazgûl, also called ringwraiths or the Nine Riders, are Sauron's most terrible servants. By definition, there's always nine of them.\n\n`Nazgul` is the multiton class.\n\n```java\npublic enum NazgulName {\n\n    KHAMUL, MURAZOR, DWAR, JI_INDUR, AKHORAHIL, HOARMURATH, ADUNAPHEL, REN, UVATHA\n}\n\npublic final class Nazgul {\n\n    private static final Map<NazgulName, Nazgul> nazguls;\n\n    @Getter\n    private final NazgulName name;\n\n    static {\n        nazguls = new ConcurrentHashMap<>();\n        nazguls.put(NazgulName.KHAMUL, new Nazgul(NazgulName.KHAMUL));\n        nazguls.put(NazgulName.MURAZOR, new Nazgul(NazgulName.MURAZOR));\n        nazguls.put(NazgulName.DWAR, new Nazgul(NazgulName.DWAR));\n        nazguls.put(NazgulName.JI_INDUR, new Nazgul(NazgulName.JI_INDUR));\n        nazguls.put(NazgulName.AKHORAHIL, new Nazgul(NazgulName.AKHORAHIL));\n        nazguls.put(NazgulName.HOARMURATH, new Nazgul(NazgulName.HOARMURATH));\n        nazguls.put(NazgulName.ADUNAPHEL, new Nazgul(NazgulName.ADUNAPHEL));\n        nazguls.put(NazgulName.REN, new Nazgul(NazgulName.REN));\n        nazguls.put(NazgulName.UVATHA, new Nazgul(NazgulName.UVATHA));\n    }\n\n    private Nazgul(NazgulName name) {\n        this.name = name;\n    }\n\n    public static Nazgul getInstance(NazgulName name) {\n        return nazguls.get(name);\n    }\n}\n```\n\nAnd here's how we access the `Nazgul` instances.\n\n```java\n  public static void main(String[] args) {\n    // eagerly initialized multiton\n    LOGGER.info(\"Printing out eagerly initialized multiton contents\");\n    LOGGER.info(\"KHAMUL={}\", Nazgul.getInstance(NazgulName.KHAMUL));\n    LOGGER.info(\"MURAZOR={}\", Nazgul.getInstance(NazgulName.MURAZOR));\n    LOGGER.info(\"DWAR={}\", Nazgul.getInstance(NazgulName.DWAR));\n    LOGGER.info(\"JI_INDUR={}\", Nazgul.getInstance(NazgulName.JI_INDUR));\n    LOGGER.info(\"AKHORAHIL={}\", Nazgul.getInstance(NazgulName.AKHORAHIL));\n    LOGGER.info(\"HOARMURATH={}\", Nazgul.getInstance(NazgulName.HOARMURATH));\n    LOGGER.info(\"ADUNAPHEL={}\", Nazgul.getInstance(NazgulName.ADUNAPHEL));\n    LOGGER.info(\"REN={}\", Nazgul.getInstance(NazgulName.REN));\n    LOGGER.info(\"UVATHA={}\", Nazgul.getInstance(NazgulName.UVATHA));\n\n    // enum multiton\n    LOGGER.info(\"Printing out enum-based multiton contents\");\n    LOGGER.info(\"KHAMUL={}\", NazgulEnum.KHAMUL);\n    LOGGER.info(\"MURAZOR={}\", NazgulEnum.MURAZOR);\n    LOGGER.info(\"DWAR={}\", NazgulEnum.DWAR);\n    LOGGER.info(\"JI_INDUR={}\", NazgulEnum.JI_INDUR);\n    LOGGER.info(\"AKHORAHIL={}\", NazgulEnum.AKHORAHIL);\n    LOGGER.info(\"HOARMURATH={}\", NazgulEnum.HOARMURATH);\n    LOGGER.info(\"ADUNAPHEL={}\", NazgulEnum.ADUNAPHEL);\n    LOGGER.info(\"REN={}\", NazgulEnum.REN);\n    LOGGER.info(\"UVATHA={}\", NazgulEnum.UVATHA);\n}\n```\n\nProgram output:\n\n```\n15:16:10.597 [main] INFO com.iluwatar.multiton.App -- Printing out eagerly initialized multiton contents\n15:16:10.600 [main] INFO com.iluwatar.multiton.App -- KHAMUL=com.iluwatar.multiton.Nazgul@4141d797\n15:16:10.600 [main] INFO com.iluwatar.multiton.App -- MURAZOR=com.iluwatar.multiton.Nazgul@38cccef\n15:16:10.600 [main] INFO com.iluwatar.multiton.App -- DWAR=com.iluwatar.multiton.Nazgul@5679c6c6\n15:16:10.600 [main] INFO com.iluwatar.multiton.App -- JI_INDUR=com.iluwatar.multiton.Nazgul@27ddd392\n15:16:10.600 [main] INFO com.iluwatar.multiton.App -- AKHORAHIL=com.iluwatar.multiton.Nazgul@19e1023e\n15:16:10.600 [main] INFO com.iluwatar.multiton.App -- HOARMURATH=com.iluwatar.multiton.Nazgul@7cef4e59\n15:16:10.600 [main] INFO com.iluwatar.multiton.App -- ADUNAPHEL=com.iluwatar.multiton.Nazgul@64b8f8f4\n15:16:10.600 [main] INFO com.iluwatar.multiton.App -- REN=com.iluwatar.multiton.Nazgul@2db0f6b2\n15:16:10.600 [main] INFO com.iluwatar.multiton.App -- UVATHA=com.iluwatar.multiton.Nazgul@3cd1f1c8\n15:16:10.600 [main] INFO com.iluwatar.multiton.App -- Printing out enum-based multiton contents\n15:16:10.601 [main] INFO com.iluwatar.multiton.App -- KHAMUL=KHAMUL\n15:16:10.601 [main] INFO com.iluwatar.multiton.App -- MURAZOR=MURAZOR\n15:16:10.601 [main] INFO com.iluwatar.multiton.App -- DWAR=DWAR\n15:16:10.601 [main] INFO com.iluwatar.multiton.App -- JI_INDUR=JI_INDUR\n15:16:10.601 [main] INFO com.iluwatar.multiton.App -- AKHORAHIL=AKHORAHIL\n15:16:10.601 [main] INFO com.iluwatar.multiton.App -- HOARMURATH=HOARMURATH\n15:16:10.601 [main] INFO com.iluwatar.multiton.App -- ADUNAPHEL=ADUNAPHEL\n15:16:10.601 [main] INFO com.iluwatar.multiton.App -- REN=REN\n15:16:10.601 [main] INFO com.iluwatar.multiton.App -- UVATHA=UVATHA\n```\n\n## When to Use the Multiton Pattern in Java\n\nUse cases for the Multiton pattern in Java\n\n* A class must have named instances, but only one instance for each unique key.\n* Global access to these instances is necessary without requiring global variables.\n* You want to manage shared resources categorized by key.\n\n## Real-World Applications of Multiton Pattern in Java\n\n* Managing database connections in different contexts.\n* Configuration settings for different environments in an application.\n\n## Benefits and Trade-offs of Multiton Pattern\n\nBenefits:\n\n* Ensures controlled access to instances based on key.\n* Reduces global state usage by encapsulating instance management within the pattern.\n\nTrade-offs:\n\n* Increased memory usage if not managed properly due to multiple instances.\n* Potential issues with concurrency if not implemented with thread safety in mind.\n\n## Related Java Design Patterns\n\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Multiton can be seen as an extension of the Singleton pattern where Singleton allows only one instance of a class, Multiton allows one instance per key.\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Multiton uses a method to create or retrieve instances, similar to how a Factory Method controls object creation.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n"
  },
  {
    "path": "multiton/etc/multiton.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <enumeration id=\"1\" language=\"java\" name=\"com.iluwatar.NazgulName\" project=\"multiton\" \n    file=\"/multiton/src/main/java/com/iluwatar/NazgulName.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"232\" y=\"516\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.Nazgul\" project=\"multiton\" \n    file=\"/multiton/src/main/java/com/iluwatar/Nazgul.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"231\" y=\"279\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"3\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"4\" name=\"name\"/>      \n      <multiplicity id=\"5\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"6\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"7\" name=\"nazguls\"/>      \n      <multiplicity id=\"8\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "multiton/etc/multiton.urm.puml",
    "content": "@startuml\npackage com.iluwatar.multiton {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Nazgul {\n    - name : NazgulName\n    - nazguls : Map<NazgulName, Nazgul> {static}\n    - Nazgul(name : NazgulName)\n    + getInstance(name : NazgulName) : Nazgul {static}\n    + getName() : NazgulName\n  }\n  enum NazgulEnum {\n    + ADUNAPHEL {static}\n    + AKHORAHIL {static}\n    + DWAR {static}\n    + HOARMURATH {static}\n    + JI_INDUR {static}\n    + KHAMUL {static}\n    + MURAZOR {static}\n    + REN {static}\n    + UVATHA {static}\n    + valueOf(name : String) : NazgulEnum {static}\n    + values() : NazgulEnum[] {static}\n  }\n  enum NazgulName {\n    + ADUNAPHEL {static}\n    + AKHORAHIL {static}\n    + DWAR {static}\n    + HOARMURATH {static}\n    + JI_INDUR {static}\n    + KHAMUL {static}\n    + MURAZOR {static}\n    + REN {static}\n    + UVATHA {static}\n    + valueOf(name : String) : NazgulName {static}\n    + values() : NazgulName[] {static}\n  }\n}\nNazgul -->  \"-name\" NazgulName\n@enduml"
  },
  {
    "path": "multiton/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>multiton</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-params</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.multiton.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "multiton/src/main/java/com/iluwatar/multiton/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.multiton;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Whereas Singleton design pattern introduces single globally accessible object, the Multiton\n * pattern defines many globally accessible objects. The client asks for the correct instance from\n * the Multiton by passing an enumeration as a parameter.\n *\n * <p>There is more than one way to implement the multiton design pattern. In the first example\n * {@link Nazgul} is the Multiton, and we can ask single {@link Nazgul} from it using {@link\n * NazgulName}. The {@link Nazgul}s are statically initialized and stored in a concurrent hash map.\n *\n * <p>In the enum implementation {@link NazgulEnum} is the multiton. It is static and mutable\n * because of the way java supports enums.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    // eagerly initialized multiton\n    LOGGER.info(\"Printing out eagerly initialized multiton contents\");\n    LOGGER.info(\"KHAMUL={}\", Nazgul.getInstance(NazgulName.KHAMUL));\n    LOGGER.info(\"MURAZOR={}\", Nazgul.getInstance(NazgulName.MURAZOR));\n    LOGGER.info(\"DWAR={}\", Nazgul.getInstance(NazgulName.DWAR));\n    LOGGER.info(\"JI_INDUR={}\", Nazgul.getInstance(NazgulName.JI_INDUR));\n    LOGGER.info(\"AKHORAHIL={}\", Nazgul.getInstance(NazgulName.AKHORAHIL));\n    LOGGER.info(\"HOARMURATH={}\", Nazgul.getInstance(NazgulName.HOARMURATH));\n    LOGGER.info(\"ADUNAPHEL={}\", Nazgul.getInstance(NazgulName.ADUNAPHEL));\n    LOGGER.info(\"REN={}\", Nazgul.getInstance(NazgulName.REN));\n    LOGGER.info(\"UVATHA={}\", Nazgul.getInstance(NazgulName.UVATHA));\n\n    // enum multiton\n    LOGGER.info(\"Printing out enum-based multiton contents\");\n    LOGGER.info(\"KHAMUL={}\", NazgulEnum.KHAMUL);\n    LOGGER.info(\"MURAZOR={}\", NazgulEnum.MURAZOR);\n    LOGGER.info(\"DWAR={}\", NazgulEnum.DWAR);\n    LOGGER.info(\"JI_INDUR={}\", NazgulEnum.JI_INDUR);\n    LOGGER.info(\"AKHORAHIL={}\", NazgulEnum.AKHORAHIL);\n    LOGGER.info(\"HOARMURATH={}\", NazgulEnum.HOARMURATH);\n    LOGGER.info(\"ADUNAPHEL={}\", NazgulEnum.ADUNAPHEL);\n    LOGGER.info(\"REN={}\", NazgulEnum.REN);\n    LOGGER.info(\"UVATHA={}\", NazgulEnum.UVATHA);\n  }\n}\n"
  },
  {
    "path": "multiton/src/main/java/com/iluwatar/multiton/Nazgul.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.multiton;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport lombok.Getter;\n\n/**\n * Nazgul is a Multiton class. Nazgul instances can be queried using {@link #getInstance} method.\n */\npublic final class Nazgul {\n\n  private static final Map<NazgulName, Nazgul> nazguls;\n\n  @Getter private final NazgulName name;\n\n  static {\n    nazguls = new ConcurrentHashMap<>();\n    nazguls.put(NazgulName.KHAMUL, new Nazgul(NazgulName.KHAMUL));\n    nazguls.put(NazgulName.MURAZOR, new Nazgul(NazgulName.MURAZOR));\n    nazguls.put(NazgulName.DWAR, new Nazgul(NazgulName.DWAR));\n    nazguls.put(NazgulName.JI_INDUR, new Nazgul(NazgulName.JI_INDUR));\n    nazguls.put(NazgulName.AKHORAHIL, new Nazgul(NazgulName.AKHORAHIL));\n    nazguls.put(NazgulName.HOARMURATH, new Nazgul(NazgulName.HOARMURATH));\n    nazguls.put(NazgulName.ADUNAPHEL, new Nazgul(NazgulName.ADUNAPHEL));\n    nazguls.put(NazgulName.REN, new Nazgul(NazgulName.REN));\n    nazguls.put(NazgulName.UVATHA, new Nazgul(NazgulName.UVATHA));\n  }\n\n  private Nazgul(NazgulName name) {\n    this.name = name;\n  }\n\n  public static Nazgul getInstance(NazgulName name) {\n    return nazguls.get(name);\n  }\n}\n"
  },
  {
    "path": "multiton/src/main/java/com/iluwatar/multiton/NazgulEnum.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.multiton;\n\n/** enum based multiton implementation. */\npublic enum NazgulEnum {\n  KHAMUL,\n  MURAZOR,\n  DWAR,\n  JI_INDUR,\n  AKHORAHIL,\n  HOARMURATH,\n  ADUNAPHEL,\n  REN,\n  UVATHA\n}\n"
  },
  {
    "path": "multiton/src/main/java/com/iluwatar/multiton/NazgulName.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.multiton;\n\n/** Each Nazgul has different {@link NazgulName}. */\npublic enum NazgulName {\n  KHAMUL,\n  MURAZOR,\n  DWAR,\n  JI_INDUR,\n  AKHORAHIL,\n  HOARMURATH,\n  ADUNAPHEL,\n  REN,\n  UVATHA\n}\n"
  },
  {
    "path": "multiton/src/test/java/com/iluwatar/multiton/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.multiton;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test if the application starts without throwing an exception. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "multiton/src/test/java/com/iluwatar/multiton/NazgulEnumTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.multiton;\n\nimport static org.junit.jupiter.api.Assertions.assertSame;\n\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.EnumSource;\n\n/** NazgulEnumTest */\nclass NazgulEnumTest {\n\n  /**\n   * Check that multiple calls to any one of the instances in the multiton returns only that one\n   * particular instance, and do that for all instances in multiton\n   */\n  @ParameterizedTest\n  @EnumSource\n  void testTheSameObjectIsReturnedWithMultipleCalls(NazgulEnum nazgulEnum) {\n    var instance1 = nazgulEnum;\n    var instance2 = nazgulEnum;\n    var instance3 = nazgulEnum;\n    assertSame(instance1, instance2);\n    assertSame(instance1, instance3);\n    assertSame(instance2, instance3);\n  }\n}\n"
  },
  {
    "path": "multiton/src/test/java/com/iluwatar/multiton/NazgulTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.multiton;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertSame;\n\nimport org.junit.jupiter.api.Test;\n\n/** NazgulTest */\nclass NazgulTest {\n\n  /**\n   * Verify if {@link Nazgul#getInstance(NazgulName)} returns the correct Nazgul multiton instance\n   */\n  @Test\n  void testGetInstance() {\n    for (final var name : NazgulName.values()) {\n      final var nazgul = Nazgul.getInstance(name);\n      assertNotNull(nazgul);\n      assertSame(nazgul, Nazgul.getInstance(name));\n      assertEquals(name, nazgul.getName());\n    }\n  }\n}\n"
  },
  {
    "path": "mute-idiom/README.md",
    "content": "---\ntitle: \"Mute Idiom Pattern in Java: Implementing Unobtrusive Exception Suppression\"\nshortTitle: Mute Idiom\ndescription: \"Discover the Mute Idiom design pattern in Java, which simplifies error handling by muting non-critical exceptions. Learn how to apply it effectively in multithreaded environments.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Context\n  - Decoupling\n  - Idiom\n  - Error handling\n  - Synchronization\n  - Thread management\n---\n\n## Also known as\n\n* Exception Suppression\n* Quiet Exception\n\n## Intent of Mute Idiom Design Pattern\n\nThe Mute Idiom in Java is a design pattern that simplifies error handling by suppressing non-critical exceptions. This approach is especially useful in multithreaded applications and complex control flow scenarios.\n\n## Detailed Explanation of Mute Idiom Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy of the Mute Idiom is found in car door locking mechanisms, where non-critical exceptions (like an already locked door) are ignored, simplifying the system's logic. Similarly, in Java, the Mute Idiom focuses on essential operations, avoiding unnecessary exception handling.\n>\n> Imagine a car equipped with an automatic locking system that attempts to lock all doors when the car reaches a certain speed. In this system, if one of the doors is already locked, the system doesn't need to alert the driver or perform any special handling; it simply skips locking that door and continues with the others. The locking system \"mutes\" the handling of already locked doors, focusing only on those that need to be locked. This approach simplifies the logic and avoids unnecessary checks, similar to how the Mute Idiom in software development suppresses handling trivial exceptions.\n\nIn plain words\n\n> The Mute Idiom design pattern suppresses the handling of trivial or non-critical exceptions to simplify code.\n\nFlowchart\n\n![Mute Idiom flowchart](./etc/mute-idiom-flowchart.png)\n\n## Programmatic Example of Mute Idiom Pattern in Java\n\nIn the following Java code example, we demonstrate the Mute Idiom by muting non-critical exceptions during the resource management process. This approach ensures error handling does not interrupt the main logic.\n\nThe Mute Idiom is a design pattern that is used to simplify error handling by muting exceptions that are deemed non-critical or expected in specific contexts. This pattern is particularly useful in multithreaded or complex control flow environments.\n\nWe have a `Resource` interface that has a `close` method which throws an `IOException`.\n\n```java\npublic interface Resource extends AutoCloseable {\n  @Override\n  void close() throws IOException;\n}\n```\n\nWe also have an `App` class that uses this `Resource`. In the `App` class, we have a `useOfLoggedMute` method that demonstrates the use of the Mute Idiom. Here, we acquire a `Resource`, utilize it, and then attempt to close it. The closing of the resource is done in a `finally` block to ensure that it is executed regardless of whether an exception is thrown or not.\n\n```java\npublic class App {\n  // ...\n\n  private static void useOfLoggedMute() {\n    Optional<Resource> resource = Optional.empty();\n    try {\n      resource = Optional.of(acquireResource());\n      utilizeResource(resource.get());\n    } finally {\n      resource.ifPresent(App::closeResource);\n    }\n  }\n\n  // ...\n}\n```\n\nThe `closeResource` method is where the Mute Idiom is applied. We use the `Mute.loggedMute` method to suppress any `IOException` that might be thrown when closing the resource. This is done because the failure to close a resource is considered a non-critical issue that does not affect the overall logic or outcome of the program.\n\n```java\npublic class App {\n  // ...\n\n  private static void closeResource(Resource resource) {\n    Mute.loggedMute(resource::close);\n  }\n\n  // ...\n}\n```\n\nIn this way, the Mute Idiom allows us to simplify error handling by reducing boilerplate code for expected exceptions, enhancing code readability and maintainability, and allowing uninterrupted execution for non-critical exceptions.\n\n## When to Use the Mute Idiom Pattern in Java\n\nThe Mute Idiom is applicable in\n\n* Scenarios where certain exceptions are predictable and do not affect the overall logic or outcome.\n* Commonly used in logging, cleanup operations, or interacting with third-party APIs in Java.\n\n## Mute Idiom Pattern Java Tutorials\n\n* [The Mute Design Pattern (JOOQ)](http://blog.jooq.org/2016/02/18/the-mute-design-pattern/)\n\n## Real-World Applications of Mute Idiom Pattern in Java\n\n* Muting exceptions in background tasks or threads where interruption is expected.\n* Handling known issues in third-party libraries where exceptions can be safely ignored.\n\n## Benefits and Trade-offs of Mute Idiom Pattern\n\nBenefits:\n\nUsing the Mute Idiom\n\n* Simplifies error handling by reducing boilerplate code for expected exceptions.\n* Enhances code readability and maintainability.\n* Allows uninterrupted execution for non-critical exceptions.\n\nTrade-offs:\n\n* Can lead to missed critical issues if overused or misapplied.\n* Makes debugging harder if exceptions are muted indiscriminately.\n\n## Related Java Design Patterns\n\n* [Null Object](https://java-design-patterns.com/patterns/null-object/): Both aim to simplify error handling; Null Object avoids null checks while Mute Idiom avoids exception handling complexities.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Can be used to wrap functionality with additional error handling or muting behaviors.\n\n## References and Credits\n\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n"
  },
  {
    "path": "mute-idiom/etc/mute-idiom.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"true\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.mute.App\" project=\"mute-idiom\" \n    file=\"/mute-idiom/src/main/java/com/iluwatar/mute/App.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"168\" y=\"234\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.mute.Mute\" project=\"mute-idiom\" \n    file=\"/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"115\" width=\"203\" x=\"70\" y=\"375\"/>    \n    <display autosize=\"false\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"3\" language=\"java\" name=\"com.iluwatar.mute.CheckedRunnable\" project=\"mute-idiom\" \n    file=\"/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"407\" y=\"432\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"4\" language=\"java\" name=\"com.iluwatar.mute.Resource\" project=\"mute-idiom\" \n    file=\"/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"383\" y=\"235\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"5\" language=\"java\" name=\"java.io.Closeable\" project=\"dao\" \n    file=\"/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"384\" y=\"109\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <dependency id=\"6\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </dependency>  \n  <dependency id=\"7\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </dependency>  \n  <dependency id=\"8\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </dependency>  \n  <generalization id=\"9\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </generalization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "mute-idiom/etc/mute-idiom.urm.puml",
    "content": "@startuml\npackage com.iluwatar.mute {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    - acquireResource() : Resource {static}\n    - closeResource(resource : Resource) {static}\n    + main(args : String[]) {static}\n    - useOfLoggedMute() {static}\n    - useOfMute() {static}\n    - utilizeResource(resource : Resource) {static}\n  }\n  interface CheckedRunnable {\n    + run() {abstract}\n  }\n  class Mute {\n    - Mute()\n    + loggedMute(runnable : CheckedRunnable) {static}\n    + mute(runnable : CheckedRunnable) {static}\n  }\n  interface Resource {\n  }\n}\n@enduml"
  },
  {
    "path": "mute-idiom/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>mute-idiom</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.mute.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "mute-idiom/src/main/java/com/iluwatar/mute/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mute;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.util.Optional;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Mute pattern is utilized when we need to suppress an exception due to an API flaw or in situation\n * when all we can do to handle the exception is to log it. This pattern should not be used\n * everywhere. It is very important to logically handle the exceptions in a system, but some\n * situations like the ones described above require this pattern, so that we don't need to repeat\n *\n * <pre>\n * <code>\n *   try {\n *     // code that may throwing exception we need to ignore or may never be thrown\n *   } catch (Exception ex) {\n *     // ignore by logging or throw error if unexpected exception occurs\n *   }\n * </code>\n * </pre>\n *\n * every time we need to ignore an exception.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args.\n   */\n  public static void main(String[] args) {\n\n    useOfLoggedMute();\n\n    useOfMute();\n  }\n\n  /*\n   * Typically used when the API declares some exception but cannot do so. Usually a\n   * signature mistake.In this example out is not supposed to throw exception as it is a\n   * ByteArrayOutputStream. So we utilize mute, which will throw AssertionError if unexpected\n   * exception occurs.\n   */\n  private static void useOfMute() {\n    var out = new ByteArrayOutputStream();\n    Mute.mute(() -> out.write(\"Hello\".getBytes()));\n  }\n\n  private static void useOfLoggedMute() {\n    Optional<Resource> resource = Optional.empty();\n    try {\n      resource = Optional.of(acquireResource());\n      utilizeResource(resource.get());\n    } finally {\n      resource.ifPresent(App::closeResource);\n    }\n  }\n\n  /*\n   * All we can do while failed close of a resource is to log it.\n   */\n  private static void closeResource(Resource resource) {\n    Mute.loggedMute(resource::close);\n  }\n\n  private static void utilizeResource(Resource resource) {\n    LOGGER.info(\"Utilizing acquired resource: {}\", resource);\n  }\n\n  private static Resource acquireResource() {\n    return new Resource() {\n\n      @Override\n      public void close() throws IOException {\n        throw new IOException(\"Error in closing resource: \" + this);\n      }\n    };\n  }\n}\n"
  },
  {
    "path": "mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mute;\n\n/** A runnable which may throw exception on execution. */\n@FunctionalInterface\npublic interface CheckedRunnable {\n  /**\n   * Same as {@link Runnable#run()} with a possibility of exception in execution.\n   *\n   * @throws Exception if any exception occurs.\n   */\n  void run() throws Exception;\n}\n"
  },
  {
    "path": "mute-idiom/src/main/java/com/iluwatar/mute/Mute.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mute;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport lombok.extern.slf4j.Slf4j;\n\n/** A utility class that allows you to utilize mute idiom. */\n@Slf4j\npublic final class Mute {\n\n  // The constructor is never meant to be called.\n  private Mute() {}\n\n  /**\n   * Executes the <code>runnable</code> and throws the exception occurred within a {@link\n   * AssertionError}. This method should be utilized to mute the operations that are guaranteed not\n   * to throw an exception. For instance {@link ByteArrayOutputStream#write(byte[])} declares in its\n   * signature that it can throw an {@link IOException}, but in reality it cannot. This is because\n   * the bulk write method is not overridden in {@link ByteArrayOutputStream}.\n   *\n   * @param runnable a runnable that should never throw an exception on execution.\n   */\n  public static void mute(CheckedRunnable runnable) {\n    try {\n      runnable.run();\n    } catch (Exception e) {\n      throw new AssertionError(e);\n    }\n  }\n\n  /**\n   * Executes the <code>runnable</code> and logs the exception occurred on {@link System#err}. This\n   * method should be utilized to mute the operations about which most you can do is log. For\n   * instance while closing a connection to database, or cleaning up a resource, all you can do is\n   * log the exception occurred.\n   *\n   * @param runnable a runnable that may throw an exception on execution.\n   */\n  public static void loggedMute(CheckedRunnable runnable) {\n    try {\n      runnable.run();\n    } catch (Exception e) {\n      e.printStackTrace();\n    }\n  }\n}\n"
  },
  {
    "path": "mute-idiom/src/main/java/com/iluwatar/mute/Resource.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mute;\n\nimport java.io.Closeable;\n\n/**\n * Represents any resource that the application might acquire and that must be closed after it is\n * utilized. Example of such resources can be a database connection, open files, sockets.\n */\npublic interface Resource extends Closeable {}\n"
  },
  {
    "path": "mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mute;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Mute idiom example runs without errors. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.mute;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.PrintStream;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** Test for the mute-idiom pattern */\nclass MuteTest {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(MuteTest.class);\n\n  private static final String MESSAGE = \"should not occur\";\n\n  @Test\n  void\n      muteShouldRunTheCheckedRunnableAndNotThrowAnyExceptionIfCheckedRunnableDoesNotThrowAnyException() {\n    assertDoesNotThrow(() -> Mute.mute(this::methodNotThrowingAnyException));\n  }\n\n  @Test\n  void muteShouldRethrowUnexpectedExceptionAsAssertionError() {\n    assertThrows(AssertionError.class, () -> Mute.mute(this::methodThrowingException));\n  }\n\n  @Test\n  void\n      loggedMuteShouldRunTheCheckedRunnableAndNotThrowAnyExceptionIfCheckedRunnableDoesNotThrowAnyException() {\n    assertDoesNotThrow(() -> Mute.mute(this::methodNotThrowingAnyException));\n  }\n\n  @Test\n  void loggedMuteShouldLogExceptionTraceBeforeSwallowingIt() {\n    var stream = new ByteArrayOutputStream();\n    System.setErr(new PrintStream(stream));\n\n    Mute.loggedMute(this::methodThrowingException);\n\n    assertTrue(stream.toString().contains(MESSAGE));\n  }\n\n  private void methodNotThrowingAnyException() {\n    LOGGER.info(\"Executed successfully\");\n  }\n\n  private void methodThrowingException() throws Exception {\n    throw new Exception(MESSAGE);\n  }\n}\n"
  },
  {
    "path": "mvnw",
    "content": "#!/bin/sh\n# ----------------------------------------------------------------------------\n# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n# ----------------------------------------------------------------------------\n\n# ----------------------------------------------------------------------------\n# Maven Start Up Batch script\n#\n# Required ENV vars:\n# ------------------\n#   JAVA_HOME - location of a JDK home dir\n#\n# Optional ENV vars\n# -----------------\n#   M2_HOME - location of maven2's installed home dir\n#   MAVEN_OPTS - parameters passed to the Java VM when running Maven\n#     e.g. to debug Maven itself, use\n#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\n#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files\n# ----------------------------------------------------------------------------\n\nif [ -z \"$MAVEN_SKIP_RC\" ] ; then\n\n  if [ -f /usr/local/etc/mavenrc ] ; then\n    . /usr/local/etc/mavenrc\n  fi\n\n  if [ -f /etc/mavenrc ] ; then\n    . /etc/mavenrc\n  fi\n\n  if [ -f \"$HOME/.mavenrc\" ] ; then\n    . \"$HOME/.mavenrc\"\n  fi\n\nfi\n\n# OS specific support.  $var _must_ be set to either true or false.\ncygwin=false;\ndarwin=false;\nmingw=false\ncase \"`uname`\" in\n  CYGWIN*) cygwin=true ;;\n  MINGW*) mingw=true;;\n  Darwin*) darwin=true\n    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home\n    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html\n    if [ -z \"$JAVA_HOME\" ]; then\n      if [ -x \"/usr/libexec/java_home\" ]; then\n        export JAVA_HOME=\"`/usr/libexec/java_home`\"\n      else\n        export JAVA_HOME=\"/Library/Java/Home\"\n      fi\n    fi\n    ;;\nesac\n\nif [ -z \"$JAVA_HOME\" ] ; then\n  if [ -r /etc/gentoo-release ] ; then\n    JAVA_HOME=`java-config --jre-home`\n  fi\nfi\n\nif [ -z \"$M2_HOME\" ] ; then\n  ## resolve links - $0 may be a link to maven's home\n  PRG=\"$0\"\n\n  # need this for relative symlinks\n  while [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n      PRG=\"$link\"\n    else\n      PRG=\"`dirname \"$PRG\"`/$link\"\n    fi\n  done\n\n  saveddir=`pwd`\n\n  M2_HOME=`dirname \"$PRG\"`/..\n\n  # make it fully qualified\n  M2_HOME=`cd \"$M2_HOME\" && pwd`\n\n  cd \"$saveddir\"\n  # echo Using m2 at $M2_HOME\nfi\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched\nif $cygwin ; then\n  [ -n \"$M2_HOME\" ] &&\n    M2_HOME=`cygpath --unix \"$M2_HOME\"`\n  [ -n \"$JAVA_HOME\" ] &&\n    JAVA_HOME=`cygpath --unix \"$JAVA_HOME\"`\n  [ -n \"$CLASSPATH\" ] &&\n    CLASSPATH=`cygpath --path --unix \"$CLASSPATH\"`\nfi\n\n# For Mingw, ensure paths are in UNIX format before anything is touched\nif $mingw ; then\n  [ -n \"$M2_HOME\" ] &&\n    M2_HOME=\"`(cd \"$M2_HOME\"; pwd)`\"\n  [ -n \"$JAVA_HOME\" ] &&\n    JAVA_HOME=\"`(cd \"$JAVA_HOME\"; pwd)`\"\nfi\n\nif [ -z \"$JAVA_HOME\" ]; then\n  javaExecutable=\"`which javac`\"\n  if [ -n \"$javaExecutable\" ] && ! [ \"`expr \\\"$javaExecutable\\\" : '\\([^ ]*\\)'`\" = \"no\" ]; then\n    # readlink(1) is not available as standard on Solaris 10.\n    readLink=`which readlink`\n    if [ ! `expr \"$readLink\" : '\\([^ ]*\\)'` = \"no\" ]; then\n      if $darwin ; then\n        javaHome=\"`dirname \\\"$javaExecutable\\\"`\"\n        javaExecutable=\"`cd \\\"$javaHome\\\" && pwd -P`/javac\"\n      else\n        javaExecutable=\"`readlink -f \\\"$javaExecutable\\\"`\"\n      fi\n      javaHome=\"`dirname \\\"$javaExecutable\\\"`\"\n      javaHome=`expr \"$javaHome\" : '\\(.*\\)/bin'`\n      JAVA_HOME=\"$javaHome\"\n      export JAVA_HOME\n    fi\n  fi\nfi\n\nif [ -z \"$JAVACMD\" ] ; then\n  if [ -n \"$JAVA_HOME\"  ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n      # IBM's JDK on AIX uses strange locations for the executables\n      JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n      JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n  else\n    JAVACMD=\"`\\\\unset -f command; \\\\command -v java`\"\n  fi\nfi\n\nif [ ! -x \"$JAVACMD\" ] ; then\n  echo \"Error: JAVA_HOME is not defined correctly.\" >&2\n  echo \"  We cannot execute $JAVACMD\" >&2\n  exit 1\nfi\n\nif [ -z \"$JAVA_HOME\" ] ; then\n  echo \"Warning: JAVA_HOME environment variable is not set.\"\nfi\n\nCLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher\n\n# traverses directory structure from process work directory to filesystem root\n# first directory with .mvn subdirectory is considered project base directory\nfind_maven_basedir() {\n\n  if [ -z \"$1\" ]\n  then\n    echo \"Path not specified to find_maven_basedir\"\n    return 1\n  fi\n\n  basedir=\"$1\"\n  wdir=\"$1\"\n  while [ \"$wdir\" != '/' ] ; do\n    if [ -d \"$wdir\"/.mvn ] ; then\n      basedir=$wdir\n      break\n    fi\n    # workaround for JBEAP-8937 (on Solaris 10/Sparc)\n    if [ -d \"${wdir}\" ]; then\n      wdir=`cd \"$wdir/..\"; pwd`\n    fi\n    # end of workaround\n  done\n  echo \"${basedir}\"\n}\n\n# concatenates all lines of a file\nconcat_lines() {\n  if [ -f \"$1\" ]; then\n    echo \"$(tr -s '\\n' ' ' < \"$1\")\"\n  fi\n}\n\nBASE_DIR=`find_maven_basedir \"$(pwd)\"`\nif [ -z \"$BASE_DIR\" ]; then\n  exit 1;\nfi\n\n##########################################################################################\n# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central\n# This allows using the maven wrapper in projects that prohibit checking in binary data.\n##########################################################################################\nif [ -r \"$BASE_DIR/.mvn/wrapper/maven-wrapper.jar\" ]; then\n    if [ \"$MVNW_VERBOSE\" = true ]; then\n      echo \"Found .mvn/wrapper/maven-wrapper.jar\"\n    fi\nelse\n    if [ \"$MVNW_VERBOSE\" = true ]; then\n      echo \"Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ...\"\n    fi\n    if [ -n \"$MVNW_REPOURL\" ]; then\n      jarUrl=\"$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar\"\n    else\n      jarUrl=\"https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar\"\n    fi\n    while IFS=\"=\" read key value; do\n      case \"$key\" in (wrapperUrl) jarUrl=\"$value\"; break ;;\n      esac\n    done < \"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties\"\n    if [ \"$MVNW_VERBOSE\" = true ]; then\n      echo \"Downloading from: $jarUrl\"\n    fi\n    wrapperJarPath=\"$BASE_DIR/.mvn/wrapper/maven-wrapper.jar\"\n    if $cygwin; then\n      wrapperJarPath=`cygpath --path --windows \"$wrapperJarPath\"`\n    fi\n\n    if command -v wget > /dev/null; then\n        if [ \"$MVNW_VERBOSE\" = true ]; then\n          echo \"Found wget ... using wget\"\n        fi\n        if [ -z \"$MVNW_USERNAME\" ] || [ -z \"$MVNW_PASSWORD\" ]; then\n            wget \"$jarUrl\" -O \"$wrapperJarPath\" || rm -f \"$wrapperJarPath\"\n        else\n            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD \"$jarUrl\" -O \"$wrapperJarPath\" || rm -f \"$wrapperJarPath\"\n        fi\n    elif command -v curl > /dev/null; then\n        if [ \"$MVNW_VERBOSE\" = true ]; then\n          echo \"Found curl ... using curl\"\n        fi\n        if [ -z \"$MVNW_USERNAME\" ] || [ -z \"$MVNW_PASSWORD\" ]; then\n            curl -o \"$wrapperJarPath\" \"$jarUrl\" -f\n        else\n            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o \"$wrapperJarPath\" \"$jarUrl\" -f\n        fi\n\n    else\n        if [ \"$MVNW_VERBOSE\" = true ]; then\n          echo \"Falling back to using Java to download\"\n        fi\n        javaClass=\"$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java\"\n        # For Cygwin, switch paths to Windows format before running javac\n        if $cygwin; then\n          javaClass=`cygpath --path --windows \"$javaClass\"`\n        fi\n        if [ -e \"$javaClass\" ]; then\n            if [ ! -e \"$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class\" ]; then\n                if [ \"$MVNW_VERBOSE\" = true ]; then\n                  echo \" - Compiling MavenWrapperDownloader.java ...\"\n                fi\n                # Compiling the Java class\n                (\"$JAVA_HOME/bin/javac\" \"$javaClass\")\n            fi\n            if [ -e \"$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class\" ]; then\n                # Running the downloader\n                if [ \"$MVNW_VERBOSE\" = true ]; then\n                  echo \" - Running MavenWrapperDownloader.java ...\"\n                fi\n                (\"$JAVA_HOME/bin/java\" -cp .mvn/wrapper MavenWrapperDownloader \"$MAVEN_PROJECTBASEDIR\")\n            fi\n        fi\n    fi\nfi\n##########################################################################################\n# End of extension\n##########################################################################################\n\nexport MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-\"$BASE_DIR\"}\nif [ \"$MVNW_VERBOSE\" = true ]; then\n  echo $MAVEN_PROJECTBASEDIR\nfi\nMAVEN_OPTS=\"$(concat_lines \"$MAVEN_PROJECTBASEDIR/.mvn/jvm.config\") $MAVEN_OPTS\"\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin; then\n  [ -n \"$M2_HOME\" ] &&\n    M2_HOME=`cygpath --path --windows \"$M2_HOME\"`\n  [ -n \"$JAVA_HOME\" ] &&\n    JAVA_HOME=`cygpath --path --windows \"$JAVA_HOME\"`\n  [ -n \"$CLASSPATH\" ] &&\n    CLASSPATH=`cygpath --path --windows \"$CLASSPATH\"`\n  [ -n \"$MAVEN_PROJECTBASEDIR\" ] &&\n    MAVEN_PROJECTBASEDIR=`cygpath --path --windows \"$MAVEN_PROJECTBASEDIR\"`\nfi\n\n# Provide a \"standardized\" way to retrieve the CLI args that will\n# work with both Windows and non-Windows executions.\nMAVEN_CMD_LINE_ARGS=\"$MAVEN_CONFIG $@\"\nexport MAVEN_CMD_LINE_ARGS\n\nWRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain\n\nexec \"$JAVACMD\" \\\n  $MAVEN_OPTS \\\n  $MAVEN_DEBUG_OPTS \\\n  -classpath \"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar\" \\\n  \"-Dmaven.home=${M2_HOME}\" \\\n  \"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}\" \\\n  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG \"$@\"\n"
  },
  {
    "path": "mvnw.cmd",
    "content": "@REM ----------------------------------------------------------------------------\n@REM Licensed to the Apache Software Foundation (ASF) under one\n@REM or more contributor license agreements.  See the NOTICE file\n@REM distributed with this work for additional information\n@REM regarding copyright ownership.  The ASF licenses this file\n@REM to you under the Apache License, Version 2.0 (the\n@REM \"License\"); you may not use this file except in compliance\n@REM with the License.  You may obtain a copy of the License at\n@REM\n@REM    http://www.apache.org/licenses/LICENSE-2.0\n@REM\n@REM Unless required by applicable law or agreed to in writing,\n@REM software distributed under the License is distributed on an\n@REM \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n@REM KIND, either express or implied.  See the License for the\n@REM specific language governing permissions and limitations\n@REM under the License.\n@REM ----------------------------------------------------------------------------\n\n@REM ----------------------------------------------------------------------------\n@REM Maven Start Up Batch script\n@REM\n@REM Required ENV vars:\n@REM JAVA_HOME - location of a JDK home dir\n@REM\n@REM Optional ENV vars\n@REM M2_HOME - location of maven2's installed home dir\n@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands\n@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending\n@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven\n@REM     e.g. to debug Maven itself, use\n@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\n@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files\n@REM ----------------------------------------------------------------------------\n\n@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'\n@echo off\n@REM set title of command window\ntitle %0\n@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'\n@if \"%MAVEN_BATCH_ECHO%\" == \"on\"  echo %MAVEN_BATCH_ECHO%\n\n@REM set %HOME% to equivalent of $HOME\nif \"%HOME%\" == \"\" (set \"HOME=%HOMEDRIVE%%HOMEPATH%\")\n\n@REM Execute a user defined script before this one\nif not \"%MAVEN_SKIP_RC%\" == \"\" goto skipRcPre\n@REM check for pre script, once with legacy .bat ending and once with .cmd ending\nif exist \"%USERPROFILE%\\mavenrc_pre.bat\" call \"%USERPROFILE%\\mavenrc_pre.bat\" %*\nif exist \"%USERPROFILE%\\mavenrc_pre.cmd\" call \"%USERPROFILE%\\mavenrc_pre.cmd\" %*\n:skipRcPre\n\n@setlocal\n\nset ERROR_CODE=0\n\n@REM To isolate internal variables from possible post scripts, we use another setlocal\n@setlocal\n\n@REM ==== START VALIDATION ====\nif not \"%JAVA_HOME%\" == \"\" goto OkJHome\n\necho.\necho Error: JAVA_HOME not found in your environment. >&2\necho Please set the JAVA_HOME variable in your environment to match the >&2\necho location of your Java installation. >&2\necho.\ngoto error\n\n:OkJHome\nif exist \"%JAVA_HOME%\\bin\\java.exe\" goto init\n\necho.\necho Error: JAVA_HOME is set to an invalid directory. >&2\necho JAVA_HOME = \"%JAVA_HOME%\" >&2\necho Please set the JAVA_HOME variable in your environment to match the >&2\necho location of your Java installation. >&2\necho.\ngoto error\n\n@REM ==== END VALIDATION ====\n\n:init\n\n@REM Find the project base dir, i.e. the directory that contains the folder \".mvn\".\n@REM Fallback to current working directory if not found.\n\nset MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%\nIF NOT \"%MAVEN_PROJECTBASEDIR%\"==\"\" goto endDetectBaseDir\n\nset EXEC_DIR=%CD%\nset WDIR=%EXEC_DIR%\n:findBaseDir\nIF EXIST \"%WDIR%\"\\.mvn goto baseDirFound\ncd ..\nIF \"%WDIR%\"==\"%CD%\" goto baseDirNotFound\nset WDIR=%CD%\ngoto findBaseDir\n\n:baseDirFound\nset MAVEN_PROJECTBASEDIR=%WDIR%\ncd \"%EXEC_DIR%\"\ngoto endDetectBaseDir\n\n:baseDirNotFound\nset MAVEN_PROJECTBASEDIR=%EXEC_DIR%\ncd \"%EXEC_DIR%\"\n\n:endDetectBaseDir\n\nIF NOT EXIST \"%MAVEN_PROJECTBASEDIR%\\.mvn\\jvm.config\" goto endReadAdditionalConfig\n\n@setlocal EnableExtensions EnableDelayedExpansion\nfor /F \"usebackq delims=\" %%a in (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\jvm.config\") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a\n@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%\n\n:endReadAdditionalConfig\n\nSET MAVEN_JAVA_EXE=\"%JAVA_HOME%\\bin\\java.exe\"\nset WRAPPER_JAR=\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.jar\"\nset WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain\n\nset DOWNLOAD_URL=\"https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar\"\n\nFOR /F \"usebackq tokens=1,2 delims==\" %%A IN (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.properties\") DO (\n    IF \"%%A\"==\"wrapperUrl\" SET DOWNLOAD_URL=%%B\n)\n\n@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central\n@REM This allows using the maven wrapper in projects that prohibit checking in binary data.\nif exist %WRAPPER_JAR% (\n    if \"%MVNW_VERBOSE%\" == \"true\" (\n        echo Found %WRAPPER_JAR%\n    )\n) else (\n    if not \"%MVNW_REPOURL%\" == \"\" (\n        SET DOWNLOAD_URL=\"%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar\"\n    )\n    if \"%MVNW_VERBOSE%\" == \"true\" (\n        echo Couldn't find %WRAPPER_JAR%, downloading it ...\n        echo Downloading from: %DOWNLOAD_URL%\n    )\n\n    powershell -Command \"&{\"^\n\t\t\"$webclient = new-object System.Net.WebClient;\"^\n\t\t\"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {\"^\n\t\t\"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');\"^\n\t\t\"}\"^\n\t\t\"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')\"^\n\t\t\"}\"\n    if \"%MVNW_VERBOSE%\" == \"true\" (\n        echo Finished downloading %WRAPPER_JAR%\n    )\n)\n@REM End of extension\n\n@REM Provide a \"standardized\" way to retrieve the CLI args that will\n@REM work with both Windows and non-Windows executions.\nset MAVEN_CMD_LINE_ARGS=%*\n\n%MAVEN_JAVA_EXE% ^\n  %JVM_CONFIG_MAVEN_PROPS% ^\n  %MAVEN_OPTS% ^\n  %MAVEN_DEBUG_OPTS% ^\n  -classpath %WRAPPER_JAR% ^\n  \"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%\" ^\n  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*\nif ERRORLEVEL 1 goto error\ngoto end\n\n:error\nset ERROR_CODE=1\n\n:end\n@endlocal & set ERROR_CODE=%ERROR_CODE%\n\nif not \"%MAVEN_SKIP_RC%\"==\"\" goto skipRcPost\n@REM check for post script, once with legacy .bat ending and once with .cmd ending\nif exist \"%USERPROFILE%\\mavenrc_post.bat\" call \"%USERPROFILE%\\mavenrc_post.bat\"\nif exist \"%USERPROFILE%\\mavenrc_post.cmd\" call \"%USERPROFILE%\\mavenrc_post.cmd\"\n:skipRcPost\n\n@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'\nif \"%MAVEN_BATCH_PAUSE%\"==\"on\" pause\n\nif \"%MAVEN_TERMINATE_CMD%\"==\"on\" exit %ERROR_CODE%\n\ncmd /C exit /B %ERROR_CODE%\n"
  },
  {
    "path": "naked-objects/README.md",
    "content": "---\ntitle: \"Naked Objects Pattern in Java: Leveraging Domain Objects for Dynamic UI Generation\"\nshortTitle: Naked Objects\ndescription: “Explore the Naked Objects design pattern in Java. Learn how to dynamically create user interfaces from domain objects with examples and best practices.”\ncategory: Architectural\nlanguage: en\ntag:\n  - Architecture\n  - Business\n  - Decoupling\n  - Domain\n  - Enterprise patterns\n  - Instantiation\n  - Object composition\n  - Persistence\n---\n\n## Also known as\n\n* Transparent Objects\n\n## Intent of Naked Objects Design Pattern\n\nTo enable the rapid development of maintainable systems by representing all business objects directly and automatically creating the user interface from these definitions. Naked Objects design pattern is essential for developers aiming to align user interfaces with domain models seamlessly.\n\n## Detailed Explanation of Naked Objects Pattern with Real-World Examples\n\nReal-world example\n\n> In a Naked Objects design pattern, a company might develop a customer relationship management (CRM) system where each business object, such as \"Customer,\" \"Order,\" and \"Product,\" is represented directly. This allows for a dynamic and adaptable UI reflecting the underlying domain model with minimal developer intervention. The user interface is automatically generated based on these domain objects, allowing sales representatives to view and edit customer information, track orders, and manage inventory without needing a separately designed UI.\n>\n> This approach ensures that any changes in the business logic or domain model are immediately reflected in the user interface, significantly reducing the development and maintenance time. For instance, if a new field, \"Loyalty Points,\" is added to the \"Customer\" object to track rewards, this field automatically appears in the CRM's user interface without additional UI development. This keeps the system flexible and closely aligned with the evolving business needs.\n\nIn plain words\n\n> The Naked Objects design pattern automatically generates a user interface from domain objects, allowing for rapid development and easy maintenance by ensuring the UI directly reflects the underlying business model.\n\nWikipedia says\n\n> Naked objects is an architectural pattern used in software engineering. It is defined by three principles:\n>\n> 1. All business logic should be encapsulated onto the domain objects. This principle is not unique to naked objects; it is a strong commitment to encapsulation.\n> 2. The user interface should be a direct representation of the domain objects, with all user actions consisting of creating, retrieving, or invoking methods on domain objects. This principle is not unique to naked objects: it is an interpretation of an object-oriented user interface.\n>\n> The naked object pattern's innovative feature arises by combining the 1st and 2nd principles into a 3rd principle: 3. The user interface shall be entirely automatically created from the definitions of the domain objects. This may be done using reflection or source code generation.\n\nArchitecture diagram\n\n![Naked Objects Architecture Diagram](./etc/naked-objects-architecture-diagram.png)\n\n\n## Programmatic Example of Naked Objects Pattern in Java\n\nConsider a simplified example with domain objects representing books and authors. In a Java-based application using the Naked Objects pattern, we define domain objects such as `Book` and `Author`. This example illustrates how Naked Objects can streamline user interface generation and domain object manipulation.\n\nSuppose we have the following domain objects in a Java-based application:\n\n````java\n@DomainObject\npublic class Book {\n    @Property\n    private String title;\n\n    @Property\n    private String author;\n\n    @Action\n    public void borrow() {\n        // Implement borrowing logic here\n    }\n}\n\n@DomainObject\npublic class Author {\n    @Property\n    private String name;\n\n    @Collection\n    public List<Book> getBooks() {\n        // Implement logic to retrieve books by this author\n    }\n\n    @Action\n    public Book createBook(String title) {\n        // Implement logic to create a new book by this author\n    }\n}\n````\n\nIn this example, we define two domain objects: `Book` and `Author`. The `Book` class has properties for the `title` and `author`, as well as an action to `borrow` the book. The `Author` class has a property for the author's `name`, a collection of books they have written (`getBooks`), and an action to create a new book (`createBook`).\n\nWith the Naked Objects framework or tool, the user interface for managing books and authors can be automatically generated based on these domain object definitions. Users can interact with the generated UI to create, retrieve, update, and delete books and authors directly through a user-friendly interface.\n\nHere's how you can use these domain objects to create and interact with books and authors programmatically:\n\n```java\nvar author = new Author();\nauthor.setName(\"J.K. Rowling\");\nvar book = author.createBook(\"Harry Potter and the Philosopher's Stone\");\nbook.setAuthor(author);\nbook.borrow();\nvar booksByAuthor = author.getBooks();\n```\n\nThis example demonstrates how the Naked Objects pattern can be implemented in a Java-based application with domain objects for books and authors. Users can directly manipulate these domain objects through the generated user interface.\n\n## When to Use the Naked Objects Pattern in Java\n\n* When aiming to create a system where the domain objects can be easily understood and manipulated without an explicit user interface design.\n* For applications requiring a dynamic, adaptable UI that reflects the underlying domain model with minimal developer intervention.\n\n## Real-World Applications of Naked Objects Pattern in Java\n\n* Enterprise applications where business rules and domain logic are primary.\n* Systems that benefit from a dynamic and adaptive user interface.\n\n## Benefits and Trade-offs of Naked Objects Pattern\n\nBenefits: \n\n* Rapid development\n* Improved maintainability\n* Easy domain understanding\n* Alignment between the UI and business model\n\nTrade-offs: \n\n* Reduced UI flexibility\n* Potential over-exposure of the domain model\n* Reliance on framework capabilities\n\n## Related Java Design Patterns\n\nActive Record: Similar in exposing domain models directly, but Active Record typically involves persistence aspects as well.\nDomain-Driven Design: Shares the focus on domain modeling but without the automatic UI generation of Naked Objects.\n\n## References and Credits\n\n* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3wlDrze)\n* [Naked Objects](https://amzn.to/3yhrfQr)\n* [Naked Objects (Richard Pawson)](http://downloads.nakedobjects.net/resources/Pawson%20thesis.pdf)\n* [Introducing Apache Isis (Apache Isis)](https://isis.apache.org/versions/1.16.0/pages/downloadable-presentations/resources/downloadable-presentations/IntroducingApacheIsis-notes.pdf)\n"
  },
  {
    "path": "notification/README.md",
    "content": "---\ntitle: \"Notification Pattern in Java: Enhancing System Communication with Event Alerts\"\nshortTitle: Notification\ndescription: \"Learn how to implement the Notification design pattern in Java with detailed explanations, code examples, and use cases. Improve your design patterns knowledge and code quality.\"\ncategory: Behavioral\nlanguage: en \ntags:\n  - Asynchronous\n  - Decoupling\n  - Event-driven\n  - Messaging\n  - Publish/subscribe\n---\n\n## Also known as\n\n* Event Listener\n\n## Intent of Notification Design Pattern\n\nThe Notification design pattern in Java aims to facilitate asynchronous communication between different parts of a system by allowing objects to subscribe to specific events and receive updates asynchronously when those events occur.\n\n## Detailed Explanation of Notification Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a weather alert system as a real-world analogous example of the Notification design pattern. In this system, a weather station collects data on weather conditions like temperature, humidity, and storm alerts. Multiple subscribers, such as news agencies, smartphone weather apps, and emergency services, are interested in receiving updates about specific weather events, like severe storms or extreme temperatures.\n>\n> When the weather station detects a significant event, it publishes this information. All subscribed entities receive these updates automatically without the weather station needing to know the details of these subscribers. For instance, a news agency might use this information to update its weather report, while emergency services might use it to prepare for potential disasters. This system exemplifies the Notification pattern's ability to decouple the publisher (the weather station) from its subscribers and deliver timely updates efficiently.\n\nIn plain words\n\n> The Notification design pattern enables an object to automatically notify a list of interested observers about changes or events without knowing the specifics of the subscribers.\n\nSequence diagram\n\n![Notification sequence diagram](./etc/notification-sequence-diagram.png)\n\n## Programmatic Example of Notification Pattern in Java\n\nThe Java Notification pattern is used to capture information passed between layers, validate the information, and return any errors to the presentation layer if needed. It reduces coupling between the producer and consumer of events, enhances flexibility and reusability of components, and allows for dynamic event subscription and unsubscription.\n\nIn this example, we'll use a form submission scenario to demonstrate the Notification pattern. The form is used to register a worker with their name, occupation, and date of birth. The form data is passed to the domain layer for validation, and any errors are returned to the presentation layer.\n\nHere's the `RegisterWorkerForm` class, which acts as our presentation layer. It takes the worker's details as input and submits the form.\n\n```java\nclass RegisterWorkerForm {\n\n    private RegisterWorkerForm registerWorkerForm;\n\n    RegisterWorkerForm(String name, String occupation, LocalDate dateOfBirth) {\n        // Initialize the form with the worker's details\n    }\n\n    void submit() {\n        // Submit the form\n        // If there are any errors, they will be captured in the worker's notification\n    }\n}\n```\n\nThe `RegisterWorker` class acts as our domain layer. It validates the worker's details and returns any errors through the `RegisterWorkerDto`.\n\n```java\nclass RegisterWorker {\n\n    RegisterWorker(String name, String occupation, LocalDate dateOfBirth) {\n        // Validate the worker's details\n        // If there are any errors, add them to the notification\n    }\n}\n```\n\nFinally, the `App` class is where the form is created and submitted.\n\n```java\npublic class App {\n\n  public static void main(String[] args) {\n    var form = new RegisterWorkerForm(\"John Doe\", \"Engineer\", LocalDate.of(1990, 1, 1));\n    form.submit();\n  }\n}\n```\n\nIn this example, if the worker's details are invalid (e.g. the name is empty), the `RegisterWorker` class will add an error to the notification. The `RegisterWorkerForm` class can then check the notification for any errors after submission. This demonstrates the Notification pattern, where information is passed between layers and any errors are returned to the presentation layer.\n\nThe form then processes the submission and returns these error messages to the user, showing our notification worked.\n\nExample output:\n\n```java\n18:10:00.075 [main] INFO com.iluwatar.RegisterWorkerForm - Error 1: Name is missing: \"\"\n18:10:00.079 [main] INFO com.iluwatar.RegisterWorkerForm - Error 2: Occupation is missing: \"\"\n18:10:00.079 [main] INFO com.iluwatar.RegisterWorkerForm - Error 4: Worker registered must be over 18: \"2016-07-13\"\n18:10:00.080 [main] INFO com.iluwatar.RegisterWorkerForm - Not registered, see errors\n```\n\n## When to Use the Notification Pattern in Java\n\n* When a change to one object requires changing others, and you don’t know how many objects need to be changed.\n* When an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently.\n* When a system component must be notified of events without making assumptions about the system’s other components.\n\n## Real-World Applications of Notification Pattern in Java\n\n* GUI frameworks where user actions trigger responses in the application.\n* Notification systems in large-scale distributed systems.\n* Event management in microservices architecture.\n\n## Benefits and Trade-offs of Notification Pattern\n\nBenefits:\n\n* Reduces coupling between the producer and consumer of events.\n* Enhances flexibility and reusability of components.\n* Allows for dynamic subscription and unsubscription to events.\n\nTrade-offs:\n\n* Can lead to a complex system if not managed well, due to the dynamic nature of subscriptions.\n* Debugging can be challenging due to the asynchronous and decoupled nature of events.\n\n## Related Java Design Patterns\n\n* [Command](https://java-design-patterns.com/patterns/command/): Can be used to encapsulate a request as an object, often used in conjunction with notifications to decouple the sender and receiver.\n* [Mediator](https://java-design-patterns.com/patterns/mediator/): Facilitates centralized communication between objects, whereas the Notification pattern is more decentralized.\n* [Observer](https://java-design-patterns.com/patterns/observer/): A foundational pattern for the Notification pattern, focusing on one-to-many dependency relationships.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions](https://amzn.to/3WcFVui)\n* [Notification Pattern (Martin Fowler)](https://martinfowler.com/eaaDev/Notification.html)\n"
  },
  {
    "path": "notification/etc/notification.urm.puml",
    "content": "@startuml\npackage com.iluwatar {\n  class App {\n    - DATE_OF_BIRTH : LocalDate {static}\n    - NAME : String {static}\n    - OCCUPATION : String {static}\n    - App()\n    + main(args : String[]) {static}\n  }\n  class DataTransferObject {\n    # notification : Notification\n    + DataTransferObject()\n    + getNotification() : Notification\n  }\n  class Notification {\n    - errors : List<NotificationError>\n    + Notification()\n    + addError(error : NotificationError)\n    + getErrors() : List<NotificationError>\n    + hasErrors() : boolean\n  }\n  class NotificationError {\n    - errorId : int\n    - errorMessage : String\n    + NotificationError(errorId : int, errorMessage : String)\n    + getErrorId() : int\n    + getErrorMessage() : String\n    + toString() : String\n  }\n  class RegisterWorker {\n    - LOGGER : Logger {static}\n    # RegisterWorker(worker : RegisterWorkerDto)\n    # fail(condition : boolean, error : NotificationError)\n    # failIfNullOrBlank(s : String, error : NotificationError)\n    # isNullOrBlank(s : String) : boolean\n    + run()\n    - validate()\n  }\n  class RegisterWorkerDto {\n    + DOB_TOO_SOON : NotificationError {static}\n    + MISSING_DOB : NotificationError {static}\n    + MISSING_NAME : NotificationError {static}\n    + MISSING_OCCUPATION : NotificationError {static}\n    - dateOfBirth : LocalDate\n    - name : String\n    - occupation : String\n    # RegisterWorkerDto()\n    + getDateOfBirth() : LocalDate\n    + getName() : String\n    + getOccupation() : String\n    + setDateOfBirth(dateOfBirth : LocalDate)\n    + setName(name : String)\n    + setOccupation(occupation : String)\n    + setupWorkerDto(name : String, occupation : String, dateOfBirth : LocalDate)\n  }\n  class RegisterWorkerForm {\n    - LOGGER : Logger {static}\n    ~ dateOfBirth : LocalDate\n    ~ name : String\n    ~ occupation : String\n    ~ service : RegisterWorkerService\n    ~ worker : RegisterWorkerDto\n    + RegisterWorkerForm(name : String, occupation : String, dateOfBirth : LocalDate)\n    - checkError(error : NotificationError, info : String)\n    - indicateErrors()\n    - saveToWorker()\n    ~ showError(info : String, message : String)\n    + submit()\n  }\n  class RegisterWorkerService {\n    + RegisterWorkerService()\n    + registerWorker(registration : RegisterWorkerDto)\n  }\n  class ServerCommand {\n    # data : DataTransferObject\n    + ServerCommand(data : DataTransferObject)\n    + getNotification() : Notification\n  }\n}\nNotification -->  \"-errors\" NotificationError\nDataTransferObject -->  \"-notification\" Notification\nRegisterWorkerForm -->  \"-service\" RegisterWorkerService\nRegisterWorkerForm -->  \"-worker\" RegisterWorkerDto\nServerCommand -->  \"-data\" DataTransferObject\nRegisterWorkerDto -->  \"-MISSING_DOB\" NotificationError\nRegisterWorkerDto -->  \"-MISSING_NAME\" NotificationError\nRegisterWorker --|> ServerCommand \nRegisterWorkerDto --|> DataTransferObject \n@enduml"
  },
  {
    "path": "notification/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-params</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <artifactId>notification</artifactId>\n</project>"
  },
  {
    "path": "notification/src/main/java/com/iluwatar/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport java.time.LocalDate;\n\n/**\n * The notification pattern captures information passed between layers, validates the information,\n * and returns any errors to the presentation layer if needed.\n *\n * <p>In this code, this pattern is implemented through the example of a form being submitted to\n * register a worker. The worker inputs their name, occupation, and date of birth to the\n * RegisterWorkerForm (which acts as our presentation layer), and passes it to the RegisterWorker\n * class (our domain layer) which validates it. Any errors caught by the domain layer are then\n * passed back to the presentation layer through the RegisterWorkerDto.\n */\npublic class App {\n\n  private static final String NAME = \"\";\n  private static final String OCCUPATION = \"\";\n  private static final LocalDate DATE_OF_BIRTH = LocalDate.of(2016, 7, 13);\n\n  public static void main(String[] args) {\n    var form = new RegisterWorkerForm(NAME, OCCUPATION, DATE_OF_BIRTH);\n    form.submit();\n  }\n}\n"
  },
  {
    "path": "notification/src/main/java/com/iluwatar/DataTransferObject.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\n\n/**\n * Layer super type for all Data Transfer Objects. Also contains code for accessing our\n * notification.\n */\n@Getter\n@NoArgsConstructor\npublic class DataTransferObject {\n\n  private final Notification notification = new Notification();\n}\n"
  },
  {
    "path": "notification/src/main/java/com/iluwatar/Notification.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\n\n/**\n * The notification. Used for storing errors and any other methods that may be necessary for when we\n * send information back to the presentation layer.\n */\n@Getter\n@NoArgsConstructor\npublic class Notification {\n\n  private final List<NotificationError> errors = new ArrayList<>();\n\n  public boolean hasErrors() {\n    return !this.errors.isEmpty();\n  }\n\n  public void addError(NotificationError error) {\n    this.errors.add(error);\n  }\n}\n"
  },
  {
    "path": "notification/src/main/java/com/iluwatar/NotificationError.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\n/**\n * Error class for storing information on the error. Error ID is not necessary, but may be useful\n * for serialisation.\n */\n@Getter\n@AllArgsConstructor\npublic class NotificationError {\n  private int errorId;\n  private String errorMessage;\n\n  @Override\n  public String toString() {\n    return \"Error \" + errorId + \": \" + errorMessage;\n  }\n}\n"
  },
  {
    "path": "notification/src/main/java/com/iluwatar/RegisterWorker.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport java.time.LocalDate;\nimport java.time.Period;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Class which handles actual internal logic and validation for worker registration. Part of the\n * domain layer which collects information and sends it back to the presentation.\n */\n@Slf4j\npublic class RegisterWorker extends ServerCommand {\n  static final int LEGAL_AGE = 18;\n\n  protected RegisterWorker(RegisterWorkerDto worker) {\n    super(worker);\n  }\n\n  /** Validates the data provided and adds it to the database in the backend. */\n  public void run() {\n\n    validate();\n    if (!super.getNotification().hasErrors()) {\n      LOGGER.info(\"Register worker in backend system\");\n    }\n  }\n\n  /** Validates our data. Checks for any errors and if found, adds to notification. */\n  private void validate() {\n    var ourData = ((RegisterWorkerDto) this.data);\n    // check if any of submitted data is not given\n    // passing for empty value validation\n    fail(isNullOrBlank(ourData.getName()), RegisterWorkerDto.MISSING_NAME);\n    fail(isNullOrBlank(ourData.getOccupation()), RegisterWorkerDto.MISSING_OCCUPATION);\n    fail(isNullOrBlank(ourData.getDateOfBirth()), RegisterWorkerDto.MISSING_DOB);\n\n    if (isNullOrBlank(ourData.getDateOfBirth())) {\n      // If DOB is null or empty\n      fail(true, RegisterWorkerDto.MISSING_DOB);\n    } else {\n      // Validating age ( should be greater than or equal to 18 )\n      Period age = Period.between(ourData.getDateOfBirth(), LocalDate.now());\n      fail(age.getYears() < LEGAL_AGE, RegisterWorkerDto.DOB_TOO_SOON);\n    }\n  }\n\n  /**\n   * Validates for null/empty value.\n   *\n   * @param obj any object\n   * @return boolean\n   */\n  protected boolean isNullOrBlank(Object obj) {\n    if (obj == null) {\n      return true;\n    }\n\n    if (obj instanceof String) {\n      return ((String) obj).trim().isEmpty();\n    }\n\n    return false;\n  }\n\n  /**\n   * If a condition is met, adds the error to our notification.\n   *\n   * @param condition condition to check for.\n   * @param error error to add if condition met.\n   */\n  protected void fail(boolean condition, NotificationError error) {\n    if (condition) {\n      super.getNotification().addError(error);\n    }\n  }\n}\n"
  },
  {
    "path": "notification/src/main/java/com/iluwatar/RegisterWorkerDto.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport java.time.LocalDate;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/**\n * Data transfer object which stores information about the worker. This is carried between objects\n * and layers to reduce the number of method calls made.\n */\n@Getter\n@Setter\npublic class RegisterWorkerDto extends DataTransferObject {\n  private String name;\n  private String occupation;\n  private LocalDate dateOfBirth;\n\n  /** Error for when name field is blank or missing. */\n  public static final NotificationError MISSING_NAME = new NotificationError(1, \"Name is missing\");\n\n  /** Error for when occupation field is blank or missing. */\n  public static final NotificationError MISSING_OCCUPATION =\n      new NotificationError(2, \"Occupation is missing\");\n\n  /** Error for when date of birth field is blank or missing. */\n  public static final NotificationError MISSING_DOB =\n      new NotificationError(3, \"Date of birth is missing\");\n\n  /** Error for when date of birth is less than 18 years ago. */\n  public static final NotificationError DOB_TOO_SOON =\n      new NotificationError(4, \"Worker registered must be over 18\");\n\n  protected RegisterWorkerDto() {\n    super();\n  }\n\n  /**\n   * Simple set up function for capturing our worker information.\n   *\n   * @param name Name of the worker\n   * @param occupation occupation of the worker\n   * @param dateOfBirth Date of Birth of the worker\n   */\n  public void setupWorkerDto(String name, String occupation, LocalDate dateOfBirth) {\n    this.name = name;\n    this.occupation = occupation;\n    this.dateOfBirth = dateOfBirth;\n  }\n}\n"
  },
  {
    "path": "notification/src/main/java/com/iluwatar/RegisterWorkerForm.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport java.time.LocalDate;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The form submitted by the user, part of the presentation layer, linked to the domain layer\n * through a data transfer object and linked to the service layer directly.\n */\n@Slf4j\npublic class RegisterWorkerForm {\n  String name;\n  String occupation;\n  LocalDate dateOfBirth;\n  RegisterWorkerDto worker;\n  RegisterWorkerService service = new RegisterWorkerService();\n\n  /**\n   * Constructor.\n   *\n   * @param name Name of the worker\n   * @param occupation occupation of the worker\n   * @param dateOfBirth Date of Birth of the worker\n   */\n  public RegisterWorkerForm(String name, String occupation, LocalDate dateOfBirth) {\n    this.name = name;\n    this.occupation = occupation;\n    this.dateOfBirth = dateOfBirth;\n  }\n\n  /** Attempts to submit the form for registering a worker. */\n  public void submit() {\n    // Transmit information to our transfer object to communicate between layers\n    saveToWorker();\n    // call the service layer to register our worker\n    service.registerWorker(worker);\n\n    // check for any errors\n    if (worker.getNotification().hasErrors()) {\n      indicateErrors();\n      LOGGER.info(\"Not registered, see errors\");\n    } else {\n      LOGGER.info(\"Registration Succeeded\");\n    }\n  }\n\n  /** Saves worker information to the data transfer object. */\n  private void saveToWorker() {\n    worker = new RegisterWorkerDto();\n    worker.setName(name);\n    worker.setOccupation(occupation);\n    worker.setDateOfBirth(dateOfBirth);\n  }\n\n  /** Check for any errors with form submission and show them to the user. */\n  public void indicateErrors() {\n    worker.getNotification().getErrors().forEach(error -> LOGGER.error(error.toString()));\n  }\n}\n"
  },
  {
    "path": "notification/src/main/java/com/iluwatar/RegisterWorkerService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\n/**\n * Service used to register a worker. This represents the basic framework of a service layer which\n * can be built upon.\n */\npublic class RegisterWorkerService {\n  /**\n   * Creates and runs a command object to do the work needed, in this case, register a worker in the\n   * system.\n   *\n   * @param registration worker to be registered if possible\n   */\n  public void registerWorker(RegisterWorkerDto registration) {\n    var cmd = new RegisterWorker(registration);\n    cmd.run();\n  }\n}\n"
  },
  {
    "path": "notification/src/main/java/com/iluwatar/ServerCommand.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport lombok.AllArgsConstructor;\n\n/**\n * Stores the dto and access the notification within it. Acting as a layer supertype in this\n * instance for the domain layer.\n */\n@AllArgsConstructor\npublic class ServerCommand {\n  protected DataTransferObject data;\n\n  /**\n   * Basic getter to extract information from our data.\n   *\n   * @return the notification stored within the data\n   */\n  public Notification getNotification() {\n    return data.getNotification();\n  }\n}\n"
  },
  {
    "path": "notification/src/test/java/com/iluwatar/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "notification/src/test/java/com/iluwatar/RegisterWorkerFormTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nimport java.time.LocalDate;\nimport org.junit.jupiter.api.Test;\n\nclass RegisterWorkerFormTest {\n\n  private RegisterWorkerForm registerWorkerForm;\n\n  @Test\n  void submitSuccessfully() {\n    // Ensure the worker is null initially\n    registerWorkerForm = new RegisterWorkerForm(\"John Doe\", \"Engineer\", LocalDate.of(1990, 1, 1));\n\n    assertNull(registerWorkerForm.worker);\n\n    // Submit the form\n    registerWorkerForm.submit();\n\n    // Verify that the worker is not null after submission\n    assertNotNull(registerWorkerForm.worker);\n\n    // Verify that the worker's properties are set correctly\n    assertEquals(\"John Doe\", registerWorkerForm.worker.getName());\n    assertEquals(\"Engineer\", registerWorkerForm.worker.getOccupation());\n    assertEquals(LocalDate.of(1990, 1, 1), registerWorkerForm.worker.getDateOfBirth());\n  }\n\n  @Test\n  void submitWithErrors() {\n    // Set up the worker with a notification containing errors\n    registerWorkerForm = new RegisterWorkerForm(null, null, null);\n\n    // Submit the form\n    registerWorkerForm.submit();\n\n    // Verify that the worker's properties remain unchanged\n    assertNull(registerWorkerForm.worker.getName());\n    assertNull(registerWorkerForm.worker.getOccupation());\n    assertNull(registerWorkerForm.worker.getDateOfBirth());\n\n    // Verify the presence of errors\n    assertEquals(registerWorkerForm.worker.getNotification().getErrors().size(), 4);\n  }\n}\n"
  },
  {
    "path": "notification/src/test/java/com/iluwatar/RegisterWorkerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.time.LocalDate;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\n\n@Slf4j\nclass RegisterWorkerTest {\n\n  @Test\n  void runSuccessfully() {\n    RegisterWorkerDto validWorkerDto = createValidWorkerDto();\n    validWorkerDto.setupWorkerDto(\"name\", \"occupation\", LocalDate.of(2000, 12, 1));\n    RegisterWorker registerWorker = new RegisterWorker(validWorkerDto);\n\n    // Run the registration process\n    registerWorker.run();\n\n    // Verify that there are no errors in the notification\n    assertFalse(registerWorker.getNotification().hasErrors());\n  }\n\n  @Test\n  void runWithMissingName() {\n    RegisterWorkerDto workerDto = createValidWorkerDto();\n    workerDto.setupWorkerDto(null, \"occupation\", LocalDate.of(2000, 12, 1));\n    RegisterWorker registerWorker = new RegisterWorker(workerDto);\n\n    // Run the registration process\n    registerWorker.run();\n\n    // Verify that the notification contains the missing name error\n    assertTrue(registerWorker.getNotification().hasErrors());\n    assertTrue(\n        registerWorker.getNotification().getErrors().contains(RegisterWorkerDto.MISSING_NAME));\n    assertEquals(registerWorker.getNotification().getErrors().size(), 1);\n  }\n\n  @Test\n  void runWithMissingOccupation() {\n    RegisterWorkerDto workerDto = createValidWorkerDto();\n    workerDto.setupWorkerDto(\"name\", null, LocalDate.of(2000, 12, 1));\n    RegisterWorker registerWorker = new RegisterWorker(workerDto);\n\n    // Run the registration process\n    registerWorker.run();\n\n    // Verify that the notification contains the missing occupation error\n    assertTrue(registerWorker.getNotification().hasErrors());\n    assertTrue(\n        registerWorker\n            .getNotification()\n            .getErrors()\n            .contains(RegisterWorkerDto.MISSING_OCCUPATION));\n    assertEquals(registerWorker.getNotification().getErrors().size(), 1);\n  }\n\n  @Test\n  void runWithMissingDOB() {\n    RegisterWorkerDto workerDto = createValidWorkerDto();\n    workerDto.setupWorkerDto(\"name\", \"occupation\", null);\n    RegisterWorker registerWorker = new RegisterWorker(workerDto);\n\n    // Run the registration process\n    registerWorker.run();\n\n    // Verify that the notification contains the missing DOB error\n    assertTrue(registerWorker.getNotification().hasErrors());\n    assertTrue(\n        registerWorker.getNotification().getErrors().contains(RegisterWorkerDto.MISSING_DOB));\n    assertEquals(registerWorker.getNotification().getErrors().size(), 2);\n  }\n\n  @Test\n  void runWithUnderageDOB() {\n    RegisterWorkerDto workerDto = createValidWorkerDto();\n    workerDto.setDateOfBirth(LocalDate.now().minusYears(17)); // Under 18\n    workerDto.setupWorkerDto(\"name\", \"occupation\", LocalDate.now().minusYears(17));\n    RegisterWorker registerWorker = new RegisterWorker(workerDto);\n\n    // Run the registration process\n    registerWorker.run();\n\n    // Verify that the notification contains the underage DOB error\n    assertTrue(registerWorker.getNotification().hasErrors());\n    assertTrue(\n        registerWorker.getNotification().getErrors().contains(RegisterWorkerDto.DOB_TOO_SOON));\n    assertEquals(registerWorker.getNotification().getErrors().size(), 1);\n  }\n\n  private RegisterWorkerDto createValidWorkerDto() {\n    return new RegisterWorkerDto();\n  }\n}\n"
  },
  {
    "path": "null-object/README.md",
    "content": "---\ntitle: \"Null Object Pattern in Java: Streamlining Error Handling with Graceful Defaults\"\nshortTitle: Null Object\ndescription: \"Learn how the Null Object Pattern simplifies your Java code by handling null references effectively. Discover its implementation, advantages, and practical use cases.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Code simplification\n  - Decoupling\n  - Polymorphism\n---\n\n## Also known as\n\n* Active Nothing\n* Stub\n\n## Intent of Null Object Design Pattern\n\nThe Null Object Pattern is an essential Java design pattern that provides a seamless way to handle absent objects without performing null checks, streamlining your Java applications.\n\n## Detailed Explanation of Null Object Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy for the Null Object pattern can be found in the context of customer service. Imagine a customer service system where there are different types of support representatives: human agents and automated bots. When a customer request is received, the system can assign it to a human agent or, if no agents are available, to an automated bot. If neither human agents nor automated bots are available, the system assigns the request to a \"Null Representative.\"\n>\n> The Null Representative is a placeholder that does nothing but ensures that the system doesn't crash or raise errors due to the absence of a support representative. It provides default responses like \"Your request is being processed\" without any actual processing, thereby maintaining system stability and avoiding the need for null checks throughout the codebase.       \n\nIn plain words\n\n> Null Object pattern handles \"empty\" objects gracefully.   \n\nWikipedia says\n\n> In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral (\"null\") behavior. The null object design pattern describes the uses of such objects and their behavior (or lack thereof).\n\nSequence diagram\n\n![Null Object sequence diagram](./etc/null-object-sequence-diagram.png)\n\n## Programmatic Example of Null Object in Java\n\nBy implementing the Null Object Pattern, Java developers can ensure that their applications handle 'empty' objects more gracefully, enhancing code stability and readability.\n\nWe are building a binary tree from nodes. There are ordinary nodes and \"empty\" nodes. Traversing the tree normally should not cause errors, so we use null object pattern where necessary.\n\nHere's the definition of `Node` interface.\n\n```java\npublic interface Node {\n\n  String getName();\n\n  int getTreeSize();\n\n  Node getLeft();\n\n  Node getRight();\n\n  void walk();\n}\n```\n\nWe have two implementations of `Node`. The normal implementation `NodeImpl` and `NullNode` for empty nodes.\n\n```java\n@Slf4j\npublic class NodeImpl implements Node {\n\n  private final String name;\n  private final Node left;\n  private final Node right;\n\n  public NodeImpl(String name, Node left, Node right) {\n    this.name = name;\n    this.left = left;\n    this.right = right;\n  }\n\n  @Override\n  public int getTreeSize() {\n    return 1 + left.getTreeSize() + right.getTreeSize();\n  }\n\n  @Override\n  public Node getLeft() {\n    return left;\n  }\n\n  @Override\n  public Node getRight() {\n    return right;\n  }\n\n  @Override\n  public String getName() {\n    return name;\n  }\n\n  @Override\n  public void walk() {\n    LOGGER.info(name);\n    if (left.getTreeSize() > 0) {\n      left.walk();\n    }\n    if (right.getTreeSize() > 0) {\n      right.walk();\n    }\n  }\n}\n\npublic final class NullNode implements Node {\n\n  private static final NullNode instance = new NullNode();\n\n  private NullNode() {\n  }\n\n  public static NullNode getInstance() {\n    return instance;\n  }\n\n  @Override\n  public int getTreeSize() {\n    return 0;\n  }\n\n  @Override\n  public Node getLeft() {\n    return null;\n  }\n\n  @Override\n  public Node getRight() {\n    return null;\n  }\n\n  @Override\n  public String getName() {\n    return null;\n  }\n\n  @Override\n  public void walk() {\n    // Do nothing\n  }\n}\n```\n\nThen we can construct and traverse the binary tree without errors as follows.\n\n```java\nvar root = new NodeImpl(\"1\", new NodeImpl(\"11\", new NodeImpl(\"111\", NullNode.getInstance(), NullNode.getInstance()), NullNode.getInstance()),\n        new NodeImpl(\"12\", NullNode.getInstance(), new NodeImpl(\"122\", NullNode.getInstance(), NullNode.getInstance())));\nroot.walk();\n```\n\nProgram output:\n\n```\n1\n11\n111\n12\n122\n```\n\n## When to Use the Null Object Pattern in Java\n\n* When you need to provide a default behavior in place of a null object.\n* To simplify the client code by eliminating null checks.\n* When a default action is preferable to handling a null reference.\n\n## Real-World Applications of Null Object Pattern in Java\n\n* Commonly used in logging systems, the Null object helps prevent NullPointerExceptions, making it a critical pattern for reliable Java software development.\n* Collections that use a NullIterator to handle empty collections gracefully.\n* GUI systems where a NullComponent can be used to represent a component that does nothing.\n\n## Benefits and Trade-offs of Null Object Pattern\n\nBenefits:\n\n* Eliminates the need for null checks, reducing the risk of NullPointerException.\n* Simplifies the client code and enhances readability.\n* Promotes the use of polymorphism by handling default behavior through a common interface.\n\nTrade-offs:\n\n* May introduce additional classes, potentially increasing the overall complexity of the system.\n* The default behavior might mask potential issues that would otherwise be caught by explicit null handling.\n\n## Related Java Design Patterns\n\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Null Object can be seen as a special case of the Strategy Pattern where the strategy is to do nothing.\n* [State](https://java-design-patterns.com/patterns/state/): Similar in that both patterns can handle different states or behaviors; Null Object is like a state that does nothing.\n* [Factory](https://java-design-patterns.com/patterns/factory/): Often used to provide Null Objects in place of actual objects.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Pattern Languages of Program Design 3](https://amzn.to/3UZkRF6)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n* [Refactoring: Improving the Design of Existing Code](https://amzn.to/3UJ7etA)\n"
  },
  {
    "path": "null-object/etc/null-object.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <interface id=\"1\" language=\"java\" name=\"com.iluwatar.nullobject.Node\" project=\"null-object\" \n    file=\"/null-object/src/main/java/com/iluwatar/nullobject/Node.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"160\" width=\"135\" x=\"90\" y=\"494\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.nullobject.NodeImpl\" project=\"null-object\" \n    file=\"/null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"196\" width=\"190\" x=\"90\" y=\"248\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.nullobject.NullNode\" project=\"null-object\" \n    file=\"/null-object/src/main/java/com/iluwatar/nullobject/NullNode.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"196\" width=\"157\" x=\"320\" y=\"248\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"4\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"5\" name=\"right\"/>      \n      <multiplicity id=\"6\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"7\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"8\" name=\"instance\"/>      \n      <multiplicity id=\"9\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"10\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </realization>  \n  <association id=\"11\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"12\" name=\"left\"/>      \n      <multiplicity id=\"13\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"14\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "null-object/etc/null-object.urm.puml",
    "content": "@startuml\npackage com.iluwatar.nullobject {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  interface Node {\n    + getLeft() : Node {abstract}\n    + getName() : String {abstract}\n    + getRight() : Node {abstract}\n    + getTreeSize() : int {abstract}\n    + walk() {abstract}\n  }\n  class NodeImpl {\n    - LOGGER : Logger {static}\n    - left : Node\n    - name : String\n    - right : Node\n    + NodeImpl(name : String, left : Node, right : Node)\n    + getLeft() : Node\n    + getName() : String\n    + getRight() : Node\n    + getTreeSize() : int\n    + walk()\n  }\n  class NullNode {\n    - instance : NullNode {static}\n    - NullNode()\n    + getInstance() : NullNode {static}\n    + getLeft() : Node\n    + getName() : String\n    + getRight() : Node\n    + getTreeSize() : int\n    + walk()\n  }\n}\nNullNode -->  \"-instance\" NullNode\nNodeImpl -->  \"-left\" Node\nNodeImpl ..|> Node \nNullNode ..|> Node \n@enduml"
  },
  {
    "path": "null-object/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>null-object</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.nullobject.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "null-object/src/main/java/com/iluwatar/nullobject/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.nullobject;\n\n/**\n * Null Object pattern replaces null values with neutral objects. Many times this simplifies\n * algorithms since no extra null checks are needed.\n *\n * <p>In this example we build a binary tree where the nodes are either normal or Null Objects. No\n * null values are used in the tree making the traversal easy.\n */\npublic class App {\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var root =\n        new NodeImpl(\n            \"1\",\n            new NodeImpl(\n                \"11\",\n                new NodeImpl(\"111\", NullNode.getInstance(), NullNode.getInstance()),\n                NullNode.getInstance()),\n            new NodeImpl(\n                \"12\",\n                NullNode.getInstance(),\n                new NodeImpl(\"122\", NullNode.getInstance(), NullNode.getInstance())));\n\n    root.walk();\n  }\n}\n"
  },
  {
    "path": "null-object/src/main/java/com/iluwatar/nullobject/Node.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.nullobject;\n\n/** Interface for binary tree node. */\npublic interface Node {\n\n  String getName();\n\n  int getTreeSize();\n\n  Node getLeft();\n\n  Node getRight();\n\n  void walk();\n}\n"
  },
  {
    "path": "null-object/src/main/java/com/iluwatar/nullobject/NodeImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.nullobject;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Implementation for binary tree's normal nodes. */\n@Slf4j\npublic record NodeImpl(String name, Node left, Node right) implements Node {\n  @Override\n  public Node getLeft() {\n    return left;\n  }\n\n  @Override\n  public Node getRight() {\n    return right;\n  }\n\n  @Override\n  public String getName() {\n    return name;\n  }\n\n  @Override\n  public int getTreeSize() {\n    return 1 + left.getTreeSize() + right.getTreeSize();\n  }\n\n  @Override\n  public void walk() {\n    LOGGER.info(name);\n    if (left.getTreeSize() > 0) {\n      left.walk();\n    }\n    if (right.getTreeSize() > 0) {\n      right.walk();\n    }\n  }\n}\n"
  },
  {
    "path": "null-object/src/main/java/com/iluwatar/nullobject/NullNode.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.nullobject;\n\n/**\n * Null Object implementation for binary tree node.\n *\n * <p>Implemented as Singleton, since all the NullNodes are the same.\n */\npublic final class NullNode implements Node {\n\n  private static final NullNode instance = new NullNode();\n\n  private NullNode() {}\n\n  public static NullNode getInstance() {\n    return instance;\n  }\n\n  @Override\n  public int getTreeSize() {\n    return 0;\n  }\n\n  @Override\n  public Node getLeft() {\n    return null;\n  }\n\n  @Override\n  public Node getRight() {\n    return null;\n  }\n\n  @Override\n  public String getName() {\n    return null;\n  }\n\n  @Override\n  public void walk() {\n    // Do nothing\n  }\n}\n"
  },
  {
    "path": "null-object/src/test/java/com/iluwatar/nullobject/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.nullobject;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.nullobject;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertSame;\n\nimport org.junit.jupiter.api.Test;\n\n/** NullNodeTest */\nclass NullNodeTest {\n\n  /** Verify if {@link NullNode#getInstance()} actually returns the same object instance */\n  @Test\n  void testGetInstance() {\n    final var instance = NullNode.getInstance();\n    assertNotNull(instance);\n    assertSame(instance, NullNode.getInstance());\n  }\n\n  @Test\n  void testFields() {\n    final var node = NullNode.getInstance();\n    assertEquals(0, node.getTreeSize());\n    assertNull(node.getName());\n    assertNull(node.getLeft());\n    assertNull(node.getRight());\n  }\n\n  /**\n   * Removed unnecessary test method for {@link NullNode#walk()} as the method doesn't have an\n   * implementation.\n   */\n}\n"
  },
  {
    "path": "null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.nullobject;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertSame;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/** TreeTest */\nclass TreeTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /**\n   * During the tests, the same tree structure will be used, shown below. End points will be\n   * terminated with the {@link NullNode} instance.\n   *\n   * <pre>\n   * root\n   * ├── level1_a\n   * │   ├── level2_a\n   * │   │   ├── level3_a\n   * │   │   └── level3_b\n   * │   └── level2_b\n   * └── level1_b\n   * </pre>\n   */\n  private static final Node TREE_ROOT;\n\n  static {\n    final var level1B = new NodeImpl(\"level1_b\", NullNode.getInstance(), NullNode.getInstance());\n    final var level2B = new NodeImpl(\"level2_b\", NullNode.getInstance(), NullNode.getInstance());\n    final var level3A = new NodeImpl(\"level3_a\", NullNode.getInstance(), NullNode.getInstance());\n    final var level3B = new NodeImpl(\"level3_b\", NullNode.getInstance(), NullNode.getInstance());\n    final var level2A = new NodeImpl(\"level2_a\", level3A, level3B);\n    final var level1A = new NodeImpl(\"level1_a\", level2A, level2B);\n    TREE_ROOT = new NodeImpl(\"root\", level1A, level1B);\n  }\n\n  /**\n   * Verify the number of items in the tree. The root has 6 children so we expect a {@link\n   * Node#getTreeSize()} of 7 {@link Node}s in total.\n   */\n  @Test\n  void testTreeSize() {\n    assertEquals(7, TREE_ROOT.getTreeSize());\n  }\n\n  /** Walk through the tree and verify if every item is handled */\n  @Test\n  void testWalk() {\n    TREE_ROOT.walk();\n\n    assertTrue(appender.logContains(\"root\"));\n    assertTrue(appender.logContains(\"level1_a\"));\n    assertTrue(appender.logContains(\"level2_a\"));\n    assertTrue(appender.logContains(\"level3_a\"));\n    assertTrue(appender.logContains(\"level3_b\"));\n    assertTrue(appender.logContains(\"level2_b\"));\n    assertTrue(appender.logContains(\"level1_b\"));\n    assertEquals(7, appender.getLogSize());\n  }\n\n  @Test\n  void testGetLeft() {\n    final var level1 = TREE_ROOT.getLeft();\n    assertNotNull(level1);\n    assertEquals(\"level1_a\", level1.getName());\n    assertEquals(5, level1.getTreeSize());\n\n    final var level2 = level1.getLeft();\n    assertNotNull(level2);\n    assertEquals(\"level2_a\", level2.getName());\n    assertEquals(3, level2.getTreeSize());\n\n    final var level3 = level2.getLeft();\n    assertNotNull(level3);\n    assertEquals(\"level3_a\", level3.getName());\n    assertEquals(1, level3.getTreeSize());\n    assertSame(NullNode.getInstance(), level3.getRight());\n    assertSame(NullNode.getInstance(), level3.getLeft());\n  }\n\n  @Test\n  void testGetRight() {\n    final var level1 = TREE_ROOT.getRight();\n    assertNotNull(level1);\n    assertEquals(\"level1_b\", level1.getName());\n    assertEquals(1, level1.getTreeSize());\n    assertSame(NullNode.getInstance(), level1.getRight());\n    assertSame(NullNode.getInstance(), level1.getLeft());\n  }\n\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender() {\n      ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public boolean logContains(String message) {\n      return log.stream().map(ILoggingEvent::getMessage).anyMatch(message::equals);\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n  }\n}\n"
  },
  {
    "path": "object-mother/README.md",
    "content": "---\ntitle: \"Object Mother Pattern in Java: Simplifying Object Creation for Testing\"\nshortTitle: Object Mother\ndescription: \"Explore the Object Mother pattern in Java for simplifying test object creation. Learn how to efficiently generate test data, reduce boilerplate, and enhance test maintainability with our in-depth guide and examples.\"\ncategory: Testing\nlanguage: en\ntag:\n  - Code simplification\n  - Instantiation\n  - Isolation\n  - Testing\n---\n\n## Also known as\n\n* Object Builder\n* Test Data Builder\n\n## Intent of Object Mother Design Pattern\n\nThe Object Mother pattern simplifies the creation of objects for testing purposes in Java, ensuring that test cases are clear and maintainable by centralizing the logic needed to instantiate objects in a consistent state.\n\n## Detailed Explanation of Object Mother Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine you're developing a Java application for a travel agency. In your system, there are different types of travelers, such as tourists, business travelers, and travel agents, each with specific attributes and behaviors. To perform thorough testing, you need to create and manipulate these traveler objects in various contexts. The Object Mother Pattern can help you generate consistent and predefined traveler objects for testing purposes, ensuring that your tests are based on known, reliable data.\n\nIn plain words\n\n> The Object Mother Pattern is a design pattern used in Java to simplify the creation of objects with specific configurations, especially for testing. Instead of manually constructing objects with varying properties for each test case, you create a dedicated \"Object Mother\" class or method that produces these objects with predefined settings. This ensures that you have consistent and predictable test data, making your tests more reliable and easier to manage.\n\nwiki.c2.com says\n\n> Object Mother starts with the factory pattern, by delivering prefabricated test-ready objects via a simple method call. It moves beyond the realm of the factory by\n> 1. facilitating the customization of created objects,\n> 2. providing methods to update the objects during the tests, and\n> 3. if necessary, deleting the object from the database at the completion of the test.\n\nMind map\n\n![Object Mother mind map](./etc/object-mother-mind-map.png)\n\nFlowchart\n\n![Object Mother flowchart](./etc/object-mother-flowchart.png)\n\n## Programmatic Example of Object Mother Pattern in Java\n\nThe Object Mother is a design pattern that aims to provide an easy way to create objects for testing purposes. It encapsulates the logic for building instances of complex objects in one place, making it easier to maintain and reuse across multiple tests.\n\nFirst, we have the `King` class. This class represents a king with certain behaviors and states. The king can be drunk or sober, happy or unhappy. The king can also flirt with a queen, which may affect his happiness.\n\n```java\npublic class King implements Royalty {\n  boolean isDrunk = false;\n  boolean isHappy = false;\n\n  @Override\n  public void makeDrunk() {\n    isDrunk = true;\n  }\n\n  @Override\n  public void makeSober() {\n    isDrunk = false;\n  }\n\n  @Override\n  public void makeHappy() {\n    isHappy = true;\n  }\n\n  @Override\n  public void makeUnhappy() {\n    isHappy = false;\n  }\n\n  public boolean isHappy() {\n    return isHappy;\n  }\n\n  public void flirt(Queen queen) {\n    var flirtStatus = queen.getFlirted(this);\n    if (!flirtStatus) {\n      this.makeUnhappy();\n    } else {\n      this.makeHappy();\n    }\n  }\n}\n```\n\nThe `RoyaltyObjectMother` class is where the Object Mother pattern is implemented. This class provides static methods to create different types of `King` and `Queen` objects. These methods encapsulate the logic for creating these objects, making it easier to create them in a consistent way across multiple tests.\n\n```java\nclass RoyaltyObjectMother {\n\n  static King createDrunkKing() {\n    var king = new King();\n    king.makeDrunk();\n    return king;\n  }\n\n  static King createHappyKing() {\n    var king = new King();\n    king.makeHappy();\n    return king;\n  }\n\n  // Other methods to create different types of King and Queen objects...\n}\n```\n\nIn the `RoyaltyObjectMotherTest` class, we can see how the Object Mother pattern is used to create objects for testing. The `RoyaltyObjectMother` class is used to create `King` and `Queen` objects in different states, which are then used in the tests.\n\n```java\nclass RoyaltyObjectMotherTest {\n\n  @Test\n  void unsuccessfulKingFlirt() {\n    var soberUnhappyKing = RoyaltyObjectMother.createSoberUnhappyKing();\n    var flirtyQueen = RoyaltyObjectMother.createFlirtyQueen();\n    soberUnhappyKing.flirt(flirtyQueen);\n    assertFalse(soberUnhappyKing.isHappy());\n  }\n\n  // Other tests...\n}\n```\n\nIn this way, the Object Mother pattern simplifies the creation of objects for testing, making the tests easier to read and maintain.\n\n## When to Use the Object Mother Pattern in Java\n\nUse the Object Mother pattern when\n\n* Creating complex objects with numerous fields for unit tests.\n* You need to reuse a standard set of objects across multiple tests.\n* Test setup is becoming cumbersome and repetitive.\n\n## Object Mother Pattern Java Tutorials\n\n* [What is an ObjectMother? (Stack Overflow)](http://stackoverflow.com/questions/923319/what-is-an-objectmother)\n* [Object Mother (c2wiki)](http://c2.com/cgi/wiki?ObjectMother)\n* [Test Data Builders: an alternative to the Object Mother pattern (Nat Pryce)](http://www.natpryce.com/articles/000714.html)\n\n## Real-World Applications of Object Mother Pattern in Java\n\n* In unit testing frameworks to create test fixtures.\n* In enterprise applications to generate standard domain objects required across multiple test cases.\n* In open-source projects like Apache Commons and Spring Framework for test object creation.\n\n## Benefits and Trade-offs of Object Mother Pattern\n\nBenefits:\n\n* Code Simplification: Reduces boilerplate code in tests, making tests more readable and easier to maintain.\n* Isolation: Ensures test data setup is isolated from test logic, enhancing clarity.\n* Consistency: Provides a consistent way to create objects, reducing the likelihood of errors in test setup.\n\nTrade-offs:\n\n* Maintenance: Requires maintaining the Object Mother class itself, which can grow complex over time.\n* Overhead: May introduce additional layers of abstraction that could complicate understanding for new developers.\n\n## Related Java Design Patterns\n\n* [Builder](https://java-design-patterns.com/patterns/builder/): Both patterns deal with object creation. The Object Mother is often simpler and used specifically in a testing context, whereas the Builder Pattern is more general-purpose.\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Similar in the sense of centralizing object creation logic. The Object Mother is specifically aimed at tests, while Factory Method is used more broadly in application code.\n\n## References and Credits\n\n* [Growing Object-Oriented Software, Guided by Tests](https://amzn.to/4dGfIuk)\n* [xUnit Test Patterns: Refactoring Test Code](https://amzn.to/4dHGDpm)\n"
  },
  {
    "path": "object-mother/etc/object-mother.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.11\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" \n  generalizations=\"true\" realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" \n  router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.objectmother.RoyaltyObjectMother\" project=\"object-mother\" \n    file=\"/object-mother/src/main/java/com/iluwatar/objectmother/RoyaltyObjectMother.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"535\" y=\"366\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.objectmother.King\" project=\"object-mother\" \n    file=\"/object-mother/src/main/java/com/iluwatar/objectmother/King.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"285\" y=\"141\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.objectmother.Queen\" project=\"object-mother\" \n    file=\"/object-mother/src/main/java/com/iluwatar/objectmother/Queen.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"783\" y=\"143\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"4\" language=\"java\" name=\"com.iluwatar.objectmother.Royalty\" project=\"object-mother\" \n    file=\"/object-mother/src/main/java/com/iluwatar/objectmother/Royalty.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"536\" y=\"142\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <realization id=\"5\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <realization id=\"6\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "object-mother/etc/object-mother.urm.puml",
    "content": "@startuml\npackage com.iluwatar.objectmother {\n  class King {\n    ~ isDrunk : boolean\n    ~ isHappy : boolean\n    + King()\n    + flirt(queen : Queen)\n    + isHappy() : boolean\n    + makeDrunk()\n    + makeHappy()\n    + makeSober()\n    + makeUnhappy()\n  }\n  class Queen {\n    - isDrunk : boolean\n    - isFlirty : boolean\n    - isHappy : boolean\n    + Queen()\n    + getFlirted(king : King) : boolean\n    + isFlirty() : boolean\n    + makeDrunk()\n    + makeHappy()\n    + makeSober()\n    + makeUnhappy()\n    + setFlirtiness(flirtiness : boolean)\n  }\n  interface Royalty {\n    + makeDrunk() {abstract}\n    + makeHappy() {abstract}\n    + makeSober() {abstract}\n    + makeUnhappy() {abstract}\n  }\n  class RoyaltyObjectMother {\n    + RoyaltyObjectMother()\n    + createDrunkKing() : King {static}\n    + createFlirtyQueen() : Queen {static}\n    + createHappyDrunkKing() : King {static}\n    + createHappyKing() : King {static}\n    + createNotFlirtyQueen() : Queen {static}\n    + createSoberUnhappyKing() : King {static}\n  }\n}\nKing ..|> Royalty \nQueen ..|> Royalty \n@enduml"
  },
  {
    "path": "object-mother/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>object-mother</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n</project>\n"
  },
  {
    "path": "object-mother/src/main/java/com/iluwatar/objectmother/King.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.objectmother;\n\n/** Defines all attributes and behaviour related to the King. */\npublic class King implements Royalty {\n  boolean isDrunk = false;\n  boolean isHappy = false;\n\n  @Override\n  public void makeDrunk() {\n    isDrunk = true;\n  }\n\n  @Override\n  public void makeSober() {\n    isDrunk = false;\n  }\n\n  @Override\n  public void makeHappy() {\n    isHappy = true;\n  }\n\n  @Override\n  public void makeUnhappy() {\n    isHappy = false;\n  }\n\n  public boolean isHappy() {\n    return isHappy;\n  }\n\n  /**\n   * Method to flirt to a queen.\n   *\n   * @param queen Queen which should be flirted.\n   */\n  public void flirt(Queen queen) {\n    var flirtStatus = queen.getFlirted(this);\n    if (!flirtStatus) {\n      this.makeUnhappy();\n    } else {\n      this.makeHappy();\n    }\n  }\n}\n"
  },
  {
    "path": "object-mother/src/main/java/com/iluwatar/objectmother/Queen.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.objectmother;\n\n/** Defines all attributes and behaviour related to the Queen. */\npublic class Queen implements Royalty {\n  private boolean isDrunk = false;\n  private boolean isHappy = false;\n  private boolean isFlirty = false;\n\n  @Override\n  public void makeDrunk() {\n    isDrunk = true;\n  }\n\n  @Override\n  public void makeSober() {\n    isDrunk = false;\n  }\n\n  @Override\n  public void makeHappy() {\n    isHappy = true;\n  }\n\n  @Override\n  public void makeUnhappy() {\n    isHappy = false;\n  }\n\n  public boolean isFlirty() {\n    return isFlirty;\n  }\n\n  public void setFlirtiness(boolean flirtiness) {\n    this.isFlirty = flirtiness;\n  }\n\n  /**\n   * Method which is called when the king is flirting to a queen.\n   *\n   * @param king King who initialized the flirt.\n   * @return A value which describes if the flirt was successful or not.\n   */\n  public boolean getFlirted(King king) {\n    return this.isFlirty && king.isHappy && !king.isDrunk;\n  }\n}\n"
  },
  {
    "path": "object-mother/src/main/java/com/iluwatar/objectmother/Royalty.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.objectmother;\n\n/** Interface contracting Royalty Behaviour. */\npublic interface Royalty {\n  void makeDrunk();\n\n  void makeSober();\n\n  void makeHappy();\n\n  void makeUnhappy();\n}\n"
  },
  {
    "path": "object-mother/src/main/java/com/iluwatar/objectmother/RoyaltyObjectMother.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.objectmother;\n\n/** Object Mother Pattern generating Royalty Types. */\npublic final class RoyaltyObjectMother {\n\n  /**\n   * Method to create a sober and unhappy king. The standard parameters are set.\n   *\n   * @return An instance of {@link com.iluwatar.objectmother.King} with the standard properties.\n   */\n  public static King createSoberUnhappyKing() {\n    return new King();\n  }\n\n  /**\n   * Method of the object mother to create a drunk king.\n   *\n   * @return A drunk {@link com.iluwatar.objectmother.King}.\n   */\n  public static King createDrunkKing() {\n    var king = new King();\n    king.makeDrunk();\n    return king;\n  }\n\n  /**\n   * Method to create a happy king.\n   *\n   * @return A happy {@link com.iluwatar.objectmother.King}.\n   */\n  public static King createHappyKing() {\n    var king = new King();\n    king.makeHappy();\n    return king;\n  }\n\n  /**\n   * Method to create a happy and drunk king.\n   *\n   * @return A drunk and happy {@link com.iluwatar.objectmother.King}.\n   */\n  public static King createHappyDrunkKing() {\n    var king = new King();\n    king.makeHappy();\n    king.makeDrunk();\n    return king;\n  }\n\n  /**\n   * Method to create a flirty queen.\n   *\n   * @return A flirty {@link com.iluwatar.objectmother.Queen}.\n   */\n  public static Queen createFlirtyQueen() {\n    var queen = new Queen();\n    queen.setFlirtiness(true);\n    return queen;\n  }\n\n  /**\n   * Method to create a not flirty queen.\n   *\n   * @return A not flirty {@link com.iluwatar.objectmother.Queen}.\n   */\n  public static Queen createNotFlirtyQueen() {\n    return new Queen();\n  }\n}\n"
  },
  {
    "path": "object-mother/src/test/java/com/iluwatar/objectmother/test/RoyaltyObjectMotherTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.objectmother.test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.objectmother.King;\nimport com.iluwatar.objectmother.Queen;\nimport com.iluwatar.objectmother.RoyaltyObjectMother;\nimport org.junit.jupiter.api.Test;\n\n/** Test Generation of Royalty Types using the object-mother */\nclass RoyaltyObjectMotherTest {\n\n  @Test\n  void unsuccessfulKingFlirt() {\n    var soberUnhappyKing = RoyaltyObjectMother.createSoberUnhappyKing();\n    var flirtyQueen = RoyaltyObjectMother.createFlirtyQueen();\n    soberUnhappyKing.flirt(flirtyQueen);\n    assertFalse(soberUnhappyKing.isHappy());\n  }\n\n  @Test\n  void queenIsBlockingFlirtCauseDrunkKing() {\n    var drunkUnhappyKing = RoyaltyObjectMother.createDrunkKing();\n    var notFlirtyQueen = RoyaltyObjectMother.createNotFlirtyQueen();\n    drunkUnhappyKing.flirt(notFlirtyQueen);\n    assertFalse(drunkUnhappyKing.isHappy());\n  }\n\n  @Test\n  void queenIsBlockingFlirt() {\n    var soberHappyKing = RoyaltyObjectMother.createHappyKing();\n    var notFlirtyQueen = RoyaltyObjectMother.createNotFlirtyQueen();\n    soberHappyKing.flirt(notFlirtyQueen);\n    assertFalse(soberHappyKing.isHappy());\n  }\n\n  @Test\n  void successfullKingFlirt() {\n    var soberHappyKing = RoyaltyObjectMother.createHappyKing();\n    var flirtyQueen = RoyaltyObjectMother.createFlirtyQueen();\n    soberHappyKing.flirt(flirtyQueen);\n    assertTrue(soberHappyKing.isHappy());\n  }\n\n  @Test\n  void testQueenType() {\n    var flirtyQueen = RoyaltyObjectMother.createFlirtyQueen();\n    var notFlirtyQueen = RoyaltyObjectMother.createNotFlirtyQueen();\n    assertEquals(flirtyQueen.getClass(), Queen.class);\n    assertEquals(notFlirtyQueen.getClass(), Queen.class);\n  }\n\n  @Test\n  void testKingType() {\n    var drunkKing = RoyaltyObjectMother.createDrunkKing();\n    var happyDrunkKing = RoyaltyObjectMother.createHappyDrunkKing();\n    var happyKing = RoyaltyObjectMother.createHappyKing();\n    var soberUnhappyKing = RoyaltyObjectMother.createSoberUnhappyKing();\n    assertEquals(drunkKing.getClass(), King.class);\n    assertEquals(happyDrunkKing.getClass(), King.class);\n    assertEquals(happyKing.getClass(), King.class);\n    assertEquals(soberUnhappyKing.getClass(), King.class);\n  }\n}\n"
  },
  {
    "path": "object-pool/README.md",
    "content": "---\ntitle: \"Object Pool Pattern in Java: Enhancing Performance with Reusable Object Management\"\nshortTitle: Object Pool\ndescription: \"Learn how the Object Pool design pattern improves performance by reusing expensive objects efficiently. Explore examples, benefits, and best practices in Java.\"\ncategory: Creational\nlanguage: en\ntag:\n  - Game programming\n  - Instantiation\n  - Memory management\n  - Performance\n  - Resource management\n  - Scalability\n---\n\n## Also known as\n\n* Resource Pool\n\n## Intent of Object Pool Design Pattern\n\nThe Object Pool design pattern in Java manages a pool of reusable objects, optimizing memory management and application performance by recycling objects rather than creating and destroying them repeatedly.\n\n## Detailed Explanation of Object Pool Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a library with a limited number of study rooms that are frequently in demand. Instead of each student building their own study room whenever they need one, the library manages a pool of available study rooms. When a student needs a study room, they check one out from the pool. After they are done, they return the room back to the pool for others to use. This ensures that the study rooms are efficiently utilized without the need to build new rooms each time, thus saving time and resources, similar to how the Object Pool pattern manages the reuse of expensive objects in software.   \n\nIn plain words\n\n> Object Pool manages a set of instances instead of creating and destroying them on demand. \n\nWikipedia says\n\n> The object pool pattern is a software creational design pattern that uses a set of initialized objects kept ready to use – a \"pool\" – rather than allocating and destroying them on demand.\n\nSequence diagram\n\n![Object Pool sequence diagram](./etc/object-pool-sequence-diagram.png)\n\n## Programmatic Example of Object Pool Pattern in Java\n\nIn our war game we need to use oliphaunts, massive and mythic beasts, but the problem is that they are extremely expensive to create. The solution is to create a pool of them, track which ones are in-use, and instead of disposing them re-use the instances.\n\nHere's the basic `Oliphaunt` class. These giants are very expensive to create.\n\n```java\npublic class Oliphaunt {\n\n    private static final AtomicInteger counter = new AtomicInteger(0);\n\n    @Getter\n    private final int id;\n\n    public Oliphaunt() {\n        id = counter.incrementAndGet();\n        try {\n            Thread.sleep(1000);\n        } catch (InterruptedException e) {\n            LOGGER.error(\"Error occurred: \", e);\n        }\n    }\n\n    @Override\n    public String toString() {\n        return String.format(\"Oliphaunt id=%d\", id);\n    }\n}\n```\n\nNext, we present the `ObjectPool` and more specifically `OliphauntPool`.\n\n```java\npublic abstract class ObjectPool<T> {\n\n  private final Set<T> available = new HashSet<>();\n  private final Set<T> inUse = new HashSet<>();\n\n  protected abstract T create();\n\n  public synchronized T checkOut() {\n    if (available.isEmpty()) {\n      available.add(create());\n    }\n    var instance = available.iterator().next();\n    available.remove(instance);\n    inUse.add(instance);\n    return instance;\n  }\n\n  public synchronized void checkIn(T instance) {\n    inUse.remove(instance);\n    available.add(instance);\n  }\n\n  @Override\n  public synchronized String toString() {\n    return String.format(\"Pool available=%d inUse=%d\", available.size(), inUse.size());\n  }\n}\n\npublic class OliphauntPool extends ObjectPool<Oliphaunt> {\n\n  @Override\n  protected Oliphaunt create() {\n    return new Oliphaunt();\n  }\n}\n```\n\nFinally, here's how we utilize the pool.\n\n```java\npublic static void main(String[] args) {\n    var pool = new OliphauntPool();\n    LOGGER.info(pool.toString());\n    var oliphaunt1 = pool.checkOut();\n    String checkedOut = \"Checked out {}\";\n\n    LOGGER.info(checkedOut, oliphaunt1);\n    LOGGER.info(pool.toString());\n    var oliphaunt2 = pool.checkOut();\n    LOGGER.info(checkedOut, oliphaunt2);\n    var oliphaunt3 = pool.checkOut();\n    LOGGER.info(checkedOut, oliphaunt3);\n    LOGGER.info(pool.toString());\n    LOGGER.info(\"Checking in {}\", oliphaunt1);\n    pool.checkIn(oliphaunt1);\n    LOGGER.info(\"Checking in {}\", oliphaunt2);\n    pool.checkIn(oliphaunt2);\n    LOGGER.info(pool.toString());\n    var oliphaunt4 = pool.checkOut();\n    LOGGER.info(checkedOut, oliphaunt4);\n    var oliphaunt5 = pool.checkOut();\n    LOGGER.info(checkedOut, oliphaunt5);\n    LOGGER.info(pool.toString());\n}\n```\n\nProgram output:\n\n```\n21:21:55.126 [main] INFO com.iluwatar.object.pool.App -- Pool available=0 inUse=0\n21:21:56.130 [main] INFO com.iluwatar.object.pool.App -- Checked out Oliphaunt id=1\n21:21:56.132 [main] INFO com.iluwatar.object.pool.App -- Pool available=0 inUse=1\n21:21:57.137 [main] INFO com.iluwatar.object.pool.App -- Checked out Oliphaunt id=2\n21:21:58.143 [main] INFO com.iluwatar.object.pool.App -- Checked out Oliphaunt id=3\n21:21:58.145 [main] INFO com.iluwatar.object.pool.App -- Pool available=0 inUse=3\n21:21:58.145 [main] INFO com.iluwatar.object.pool.App -- Checking in Oliphaunt id=1\n21:21:58.145 [main] INFO com.iluwatar.object.pool.App -- Checking in Oliphaunt id=2\n21:21:58.146 [main] INFO com.iluwatar.object.pool.App -- Pool available=2 inUse=1\n21:21:58.146 [main] INFO com.iluwatar.object.pool.App -- Checked out Oliphaunt id=2\n21:21:58.146 [main] INFO com.iluwatar.object.pool.App -- Checked out Oliphaunt id=1\n21:21:58.147 [main] INFO com.iluwatar.object.pool.App -- Pool available=0 inUse=3\n```\n\n## When to Use the Object Pool Pattern in Java\n\nUse the Object Pool pattern when\n\n* You need to frequently create and destroy objects, leading to high resource allocation and deallocation costs.\n* The objects are expensive to create and maintain (e.g., database connections, thread pools).\n* A fixed number of objects need to be controlled, like in connection pooling.\n* Object reuse can significantly improve system performance and resource management.\n\n## Real-World Applications of Object Mother Pattern in Java\n\n* Database connection pooling in Java applications.\n* Thread pooling in Java concurrent programming.\n* Pooling of socket connections in network applications.\n* Object pools in game development for frequently created and destroyed game objects.\n\n## Benefits and Trade-offs of Object Pool Pattern\n\nBenefits:\n\n* Improved Performance: Reduces the overhead of object creation and garbage collection.\n* Resource Management: Controls the number of instances, reducing resource contention and limiting resource usage.\n* Scalability: Allows the application to handle more requests by reusing a fixed number of objects.\n\nTrade-offs:\n\n* Complexity: Adds complexity to the codebase, requiring careful management of the pool.\n* Thread Safety: Requires careful handling of concurrent access to the pool, introducing potential synchronization issues.\n* Initialization Cost: Initial creation of the pool can be resource-intensive.\n\n## Related Java Design Patterns\n\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Ensures a single instance of the pool is used, providing a global point of access.\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Shares fine-grained objects to reduce memory usage, complementing object pooling by managing object state efficiently.\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Often used to create objects within the pool, abstracting the instantiation process.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n"
  },
  {
    "path": "object-pool/etc/object-pool.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \r\n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \r\n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.ObjectPool\" project=\"object-pool\" \r\n    file=\"/object-pool/src/main/java/com/iluwatar/ObjectPool.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"133\" y=\"239\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.OliphauntPool\" project=\"object-pool\" \r\n    file=\"/object-pool/src/main/java/com/iluwatar/OliphauntPool.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"133\" y=\"423\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.Oliphaunt\" project=\"object-pool\" \r\n    file=\"/object-pool/src/main/java/com/iluwatar/Oliphaunt.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"153\" width=\"102\" x=\"250\" y=\"145\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <generalization id=\"4\">    \r\n    <end type=\"SOURCE\" refId=\"2\"/>    \r\n    <end type=\"TARGET\" refId=\"1\"/>  \r\n  </generalization>  \r\n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \r\n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \r\n  </classifier-display>  \r\n  <association-display labels=\"true\" multiplicity=\"true\"/>\r\n</class-diagram>"
  },
  {
    "path": "object-pool/etc/object-pool.urm.puml",
    "content": "@startuml\npackage com.iluwatar.object.pool {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  abstract class ObjectPool<T> {\n    - available : Set<T>\n    - inUse : Set<T>\n    + ObjectPool<T>()\n    + checkIn(instance : T)\n    + checkOut() : T\n    # create() : T {abstract}\n    + toString() : String\n  }\n  class Oliphaunt {\n    - counter : AtomicInteger {static}\n    - id : int\n    + Oliphaunt()\n    + getId() : int\n    + toString() : String\n  }\n  class OliphauntPool {\n    + OliphauntPool()\n    # create() : Oliphaunt\n  }\n}\nOliphauntPool --|> ObjectPool \n@enduml"
  },
  {
    "path": "object-pool/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>object-pool</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.object.pool.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "object-pool/src/main/java/com/iluwatar/object/pool/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.object.pool;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * When it is necessary to work with a large number of objects that are particularly expensive to\n * instantiate and each object is only needed for a short period of time, the performance of an\n * entire application may be adversely affected. An object pool design pattern may be deemed\n * desirable in cases such as these.\n *\n * <p>The object pool design pattern creates a set of objects that may be reused. When a new object\n * is needed, it is requested from the pool. If a previously prepared object is available it is\n * returned immediately, avoiding the instantiation cost. If no objects are present in the pool, a\n * new item is created and returned. When the object has been used and is no longer needed, it is\n * returned to the pool, allowing it to be used again in the future without repeating the\n * computationally expensive instantiation process. It is important to note that once an object has\n * been used and returned, existing references will become invalid.\n *\n * <p>In this example we have created {@link OliphauntPool} inheriting from generic {@link\n * ObjectPool}. {@link Oliphaunt}s can be checked out from the pool and later returned to it. The\n * pool tracks created instances and their status (available, inUse).\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var pool = new OliphauntPool();\n    LOGGER.info(pool.toString());\n    var oliphaunt1 = pool.checkOut();\n    String checkedOut = \"Checked out {}\";\n\n    LOGGER.info(checkedOut, oliphaunt1);\n    LOGGER.info(pool.toString());\n    var oliphaunt2 = pool.checkOut();\n    LOGGER.info(checkedOut, oliphaunt2);\n    var oliphaunt3 = pool.checkOut();\n    LOGGER.info(checkedOut, oliphaunt3);\n    LOGGER.info(pool.toString());\n    LOGGER.info(\"Checking in {}\", oliphaunt1);\n    pool.checkIn(oliphaunt1);\n    LOGGER.info(\"Checking in {}\", oliphaunt2);\n    pool.checkIn(oliphaunt2);\n    LOGGER.info(pool.toString());\n    var oliphaunt4 = pool.checkOut();\n    LOGGER.info(checkedOut, oliphaunt4);\n    var oliphaunt5 = pool.checkOut();\n    LOGGER.info(checkedOut, oliphaunt5);\n    LOGGER.info(pool.toString());\n  }\n}\n"
  },
  {
    "path": "object-pool/src/main/java/com/iluwatar/object/pool/ObjectPool.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.object.pool;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * Generic object pool.\n *\n * @param <T> Type T of Object in the Pool\n */\npublic abstract class ObjectPool<T> {\n\n  private final Set<T> available = new HashSet<>();\n  private final Set<T> inUse = new HashSet<>();\n\n  protected abstract T create();\n\n  /** Checkout object from pool. */\n  public synchronized T checkOut() {\n    if (available.isEmpty()) {\n      available.add(create());\n    }\n    var instance = available.iterator().next();\n    available.remove(instance);\n    inUse.add(instance);\n    return instance;\n  }\n\n  public synchronized void checkIn(T instance) {\n    inUse.remove(instance);\n    available.add(instance);\n  }\n\n  @Override\n  public synchronized String toString() {\n    return String.format(\"Pool available=%d inUse=%d\", available.size(), inUse.size());\n  }\n}\n"
  },
  {
    "path": "object-pool/src/main/java/com/iluwatar/object/pool/Oliphaunt.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.object.pool;\n\nimport java.util.concurrent.atomic.AtomicInteger;\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Oliphaunts are expensive to create. */\n@Slf4j\npublic class Oliphaunt {\n\n  private static final AtomicInteger counter = new AtomicInteger(0);\n\n  @Getter private final int id;\n\n  /** Constructor. */\n  public Oliphaunt() {\n    id = counter.incrementAndGet();\n    try {\n      Thread.sleep(1000);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Error occurred: \", e);\n    }\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\"Oliphaunt id=%d\", id);\n  }\n}\n"
  },
  {
    "path": "object-pool/src/main/java/com/iluwatar/object/pool/OliphauntPool.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.object.pool;\n\n/** Oliphaunt object pool. */\npublic class OliphauntPool extends ObjectPool<Oliphaunt> {\n\n  @Override\n  protected Oliphaunt create() {\n    return new Oliphaunt();\n  }\n}\n"
  },
  {
    "path": "object-pool/src/test/java/com/iluwatar/object/pool/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.object.pool;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "object-pool/src/test/java/com/iluwatar/object/pool/OliphauntPoolTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.object.pool;\n\nimport static java.time.Duration.ofMillis;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotSame;\nimport static org.junit.jupiter.api.Assertions.assertSame;\nimport static org.junit.jupiter.api.Assertions.assertTimeout;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\n\n/** OliphauntPoolTest. */\nclass OliphauntPoolTest {\n\n  /**\n   * Use the same object 100 times subsequently. This should not take much time since the heavy\n   * object instantiation is done only once. Verify if we get the same object each time.\n   */\n  @Test\n  void testSubsequentCheckinCheckout() {\n    assertTimeout(\n        ofMillis(5000),\n        () -> {\n          final var pool = new OliphauntPool();\n          assertEquals(\"Pool available=0 inUse=0\", pool.toString());\n\n          final var expectedOliphaunt = pool.checkOut();\n          assertEquals(\"Pool available=0 inUse=1\", pool.toString());\n\n          pool.checkIn(expectedOliphaunt);\n          assertEquals(\"Pool available=1 inUse=0\", pool.toString());\n\n          for (int i = 0; i < 100; i++) {\n            final var oliphaunt = pool.checkOut();\n            assertEquals(\"Pool available=0 inUse=1\", pool.toString());\n            assertSame(expectedOliphaunt, oliphaunt);\n            assertEquals(expectedOliphaunt.getId(), oliphaunt.getId());\n            assertEquals(expectedOliphaunt.toString(), oliphaunt.toString());\n\n            pool.checkIn(oliphaunt);\n            assertEquals(\"Pool available=1 inUse=0\", pool.toString());\n          }\n        });\n  }\n\n  /**\n   * Use the same object 100 times subsequently. This should not take much time since the heavy\n   * object instantiation is done only once. Verify if we get the same object each time.\n   */\n  @Test\n  void testConcurrentCheckinCheckout() {\n    assertTimeout(\n        ofMillis(5000),\n        () -> {\n          final var pool = new OliphauntPool();\n          assertEquals(pool.toString(), \"Pool available=0 inUse=0\");\n\n          final var firstOliphaunt = pool.checkOut();\n          assertEquals(pool.toString(), \"Pool available=0 inUse=1\");\n\n          final var secondOliphaunt = pool.checkOut();\n          assertEquals(pool.toString(), \"Pool available=0 inUse=2\");\n\n          assertNotSame(firstOliphaunt, secondOliphaunt);\n          assertEquals(firstOliphaunt.getId() + 1, secondOliphaunt.getId());\n\n          // After checking in the second, we should get the same when checking out a new oliphaunt\n          // ...\n          pool.checkIn(secondOliphaunt);\n          assertEquals(pool.toString(), \"Pool available=1 inUse=1\");\n\n          final var oliphaunt3 = pool.checkOut();\n          assertEquals(pool.toString(), \"Pool available=0 inUse=2\");\n          assertSame(secondOliphaunt, oliphaunt3);\n\n          // ... and the same applies for the first one\n          pool.checkIn(firstOliphaunt);\n          assertEquals(pool.toString(), \"Pool available=1 inUse=1\");\n\n          final var oliphaunt4 = pool.checkOut();\n          assertEquals(pool.toString(), \"Pool available=0 inUse=2\");\n          assertSame(firstOliphaunt, oliphaunt4);\n\n          // When both oliphaunt return to the pool, we should still get the same instances\n          pool.checkIn(firstOliphaunt);\n          assertEquals(pool.toString(), \"Pool available=1 inUse=1\");\n\n          pool.checkIn(secondOliphaunt);\n          assertEquals(pool.toString(), \"Pool available=2 inUse=0\");\n\n          // The order of the returned instances is not determined, so just put them in a list\n          // and verify if both expected instances are in there.\n          final var oliphaunts = List.of(pool.checkOut(), pool.checkOut());\n          assertEquals(pool.toString(), \"Pool available=0 inUse=2\");\n          assertTrue(oliphaunts.contains(firstOliphaunt));\n          assertTrue(oliphaunts.contains(secondOliphaunt));\n        });\n  }\n}\n"
  },
  {
    "path": "observer/README.md",
    "content": "---\ntitle: \"Observer Pattern in Java: Mastering Reactive Interfaces in Java Applications\"\nshortTitle: Observer\ndescription: \"Learn the Observer design pattern in Java. Discover its intent, applicability, and real-world examples. Understand how it promotes loose coupling and dynamic observer management. Ideal for software developers and architects.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Decoupling\n  - Event-driven\n  - Gang of Four\n  - Publish/subscribe\n---\n\n## Also known as\n\n* Dependents\n\n## Intent of Observer Design Pattern\n\nThe Observer pattern in Java defines a one-to-many relationship between objects, ensuring that when one object updates its state, all dependent observers are notified and updated automatically, enhancing system responsiveness and modularity.\n\n## Detailed Explanation of Observer Pattern with Real-World Examples\n\nReal-world example\n\n> In a real-world example, consider a news agency system where the agency (subject) publishes news articles, and multiple news outlets (observers) subscribe to receive updates. Whenever the news agency publishes a new article, it automatically notifies all the subscribed news outlets. These outlets can then update their platforms (like websites, TV broadcasts, or newspapers) with the latest news. This ensures that all subscribers get the latest information without the news agency needing to know the specifics of each outlet's update process. This decouples the news agency from the subscribers, promoting flexibility and modularity in how updates are handled.\n\nIn plain words\n\n> Implement the Observer interface to actively monitor and respond to state changes in Java applications, improving event-driven programming efficiency.\n\nWikipedia says\n\n> The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.\n\nSequence diagram\n\n![Observer sequence diagram](./etc/observer-sequence-diagram.png)\n\n## Programmatic Example of Observer Pattern in Java\n\nIn a land far away live the races of hobbits and orcs. Both of them are mostly outdoors, so they closely follow the weather changes. One could say that they are constantly observing the weather.\n\nLet's first introduce the `WeatherObserver` interface and our races, `Orcs` and `Hobbits`.\n\n```java\npublic interface WeatherObserver {\n\n  void update(WeatherType currentWeather);\n}\n\n@Slf4j\npublic class Orcs implements WeatherObserver {\n\n  @Override\n  public void update(WeatherType currentWeather) {\n    LOGGER.info(\"The orcs are facing \" + currentWeather.getDescription() + \" weather now\");\n  }\n}\n\n@Slf4j\npublic class Hobbits implements WeatherObserver {\n\n  @Override\n  public void update(WeatherType currentWeather) {\n    switch (currentWeather) {\n      LOGGER.info(\"The hobbits are facing \" + currentWeather.getDescription() + \" weather now\");\n    }\n  }\n}\n```\n\nThen here's the `Weather` that is constantly changing.\n\n```java\n@Slf4j\npublic class Weather {\n\n  private WeatherType currentWeather;\n  private final List<WeatherObserver> observers;\n\n  public Weather() {\n    observers = new ArrayList<>();\n    currentWeather = WeatherType.SUNNY;\n  }\n\n  public void addObserver(WeatherObserver obs) {\n    observers.add(obs);\n  }\n\n  public void removeObserver(WeatherObserver obs) {\n    observers.remove(obs);\n  }\n\n  /**\n   * Makes time pass for weather.\n   */\n  public void timePasses() {\n    var enumValues = WeatherType.values();\n    currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length];\n    LOGGER.info(\"The weather changed to {}.\", currentWeather);\n    notifyObservers();\n  }\n\n  private void notifyObservers() {\n    for (var obs : observers) {\n      obs.update(currentWeather);\n    }\n  }\n}\n```\n\nHere's the full example in action.\n\n```java\n  public static void main(String[] args) {\n\n    var weather = new Weather();\n    weather.addObserver(new Orcs());\n    weather.addObserver(new Hobbits());\n\n    weather.timePasses();\n    weather.timePasses();\n    weather.timePasses();\n    weather.timePasses();\n\n    // Generic observer inspired by Java Generics and Collections by Naftalin & Wadler\n    LOGGER.info(\"--Running generic version--\");\n    var genericWeather = new GenWeather();\n    genericWeather.addObserver(new GenOrcs());\n    genericWeather.addObserver(new GenHobbits());\n\n    genericWeather.timePasses();\n    genericWeather.timePasses();\n    genericWeather.timePasses();\n    genericWeather.timePasses();\n  }\n```\n\nProgram output:\n\n```\n21:28:08.310 [main] INFO com.iluwatar.observer.Weather -- The weather changed to rainy.\n21:28:08.312 [main] INFO com.iluwatar.observer.Orcs -- The orcs are facing Rainy weather now\n21:28:08.312 [main] INFO com.iluwatar.observer.Hobbits -- The hobbits are facing Rainy weather now\n21:28:08.312 [main] INFO com.iluwatar.observer.Weather -- The weather changed to windy.\n21:28:08.312 [main] INFO com.iluwatar.observer.Orcs -- The orcs are facing Windy weather now\n21:28:08.312 [main] INFO com.iluwatar.observer.Hobbits -- The hobbits are facing Windy weather now\n21:28:08.312 [main] INFO com.iluwatar.observer.Weather -- The weather changed to cold.\n21:28:08.312 [main] INFO com.iluwatar.observer.Orcs -- The orcs are facing Cold weather now\n21:28:08.312 [main] INFO com.iluwatar.observer.Hobbits -- The hobbits are facing Cold weather now\n21:28:08.312 [main] INFO com.iluwatar.observer.Weather -- The weather changed to sunny.\n21:28:08.312 [main] INFO com.iluwatar.observer.Orcs -- The orcs are facing Sunny weather now\n21:28:08.312 [main] INFO com.iluwatar.observer.Hobbits -- The hobbits are facing Sunny weather now\n21:28:08.312 [main] INFO com.iluwatar.observer.App -- --Running generic version--\n21:28:08.313 [main] INFO com.iluwatar.observer.generic.GenWeather -- The weather changed to rainy.\n21:28:08.313 [main] INFO com.iluwatar.observer.generic.GenOrcs -- The orcs are facing Rainy weather now\n21:28:08.313 [main] INFO com.iluwatar.observer.generic.GenHobbits -- The hobbits are facing Rainy weather now\n21:28:08.313 [main] INFO com.iluwatar.observer.generic.GenWeather -- The weather changed to windy.\n21:28:08.313 [main] INFO com.iluwatar.observer.generic.GenOrcs -- The orcs are facing Windy weather now\n21:28:08.313 [main] INFO com.iluwatar.observer.generic.GenHobbits -- The hobbits are facing Windy weather now\n21:28:08.313 [main] INFO com.iluwatar.observer.generic.GenWeather -- The weather changed to cold.\n21:28:08.313 [main] INFO com.iluwatar.observer.generic.GenOrcs -- The orcs are facing Cold weather now\n21:28:08.313 [main] INFO com.iluwatar.observer.generic.GenHobbits -- The hobbits are facing Cold weather now\n21:28:08.313 [main] INFO com.iluwatar.observer.generic.GenWeather -- The weather changed to sunny.\n21:28:08.313 [main] INFO com.iluwatar.observer.generic.GenOrcs -- The orcs are facing Sunny weather now\n21:28:08.313 [main] INFO com.iluwatar.observer.generic.GenHobbits -- The hobbits are facing Sunny weather now\n```\n\n## When to Use the Observer Pattern in Java\n\nUse the Observer pattern in any of the following situations:\n\n* When an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently.\n* When a change to one object requires changing others, and you don't know how many objects need to be changed.\n* When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled.\n\n## Real-World Applications of Observer Pattern in Java\n\n* [java.util.Observer](http://docs.oracle.com/javase/8/docs/api/java/util/Observer.html)\n* [java.util.EventListener](http://docs.oracle.com/javase/8/docs/api/java/util/EventListener.html)\n* [javax.servlet.http.HttpSessionBindingListener](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionBindingListener.html)\n* [RxJava](https://github.com/ReactiveX/RxJava)\n* Model-View-Controller (MVC) frameworks.\n* Event handling systems.\n\n## Benefits and Trade-offs of Observer Pattern\n\nBenefits:\n\n* This Java design pattern promotes loose coupling, allowing the subject and its observers to interact without tight dependencies, facilitating easier maintenance and scalability.\n* Allows dynamic subscription and unsubscription of observers.\n\nTrade-offs:\n\n* Can lead to memory leaks if observers are not properly deregistered.\n* The order of notification is not specified, leading to potential unexpected behavior.\n* Potential for performance issues with a large number of observers.\n\n## Related Java Design Patterns\n\n* [Mediator](https://java-design-patterns.com/patterns/mediator/): Encapsulates how a set of objects interact, which can be used to reduce the direct dependencies among objects.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Often used with the Observer pattern to ensure a single instance of the subject.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Java Generics and Collections](https://amzn.to/3VhOBxp)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Pattern-Oriented Software Architecture Volume 1: A System of Patterns](https://amzn.to/3xZ1ELU)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "observer/etc/observer.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.2.3\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.observer.Hobbits\" project=\"observer\" \n    file=\"/observer/src/main/java/com/iluwatar/observer/Hobbits.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"723\" y=\"333\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"2\" language=\"java\" name=\"com.iluwatar.observer.WeatherObserver\" project=\"observer\" \n    file=\"/observer/src/main/java/com/iluwatar/observer/WeatherObserver.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"454\" y=\"330\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.observer.Orcs\" project=\"observer\" \n    file=\"/observer/src/main/java/com/iluwatar/observer/Orcs.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"454\" y=\"468\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.observer.Weather\" project=\"observer\" \n    file=\"/observer/src/main/java/com/iluwatar/observer/Weather.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"454\" y=\"129\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <enumeration id=\"5\" language=\"java\" name=\"com.iluwatar.observer.WeatherType\" project=\"observer\" \n    file=\"/observer/src/main/java/com/iluwatar/observer/WeatherType.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"791\" y=\"129\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <association id=\"6\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"7\" name=\"observers\">        \n        <position height=\"0\" width=\"0\" x=\"-41\" y=\"-202\"/>      \n      </attribute>      \n      <multiplicity id=\"8\" minimum=\"0\" maximum=\"2147483647\">        \n        <position height=\"0\" width=\"0\" x=\"-41\" y=\"-202\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"9\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </realization>  \n  <realization id=\"10\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </realization>  \n  <association id=\"11\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"12\" name=\"currentWeather\">        \n        <position height=\"0\" width=\"0\" x=\"91\" y=\"-448\"/>      \n      </attribute>      \n      <multiplicity id=\"13\" minimum=\"1\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"91\" y=\"-448\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "observer/etc/observer.urm.puml",
    "content": "@startuml\npackage com.iluwatar.observer {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Hobbits {\n    - LOGGER : Logger {static}\n    + Hobbits()\n    + update(currentWeather : WeatherType)\n  }\n  class Orcs {\n    - LOGGER : Logger {static}\n    + Orcs()\n    + update(currentWeather : WeatherType)\n  }\n  class Weather {\n    - LOGGER : Logger {static}\n    - currentWeather : WeatherType\n    - observers : List<WeatherObserver>\n    + Weather()\n    + addObserver(obs : WeatherObserver)\n    - notifyObservers()\n    + removeObserver(obs : WeatherObserver)\n    + timePasses()\n  }\n  interface WeatherObserver {\n    + update(WeatherType) {abstract}\n  }\n  enum WeatherType {\n    + COLD {static}\n    + RAINY {static}\n    + SUNNY {static}\n    + WINDY {static}\n    + description String\n    + toString() : String\n    + getDescription() : String\n    + valueOf(name : String) : WeatherType {static}\n    + values() : WeatherType[] {static}\n  }\n}\npackage com.iluwatar.observer.generic {\n  class GHobbits {\n    - LOGGER : Logger {static}\n    + GHobbits()\n    + update(weather : GWeather, weatherType : WeatherType)\n  }\n  class GOrcs {\n    - LOGGER : Logger {static}\n    + GOrcs()\n    + update(weather : GWeather, weatherType : WeatherType)\n  }\n  class GWeather {\n    - LOGGER : Logger {static}\n    - currentWeather : WeatherType\n    + GWeather()\n    + timePasses()\n  }\n  abstract class Observable<S extends Observable, O extends Observer<S, O, A>, A> {\n    # observers : List<O extends Observer<S, O, A>>\n    + Observable<S extends Observable, O extends Observer<S, O, A>, A>()\n    + addObserver(observer : O extends Observer<S, O, A>)\n    + notifyObservers(argument : A)\n    + removeObserver(observer : O extends Observer<S, O, A>)\n  }\n  interface Observer<S extends Observable<S, O, A>, O extends Observer, A> {\n    + update(S extends Observable<S, O, A>, A) {abstract}\n  }\n  interface Race {\n  }\n}\nWeather -->  \"-currentWeather\" WeatherType\nGWeather -->  \"-currentWeather\" WeatherType\nWeather -->  \"-observers\" WeatherObserver\nHobbits ..|> WeatherObserver\nOrcs ..|> WeatherObserver\nGHobbits ..|> Race\nGOrcs ..|> Race\nGWeather --|> Observable\nRace --|> Observer\n@enduml\n"
  },
  {
    "path": "observer/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>observer</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-params</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.observer.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "observer/src/main/java/com/iluwatar/observer/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer;\n\nimport com.iluwatar.observer.generic.GenHobbits;\nimport com.iluwatar.observer.generic.GenOrcs;\nimport com.iluwatar.observer.generic.GenWeather;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Observer pattern is a software design pattern in which an object, called the subject,\n * maintains a list of its dependents, called observers, and notifies them automatically of any\n * state changes, usually by calling one of their methods. It is mainly used to implement\n * distributed event handling systems. The Observer pattern is also a key part in the familiar\n * model–view–controller (MVC) architectural pattern. The Observer pattern is implemented in\n * numerous programming libraries and systems, including almost all GUI toolkits.\n *\n * <p>In this example {@link Weather} has a state that can be observed. The {@link Orcs} and {@link\n * Hobbits} register as observers and receive notifications when the {@link Weather} changes.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var weather = new Weather();\n    weather.addObserver(new Orcs());\n    weather.addObserver(new Hobbits());\n\n    weather.timePasses();\n    weather.timePasses();\n    weather.timePasses();\n    weather.timePasses();\n\n    // Generic observer inspired by Java Generics and Collections by Naftalin & Wadler\n    LOGGER.info(\"--Running generic version--\");\n    var genericWeather = new GenWeather();\n    genericWeather.addObserver(new GenOrcs());\n    genericWeather.addObserver(new GenHobbits());\n\n    genericWeather.timePasses();\n    genericWeather.timePasses();\n    genericWeather.timePasses();\n    genericWeather.timePasses();\n  }\n}\n"
  },
  {
    "path": "observer/src/main/java/com/iluwatar/observer/Hobbits.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Hobbits. */\n@Slf4j\npublic class Hobbits implements WeatherObserver {\n\n  @Override\n  public void update(WeatherType currentWeather) {\n    LOGGER.info(\"The hobbits are facing {} weather now\", currentWeather.getDescription());\n  }\n}\n"
  },
  {
    "path": "observer/src/main/java/com/iluwatar/observer/Orcs.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Orcs. */\n@Slf4j\npublic class Orcs implements WeatherObserver {\n\n  @Override\n  public void update(WeatherType currentWeather) {\n    LOGGER.info(\"The orcs are facing \" + currentWeather.getDescription() + \" weather now\");\n  }\n}\n"
  },
  {
    "path": "observer/src/main/java/com/iluwatar/observer/Weather.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Weather can be observed by implementing {@link WeatherObserver} interface and registering as\n * listener.\n */\n@Slf4j\npublic class Weather {\n\n  private WeatherType currentWeather;\n  private final List<WeatherObserver> observers;\n\n  public Weather() {\n    observers = new ArrayList<>();\n    currentWeather = WeatherType.SUNNY;\n  }\n\n  public void addObserver(WeatherObserver obs) {\n    observers.add(obs);\n  }\n\n  public void removeObserver(WeatherObserver obs) {\n    observers.remove(obs);\n  }\n\n  /** Makes time pass for weather. */\n  public void timePasses() {\n    var enumValues = WeatherType.values();\n    currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length];\n    LOGGER.info(\"The weather changed to {}.\", currentWeather);\n    notifyObservers();\n  }\n\n  private void notifyObservers() {\n    for (var obs : observers) {\n      obs.update(currentWeather);\n    }\n  }\n}\n"
  },
  {
    "path": "observer/src/main/java/com/iluwatar/observer/WeatherObserver.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer;\n\n/** Observer interface. */\npublic interface WeatherObserver {\n\n  void update(WeatherType currentWeather);\n}\n"
  },
  {
    "path": "observer/src/main/java/com/iluwatar/observer/WeatherType.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer;\n\nimport lombok.Getter;\n\n/** WeatherType enumeration. */\npublic enum WeatherType {\n  SUNNY(\"Sunny\"),\n  RAINY(\"Rainy\"),\n  WINDY(\"Windy\"),\n  COLD(\"Cold\");\n\n  @Getter private final String description;\n\n  WeatherType(String description) {\n    this.description = description;\n  }\n\n  @Override\n  public String toString() {\n    return this.name().toLowerCase();\n  }\n}\n"
  },
  {
    "path": "observer/src/main/java/com/iluwatar/observer/generic/GenHobbits.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer.generic;\n\nimport com.iluwatar.observer.WeatherType;\nimport lombok.extern.slf4j.Slf4j;\n\n/** GHobbits. */\n@Slf4j\npublic class GenHobbits implements Race {\n\n  @Override\n  public void update(GenWeather weather, WeatherType weatherType) {\n    LOGGER.info(\"The hobbits are facing \" + weatherType.getDescription() + \" weather now\");\n  }\n}\n"
  },
  {
    "path": "observer/src/main/java/com/iluwatar/observer/generic/GenOrcs.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer.generic;\n\nimport com.iluwatar.observer.WeatherType;\nimport lombok.extern.slf4j.Slf4j;\n\n/** GOrcs. */\n@Slf4j\npublic class GenOrcs implements Race {\n\n  @Override\n  public void update(GenWeather weather, WeatherType weatherType) {\n    LOGGER.info(\"The orcs are facing \" + weatherType.getDescription() + \" weather now\");\n  }\n}\n"
  },
  {
    "path": "observer/src/main/java/com/iluwatar/observer/generic/GenWeather.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer.generic;\n\nimport com.iluwatar.observer.WeatherType;\nimport lombok.extern.slf4j.Slf4j;\n\n/** GWeather. */\n@Slf4j\npublic class GenWeather extends Observable<GenWeather, Race, WeatherType> {\n\n  private WeatherType currentWeather;\n\n  public GenWeather() {\n    currentWeather = WeatherType.SUNNY;\n  }\n\n  /** Makes time pass for weather. */\n  public void timePasses() {\n    var enumValues = WeatherType.values();\n    currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length];\n    LOGGER.info(\"The weather changed to {}.\", currentWeather);\n    notifyObservers(currentWeather);\n  }\n}\n"
  },
  {
    "path": "observer/src/main/java/com/iluwatar/observer/generic/Observable.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer.generic;\n\nimport java.util.List;\nimport java.util.concurrent.CopyOnWriteArrayList;\n\n/**\n * Generic observer inspired by Java Generics and Collection by {@literal Naftalin & Wadler}.\n *\n * @param <S> Subject\n * @param <O> Observer\n * @param <A> Argument type\n */\npublic abstract class Observable<S extends Observable<S, O, A>, O extends Observer<S, O, A>, A> {\n\n  protected final List<O> observers;\n\n  public Observable() {\n    this.observers = new CopyOnWriteArrayList<>();\n  }\n\n  public void addObserver(O observer) {\n    this.observers.add(observer);\n  }\n\n  public void removeObserver(O observer) {\n    this.observers.remove(observer);\n  }\n\n  /** Notify observers. */\n  @SuppressWarnings(\"unchecked\")\n  public void notifyObservers(A argument) {\n    for (var observer : observers) {\n      observer.update((S) this, argument);\n    }\n  }\n}\n"
  },
  {
    "path": "observer/src/main/java/com/iluwatar/observer/generic/Observer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer.generic;\n\n/**\n * Observer.\n *\n * @param <S> Observable\n * @param <O> Observer\n * @param <A> Action\n */\npublic interface Observer<S extends Observable<S, O, A>, O extends Observer<S, O, A>, A> {\n\n  void update(S subject, A argument);\n}\n"
  },
  {
    "path": "observer/src/main/java/com/iluwatar/observer/generic/Race.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer.generic;\n\nimport com.iluwatar.observer.WeatherType;\n\n/** Race. */\npublic interface Race extends Observer<GenWeather, Race, WeatherType> {}\n"
  },
  {
    "path": "observer/src/test/java/com/iluwatar/observer/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "observer/src/test/java/com/iluwatar/observer/HobbitsTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer;\n\nimport java.util.Collection;\nimport java.util.List;\n\n/** HobbitsTest */\nclass HobbitsTest extends WeatherObserverTest<Hobbits> {\n\n  @Override\n  public Collection<Object[]> dataProvider() {\n    return List.of(\n        new Object[] {WeatherType.SUNNY, \"The hobbits are facing Sunny weather now\"},\n        new Object[] {WeatherType.RAINY, \"The hobbits are facing Rainy weather now\"},\n        new Object[] {WeatherType.WINDY, \"The hobbits are facing Windy weather now\"},\n        new Object[] {WeatherType.COLD, \"The hobbits are facing Cold weather now\"});\n  }\n\n  /** Create a new test with the given weather and expected response */\n  public HobbitsTest() {\n    super(Hobbits::new);\n  }\n}\n"
  },
  {
    "path": "observer/src/test/java/com/iluwatar/observer/OrcsTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer;\n\nimport java.util.Collection;\nimport java.util.List;\n\n/** OrcsTest */\nclass OrcsTest extends WeatherObserverTest<Orcs> {\n\n  @Override\n  public Collection<Object[]> dataProvider() {\n    return List.of(\n        new Object[] {WeatherType.SUNNY, \"The orcs are facing Sunny weather now\"},\n        new Object[] {WeatherType.RAINY, \"The orcs are facing Rainy weather now\"},\n        new Object[] {WeatherType.WINDY, \"The orcs are facing Windy weather now\"},\n        new Object[] {WeatherType.COLD, \"The orcs are facing Cold weather now\"});\n  }\n\n  /** Create a new test with the given weather and expected response */\n  public OrcsTest() {\n    super(Orcs::new);\n  }\n}\n"
  },
  {
    "path": "observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.observer.utils.InMemoryAppender;\nimport java.util.Collection;\nimport java.util.function.Supplier;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.TestInstance;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\n/**\n * Weather Observer Tests\n *\n * @param <O> Type of WeatherObserver\n */\n@TestInstance(TestInstance.Lifecycle.PER_CLASS)\npublic abstract class WeatherObserverTest<O extends WeatherObserver> {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /** The observer instance factory */\n  private final Supplier<O> factory;\n\n  /**\n   * Create a new test instance using the given parameters\n   *\n   * @param factory The factory, used to create an instance of the tested observer\n   */\n  WeatherObserverTest(final Supplier<O> factory) {\n    this.factory = factory;\n  }\n\n  public abstract Collection<Object[]> dataProvider();\n\n  /** Verify if the weather has the expected influence on the observer */\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testObserver(WeatherType weather, String response) {\n    final var observer = this.factory.get();\n    assertEquals(0, appender.getLogSize());\n\n    observer.update(weather);\n    assertEquals(response, appender.getLastMessage());\n    assertEquals(1, appender.getLogSize());\n  }\n}\n"
  },
  {
    "path": "observer/src/test/java/com/iluwatar/observer/WeatherTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.inOrder;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport com.iluwatar.observer.utils.InMemoryAppender;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** WeatherTest */\nclass WeatherTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(Weather.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /**\n   * Add a {@link WeatherObserver}, verify if it gets notified of a weather change, remove the\n   * observer again and verify that there are no more notifications.\n   */\n  @Test\n  void testAddRemoveObserver() {\n    final var observer = mock(WeatherObserver.class);\n\n    final var weather = new Weather();\n    weather.addObserver(observer);\n    verifyNoMoreInteractions(observer);\n\n    weather.timePasses();\n    assertEquals(\"The weather changed to rainy.\", appender.getLastMessage());\n    verify(observer).update(WeatherType.RAINY);\n\n    weather.removeObserver(observer);\n    weather.timePasses();\n    assertEquals(\"The weather changed to windy.\", appender.getLastMessage());\n\n    verifyNoMoreInteractions(observer);\n    assertEquals(2, appender.getLogSize());\n  }\n\n  /** Verify if the weather passes in the order of the {@link WeatherType}s */\n  @Test\n  void testTimePasses() {\n    final var observer = mock(WeatherObserver.class);\n    final var weather = new Weather();\n    weather.addObserver(observer);\n\n    final var inOrder = inOrder(observer);\n    final var weatherTypes = WeatherType.values();\n    for (var i = 1; i < 20; i++) {\n      weather.timePasses();\n      inOrder.verify(observer).update(weatherTypes[i % weatherTypes.length]);\n    }\n\n    verifyNoMoreInteractions(observer);\n  }\n}\n"
  },
  {
    "path": "observer/src/test/java/com/iluwatar/observer/generic/GHobbitsTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer.generic;\n\nimport com.iluwatar.observer.WeatherType;\nimport java.util.Collection;\nimport java.util.List;\n\n/** GHobbitsTest. */\nclass GHobbitsTest extends ObserverTest<GenHobbits> {\n\n  @Override\n  public Collection<Object[]> dataProvider() {\n    return List.of(\n        new Object[] {WeatherType.SUNNY, \"The hobbits are facing Sunny weather now\"},\n        new Object[] {WeatherType.RAINY, \"The hobbits are facing Rainy weather now\"},\n        new Object[] {WeatherType.WINDY, \"The hobbits are facing Windy weather now\"},\n        new Object[] {WeatherType.COLD, \"The hobbits are facing Cold weather now\"});\n  }\n\n  /** Create a new test with the given weather and expected response. */\n  public GHobbitsTest() {\n    super(GenHobbits::new);\n  }\n}\n"
  },
  {
    "path": "observer/src/test/java/com/iluwatar/observer/generic/GWeatherTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer.generic;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.inOrder;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport com.iluwatar.observer.WeatherObserver;\nimport com.iluwatar.observer.WeatherType;\nimport com.iluwatar.observer.utils.InMemoryAppender;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** GWeatherTest */\nclass GWeatherTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(GenWeather.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /**\n   * Add a {@link WeatherObserver}, verify if it gets notified of a weather change, remove the\n   * observer again and verify that there are no more notifications.\n   */\n  @Test\n  void testAddRemoveObserver() {\n    final var observer = mock(Race.class);\n\n    final var weather = new GenWeather();\n    weather.addObserver(observer);\n    verifyNoMoreInteractions(observer);\n\n    weather.timePasses();\n    assertEquals(\"The weather changed to rainy.\", appender.getLastMessage());\n    verify(observer).update(weather, WeatherType.RAINY);\n\n    weather.removeObserver(observer);\n    weather.timePasses();\n    assertEquals(\"The weather changed to windy.\", appender.getLastMessage());\n\n    verifyNoMoreInteractions(observer);\n    assertEquals(2, appender.getLogSize());\n  }\n\n  /** Verify if the weather passes in the order of the {@link WeatherType}s */\n  @Test\n  void testTimePasses() {\n    final var observer = mock(Race.class);\n    final var weather = new GenWeather();\n    weather.addObserver(observer);\n\n    final var inOrder = inOrder(observer);\n    final var weatherTypes = WeatherType.values();\n    for (var i = 1; i < 20; i++) {\n      weather.timePasses();\n      inOrder.verify(observer).update(weather, weatherTypes[i % weatherTypes.length]);\n    }\n\n    verifyNoMoreInteractions(observer);\n  }\n}\n"
  },
  {
    "path": "observer/src/test/java/com/iluwatar/observer/generic/ObserverTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer.generic;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.observer.WeatherType;\nimport com.iluwatar.observer.utils.InMemoryAppender;\nimport java.util.Collection;\nimport java.util.function.Supplier;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.TestInstance;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\n/**\n * Test for Observers\n *\n * @param <O> Type of Observer\n */\n@TestInstance(TestInstance.Lifecycle.PER_CLASS)\npublic abstract class ObserverTest<O extends Observer<?, ?, WeatherType>> {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /** The observer instance factory */\n  private final Supplier<O> factory;\n\n  /**\n   * Create a new test instance using the given parameters\n   *\n   * @param factory The factory, used to create an instance of the tested observer\n   */\n  ObserverTest(final Supplier<O> factory) {\n    this.factory = factory;\n  }\n\n  public abstract Collection<Object[]> dataProvider();\n\n  /** Verify if the weather has the expected influence on the observer */\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testObserver(WeatherType weather, String response) {\n    final var observer = this.factory.get();\n    assertEquals(0, appender.getLogSize());\n\n    observer.update(null, weather);\n    assertEquals(response, appender.getLastMessage());\n    assertEquals(1, appender.getLogSize());\n  }\n}\n"
  },
  {
    "path": "observer/src/test/java/com/iluwatar/observer/generic/OrcsTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer.generic;\n\nimport com.iluwatar.observer.WeatherType;\nimport java.util.Collection;\nimport java.util.List;\n\n/** OrcsTest */\nclass OrcsTest extends ObserverTest<GenOrcs> {\n\n  @Override\n  public Collection<Object[]> dataProvider() {\n    return List.of(\n        new Object[] {WeatherType.SUNNY, \"The orcs are facing Sunny weather now\"},\n        new Object[] {WeatherType.RAINY, \"The orcs are facing Rainy weather now\"},\n        new Object[] {WeatherType.WINDY, \"The orcs are facing Windy weather now\"},\n        new Object[] {WeatherType.COLD, \"The orcs are facing Cold weather now\"});\n  }\n\n  /** Create a new test with the given weather and expected response */\n  public OrcsTest() {\n    super(GenOrcs::new);\n  }\n}\n"
  },
  {
    "path": "observer/src/test/java/com/iluwatar/observer/utils/InMemoryAppender.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.observer.utils;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.slf4j.LoggerFactory;\n\n/** InMemory Log Appender Util. */\npublic class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n  private final List<ILoggingEvent> log = new LinkedList<>();\n\n  public InMemoryAppender(Class clazz) {\n    ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this);\n    start();\n  }\n\n  public InMemoryAppender() {\n    ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n    start();\n  }\n\n  @Override\n  protected void append(ILoggingEvent eventObject) {\n    log.add(eventObject);\n  }\n\n  public int getLogSize() {\n    return log.size();\n  }\n\n  public String getLastMessage() {\n    return log.get(log.size() - 1).getFormattedMessage();\n  }\n}\n"
  },
  {
    "path": "optimistic-offline-lock/README.md",
    "content": "---\ntitle: \"Optimistic Offline Lock Pattern in Java: Mastering Conflict Resolution in Database Transactions\"\nshortTitle: Optimistic Offline Lock\ndescription: \"Explore the Optimistic Offline Lock design pattern in Java with detailed implementation guidelines and practical examples. Learn how to manage data concurrency effectively in your Java applications.\"\ncategory: Data access\nlanguage: en\ntag:\n  - Concurrency\n  - Data access\n  - Fault tolerance\n  - Isolation\n  - Persistence\n  - Transactions\n---\n\n## Also known as\n\n* Optimistic Concurrency Control\n\n## Intent of Optimistic Offline Lock Design Pattern\n\nThe Optimistic Offline Lock pattern in Java is specifically designed to manage concurrent data modifications without the need for long-duration database locks, thus enhancing system performance and scalability.\n\n## Detailed Explanation of Optimistic Offline Lock Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a library with multiple users checking out and returning books. Instead of locking each book while a user is browsing or deciding whether to borrow it, the library uses an optimistic approach. Each book has a timestamp or version number. When a user decides to borrow a book, they check the book's version number. If it matches the current version, the transaction proceeds. If another user has borrowed the book in the meantime, causing a version mismatch, the first user is informed to retry. This approach allows multiple users to browse and attempt to borrow books concurrently, improving the library's efficiency and user satisfaction without locking the entire catalog.\n\nIn plain words\n\n> The Optimistic Offline Lock pattern manages concurrent data modifications by allowing transactions to proceed without locks, resolving conflicts only when they occur to enhance performance and scalability.\n\nWikipedia says\n\n> Optimistic concurrency control (OCC), also known as optimistic locking, is a concurrency control method applied to transactional systems such as relational database management systems and software transactional memory.\n\nSequence diagram\n\n![Optimistic Offline Lock sequence diagram](./etc/optimistic-offline-lock-sequence-diagram.png)\n\n## Programmatic Example of Optimistic Offline Lock Pattern in Java\n\nIn this section, we delve into the practical implementation of the Optimistic Offline Lock in Java. By following these steps, you can ensure that your application handles data conflicts and concurrency with minimal overhead.\n\nThe Optimistic Offline Lock pattern is a concurrency control method that allows multiple transactions to proceed without locks, resolving conflicts only when they occur. This pattern is useful in scenarios where the likelihood of conflicting transactions is low and long-duration locks could hamper performance and scalability.\n\nFirst, we have a `Card` entity that represents a bank card with a sum of money and a version number.\n\n```java\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class Card {\n\n    private long id;\n\n    private long personId;\n\n    private float sum;\n\n    private int version;\n}\n```\n\nThe `CardUpdateService` class implements the `UpdateService` interface and provides a method `doUpdate` to update the Card entity. The `doUpdate` method first retrieves the current version of the `Card` entity. It then performs some business logic to update the sum of money in the `Card`. Before updating the `Card` in the database, it checks if the version of the `Card` in the database is the same as the initial version it retrieved. If the versions match, it proceeds with the update. If the versions do not match, it means that another transaction has updated the `Card` in the meantime, and it throws an `ApplicationException`.\n\n```java\n\n@RequiredArgsConstructor\npublic class CardUpdateService implements UpdateService<Card> {\n\n    private final JpaRepository<Card> cardJpaRepository;\n\n    @Override\n    @Transactional(rollbackFor = ApplicationException.class) //will roll back transaction in case ApplicationException\n    public Card doUpdate(Card card, long cardId) {\n        float additionalSum = card.getSum();\n        Card cardToUpdate = cardJpaRepository.findById(cardId);\n        int initialVersion = cardToUpdate.getVersion();\n        float resultSum = cardToUpdate.getSum() + additionalSum;\n        cardToUpdate.setSum(resultSum);\n        //Maybe more complex business-logic e.g. HTTP-requests and so on\n\n        if (initialVersion != cardJpaRepository.getEntityVersionById(cardId)) {\n            String exMessage = String.format(\"Entity with id %s were updated in another transaction\", cardId);\n            throw new ApplicationException(exMessage);\n        }\n\n        cardJpaRepository.update(cardToUpdate);\n        return cardToUpdate;\n    }\n}\n```\n\nIn this code snippet, the doUpdate method in the CardUpdateService class is a programmatic example of the Optimistic Offline Lock pattern. It allows the Card entity to be updated without locks and resolves conflicts by checking the version of the Card before the update.\n\n## When to Use the Optimistic Offline Lock Pattern in Java\n\n* When multiple transactions need to access and modify the same data simultaneously without causing data inconsistencies.\n* In systems where the likelihood of conflicting transactions is low.\n* When you want to avoid long-duration locks that could hamper performance and scalability.\n\n## Optimistic Offline Lock Pattern Java Tutorials\n\n* [Offline Concurrency Control (Baeldung)](https://www.baeldung.com/cs/offline-concurrency-control)\n* [Optimistic Locking in JPA (Baeldung)](https://www.baeldung.com/jpa-optimistic-locking)\n\n## Real-World Applications of Optimistic Offline Lock Pattern in Java\n\n* Web-based applications with high-read, low-write access patterns.\n* Distributed systems where locking resources for long durations is not feasible.\n* Java enterprise applications using JPA or Hibernate for data persistence.\n\n## Benefits and Trade-offs of Optimistic Offline Lock Pattern\n\nBenefits:\n\n* Reduces the need for locking resources, which improves performance.\n* Increases system scalability by allowing more transactions to proceed concurrently.\n* Simplifies transaction management by handling conflicts only when they occur.\n\nTrade-offs:\n\n* Requires additional logic (versioning, rollback/retry) to handle conflicts, which can complicate the application code.\n* Can lead to more frequent retries of transactions if conflicts are common.\n* Not suitable for high-conflict scenarios where frequent data modification collisions occur.\n\n## Related Java Design Patterns\n\n* Pessimistic Offline Lock: Unlike the Optimistic Offline Lock, this pattern uses locks to prevent conflicts by locking the data during the entire transaction. It is useful in high-conflict scenarios.\n* [Unit of Work](https://java-design-patterns.com/patterns/unit-of-work/): Helps in managing a set of changes as a single transaction, ensuring data integrity. It can be used in conjunction with Optimistic Offline Lock to handle complex transactions.\n* [Version Number](https://java-design-patterns.com/patterns/version-number/): A common technique used in Optimistic Offline Lock to detect conflicts by maintaining a version number for each data entity.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Java Persistence with Hibernate](https://amzn.to/44tP1ox)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Optimistic Offline Lock (Martin Fowler)](https://martinfowler.com/eaaCatalog/optimisticOfflineLock.html)\n"
  },
  {
    "path": "optimistic-offline-lock/etc/optimistic-offline-lock.urm.puml",
    "content": "@startuml\npackage com.iluwatar.repository {\n  interface JpaRepository<T> {\n    + findById(long) : T {abstract}\n    + getEntityVersionById(long) : int {abstract}\n    + update(T) : int {abstract}\n  }\n}\npackage com.iluwatar.api {\n  interface UpdateService<T> {\n    + doUpdate(T, long) : T {abstract}\n  }\n}\npackage com.iluwatar.service {\n  class CardUpdateService {\n    - cardJpaRepository : JpaRepository<Card>\n    + CardUpdateService(cardJpaRepository : JpaRepository<Card>)\n    + doUpdate(obj : Card, id : long) : Card\n  }\n}\npackage com.iluwatar.model {\n  class Card {\n    - id : long\n    - personId : long\n    - sum : float\n    - version : int\n    + Card()\n    + Card(id : long, personId : long, sum : float, version : int)\n    + builder() : CardBuilder {static}\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getId() : long\n    + getPersonId() : long\n    + getSum() : float\n    + getVersion() : int\n    + hashCode() : int\n    + setId(id : long)\n    + setPersonId(personId : long)\n    + setSum(sum : float)\n    + setVersion(version : int)\n    + toString() : String\n  }\n  class CardBuilder {\n    - id : long\n    - personId : long\n    - sum : float\n    - version : int\n    ~ CardBuilder()\n    + build() : Card\n    + id(id : long) : CardBuilder\n    + personId(personId : long) : CardBuilder\n    + sum(sum : float) : CardBuilder\n    + toString() : String\n    + version(version : int) : CardBuilder\n  }\n}\nCardUpdateService -->  \"-cardJpaRepository\" JpaRepository\nCardUpdateService ..|> UpdateService \n@enduml"
  },
  {
    "path": "optimistic-offline-lock/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>optimistic-offline-lock</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n</project>\n"
  },
  {
    "path": "optimistic-offline-lock/src/main/java/com/iluwatar/api/UpdateService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.api;\n\n/**\n * Service for entity update.\n *\n * @param <T> target entity\n */\npublic interface UpdateService<T> {\n\n  /**\n   * Update entity.\n   *\n   * @param obj entity to update\n   * @param id primary key\n   * @return modified entity\n   */\n  T doUpdate(T obj, long id);\n}\n"
  },
  {
    "path": "optimistic-offline-lock/src/main/java/com/iluwatar/exception/ApplicationException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.exception;\n\n/** Exception happens in application during business-logic execution. */\npublic class ApplicationException extends RuntimeException {\n\n  /**\n   * Inherited constructor with exception message.\n   *\n   * @param message exception message\n   */\n  public ApplicationException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "optimistic-offline-lock/src/main/java/com/iluwatar/model/Card.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.model;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/** Bank card entity. */\n@Data\n@Builder\n@NoArgsConstructor\n@AllArgsConstructor\npublic class Card {\n\n  /** Primary key. */\n  private long id;\n\n  /** Foreign key points to card's owner. */\n  private long personId;\n\n  /** Sum of money. */\n  private float sum;\n\n  /** Current version of object. */\n  private int version;\n}\n"
  },
  {
    "path": "optimistic-offline-lock/src/main/java/com/iluwatar/repository/JpaRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.repository;\n\n/**\n * Imitation of Spring's JpaRepository.\n *\n * @param <T> target database entity\n */\npublic interface JpaRepository<T> {\n\n  /**\n   * Get object by its PK.\n   *\n   * @param id primary key\n   * @return {@link T}\n   */\n  T findById(long id);\n\n  /**\n   * Get current object version.\n   *\n   * @param id primary key\n   * @return object's version\n   */\n  int getEntityVersionById(long id);\n\n  /**\n   * Update object.\n   *\n   * @param obj entity to update\n   * @return number of modified records\n   */\n  int update(T obj);\n}\n"
  },
  {
    "path": "optimistic-offline-lock/src/main/java/com/iluwatar/service/CardUpdateService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.service;\n\nimport com.iluwatar.api.UpdateService;\nimport com.iluwatar.exception.ApplicationException;\nimport com.iluwatar.model.Card;\nimport com.iluwatar.repository.JpaRepository;\nimport lombok.RequiredArgsConstructor;\n\n/** Service to update {@link Card} entity. */\n@RequiredArgsConstructor\npublic class CardUpdateService implements UpdateService<Card> {\n\n  private final JpaRepository<Card> cardJpaRepository;\n\n  @Override\n  public Card doUpdate(Card obj, long id) {\n    float additionalSum = obj.getSum();\n    Card cardToUpdate = cardJpaRepository.findById(id);\n    int initialVersion = cardToUpdate.getVersion();\n    float resultSum = cardToUpdate.getSum() + additionalSum;\n    cardToUpdate.setSum(resultSum);\n    // Maybe more complex business-logic e.g. HTTP-requests and so on\n\n    if (initialVersion != cardJpaRepository.getEntityVersionById(id)) {\n      String exMessage = String.format(\"Entity with id %s were updated in another transaction\", id);\n      throw new ApplicationException(exMessage);\n    }\n\n    cardJpaRepository.update(cardToUpdate);\n    return cardToUpdate;\n  }\n}\n"
  },
  {
    "path": "optimistic-offline-lock/src/test/java/com/iluwatar/OptimisticLockTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport static org.mockito.Mockito.eq;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.exception.ApplicationException;\nimport com.iluwatar.model.Card;\nimport com.iluwatar.repository.JpaRepository;\nimport com.iluwatar.service.CardUpdateService;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\n@SuppressWarnings({\"rawtypes\", \"unchecked\"})\npublic class OptimisticLockTest {\n\n  private CardUpdateService cardUpdateService;\n\n  private JpaRepository cardRepository;\n\n  @BeforeEach\n  public void setUp() {\n    cardRepository = Mockito.mock(JpaRepository.class);\n    cardUpdateService = new CardUpdateService(cardRepository);\n  }\n\n  @Test\n  public void shouldNotUpdateEntityOnDifferentVersion() {\n    int initialVersion = 1;\n    long cardId = 123L;\n    Card card = Card.builder().id(cardId).version(initialVersion).sum(123f).build();\n    when(cardRepository.findById(eq(cardId))).thenReturn(card);\n    when(cardRepository.getEntityVersionById(Mockito.eq(cardId))).thenReturn(initialVersion + 1);\n\n    Assertions.assertThrows(\n        ApplicationException.class, () -> cardUpdateService.doUpdate(card, cardId));\n  }\n\n  @Test\n  public void shouldUpdateOnSameVersion() {\n    int initialVersion = 1;\n    long cardId = 123L;\n    Card card = Card.builder().id(cardId).version(initialVersion).sum(123f).build();\n    when(cardRepository.findById(eq(cardId))).thenReturn(card);\n    when(cardRepository.getEntityVersionById(Mockito.eq(cardId))).thenReturn(initialVersion);\n\n    cardUpdateService.doUpdate(card, cardId);\n\n    Mockito.verify(cardRepository).update(Mockito.any());\n  }\n}\n"
  },
  {
    "path": "page-controller/README.md",
    "content": "---\ntitle: \"Page Controller Pattern in Java: Centralizing Web Page Logic for Cleaner Design\"\nshortTitle: Page Controller\ndescription: \"Explore the Page Controller design pattern in Java with detailed examples. Learn how it handles web application requests and improves architectural organization.\"\ncategory: Architectural\nlanguage: en\ntags:\n  - API design\n  - Business\n  - Client-server\n  - Decoupling\n  - Enterprise patterns\n  - Layered architecture\n  - Presentation\n  - Web development\n---\n\n## Intent of Page Controller Design Pattern\n\nThe Page Controller pattern is intended to handle requests for a specific page or action within a web application, processing input, and determining the appropriate view for rendering the response.\n\n## Detailed Explanation of Page Controller Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a large department store with multiple specialized counters: Customer Service, Returns, Electronics, and Clothing. Each counter has a dedicated staff member who handles specific tasks for that department.\n>\n> In this analogy, the department store is the web application, and each specialized counter represents a Page Controller. The Customer Service counter (Page Controller) handles customer inquiries, the Returns counter processes returns and exchanges, the Electronics counter assists with electronic goods, and the Clothing counter manages clothing-related requests. Each counter operates independently, addressing the specific needs of their respective department, just as each Page Controller handles requests for a specific page or action within the web application.\n\nIn plain words\n\n> The Page Controller pattern handles requests for specific pages or actions within a Java web application, processing input, executing business logic, and determining the appropriate view for rendering the response, enhancing response handling and system architecture.\n\nArchitecture diagram\n\n![Page Controller Architecture Diagram](./etc/page-controller-architecture-diagram.png)\n\n## Programmatic Example of Page Controller Pattern in Java\n\nThe Page Controller design pattern is a pattern used in web development where each page of a website is associated with a class or function known as a controller. The controller handles the HTTP requests for that page and determines which model and view to use. Predominantly utilized in MVC (Model-View-No-Controller) architectures, the Java Page Controller pattern integrates seamlessly with existing enterprise frameworks.\n\nIn the provided code, we have an example of the Page Controller pattern implemented using Spring Boot in Java. Let's break it down:\n\n1. **SignupController**: This is a Page Controller for the signup page. It handles HTTP GET and POST requests at the \"/signup\" path. The GET request returns the signup page, and the POST request processes the signup form and redirects to the user page.\n\n```java\n@Controller\n@Component\npublic class SignupController {\n  SignupView view = new SignupView();\n\n  @GetMapping(\"/signup\")\n  public String getSignup() {\n    return view.display();\n  }\n\n  @PostMapping(\"/signup\")\n  public String create(SignupModel form, RedirectAttributes redirectAttributes) {\n    redirectAttributes.addAttribute(\"name\", form.getName());\n    redirectAttributes.addAttribute(\"email\", form.getEmail());\n    redirectAttributes.addFlashAttribute(\"userInfo\", form);\n    return view.redirect(form);\n  }\n}\n```\n\n2. **UserController**: This is another Page Controller, this time for the user page. It handles HTTP GET requests at the \"/user\" path, returning the user page.\n\n```java\n@Slf4j\n@Controller\npublic class UserController {\n  UserView view = new UserView();\n\n  @GetMapping(\"/user\")\n  public String getUserPath(SignupModel form, Model model) {\n    model.addAttribute(\"name\", form.getName());\n    model.addAttribute(\"email\", form.getEmail());\n    return view.display(form);\n  }\n}\n```\n\n3. **SignupModel and UserModel**: These are the data models used by the controllers. They hold the data to be displayed on the page.\n\n```java\n@Component\n@Getter\n@Setter\npublic class SignupModel {\n  private String name;\n  private String email;\n  private String password;\n}\n\n@Getter\n@Setter\npublic class UserModel {\n  private String name;\n  private String email;\n}\n```\n\n4. **SignupView and UserView**: These are the views used by the controllers. They determine how the data is presented to the user.\n\n```java\n@Slf4j\npublic class SignupView {\n  public String display() {\n    return \"/signup\";\n  }\n\n  public String redirect(SignupModel form) {\n    return \"redirect:/user\";\n  }\n}\n\n@Slf4j\npublic class UserView {\n  public String display(SignupModel user) {\n    return \"/user\";\n  }\n}\n```\n\nIn this example, the controllers (`SignupController` and `UserController`) are the Page Controllers. They handle the HTTP requests for their respective pages and determine which model and view to use. The models (`SignupModel` and `UserModel`) hold the data for the page, and the views (`SignupView` and `UserView`) determine how that data is presented. This separation of concerns makes the code easier to manage and maintain.\n\n## When to Use the Page Controller Pattern in Java\n\n* When developing a web application where each page or action needs specific processing.\n* When aiming to separate the request handling logic from the view rendering logic.\n* In scenarios where a clear separation of concerns between different layers (controller, view) is required.\n\n## Real-World Applications of Page Controller Pattern in Java\n\n* Spring MVC (Java)\n* Apache Struts\n* JSF (JavaServer Faces)\n\n## Benefits and Trade-offs of Page Controller Pattern\n\nBenefits:\n\n* [Separation of Concerns](https://java-design-patterns.com/principles/#separation-of-concerns): Clearly separates the controller logic from the view, making the application easier to manage and maintain.\n* Reusability: Common logic can be reused across multiple controllers, reducing code duplication.\n* Testability: Controllers can be tested independently of the view, improving unit test coverage.\n\nTrade-offs:\n\n* Complexity: Can add complexity to the application structure, requiring careful organization and documentation.\n* Overhead: May introduce performance overhead due to additional layers of abstraction and processing.\n\n## Related Java Design Patterns\n\n* [Front Controller](https://java-design-patterns.com/patterns/front-controller/): Often used in conjunction with Page Controller to handle common pre-processing logic such as authentication and logging.\n* View Helper: Works alongside Page Controller to assist in preparing the view, often handling formatting and other presentation logic.\n* [Model-View-Controller (MVC)](https://java-design-patterns.com/patterns/model-view-controller/): Page Controller is a fundamental part of the MVC architecture, acting as the Controller.\n\n## References and Credits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap)\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Page Controller (Martin Fowler)](https://www.martinfowler.com/eaaCatalog/pageController.html)\n"
  },
  {
    "path": "page-controller/etc/page-controller.urm.puml",
    "content": "@startuml\npackage com.iluwatar.page.controller {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class SignupController {\n    - LOGGER : Logger {static}\n    ~ view : SignupView\n    ~ SignupController()\n    + create(form : SignupModel, redirectAttributes : RedirectAttributes) : String\n    + getSignup() : String\n  }\n  class SignupModel {\n    - email : String\n    - name : String\n    - password : String\n    + SignupModel()\n    + SignupModel(name : String, email : String, password : String)\n    + getEmail() : String\n    + getName() : String\n    + getPassword() : String\n    + setEmail(email : String)\n    + setName(name : String)\n    + setPassword(password : String)\n  }\n  class SignupView {\n    - LOGGER : Logger {static}\n    + SignupView()\n    + display() : String\n    + redirect(form : SignupModel) : String\n  }\n  class UserController {\n    - LOGGER : Logger {static}\n    ~ view : UserView\n    + UserController()\n    + getUserPath(form : SignupModel, model : Model) : String\n  }\n  class UserModel {\n    - email : String\n    - name : String\n    + UserModel()\n    + getEmail() : String\n    + getName() : String\n    + setEmail(email : String)\n    + setName(name : String)\n  }\n  class UserView {\n    - LOGGER : Logger {static}\n    + UserView()\n    + display(user : SignupModel) : String\n  }\n}\nUserController -->  \"-view\" UserView\nUserController -->  \"-model\" UserModel\nSignupController -->  \"-view\" SignupView\nSignupController -->  \"-model\" SignupModel\n@enduml"
  },
  {
    "path": "page-controller/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n      <groupId>com.iluwatar</groupId>\n      <artifactId>java-design-patterns</artifactId>\n      <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>page-controller</artifactId>\n    <name>page-controller</name>\n    <description>page-controller</description>\n\n  <dependencies>\n    <dependency>\n      <groupId>org.springframework</groupId>\n      <artifactId>spring-webmvc</artifactId>\n        <version>6.2.5</version>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-web</artifactId>\n    </dependency>\n    <dependency>\n       <groupId>org.springframework</groupId>\n       <artifactId>spring-context</artifactId>\n        <version>6.2.5</version>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-thymeleaf</artifactId>\n        <version>3.4.4</version>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n        <groupId>org.mockito</groupId>\n        <artifactId>mockito-core</artifactId>\n        <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-test</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.page.controller.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "page-controller/src/main/java/com/iluwatar/page/controller/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.page.controller;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * Page Controller pattern is utilized when we want to simplify relationship in a dynamic website.\n * It is an approach of one front page leading to one logical file that handles HTTP requests and\n * actions. In this example, we build a website with signup page handling an input form with Signup\n * Controller, Signup View, and Signup Model and after signup, it is redirected to a user page\n * handling with User Controller, User View, and User Model.\n */\n@Slf4j\n@SpringBootApplication\npublic class App {\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(final String[] args) {\n    SpringApplication.run(App.class, args);\n  }\n}\n"
  },
  {
    "path": "page-controller/src/main/java/com/iluwatar/page/controller/SignupController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.page.controller;\n\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.stereotype.Component;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.servlet.mvc.support.RedirectAttributes;\n\n/** Signup Controller. */\n@Slf4j\n@Controller\n@Component\npublic class SignupController {\n  SignupView view = new SignupView();\n\n  /** Signup Controller can handle http request and decide which model and view use. */\n  SignupController() {}\n\n  /** Handle http GET request. */\n  @GetMapping(\"/signup\")\n  public String getSignup() {\n    return view.display();\n  }\n\n  /** Handle http POST request and access model and view. */\n  @PostMapping(\"/signup\")\n  public String create(SignupModel form, RedirectAttributes redirectAttributes) {\n    LOGGER.info(form.getName());\n    LOGGER.info(form.getEmail());\n    redirectAttributes.addAttribute(\"name\", form.getName());\n    redirectAttributes.addAttribute(\"email\", form.getEmail());\n    redirectAttributes.addFlashAttribute(\"userInfo\", form);\n    return view.redirect(form);\n  }\n}\n"
  },
  {
    "path": "page-controller/src/main/java/com/iluwatar/page/controller/SignupModel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.page.controller;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.springframework.stereotype.Component;\n\n/** ignup model. */\n@Component\n@Data\n@NoArgsConstructor\npublic class SignupModel {\n  private String name;\n  private String email;\n  private String password;\n}\n"
  },
  {
    "path": "page-controller/src/main/java/com/iluwatar/page/controller/SignupView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.page.controller;\n\nimport lombok.NoArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Signup View. */\n@Slf4j\n@NoArgsConstructor\npublic class SignupView {\n\n  public String display() {\n    LOGGER.info(\"display signup front page\");\n    return \"/signup\";\n  }\n\n  /** redirect to user page. */\n  public String redirect(SignupModel form) {\n    LOGGER.info(\n        \"Redirect to user page with \" + \"name \" + form.getName() + \" email \" + form.getEmail());\n    return \"redirect:/user\";\n  }\n}\n"
  },
  {
    "path": "page-controller/src/main/java/com/iluwatar/page/controller/UserController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.page.controller;\n\nimport lombok.NoArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.GetMapping;\n\n/** User Controller. */\n@Slf4j\n@Controller\n@NoArgsConstructor\npublic class UserController {\n  private final UserView view = new UserView();\n\n  /** Handle http GET request and access view and model. */\n  @GetMapping(\"/user\")\n  public String getUserPath(SignupModel form, Model model) {\n    model.addAttribute(\"name\", form.getName());\n    model.addAttribute(\"email\", form.getEmail());\n    return view.display(form);\n  }\n}\n"
  },
  {
    "path": "page-controller/src/main/java/com/iluwatar/page/controller/UserModel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.page.controller;\n\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/** User model. */\n@Data\n@NoArgsConstructor\npublic class UserModel {\n  private String name;\n  private String email;\n}\n"
  },
  {
    "path": "page-controller/src/main/java/com/iluwatar/page/controller/UserView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.page.controller;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** User view class generating html file. */\n@Slf4j\npublic class UserView {\n  /**\n   * displaying command to generate html.\n   *\n   * @param user model content.\n   */\n  public String display(SignupModel user) {\n    LOGGER.info(\"display user html\" + \" name \" + user.getName() + \" email \" + user.getEmail());\n    return \"/user\";\n  }\n}\n"
  },
  {
    "path": "page-controller/src/main/resources/application.properties",
    "content": "#\n# This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n#\n# The MIT License\n# Copyright © 2014-2022 Ilkka Seppälä\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nserver.port=51515\n"
  },
  {
    "path": "page-controller/src/main/resources/templates/signup.html",
    "content": "<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<!DOCTYPE HTML>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n  <title> Signup </title>\n</head>\n\n<body>\n<H1>Sign Up</H1>\n<form action=\"#\" th:action=\"@{/signup}\" method=\"post\" th:object=\"${signup}\">\n  <div style=\"margin:20px\">\n    <label>Name</label>\n    <input type=\"text\" id=\"name\" name=\"name\"/>\n  </div>\n  <div style=\"margin:20px\">\n    <label>Email</label>\n    <input type=\"text\" id=\"email\" name=\"email\"/>\n  </div>\n  <div style=\"margin:20px\">\n    <label>password</label>\n    <input type=\"password\" id=\"password\" name=\"password\"/>\n  </div>\n  <div style=\"margin:20px\">\n    <input type=\"submit\" value=\"Signup\">\n  </div>\n</form>\n</body>\n"
  },
  {
    "path": "page-controller/src/main/resources/templates/user.html",
    "content": "<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<!DOCTYPE HTML>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n  <title> User </title>\n</head>\n\n<body>\n<h1>Your Information</h1>\n<p>Name: <span th:text=\"${name}\"></span></p>\n<p>Email: <span th:text=\"${email}\"></span></p>\n</body>"
  },
  {
    "path": "page-controller/src/test/java/com/iluwatar/page/controller/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.page.controller;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\npublic class AppTest {\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "page-controller/src/test/java/com/iluwatar/page/controller/SignupControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.page.controller;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.web.servlet.mvc.support.RedirectAttributes;\nimport org.springframework.web.servlet.mvc.support.RedirectAttributesModelMap;\n\n/** Test for Signup Controller */\npublic class SignupControllerTest {\n\n  /** Verify if user can sign up and redirect to user page */\n  @Test\n  void testSignup() {\n    var controller = new SignupController();\n    controller.getSignup();\n\n    RedirectAttributes redirectAttributes = new RedirectAttributesModelMap();\n    String redirectPath = controller.create(retrieveSignupData(), redirectAttributes);\n    assertEquals(\"redirect:/user\", redirectPath);\n  }\n\n  public static SignupModel retrieveSignupData() {\n    SignupModel model = new SignupModel();\n    model.setName(\"Lily\");\n    model.setEmail(\"lily@email.com\");\n    model.setPassword(\"password1234\");\n    return model;\n  }\n}\n"
  },
  {
    "path": "page-controller/src/test/java/com/iluwatar/page/controller/SignupModelTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.page.controller;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test for Signup Model */\npublic class SignupModelTest {\n  /** Verify if a user can set a name properly */\n  @Test\n  void testSetName() {\n    SignupModel model = new SignupModel();\n    model.setName(\"Lily\");\n    assertEquals(\"Lily\", model.getName());\n  }\n\n  /** Verify if a user can set an email properly */\n  @Test\n  void testSetEmail() {\n    SignupModel model = new SignupModel();\n    model.setEmail(\"Lily@email\");\n    assertEquals(\"Lily@email\", model.getEmail());\n  }\n\n  /** Verify if a user can set a password properly */\n  @Test\n  void testSetPassword() {\n    SignupModel model = new SignupModel();\n    model.setPassword(\"password1234\");\n    assertEquals(\"password1234\", model.getPassword());\n  }\n}\n"
  },
  {
    "path": "page-controller/src/test/java/com/iluwatar/page/controller/UserControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.page.controller;\n\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.web.servlet.MockMvc;\n\n@ExtendWith(SpringExtension.class)\n@SpringBootTest\n@AutoConfigureMockMvc\npublic class UserControllerTest {\n  private UserController userController;\n\n  @Autowired MockMvc mockMvc;\n\n  /** Verify if view and model are directed properly */\n  @Test\n  void testGetUserPath() throws Exception {\n    this.mockMvc\n        .perform(get(\"/user\").param(\"name\", \"Lily\").param(\"email\", \"Lily@email.com\"))\n        .andExpect(status().isOk())\n        .andExpect(model().attribute(\"name\", \"Lily\"))\n        .andExpect(model().attribute(\"email\", \"Lily@email.com\"))\n        .andReturn();\n  }\n}\n"
  },
  {
    "path": "page-controller/src/test/java/com/iluwatar/page/controller/UserModelTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.page.controller;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\npublic class UserModelTest {\n  /** Verify if a user can set a name properly */\n  @Test\n  void testSetName() {\n    UserModel model = new UserModel();\n    model.setName(\"Lily\");\n    assertEquals(\"Lily\", model.getName());\n  }\n\n  /** Verify if a user can set an email properly */\n  @Test\n  void testSetEmail() {\n    UserModel model = new UserModel();\n    model.setEmail(\"Lily@email\");\n    assertEquals(\"Lily@email\", model.getEmail());\n  }\n}\n"
  },
  {
    "path": "page-object/README.md",
    "content": "---\ntitle: \"Page Object Pattern in Java: Streamlining UI Testing for Better Maintainability\"\nshortTitle: Page Object\ndescription: \"Explore the Page Object design pattern for Java. Learn how to implement, use, and optimize this pattern for better code maintainability and test automation in Java applications.\"\ncategory: Testing\nlanguage: en\ntag:\n  - Abstraction\n  - Code simplification\n  - Decoupling\n  - Encapsulation\n  - Testing\n  - Web development\n---\n\n## Also known as\n\n* Page Object Model (POM)\n\n## Intent of Page Object Design Pattern\n\nThe Page Object pattern in Java aims to create a model of the UI elements of a web page to improve the maintainability and readability of test automation code.\n\n## Detailed Explanation of Page Object Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a large corporate office where a receptionist directs visitors to the appropriate department. The receptionist serves as a single point of contact for all incoming visitors, simplifying the process of navigation within the building. Each department provides the receptionist with specific instructions on how to direct visitors to their office.\n>\n> In this analogy, the receptionist is like a Page Object in a testing framework. The receptionist abstracts the complexities of the office layout from the visitors, just as the Page Object abstracts the details of interacting with web elements from the test scripts. When the layout of the office changes, only the receptionist's instructions need to be updated, not the way visitors are directed, similar to how only the Page Object needs to be updated when the web UI changes, not the test scripts.\n\nIn plain words\n\n> The Page Object design pattern creates an abstraction layer for web pages, encapsulating their elements and interactions to simplify and maintain automated UI testing scripts.\n\nselenium.dev says\n\n> Within your web app’s UI, there are areas where your tests interact with. A Page Object only models these as objects within the test code. This reduces the amount of duplicated code and means that if the UI changes, the fix needs only to be applied in one place.\n>\n> Page Object is a Design Pattern that has become popular in test automation for enhancing test maintenance and reducing code duplication. A page object is an object-oriented class that serves as an interface to a page of your AUT. The tests then use the methods of this page object class whenever they need to interact with the UI of that page. The benefit is that if the UI changes for the page, the tests themselves don’t need to change, only the code within the page object needs to change. Subsequently, all changes to support that new UI are located in one place.\n\nMind map\n\n![Page Object mind map](./etc/page-object-mind-map.png)\n\nFlowchart\n\n![Page Object flowchart](./etc/page-object-flowchart.png)\n\n## Programmatic Example of Page Object Pattern in Java\n\nThe Page Object design pattern is a popular design pattern in test automation. It helps in enhancing test maintenance and reducing code duplication. A page object is an object-oriented class that serves as an interface to a page of your Application Under Test (AUT). The tests then use the methods of this page object class whenever they need to interact with the UI of that page. The benefit is that if the UI changes for the page, the tests themselves don’t need to change, only the code within the page object needs to change. Subsequently, all changes to support that new UI are located in one place.\n\nLet's consider a simple programmatic example of the Page Object pattern for a login page using Selenium in Java:\n\n```java\npublic class LoginPage {\n    private final WebDriver driver;\n\n    // Web elements on the login page\n    private final By usernameInput = By.id(\"username\");\n    private final By passwordInput = By.id(\"password\");\n    private final By loginButton = By.id(\"login-button\");\n\n    public LoginPage(WebDriver driver) {\n        this.driver = driver;\n    }\n\n    // Methods to interact with the login page\n\n    public void enterUsername(String username) {\n        WebElement usernameElement = driver.findElement(usernameInput);\n        usernameElement.sendKeys(username);\n    }\n\n    public void enterPassword(String password) {\n        WebElement passwordElement = driver.findElement(passwordInput);\n        passwordElement.sendKeys(password);\n    }\n\n    public void clickLoginButton() {\n        WebElement loginButtonElement = driver.findElement(loginButton);\n        loginButtonElement.click();\n    }\n\n    // Other methods specific to the login page if needed\n}\n```\n\nIn this example, the `LoginPage` class represents the login page of a web application. It encapsulates the web elements on the page and provides methods to interact with those elements. The actual Selenium WebDriver instance is passed to the constructor, allowing the methods to perform actions on the web page.\n\nThis Page Object can be used in test scripts to interact with the login page without exposing the details of the page structure in the test code, promoting maintainability and reusability.\n\n## When to Use the Page Object Pattern in Java\n\nUse the Page Object pattern when\n\n* Automating UI tests for web applications.\n* You want to separate the UI actions from the test logic.\n* Enhancing test code readability and reducing duplication.\n* Simplifying maintenance when the web UI changes.\n\n## Real-World Applications of Page Object Pattern in Java\n\n* Selenium WebDriver tests for web applications.\n* Automated UI testing frameworks in Java.\n* Popular test automation frameworks like TestNG and JUnit.\n\n## Benefits and Trade-offs of Page Object Pattern\n\nBenefits:\n\n* Encapsulation: Isolates the page elements and actions from test scripts.\n* Code simplification: Reduces code duplication and improves readability.\n* Maintainability: Easy to update when the UI changes, as changes are confined to page objects.\n* Abstraction: Test scripts focus on what the user does rather than how the actions are performed on the UI.\n\nTrade-offs:\n\n* Initial Setup: Requires extra effort to design and implement page objects.\n* Complexity: Overuse may lead to a complex structure with many page objects and methods.\n\n## Related Java Design Patterns\n\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Can be used alongside Page Objects to add additional responsibilities to objects dynamically.\n* [Facade](https://java-design-patterns.com/patterns/facade/): Both provide a simplified interface to a complex subsystem. Page Object abstracts the complexities of the UI.\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): Acts as a surrogate or placeholder, which can also be used for lazy initialization of page objects.\n\n## References and Credits\n\n* [Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation](https://amzn.to/4bjhTSK)\n* [Selenium Design Patterns and Best Practices](https://amzn.to/4aofYv8)\n* [Selenium Testing Tools Cookbook](https://amzn.to/3K1QxEN)\n* [Page Object (Martin Fowler)](http://martinfowler.com/bliki/PageObject.html)\n* [Page Objects (Selenium)](https://github.com/SeleniumHQ/selenium/wiki/PageObjects)\n"
  },
  {
    "path": "page-object/etc/page-object.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.9\" icons=\"true\" always-add-relationships=\"false\" generalizations=\"true\" realizations=\"true\" \n  associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "page-object/etc/page-object.urm.puml",
    "content": "@startuml\n@enduml"
  },
  {
    "path": "page-object/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>page-object</artifactId>\n  <packaging>pom</packaging>\n  <modules>\n    <module>sample-application</module>\n    <module>test-automation</module>\n  </modules>\n  <dependencies>\n    <dependency>\n      <groupId>org.htmlunit</groupId>\n      <artifactId>htmlunit</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.pageobject.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "page-object/sample-application/etc/page-object.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.9\" icons=\"true\" always-add-relationships=\"false\" generalizations=\"true\" realizations=\"true\" \n  associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "page-object/sample-application/etc/sample-application.urm.puml",
    "content": "@startuml\npackage com.iluwatar.pageobject {\n  class App {\n    - LOGGER : Logger {static}\n    - App()\n    + main(args : String[]) {static}\n  }\n}\n@enduml"
  },
  {
    "path": "page-object/sample-application/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <artifactId>page-object</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n  </dependencies>\n  <artifactId>sample-application</artifactId>\n</project>\n"
  },
  {
    "path": "page-object/sample-application/src/main/java/com/iluwatar/pageobject/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject;\n\nimport java.awt.Desktop;\nimport java.io.File;\nimport java.io.IOException;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Page Object pattern wraps an UI component with an application specific API allowing you to\n * manipulate the UI elements without having to dig around with the underlying UI technology used.\n * This is especially useful for testing as it means your tests will be less brittle. Your tests can\n * concentrate on the actual test cases where as the manipulation of the UI can be left to the\n * internals of the page object itself.\n *\n * <p>Due to this reason, it has become very popular within the test automation community. In\n * particular, it is very common in that the page object is used to represent the html pages of a\n * web application that is under test. This web application is referred to as AUT (Application Under\n * Test). A web browser automation tool/framework like Selenium for instance, is then used to drive\n * the automating of the browser navigation and user actions journeys through this web application.\n * Your test class would therefore only be responsible for particular test cases and page object\n * would be used by the test class for UI manipulation required for the tests.\n *\n * <p>In this implementation rather than using Selenium, the HtmlUnit library is used as a\n * replacement to represent the specific html elements and to drive the browser. The purpose of this\n * example is just to provide a simple version that showcase the intentions of this pattern and how\n * this pattern is used in order to understand it.\n */\n@Slf4j\npublic final class App {\n\n  private App() {}\n\n  /**\n   * Application entry point\n   *\n   * <p>The application under development is a web application. Normally you would probably have a\n   * backend that is probably implemented in an object-oriented language (e.g. Java) that serves the\n   * frontend which comprises of a series of HTML, CSS, JS etc...\n   *\n   * <p>For illustrations purposes only, a very simple static html app is used here. This main\n   * method just fires up this simple web app in a default browser.\n   *\n   * @param args arguments\n   */\n  public static void main(String[] args) {\n\n    try {\n      var classLoader = App.class.getClassLoader();\n      var applicationFile = new File(classLoader.getResource(\"sample-ui/login.html\").getPath());\n\n      // should work for unix like OS (mac, unix etc...)\n      if (Desktop.isDesktopSupported()) {\n        Desktop.getDesktop().open(applicationFile);\n\n      } else {\n        // java Desktop not supported - above unlikely to work for Windows so try instead...\n        Runtime.getRuntime().exec(\"cmd.exe start \" + applicationFile);\n      }\n\n    } catch (IOException ex) {\n      LOGGER.error(\"An error occurred.\", ex);\n    }\n  }\n}\n"
  },
  {
    "path": "page-object/sample-application/src/main/resources/sample-ui/album-list.html",
    "content": "<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Album List</title>\n    <link rel=\"stylesheet\" href=\"css/style.css\">\n    <link rel=\"stylesheet\" href=\"css/album-list.css\">\n</head>\n<body>\n    <header>\n    \t<h1>My Album Viewer</h1>\n    </header>\n\n    <section>\n    \t<div>\n    \t\t<table>\n    \t\t\t<tr>\n                    <th>Album Title</th>\n                    <th>Album Year</th>\n                    <th>Album Rating</th>\n                    <th>Number of Songs</th>\n                    <th>Artist</th>\n                </tr>\n    \t\t\t<tr class=\"album\">\n    \t\t\t\t<td><a href=\"album-page.html\">21</a></td>\n                    <td>2011</td>\n                    <td>A</td>\n                    <td>11</td>\n                    <td>Adele</td>\n    \t\t\t</tr>\n    \t\t</table>\n    \t</div>\n    </section>\n\n</body>\n</html>"
  },
  {
    "path": "page-object/sample-application/src/main/resources/sample-ui/album-page.html",
    "content": "<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Album Page</title>\n    <link rel=\"stylesheet\" href=\"css/style.css\">\n</head>\n<body>\n    <header>\n    \t<h1 id=\"pageHeader\">21</h1>\n    </header>\n\n    <section>\n    \t<div>\n            <form>\n        \t\t<table>\n                    <tr><td>Title:</td><td><input type=\"text\" id=\"albumTitle\" value=\"21\"></td></tr>\n                    <tr><td>Artist:</td><td><input type=\"text\" id=\"albumArtist\" value=\"Adele\"></td></tr>\n                    <tr>\n                        <td>Year:</td>\n                        <td>\n                            <select id=\"albumYear\">\n                                <option>2011</option>\n                                <option>2012</option>    \n                                <option>2013</option>\n                                <option>2014</option>\n                                <option>2015</option>\n                                <option>2016</option>\n                            </select>\n                        </td>\n                    </tr>\n                    <tr>\n                        <td>Rating:</td>\n                        <td><input type=\"text\" id=\"albumRating\" value=\"A\"></td>\n                    </tr>\n                    <tr>\n                        <td>Number of Songs:</td>\n                        <td><input type=\"number\" id=\"numberOfSongs\" value=\"12\"></td>\n                    </tr>\n                    <tr>\n                        <td><input type=\"submit\" id=\"cancelButton\" value=\"Cancel\"></td>\n                        <td><input type=\"submit\" id=\"saveButton\" value=\"Save\"></td>\n                    </tr>\n                </table>\n            </form>    \n    \t</div>\n    </section>\n\n</body>\n</html>"
  },
  {
    "path": "page-object/sample-application/src/main/resources/sample-ui/css/album-list.css",
    "content": "/**\n * The MIT License\n * Copyright © 2014-2021 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n<!--\n\n    The MIT License\n    Copyright (c) 2014-2016 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\ntable {\n    font-size: 16px;\n    border-collapse: collapse;\n}\n\nth {\n    background-color: #FFFFFF;\n    border: 1px solid black;\n    color: black;\n    width: 150px;\n    height: 20px;\n}\n\ntd {\n    border: 1px solid black;\n    background-color: white;\n}\n\nth, td {\n    padding: 15px;\n    text-align: left;\n}"
  },
  {
    "path": "page-object/sample-application/src/main/resources/sample-ui/css/style.css",
    "content": "/**\n * The MIT License\n * Copyright © 2014-2021 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n<!--\n\n    The MIT License\n    Copyright (c) 2014-2016 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\nbody {\n    font-family: \"Trebuchet MS\", Arial, Helvetica, sans-serif;\n}"
  },
  {
    "path": "page-object/sample-application/src/main/resources/sample-ui/login.html",
    "content": "<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Login</title>\n    <link rel=\"stylesheet\" href=\"css/style.css\">\n</head>\n<body>\n<header>\n    <h1>Login</h1>\n</header>\n\n<section>\n    <form method=\"post\" action=\"album-list.html\">\n        <table>\n            <tr><td>Username:</td><td><input type=\"text\" id=\"username\"></td></tr>\n            <tr><td>Password:</td><td><input type=\"password\" id=\"password\"></td></tr>\n            <tr><td><input type=\"submit\" id=\"loginButton\" value=\"Login\"></td></tr>\n        </table>\n\n    </form>\n</section>\n</body>\n</html>"
  },
  {
    "path": "page-object/src/main/java/com/iluwatar/pageobject/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject;\n\nimport java.awt.Desktop;\nimport java.io.File;\nimport java.io.IOException;\n\n/**\n * Page Object pattern wraps an UI component with an application specific API allowing you to\n * manipulate the UI elements without having to dig around with the underlying UI technology used.\n * This is especially useful for testing as it means your tests will be less brittle. Your tests can\n * concentrate on the actual test cases where as the manipulation of the UI can be left to the\n * internals of the page object itself.\n *\n * <p>Due to this reason, it has become very popular within the test automation community. In\n * particular, it is very common in that the page object is used to represent the html pages of a\n * web application that is under test. This web application is referred to as AUT (Application Under\n * Test). A web browser automation tool/framework like Selenium for instance, is then used to drive\n * the automating of the browser navigation and user actions journeys through this web application.\n * Your test class would therefore only be responsible for particular test cases and page object\n * would be used by the test class for UI manipulation required for the tests.\n *\n * <p>In this implementation rather than using Selenium, the HtmlUnit library is used as a\n * replacement to represent the specific html elements and to drive the browser. The purpose of this\n * example is just to provide a simple version that showcase the intentions of this pattern and how\n * this pattern is used in order to understand it.\n */\npublic final class App {\n\n  private App() {}\n\n  /**\n   * Application entry point\n   *\n   * <p>The application under development is a web application. Normally you would probably have a\n   * backend that is probably implemented in an object-oriented language (e.g. Java) that serves the\n   * frontend which comprises of a series of HTML, CSS, JS etc...\n   *\n   * <p>For illustrations purposes only, a very simple static html app is used here. This main\n   * method just fires up this simple web app in a default browser.\n   *\n   * @param args arguments\n   */\n  public static void main(String[] args) {\n\n    try {\n      var classLoader = App.class.getClassLoader();\n      var applicationFile = new File(classLoader.getResource(\"sample-ui/login.html\").getPath());\n\n      // Should work for unix like OS (mac, unix etc...)\n      if (Desktop.isDesktopSupported()) {\n        Desktop.getDesktop().open(applicationFile);\n\n      } else {\n        // Java Desktop not supported - above unlikely to work for Windows so try the\n        // following instead...\n        Runtime.getRuntime().exec(\"cmd.exe start \" + applicationFile);\n      }\n\n    } catch (IOException ex) {\n      ex.printStackTrace();\n    }\n  }\n}\n"
  },
  {
    "path": "page-object/src/main/resources/sample-ui/album-list.html",
    "content": "<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Album List</title>\n    <link rel=\"stylesheet\" href=\"css/style.css\">\n    <link rel=\"stylesheet\" href=\"css/album-list.css\">\n</head>\n<body>\n    <header>\n    \t<h1>My Album Viewer</h1>\n    </header>\n\n    <section>\n    \t<div>\n    \t\t<table>\n    \t\t\t<tr>\n                    <th>Album Title</th>\n                    <th>Album Year</th>\n                    <th>Album Rating</th>\n                    <th>Number of Songs</th>\n                    <th>Artist</th>\n                </tr>\n    \t\t\t<tr class=\"album\">\n    \t\t\t\t<td><a href=\"album-page.html\">21</a></td>\n                    <td>2011</td>\n                    <td>A</td>\n                    <td>11</td>\n                    <td>Adele</td>\n    \t\t\t</tr>\n    \t\t</table>\n    \t</div>\n    </section>\n\n</body>\n</html>"
  },
  {
    "path": "page-object/src/main/resources/sample-ui/album-page.html",
    "content": "<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Album Page</title>\n    <link rel=\"stylesheet\" href=\"css/style.css\">\n</head>\n<body>\n    <header>\n    \t<h1 id=\"pageHeader\">21</h1>\n    </header>\n\n    <section>\n    \t<div>\n            <form>\n        \t\t<table>\n                    <tr><td>Title:</td><td><input type=\"text\" id=\"albumTitle\" value=\"21\"></td></tr>\n                    <tr><td>Artist:</td><td><input type=\"text\" id=\"albumArtist\" value=\"Adele\"></td></tr>\n                    <tr>\n                        <td>Year:</td>\n                        <td>\n                            <select id=\"albumYear\">\n                                <option>2011</option>\n                                <option>2012</option>    \n                                <option>2013</option>\n                                <option>2014</option>\n                                <option>2015</option>\n                                <option>2016</option>\n                            </select>\n                        </td>\n                    </tr>\n                    <tr>\n                        <td>Rating:</td>\n                        <td><input type=\"text\" id=\"albumRating\" value=\"A\"></td>\n                    </tr>\n                    <tr>\n                        <td>Number of Songs:</td>\n                        <td><input type=\"number\" id=\"numberOfSongs\" value=\"12\"></td>\n                    </tr>\n                    <tr>\n                        <td><input type=\"submit\" id=\"cancelButton\" value=\"Cancel\"></td>\n                        <td><input type=\"submit\" id=\"saveButton\" value=\"Save\"></td>\n                    </tr>\n                </table>\n            </form>    \n    \t</div>\n    </section>\n\n</body>\n</html>"
  },
  {
    "path": "page-object/src/main/resources/sample-ui/css/album-list.css",
    "content": "/**\n * The MIT License\n * Copyright © 2014-2021 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n<!--\n\n    The MIT License\n    Copyright (c) 2014-2016 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\ntable {\n    font-size: 16px;\n    border-collapse: collapse;\n}\n\nth {\n    background-color: #FFFFFF;\n    border: 1px solid black;\n    color: black;\n    width: 150px;\n    height: 20px;\n}\n\ntd {\n    border: 1px solid black;\n    background-color: white;\n}\n\nth, td {\n    padding: 15px;\n    text-align: left;\n}"
  },
  {
    "path": "page-object/src/main/resources/sample-ui/css/style.css",
    "content": "/**\n * The MIT License\n * Copyright © 2014-2021 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n<!--\n\n    The MIT License\n    Copyright (c) 2014-2016 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\nbody {\n    font-family: \"Trebuchet MS\", Arial, Helvetica, sans-serif;\n}"
  },
  {
    "path": "page-object/src/main/resources/sample-ui/login.html",
    "content": "<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Login</title>\n    <link rel=\"stylesheet\" href=\"css/style.css\">\n</head>\n<body>\n<header>\n    <h1>Login</h1>\n</header>\n\n<section>\n    <form method=\"post\" action=\"album-list.html\">\n        <table>\n            <tr><td>Username:</td><td><input type=\"text\" id=\"username\"></td></tr>\n            <tr><td>Password:</td><td><input type=\"password\" id=\"password\"></td></tr>\n            <tr><td><input type=\"submit\" id=\"loginButton\" value=\"Login\"></td></tr>\n        </table>\n\n    </form>\n</section>\n</body>\n</html>"
  },
  {
    "path": "page-object/src/test/java/com/iluwatar/pageobject/AlbumListPageTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.pageobject.pages.AlbumListPage;\nimport org.htmlunit.WebClient;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Test Album Selection and Album Listing */\nclass AlbumListPageTest {\n\n  private final AlbumListPage albumListPage = new AlbumListPage(new WebClient());\n\n  @BeforeEach\n  void setUp() {\n    albumListPage.navigateToPage();\n  }\n\n  @Test\n  void testSelectAlbum() {\n    var albumPage = albumListPage.selectAlbum(\"21\");\n    albumPage.navigateToPage();\n    assertTrue(albumPage.isAt());\n  }\n}\n"
  },
  {
    "path": "page-object/src/test/java/com/iluwatar/pageobject/AlbumPageTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.pageobject.pages.AlbumPage;\nimport org.htmlunit.WebClient;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Test Album Page Operations */\nclass AlbumPageTest {\n\n  private final AlbumPage albumPage = new AlbumPage(new WebClient());\n\n  @BeforeEach\n  void setUp() {\n    albumPage.navigateToPage();\n  }\n\n  @Test\n  void testSaveAlbum() {\n\n    var albumPageAfterChanges =\n        albumPage\n            .changeAlbumTitle(\"25\")\n            .changeArtist(\"Adele Laurie Blue Adkins\")\n            .changeAlbumYear(2015)\n            .changeAlbumRating(\"B\")\n            .changeNumberOfSongs(20)\n            .saveChanges();\n\n    assertTrue(albumPageAfterChanges.isAt());\n  }\n\n  @Test\n  void testCancelChanges() {\n    var albumListPage = albumPage.cancelChanges();\n    albumListPage.navigateToPage();\n    assertTrue(albumListPage.isAt());\n  }\n}\n"
  },
  {
    "path": "page-object/src/test/java/com/iluwatar/pageobject/LoginPageTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.pageobject.pages.LoginPage;\nimport org.htmlunit.WebClient;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Test Login Page Object */\nclass LoginPageTest {\n\n  private final LoginPage loginPage = new LoginPage(new WebClient());\n\n  @BeforeEach\n  void setUp() {\n    loginPage.navigateToPage();\n  }\n\n  @Test\n  void testLogin() {\n    var albumListPage = loginPage.enterUsername(\"admin\").enterPassword(\"password\").login();\n    albumListPage.navigateToPage();\n    assertTrue(albumListPage.isAt());\n  }\n}\n"
  },
  {
    "path": "page-object/src/test/java/com/iluwatar/pageobject/pages/AlbumListPage.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject.pages;\n\nimport java.io.IOException;\nimport java.util.List;\nimport org.htmlunit.WebClient;\nimport org.htmlunit.html.HtmlAnchor;\nimport org.htmlunit.html.HtmlPage;\n\n/** Page Object encapsulating the Album List page (album-list.html) */\npublic class AlbumListPage extends Page {\n\n  private static final String ALBUM_LIST_HTML_FILE = \"album-list.html\";\n  private static final String PAGE_URL = \"file:\" + AUT_PATH + ALBUM_LIST_HTML_FILE;\n\n  private HtmlPage page;\n\n  /** Constructor */\n  public AlbumListPage(WebClient webClient) {\n    super(webClient);\n  }\n\n  /**\n   * Navigates to the Album List Page\n   *\n   * @return {@link AlbumListPage}\n   */\n  public AlbumListPage navigateToPage() {\n    try {\n      page = this.webClient.getPage(PAGE_URL);\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n    return this;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public boolean isAt() {\n    return \"Album List\".equals(page.getTitleText());\n  }\n\n  /**\n   * Selects an album by the given album title\n   *\n   * @param albumTitle the title of the album to click\n   * @return the album page\n   */\n  public AlbumPage selectAlbum(String albumTitle) {\n    // uses XPath to find list of html anchor tags with the class album in it\n    var albumLinks = (List<HtmlAnchor>) page.getByXPath(\"//tr[@class='album']//a\");\n    for (var anchor : albumLinks) {\n      if (anchor.getTextContent().equals(albumTitle)) {\n        try {\n          anchor.click();\n          return new AlbumPage(webClient);\n        } catch (IOException e) {\n          e.printStackTrace();\n        }\n      }\n    }\n    throw new IllegalArgumentException(\"No links with the album title: \" + albumTitle);\n  }\n}\n"
  },
  {
    "path": "page-object/src/test/java/com/iluwatar/pageobject/pages/AlbumPage.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject.pages;\n\nimport java.io.IOException;\nimport org.htmlunit.WebClient;\nimport org.htmlunit.html.HtmlNumberInput;\nimport org.htmlunit.html.HtmlPage;\nimport org.htmlunit.html.HtmlSelect;\nimport org.htmlunit.html.HtmlSubmitInput;\nimport org.htmlunit.html.HtmlTextInput;\n\n/** Page Object encapsulating the Album Page (album-page.html) */\npublic class AlbumPage extends Page {\n\n  private static final String ALBUM_PAGE_HTML_FILE = \"album-page.html\";\n  private static final String PAGE_URL = \"file:\" + AUT_PATH + ALBUM_PAGE_HTML_FILE;\n\n  private HtmlPage page;\n\n  /** Constructor */\n  public AlbumPage(WebClient webClient) {\n    super(webClient);\n  }\n\n  /**\n   * Navigates to the album page\n   *\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage navigateToPage() {\n    try {\n      page = this.webClient.getPage(PAGE_URL);\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n    return this;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public boolean isAt() {\n    return \"Album Page\".equals(page.getTitleText());\n  }\n\n  /**\n   * Sets the album title input text field\n   *\n   * @param albumTitle the new album title value to set\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage changeAlbumTitle(String albumTitle) {\n    var albumTitleInputTextField = (HtmlTextInput) page.getElementById(\"albumTitle\");\n    albumTitleInputTextField.setText(albumTitle);\n    return this;\n  }\n\n  /**\n   * Sets the artist input text field\n   *\n   * @param artist the new artist value to set\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage changeArtist(String artist) {\n    var artistInputTextField = (HtmlTextInput) page.getElementById(\"albumArtist\");\n    artistInputTextField.setText(artist);\n    return this;\n  }\n\n  /**\n   * Selects the select's option value based on the year value given\n   *\n   * @param year the new year value to set\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage changeAlbumYear(int year) {\n    var albumYearSelectOption = (HtmlSelect) page.getElementById(\"albumYear\");\n    var yearOption = albumYearSelectOption.getOptionByValue(Integer.toString(year));\n    albumYearSelectOption.setSelectedAttribute(yearOption, true);\n    return this;\n  }\n\n  /**\n   * Sets the album rating input text field\n   *\n   * @param albumRating the new album rating value to set\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage changeAlbumRating(String albumRating) {\n    var albumRatingInputTextField = (HtmlTextInput) page.getElementById(\"albumRating\");\n    albumRatingInputTextField.setText(albumRating);\n    return this;\n  }\n\n  /**\n   * Sets the number of songs number input field\n   *\n   * @param numberOfSongs the new number of songs value to be set\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage changeNumberOfSongs(int numberOfSongs) {\n    var numberOfSongsNumberField = (HtmlNumberInput) page.getElementById(\"numberOfSongs\");\n    numberOfSongsNumberField.setText(Integer.toString(numberOfSongs));\n    return this;\n  }\n\n  /**\n   * Cancel changes made by clicking the cancel button\n   *\n   * @return {@link AlbumListPage}\n   */\n  public AlbumListPage cancelChanges() {\n    var cancelButton = (HtmlSubmitInput) page.getElementById(\"cancelButton\");\n    try {\n      cancelButton.click();\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n    return new AlbumListPage(webClient);\n  }\n\n  /**\n   * Saves changes made by clicking the save button\n   *\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage saveChanges() {\n    var saveButton = (HtmlSubmitInput) page.getElementById(\"saveButton\");\n    try {\n      saveButton.click();\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n    return this;\n  }\n}\n"
  },
  {
    "path": "page-object/src/test/java/com/iluwatar/pageobject/pages/LoginPage.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject.pages;\n\nimport java.io.IOException;\nimport org.htmlunit.WebClient;\nimport org.htmlunit.html.HtmlPage;\nimport org.htmlunit.html.HtmlPasswordInput;\nimport org.htmlunit.html.HtmlSubmitInput;\nimport org.htmlunit.html.HtmlTextInput;\n\n/** Page Object encapsulating the Login Page (login.html) */\npublic class LoginPage extends Page {\n\n  private static final String LOGIN_PAGE_HTML_FILE = \"login.html\";\n  private static final String PAGE_URL = \"file:\" + AUT_PATH + LOGIN_PAGE_HTML_FILE;\n\n  private HtmlPage page;\n\n  /**\n   * Constructor\n   *\n   * @param webClient {@link WebClient}\n   */\n  public LoginPage(WebClient webClient) {\n    super(webClient);\n  }\n\n  /**\n   * Navigates to the Login page\n   *\n   * @return {@link LoginPage}\n   */\n  public LoginPage navigateToPage() {\n    try {\n      page = this.webClient.getPage(PAGE_URL);\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n    return this;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public boolean isAt() {\n    return \"Login\".equals(page.getTitleText());\n  }\n\n  /**\n   * Enters the username into the username input text field\n   *\n   * @param username the username to enter\n   * @return {@link LoginPage}\n   */\n  public LoginPage enterUsername(String username) {\n    var usernameInputTextField = (HtmlTextInput) page.getElementById(\"username\");\n    usernameInputTextField.setText(username);\n    return this;\n  }\n\n  /**\n   * Enters the password into the password input password field\n   *\n   * @param password the password to enter\n   * @return {@link LoginPage}\n   */\n  public LoginPage enterPassword(String password) {\n    var passwordInputPasswordField = (HtmlPasswordInput) page.getElementById(\"password\");\n    passwordInputPasswordField.setText(password);\n    return this;\n  }\n\n  /**\n   * Clicking on the login button to 'login'\n   *\n   * @return {@link AlbumListPage} - this is the page that user gets navigated to once successfully\n   *     logged in\n   */\n  public AlbumListPage login() {\n    var loginButton = (HtmlSubmitInput) page.getElementById(\"loginButton\");\n    try {\n      loginButton.click();\n    } catch (IOException e) {\n      e.printStackTrace();\n    }\n    return new AlbumListPage(webClient);\n  }\n}\n"
  },
  {
    "path": "page-object/src/test/java/com/iluwatar/pageobject/pages/Page.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject.pages;\n\nimport org.htmlunit.WebClient;\n\n/** Encapsulation for a generic 'Page' */\npublic abstract class Page {\n\n  /** Application Under Test path This directory location is where html web pages are located */\n  public static final String AUT_PATH = \"src/main/resources/sample-ui/\";\n\n  protected final WebClient webClient;\n\n  /**\n   * Constructor\n   *\n   * @param webClient {@link WebClient}\n   */\n  public Page(WebClient webClient) {\n    this.webClient = webClient;\n  }\n\n  /**\n   * Checks that the current page is actually the page this page object represents\n   *\n   * @return true if so, otherwise false\n   */\n  public abstract boolean isAt();\n}\n"
  },
  {
    "path": "page-object/test-automation/etc/test-automation.urm.puml",
    "content": "@startuml\npackage com.iluwatar.pageobject {\n  class AlbumListPage {\n    - ALBUM_LIST_HTML_FILE : String {static}\n    - LOGGER : Logger {static}\n    - PAGE_URL : String {static}\n    - page : HtmlPage\n    + AlbumListPage(webClient : WebClient)\n    + isAt() : boolean\n    + navigateToPage() : AlbumListPage\n    + selectAlbum(albumTitle : String) : AlbumPage\n  }\n  class AlbumPage {\n    - ALBUM_PAGE_HTML_FILE : String {static}\n    - LOGGER : Logger {static}\n    - PAGE_URL : String {static}\n    - page : HtmlPage\n    + AlbumPage(webClient : WebClient)\n    + cancelChanges() : AlbumListPage\n    + changeAlbumRating(albumRating : String) : AlbumPage\n    + changeAlbumTitle(albumTitle : String) : AlbumPage\n    + changeAlbumYear(year : int) : AlbumPage\n    + changeArtist(artist : String) : AlbumPage\n    + changeNumberOfSongs(numberOfSongs : int) : AlbumPage\n    + isAt() : boolean\n    + navigateToPage() : AlbumPage\n    + saveChanges() : AlbumPage\n  }\n  class LoginPage {\n    - LOGGER : Logger {static}\n    - LOGIN_PAGE_HTML_FILE : String {static}\n    - PAGE_URL : String {static}\n    - page : HtmlPage\n    + LoginPage(webClient : WebClient)\n    + enterPassword(password : String) : LoginPage\n    + enterUsername(username : String) : LoginPage\n    + isAt() : boolean\n    + login() : AlbumListPage\n    + navigateToPage() : LoginPage\n  }\n  abstract class Page {\n    + AUT_PATH : String {static}\n    # webClient : WebClient\n    + Page(webClient : WebClient)\n    + isAt() : boolean {abstract}\n  }\n}\nAlbumListPage --|> Page \nAlbumPage --|> Page \nLoginPage --|> Page \n@enduml"
  },
  {
    "path": "page-object/test-automation/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <artifactId>page-object</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>test-automation</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.htmlunit</groupId>\n      <artifactId>htmlunit</artifactId>\n    </dependency>\n  </dependencies>\n</project>\n"
  },
  {
    "path": "page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumListPage.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject;\n\nimport java.io.IOException;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\nimport org.htmlunit.WebClient;\nimport org.htmlunit.html.HtmlAnchor;\nimport org.htmlunit.html.HtmlPage;\n\n/** Page Object encapsulating the Album List page (album-list.html) */\n@Slf4j\npublic class AlbumListPage extends Page {\n  private static final String ALBUM_LIST_HTML_FILE = \"album-list.html\";\n  private static final String PAGE_URL = \"file:\" + AUT_PATH + ALBUM_LIST_HTML_FILE;\n\n  private HtmlPage page;\n\n  /** Constructor. */\n  public AlbumListPage(WebClient webClient) {\n    super(webClient);\n  }\n\n  /**\n   * Navigates to the Album List Page.\n   *\n   * @return {@link AlbumListPage}\n   */\n  public AlbumListPage navigateToPage() {\n    try {\n      page = this.webClient.getPage(PAGE_URL);\n    } catch (IOException e) {\n      LOGGER.error(\"An error occurred on navigateToPage.\", e);\n    }\n    return this;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public boolean isAt() {\n    return \"Album List\".equals(page.getTitleText());\n  }\n\n  /**\n   * Selects an album by the given album title.\n   *\n   * @param albumTitle the title of the album to click\n   * @return the album page\n   */\n  public AlbumPage selectAlbum(String albumTitle) {\n    // uses XPath to find list of html anchor tags with the class album in it\n    var albumLinks = (List<Object>) page.getByXPath(\"//tr[@class='album']//a\");\n    for (var anchor : albumLinks) {\n      if (((HtmlAnchor) anchor).getTextContent().equals(albumTitle)) {\n        try {\n          ((HtmlAnchor) anchor).click();\n          return new AlbumPage(webClient);\n        } catch (IOException e) {\n          LOGGER.error(\"An error occurred on selectAlbum\", e);\n        }\n      }\n    }\n    throw new IllegalArgumentException(\"No links with the album title: \" + albumTitle);\n  }\n}\n"
  },
  {
    "path": "page-object/test-automation/src/main/java/com/iluwatar/pageobject/AlbumPage.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject;\n\nimport java.io.IOException;\nimport lombok.extern.slf4j.Slf4j;\nimport org.htmlunit.WebClient;\nimport org.htmlunit.html.HtmlNumberInput;\nimport org.htmlunit.html.HtmlPage;\nimport org.htmlunit.html.HtmlSelect;\nimport org.htmlunit.html.HtmlSubmitInput;\nimport org.htmlunit.html.HtmlTextInput;\n\n/** Page Object encapsulating the Album Page (album-page.html) */\n@Slf4j\npublic class AlbumPage extends Page {\n  private static final String ALBUM_PAGE_HTML_FILE = \"album-page.html\";\n  private static final String PAGE_URL = \"file:\" + AUT_PATH + ALBUM_PAGE_HTML_FILE;\n\n  private HtmlPage page;\n\n  /** Constructor. */\n  public AlbumPage(WebClient webClient) {\n    super(webClient);\n  }\n\n  /**\n   * Navigates to the album page.\n   *\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage navigateToPage() {\n    try {\n      page = this.webClient.getPage(PAGE_URL);\n    } catch (IOException e) {\n      LOGGER.error(\"An error occurred on navigateToPage.\", e);\n    }\n    return this;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public boolean isAt() {\n    return \"Album Page\".equals(page.getTitleText());\n  }\n\n  /**\n   * Sets the album title input text field.\n   *\n   * @param albumTitle the new album title value to set\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage changeAlbumTitle(String albumTitle) {\n    var albumTitleInputTextField = (HtmlTextInput) page.getElementById(\"albumTitle\");\n    albumTitleInputTextField.setText(albumTitle);\n    return this;\n  }\n\n  /**\n   * Sets the artist input text field.\n   *\n   * @param artist the new artist value to set\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage changeArtist(String artist) {\n    var artistInputTextField = (HtmlTextInput) page.getElementById(\"albumArtist\");\n    artistInputTextField.setText(artist);\n    return this;\n  }\n\n  /**\n   * Selects the select's option value based on the year value given.\n   *\n   * @param year the new year value to set\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage changeAlbumYear(int year) {\n    var albumYearSelectOption = (HtmlSelect) page.getElementById(\"albumYear\");\n    var yearOption = albumYearSelectOption.getOptionByValue(Integer.toString(year));\n    albumYearSelectOption.setSelectedAttribute(yearOption, true);\n    return this;\n  }\n\n  /**\n   * Sets the album rating input text field.\n   *\n   * @param albumRating the new album rating value to set\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage changeAlbumRating(String albumRating) {\n    var albumRatingInputTextField = (HtmlTextInput) page.getElementById(\"albumRating\");\n    albumRatingInputTextField.setText(albumRating);\n    return this;\n  }\n\n  /**\n   * Sets the number of songs number input field.\n   *\n   * @param numberOfSongs the new number of songs value to be set\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage changeNumberOfSongs(int numberOfSongs) {\n    var numberOfSongsNumberField = (HtmlNumberInput) page.getElementById(\"numberOfSongs\");\n    numberOfSongsNumberField.setText(Integer.toString(numberOfSongs));\n    return this;\n  }\n\n  /**\n   * Cancel changes made by clicking the cancel button.\n   *\n   * @return {@link AlbumListPage}\n   */\n  public AlbumListPage cancelChanges() {\n    var cancelButton = (HtmlSubmitInput) page.getElementById(\"cancelButton\");\n    try {\n      cancelButton.click();\n    } catch (IOException e) {\n      LOGGER.error(\"An error occurred on cancelChanges.\", e);\n    }\n    return new AlbumListPage(webClient);\n  }\n\n  /**\n   * Saves changes made by clicking the save button.\n   *\n   * @return {@link AlbumPage}\n   */\n  public AlbumPage saveChanges() {\n    var saveButton = (HtmlSubmitInput) page.getElementById(\"saveButton\");\n    try {\n      saveButton.click();\n    } catch (IOException e) {\n      LOGGER.error(\"An error occurred on saveChanges.\", e);\n    }\n    return this;\n  }\n}\n"
  },
  {
    "path": "page-object/test-automation/src/main/java/com/iluwatar/pageobject/LoginPage.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject;\n\nimport java.io.IOException;\nimport lombok.extern.slf4j.Slf4j;\nimport org.htmlunit.WebClient;\nimport org.htmlunit.html.HtmlPage;\nimport org.htmlunit.html.HtmlPasswordInput;\nimport org.htmlunit.html.HtmlSubmitInput;\nimport org.htmlunit.html.HtmlTextInput;\n\n/** Page Object encapsulating the Login Page (login.html) */\n@Slf4j\npublic class LoginPage extends Page {\n  private static final String LOGIN_PAGE_HTML_FILE = \"login.html\";\n  private static final String PAGE_URL = \"file:\" + AUT_PATH + LOGIN_PAGE_HTML_FILE;\n\n  private HtmlPage page;\n\n  /**\n   * Constructor.\n   *\n   * @param webClient {@link WebClient}\n   */\n  public LoginPage(WebClient webClient) {\n    super(webClient);\n  }\n\n  /**\n   * Navigates to the Login page.\n   *\n   * @return {@link LoginPage}\n   */\n  public LoginPage navigateToPage() {\n    try {\n      page = this.webClient.getPage(PAGE_URL);\n    } catch (IOException e) {\n      LOGGER.error(\"An error occurred on navigateToPage.\", e);\n    }\n    return this;\n  }\n\n  /** {@inheritDoc} */\n  @Override\n  public boolean isAt() {\n    return \"Login\".equals(page.getTitleText());\n  }\n\n  /**\n   * Enters the username into the username input text field.\n   *\n   * @param username the username to enter\n   * @return {@link LoginPage}\n   */\n  public LoginPage enterUsername(String username) {\n    var usernameInputTextField = (HtmlTextInput) page.getElementById(\"username\");\n    usernameInputTextField.setText(username);\n    return this;\n  }\n\n  /**\n   * Enters the password into the password input password field.\n   *\n   * @param password the password to enter\n   * @return {@link LoginPage}\n   */\n  public LoginPage enterPassword(String password) {\n    var passwordInputPasswordField = (HtmlPasswordInput) page.getElementById(\"password\");\n    passwordInputPasswordField.setText(password);\n    return this;\n  }\n\n  /**\n   * Clicking on the login button to 'login'.\n   *\n   * @return {@link AlbumListPage} - this is the page that user gets navigated to once successfully\n   *     logged in\n   */\n  public AlbumListPage login() {\n    var loginButton = (HtmlSubmitInput) page.getElementById(\"loginButton\");\n    try {\n      loginButton.click();\n    } catch (IOException e) {\n      LOGGER.error(\"An error occurred on login.\", e);\n    }\n    return new AlbumListPage(webClient);\n  }\n}\n"
  },
  {
    "path": "page-object/test-automation/src/main/java/com/iluwatar/pageobject/Page.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject;\n\nimport org.htmlunit.WebClient;\n\n/** Encapsulation for a generic 'Page'. */\npublic abstract class Page {\n\n  /** Application Under Test path This directory location is where html web pages are located. */\n  public static final String AUT_PATH = \"../sample-application/src/main/resources/sample-ui/\";\n\n  protected final WebClient webClient;\n\n  /**\n   * Constructor.\n   *\n   * @param webClient {@link WebClient}\n   */\n  public Page(WebClient webClient) {\n    this.webClient = webClient;\n  }\n\n  /**\n   * Checks that the current page is actually the page this page object represents.\n   *\n   * @return true if so, otherwise false\n   */\n  public abstract boolean isAt();\n}\n"
  },
  {
    "path": "page-object/test-automation/src/test/java/com/iluwatar/pageobject/AlbumListPageTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.htmlunit.WebClient;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Test Album Selection and Album Listing */\nclass AlbumListPageTest {\n\n  private final AlbumListPage albumListPage = new AlbumListPage(new WebClient());\n\n  @BeforeEach\n  void setUp() {\n    albumListPage.navigateToPage();\n  }\n\n  @Test\n  void testSelectAlbum() {\n    var albumPage = albumListPage.selectAlbum(\"21\");\n    albumPage.navigateToPage();\n    assertTrue(albumPage.isAt());\n  }\n}\n"
  },
  {
    "path": "page-object/test-automation/src/test/java/com/iluwatar/pageobject/AlbumPageTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.htmlunit.WebClient;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Test Album Page Operations */\nclass AlbumPageTest {\n\n  private final AlbumPage albumPage = new AlbumPage(new WebClient());\n\n  @BeforeEach\n  void setUp() {\n    albumPage.navigateToPage();\n  }\n\n  @Test\n  void testSaveAlbum() {\n\n    var albumPageAfterChanges =\n        albumPage\n            .changeAlbumTitle(\"25\")\n            .changeArtist(\"Adele Laurie Blue Adkins\")\n            .changeAlbumYear(2015)\n            .changeAlbumRating(\"B\")\n            .changeNumberOfSongs(20)\n            .saveChanges();\n\n    assertTrue(albumPageAfterChanges.isAt());\n  }\n\n  @Test\n  void testCancelChanges() {\n    var albumListPage = albumPage.cancelChanges();\n    albumListPage.navigateToPage();\n    assertTrue(albumListPage.isAt());\n  }\n}\n"
  },
  {
    "path": "page-object/test-automation/src/test/java/com/iluwatar/pageobject/LoginPageTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pageobject;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.htmlunit.WebClient;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Test Login Page Object */\nclass LoginPageTest {\n\n  private final LoginPage loginPage = new LoginPage(new WebClient());\n\n  @BeforeEach\n  void setUp() {\n    loginPage.navigateToPage();\n  }\n\n  @Test\n  void testLogin() {\n    var albumListPage = loginPage.enterUsername(\"admin\").enterPassword(\"password\").login();\n    albumListPage.navigateToPage();\n    assertTrue(albumListPage.isAt());\n  }\n}\n"
  },
  {
    "path": "parameter-object/README.md",
    "content": "---\ntitle: \"Parameter Object Pattern in Java: Simplifying Method Signatures with Structured Data\"\nshortTitle: Parameter Object\ndescription: \"Explore the Parameter Object pattern at Java Design Patterns. Learn how it simplifies method signatures, enhances maintainability, and promotes encapsulation with real-world examples and detailed code snippets.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Abstraction\n  - Code simplification\n  - Decoupling\n  - Encapsulation\n  - Object composition\n---\n\n## Also known as\n\n* Argument Object\n\n## Intent of Parameter Object Design Pattern\n\nThe Parameter Object pattern is a key Java design pattern aimed at improving code maintainability by reducing method complexity through encapsulation of parameters into a single object.\n\n## Detailed Explanation of Parameter Object Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine booking a travel package that includes a flight, hotel, and car rental. Instead of asking the customer to provide separate details for each component (flight details, hotel details, and car rental details) every time, a travel agent asks the customer to fill out a single comprehensive form that encapsulates all the necessary information:\n>\n> - Flight details: Departure city, destination city, departure date, return date.\n> - Hotel details: Hotel name, check-in date, check-out date, room type.\n> - Car rental details: Pickup location, drop-off location, rental dates, car type.\n> \n> In this analogy, the comprehensive form is the parameter object. It groups together all related details (parameters) into a single entity, making the booking process more streamlined and manageable. The travel agent (method) only needs to handle one form (parameter object) instead of juggling multiple pieces of information.\n\nIn plain words\n\n> The Parameter Object pattern encapsulates multiple related parameters into a single object to simplify method signatures and enhance code maintainability.\n\nwiki.c2.com says\n\n> Replace the LongParameterList with a ParameterObject; an object or structure with data members representing the arguments to be passed in.\n\nMind map\n\n![Parameter Object mind map](./etc/parameter-object-mind-map.png)\n\nFlowchart\n\n![Parameter Object flowchart](./etc/parameter-object-flowchart.png)\n\n## Programmatic Example of Parameter Object Pattern in Java\n\nThe Parameter Object design pattern is a way to group multiple parameters into a single object. This simplifies method signatures and enhances code maintainability enabling Java developers to streamline complex method calls, focusing on cleaner and more maintainable Java code.\n\nFirst, let's look at the `ParameterObject` class. This class encapsulates the parameters needed for the search operation. It uses [Builder pattern](https://java-design-patterns.com/patterns/builder/) to allow for easy creation of objects, even when there are many parameters.\n\n```java\npublic class ParameterObject {\n\n    private final String type;\n    private final String sortBy;\n    private final SortOrder sortOrder;\n\n    private ParameterObject(Builder builder) {\n        this.type = builder.type;\n        this.sortBy = builder.sortBy;\n        this.sortOrder = builder.sortOrder;\n    }\n\n    public static Builder newBuilder() {\n        return new Builder();\n    }\n\n    // getters and Builder class omitted for brevity\n}\n```\n\nThe `Builder` class inside `ParameterObject` provides a way to construct a `ParameterObject` instance. It has methods for setting each of the parameters, and a `build` method to create the `ParameterObject`.\n\n```java\npublic static class Builder {\n\n    private String type = \"all\";\n    private String sortBy = \"price\";\n    private SortOrder sortOrder = SortOrder.ASCENDING;\n\n    public Builder withType(String type) {\n        this.type = type;\n        return this;\n    }\n\n    public Builder sortBy(String sortBy) {\n        this.sortBy = sortBy;\n        return this;\n    }\n\n    public Builder sortOrder(SortOrder sortOrder) {\n        this.sortOrder = sortOrder;\n        return this;\n    }\n\n    public ParameterObject build() {\n        return new ParameterObject(this);\n    }\n}\n```\n\nThe `SearchService` class has a `search()` method that takes a `ParameterObject` as a parameter. This method uses the parameters encapsulated in the `ParameterObject` to perform a search operation.\n\n```java\npublic class SearchService {\n\n    public String search(ParameterObject parameterObject) {\n        return getQuerySummary(parameterObject.getType(), parameterObject.getSortBy(),\n                parameterObject.getSortOrder());\n    }\n\n    // getQuerySummary method omitted for brevity\n}\n```\n\nFinally, in the `App` class, we create a `ParameterObject` using its builder, and then pass it to the `search()` method of `SearchService`.\n\n```java\npublic class App {\n\n    public static void main(String[] args) {\n        ParameterObject params = ParameterObject.newBuilder()\n                .withType(\"sneakers\")\n                .sortBy(\"brand\")\n                .build();\n        LOGGER.info(params.toString());\n        LOGGER.info(new SearchService().search(params));\n    }\n}\n```\n\nThis example demonstrates how the Parameter Object pattern can simplify method signatures and make the code more maintainable. It also shows how the pattern can be combined with the Builder pattern to make object creation more flexible and readable.\n\n## When to Use the Parameter Object Pattern in Java\n\n* Methods require multiple parameters that logically belong together.\n* There is a need to reduce the complexity of method signatures.\n* The parameters may need to evolve over time, adding more properties without breaking existing method signatures.\n* It’s beneficial to pass data through a method chain.\n\n## Parameter Object Pattern Java Tutorials\n\n* [Does Java have default parameters? (Daniel Olszewski)](http://dolszewski.com/java/java-default-parameters)\n\n## Real-World Applications of Parameter Object Pattern in Java\n\n* Java Libraries: Many Java frameworks and libraries use this pattern. For example, Java’s java.util.Calendar class has various methods where parameter objects are used to represent date and time components.\n* Enterprise Applications: In large enterprise systems, parameter objects are used to encapsulate configuration data passed to services or API endpoints.\n\n## Benefits and Trade-offs of Parameter Object Pattern\n\nBenefits:\n\n* Encapsulation: Groups related parameters into a single object, promoting encapsulation.\n* Maintainability: Reduces method signature changes when parameters need to be added or modified.\n* Readability: Simplifies method signatures, making the code easier to read and understand.\n* Reusability: Parameter objects can be reused across different methods, reducing redundancy.\n\nTrade-offs:\n\n* Overhead: Introducing parameter objects can add some overhead, especially for simple methods that do not benefit significantly from this abstraction.\n* Complexity: The initial creation of parameter objects might add complexity, especially for beginners.\n\n## Related Patterns\n\n* [Builder](https://java-design-patterns.com/patterns/builder/): Helps in creating complex objects step-by-step, often used in conjunction with parameter objects to manage the construction of these objects.\n* [Composite](https://java-design-patterns.com/patterns/composite/): Sometimes used with parameter objects to handle hierarchical parameter data.\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Can be used to create instances of parameter objects, particularly when different parameter combinations are needed.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Refactoring: Improving the Design of Existing Code](https://amzn.to/3TVEgaB)\n"
  },
  {
    "path": "parameter-object/etc/parameter-object.urm.puml",
    "content": "@startuml\npackage com.iluwatar.parameter.object {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class ParameterObject {\n    + DEFAULT_SORT_BY : String {static}\n    + DEFAULT_SORT_ORDER : SortOrder {static}\n    - sortBy : String\n    - sortOrder : SortOrder\n    - type : String\n    - ParameterObject(builder : Builder)\n    + getSortBy() : String\n    + getSortOrder() : SortOrder\n    + getType() : String\n    + newBuilder() : Builder {static}\n    + setSortBy(sortBy : String)\n    + setSortOrder(sortOrder : SortOrder)\n    + setType(type : String)\n  }\n  class Builder {\n    - sortBy : String\n    - sortOrder : SortOrder\n    - type : String\n    - Builder()\n    + build() : ParameterObject\n    + sortBy(sortBy : String) : Builder\n    + sortOrder(sortOrder : SortOrder) : Builder\n    + withType(type : String) : Builder\n  }\n  class SearchService {\n    + SearchService()\n    - getQuerySummary(type : String, sortBy : String, sortOrder : SortOrder) : String\n    + search(parameterObject : ParameterObject) : String\n    + search(type : String, sortBy : String) : String\n    + search(type : String, sortOrder : SortOrder) : String\n  }\n  enum SortOrder {\n    + ASC {static}\n    + DESC {static}\n    - value : String\n    + getValue() : String\n    + valueOf(name : String) : SortOrder {static}\n    + values() : SortOrder[] {static}\n  }\n}\nBuilder -->  \"-sortOrder\" SortOrder\nBuilder ..+ ParameterObject\nParameterObject -->  \"-DEFAULT_SORT_ORDER\" SortOrder\n@enduml\n"
  },
  {
    "path": "parameter-object/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>parameter-object</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.parameter.object.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "parameter-object/src/main/java/com/iluwatar/parameter/object/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.parameter.object;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * The syntax of Java language doesn’t allow you to declare a method with a predefined value for a\n * parameter. Probably the best option to achieve default method parameters in Java is by using the\n * method overloading. Method overloading allows you to declare several methods with the same name\n * but with a different number of parameters. But the main problem with method overloading as a\n * solution for default parameter values reveals itself when a method accepts multiple parameters.\n * Creating an overloaded method for each possible combination of parameters might be cumbersome. To\n * deal with this issue, the Parameter Object pattern is used. The Parameter Object is simply a\n * wrapper object for all parameters of a method. It is nothing more than just a regular POJO. The\n * advantage of the Parameter Object over a regular method parameter list is the fact that class\n * fields can have default values. Once the wrapper class is created for the method parameter list,\n * a corresponding builder class is also created. Usually it's an inner static class. The final step\n * is to use the builder to construct a new parameter object. For those parameters that are skipped,\n * their default values are going to be used.\n */\npublic class App {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    ParameterObject params =\n        ParameterObject.newBuilder().withType(\"sneakers\").sortBy(\"brand\").build();\n    LOGGER.info(params.toString());\n    LOGGER.info(new SearchService().search(params));\n  }\n}\n"
  },
  {
    "path": "parameter-object/src/main/java/com/iluwatar/parameter/object/ParameterObject.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.parameter.object;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** ParameterObject. */\n@Getter\n@Setter\npublic class ParameterObject {\n\n  /** Default values are defined here. */\n  public static final String DEFAULT_SORT_BY = \"price\";\n\n  public static final SortOrder DEFAULT_SORT_ORDER = SortOrder.ASC;\n\n  private String type;\n\n  /** Default values are assigned here. */\n  private String sortBy = DEFAULT_SORT_BY;\n\n  private SortOrder sortOrder = DEFAULT_SORT_ORDER;\n\n  /** Overriding default values on object creation only when builder object has a valid value. */\n  private ParameterObject(Builder builder) {\n    setType(builder.type);\n    setSortBy(builder.sortBy != null && !builder.sortBy.isBlank() ? builder.sortBy : sortBy);\n    setSortOrder(builder.sortOrder != null ? builder.sortOrder : sortOrder);\n  }\n\n  public static Builder newBuilder() {\n    return new Builder();\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\n        \"ParameterObject[type='%s', sortBy='%s', sortOrder='%s']\", type, sortBy, sortOrder);\n  }\n\n  /** Builder for ParameterObject. */\n  public static final class Builder {\n\n    private String type;\n    private String sortBy;\n    private SortOrder sortOrder;\n\n    private Builder() {}\n\n    public Builder withType(String type) {\n      this.type = type;\n      return this;\n    }\n\n    public Builder sortBy(String sortBy) {\n      this.sortBy = sortBy;\n      return this;\n    }\n\n    public Builder sortOrder(SortOrder sortOrder) {\n      this.sortOrder = sortOrder;\n      return this;\n    }\n\n    public ParameterObject build() {\n      return new ParameterObject(this);\n    }\n  }\n}\n"
  },
  {
    "path": "parameter-object/src/main/java/com/iluwatar/parameter/object/SearchService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.parameter.object;\n\n/** SearchService to demonstrate parameter object pattern. */\npublic class SearchService {\n\n  /**\n   * Below two methods of name `search` is overloaded so that we can send a default value for one of\n   * the criteria and call the final api. A default SortOrder is sent in the first method and a\n   * default SortBy is sent in the second method. So two separate method definitions are needed for\n   * having default values for one argument in each case. Hence, multiple overloaded methods are\n   * needed as the number of argument increases.\n   */\n  public String search(String type, String sortBy) {\n    return getQuerySummary(type, sortBy, SortOrder.ASC);\n  }\n\n  public String search(String type, SortOrder sortOrder) {\n    return getQuerySummary(type, \"price\", sortOrder);\n  }\n\n  /**\n   * The need for multiple method definitions can be avoided by the Parameter Object pattern. Below\n   * is the example where only one method is required and all the logic for having default values\n   * are abstracted into the Parameter Object at the time of object creation.\n   */\n  public String search(ParameterObject parameterObject) {\n    return getQuerySummary(\n        parameterObject.getType(), parameterObject.getSortBy(), parameterObject.getSortOrder());\n  }\n\n  private String getQuerySummary(String type, String sortBy, SortOrder sortOrder) {\n    return String.format(\n        \"Requesting shoes of type \\\"%s\\\" sorted by \\\"%s\\\" in \\\"%sending\\\" order..\",\n        type, sortBy, sortOrder.getValue());\n  }\n}\n"
  },
  {
    "path": "parameter-object/src/main/java/com/iluwatar/parameter/object/SortOrder.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.parameter.object;\n\nimport lombok.Getter;\n\n/** enum for sort order types. */\npublic enum SortOrder {\n  ASC(\"asc\"),\n  DESC(\"desc\");\n\n  @Getter private String value;\n\n  SortOrder(String value) {\n    this.value = value;\n  }\n}\n"
  },
  {
    "path": "parameter-object/src/test/java/com/iluwatar/parameter/object/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.parameter.object;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "parameter-object/src/test/java/com/iluwatar/parameter/object/ParameterObjectTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.parameter.object;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nclass ParameterObjectTest {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(ParameterObjectTest.class);\n\n  @Test\n  void testForDefaultSortBy() {\n    // Creating parameter object with default value for SortBy set\n    ParameterObject params =\n        ParameterObject.newBuilder().withType(\"sneakers\").sortOrder(SortOrder.DESC).build();\n\n    assertEquals(ParameterObject.DEFAULT_SORT_BY, params.getSortBy(), \"Default SortBy is not set.\");\n    LOGGER.info(\n        \"{} Default parameter value is set during object creation as no value is passed.\",\n        \"SortBy\");\n  }\n\n  @Test\n  void testForDefaultSortOrder() {\n    // Creating parameter object with default value for SortOrder set\n    ParameterObject params =\n        ParameterObject.newBuilder().withType(\"sneakers\").sortBy(\"brand\").build();\n\n    assertEquals(\n        ParameterObject.DEFAULT_SORT_ORDER, params.getSortOrder(), \"Default SortOrder is not set.\");\n    LOGGER.info(\n        \"{} Default parameter value is set during object creation as no value is passed.\",\n        \"SortOrder\");\n  }\n}\n"
  },
  {
    "path": "parameter-object/src/test/java/com/iluwatar/parameter/object/SearchServiceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.parameter.object;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nclass SearchServiceTest {\n  private static final Logger LOGGER = LoggerFactory.getLogger(SearchServiceTest.class);\n  private ParameterObject parameterObject;\n  private SearchService searchService;\n\n  @BeforeEach\n  void setUp() {\n    // Creating parameter object with default values set\n    parameterObject = ParameterObject.newBuilder().withType(\"sneakers\").build();\n\n    searchService = new SearchService();\n  }\n\n  /** Testing parameter object against the overloaded method to verify if the behaviour is same. */\n  @Test\n  void testDefaultParametersMatch() {\n    assertEquals(\n        searchService.search(parameterObject),\n        searchService.search(\"sneakers\", SortOrder.ASC),\n        \"Default Parameter values do not not match.\");\n    LOGGER.info(\"SortBy Default parameter value matches.\");\n\n    assertEquals(\n        searchService.search(parameterObject),\n        searchService.search(\"sneakers\", \"price\"),\n        \"Default Parameter values do not not match.\");\n    LOGGER.info(\"SortOrder Default parameter value matches.\");\n\n    LOGGER.info(\"testDefaultParametersMatch executed successfully without errors.\");\n  }\n}\n"
  },
  {
    "path": "partial-response/README.md",
    "content": "---\ntitle: \"Partial Response Pattern in Java: Optimizing Data Delivery for Efficient Web Services\"\nshortTitle: Partial Response\ndescription: \"Explore the Partial Response design pattern for APIs, a strategy to boost performance by allowing clients to process data as soon as it becomes available. Learn how it improves scalability and reduces server load.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - API design\n  - Asynchronous\n  - Client-server\n  - Decoupling\n  - Performance\n  - Scalability\n  - Web development\n---\n\n## Also known as\n\n* Incremental Response\n* Partial Result\n\n## Intent of Partial Response Design Pattern\n\nTo enable an application to return a partial response to a client, improving perceived performance and enabling the client to start processing parts of the data before the entire response is available.\n\n## Detailed Explanation of Partial Response Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a restaurant where a customer orders a multi-course meal. Instead of waiting until all courses are prepared before serving, the restaurant brings out each dish as soon as it's ready. This allows the customer to start enjoying the meal without delay, improves the dining experience, and optimizes the kitchen's workflow by letting them prepare and serve courses incrementally. Similarly, in software, the Partial Response design pattern delivers portions of data as they become available, allowing the client to begin processing immediately and improving overall performance and responsiveness.\n\nIn plain words\n\n> The Partial Response design pattern allows a system to send portions of data to the client as they become available, enabling the client to start processing the data before the complete response is received.\n\nSequence diagram\n\n![Partial Response sequence diagram](./etc/partial-response-sequence-diagram.png)\n\n## Programmatic Example of Partial Response Pattern in Java\n\nThe Partial Response design pattern allows clients to specify which fields of a resource they need. This pattern is useful for reducing the amount of data transferred over the network and allowing clients to start processing data sooner.\n\nThe programmatic example shows a simple video streaming application.\n\n`Video` class represents a video object with several fields.\n\n```java\npublic class Video {\n    private String id;\n    private String title;\n    private String description;\n    private String url;\n\n    // Getters and setters...\n}\n```\n\n`FieldJsonMapper` utility class converts video objects to JSON, including only the requested fields. Method `mapFields` takes a `Video` object and a set of field names. It creates a JSON object including only the specified fields. The `ObjectMapper` from Jackson library is used to build the JSON object.\n\n```java\npublic class FieldJsonMapper {\n    private static final ObjectMapper mapper = new ObjectMapper();\n\n    public static ObjectNode mapFields(Video video, Set<String> fields) {\n        ObjectNode node = mapper.createObjectNode();\n\n        if (fields.contains(\"id\")) {\n            node.put(\"id\", video.getId());\n        }\n        if (fields.contains(\"title\")) {\n            node.put(\"title\", video.getTitle());\n        }\n        if (fields.contains(\"description\")) {\n            node.put(\"description\", video.getDescription());\n        }\n        if (fields.contains(\"url\")) {\n            node.put(\"url\", video.getUrl());\n        }\n\n        return node;\n    }\n}\n```\n\n`VideoResource` class handles HTTP requests and returns only the requested fields of the video data.\n\n- The `VideoResource` class is a RESTful resource handling HTTP GET requests.\n- The `getVideo` method fetches a `Video` by its ID and processes the `fields` query parameter.\n- It splits the `fields` parameter into a set of field names, uses `FieldJsonMapper` to include only those fields in the response, and returns the partial JSON response.\n\n```java\n@Path(\"/videos\")\npublic class VideoResource {\n    @GET\n    @Path(\"/{id}\")\n    @Produces(MediaType.APPLICATION_JSON)\n    public Response getVideo(@PathParam(\"id\") String id, @QueryParam(\"fields\") String fieldsParam) {\n        Video video = findVideoById(id); // Assume this method fetches the video by ID\n\n        Set<String> fields = new HashSet<>(Arrays.asList(fieldsParam.split(\",\")));\n        ObjectNode responseNode = FieldJsonMapper.mapFields(video, fields);\n\n        return Response.ok(responseNode.toString()).build();\n    }\n\n    private Video findVideoById(String id) {\n        // Dummy data for demonstration purposes\n        Video video = new Video();\n        video.setId(id);\n        video.setTitle(\"Sample Video\");\n        video.setDescription(\"This is a sample video.\");\n        video.setUrl(\"http://example.com/sample-video\");\n\n        return video;\n    }\n}\n```\n\n`App` class initializes the web server and registers the `VideoResource`.\n\n- The `App` class sets up the server using Jersey.\n- It registers the `VideoResource` class, which will handle incoming HTTP requests.\n- The server listens on `http://localhost:8080/`.\n\n```java\npublic class App {\n    public static void main(String[] args) {\n        ResourceConfig config = new ResourceConfig();\n        config.register(VideoResource.class);\n        SimpleContainerFactory.create(\"http://localhost:8080/\", config);\n    }\n}\n```\n\nTo summarize, in this example:\n\n- The `Video` class defines the video data structure.\n- The `FieldJsonMapper` class helps create JSON responses including only the requested fields.\n- The `VideoResource` class processes client requests, fetching the necessary video data and returning partial responses based on the specified fields.\n- The `App` class configures and starts the web server.\n\nBy implementing the Partial Response design pattern, clients can request only the necessary data, enhancing performance and reducing bandwidth usage.\n\n## When to Use the Partial Response Pattern in Java\n\nUse the Partial Response pattern when\n\n* Utilize the Partial Response pattern when dealing with large data sets or APIs that require improved load time and performance.\n* When it’s beneficial for the client to begin processing the data as it arrives rather than waiting for the complete response.\n* In APIs where different clients might need different subsets of data, allowing them to specify what they need.\n\n## Real-World Applications of Partial Response Pattern in Java\n\nThis pattern is widely adopted in\n\n* RESTful APIs allowing clients to specify fields they want using query parameters.\n* Streaming large datasets where initial parts of the data can be sent immediately (e.g., video streaming).\n* GraphQL queries where clients can request only specific fields to be returned.\n\n## Benefits and Trade-offs of Partial Response Pattern\n\nBenefits:\n\n* Improved Performance: Reduces wait time for the client by allowing it to start processing data as soon as it begins to arrive.\n* Resource Optimization: Decreases server load and bandwidth usage by sending only the required data.\n* Scalability: Enhances system scalability by handling large datasets more efficiently and reducing the likelihood of timeouts.\n\nTrade-offs:\n\n* Complexity: Increases the complexity of both client and server implementations to handle partial responses properly.\n* Error Handling: May complicate error handling and recovery if only parts of the data are received correctly.\n* State Management: Requires careful management of state, especially if the partial responses are to be processed incrementally.\n\n## Related Java Design Patterns\n\n* Asynchronous Messaging: Often used together with asynchronous messaging patterns to handle partial responses without blocking the client.\n* [Caching](https://java-design-patterns.com/patterns/caching/): Can be combined with caching patterns to store partial responses and avoid redundant data transfers.\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): The proxy can intercept requests and manage partial responses, providing a buffer between the client and server.\n\n## References and Credits\n\n* [Building Microservices](https://amzn.to/3UACtrU)\n* [Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems](https://amzn.to/4dKEwBa)\n* [RESTful Web APIs: Services for a Changing World](https://amzn.to/3wG4fu3)\n"
  },
  {
    "path": "partial-response/etc/partial-response.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.2.1\" icons=\"true\" always-add-relationships=\"false\" generalizations=\"true\" realizations=\"true\" \n  associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.partialresponse.Video\" project=\"partial-response\" \n    file=\"/partial-response/src/main/java/com/iluwatar/partialresponse/Video.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"322\" y=\"457\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.partialresponse.FieldJsonMapper\" project=\"partial-response\" \n    file=\"/partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"772\" y=\"412\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.partialresponse.VideoClientApp\" project=\"partial-response\" \n    file=\"/partial-response/src/main/java/com/iluwatar/partialresponse/VideoClientApp.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"215\" y=\"125\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.partialresponse.VideoResource\" project=\"partial-response\" \n    file=\"/partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"101\" width=\"319\" x=\"476\" y=\"66\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"5\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"6\" name=\"videos\"/>      \n      <multiplicity id=\"7\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"8\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"9\" name=\"fieldJsonMapper\"/>      \n      <multiplicity id=\"10\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "partial-response/etc/partial-response.urm.puml",
    "content": "@startuml\npackage com.iluwatar.partialresponse {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class FieldJsonMapper {\n    + FieldJsonMapper()\n    - getString(video : Video, declaredField : Field) : String\n    + toJson(video : Video, fields : String[]) : String\n  }\n  class Video {\n    - description : String\n    - director : String\n    - id : Integer\n    - language : String\n    - length : Integer\n    - title : String\n    + Video(id : Integer, title : String, len : Integer, desc : String, director : String, lang : String)\n    + toString() : String\n  }\n  class VideoResource {\n    - fieldJsonMapper : FieldJsonMapper\n    - videos : Map<Integer, Video>\n    + VideoResource(fieldJsonMapper : FieldJsonMapper, videos : Map<Integer, Video>)\n    + getDetails(id : Integer, fields : String[]) : String\n  }\n}\nVideoResource -->  \"-fieldJsonMapper\" FieldJsonMapper\n@enduml"
  },
  {
    "path": "partial-response/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>partial-response</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-junit-jupiter</artifactId>\n      <version>5.16.1</version>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.partialresponse.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "partial-response/src/main/java/com/iluwatar/partialresponse/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.partialresponse;\n\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Partial response pattern is a design pattern in which client specifies fields to fetch to\n * serve. Here {@link App} is playing as client for {@link VideoResource} server. Client ask for\n * specific fields information in video to server.\n *\n * <p>{@link VideoResource} act as server to serve video information.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Method as act client and request to server for video details.\n   *\n   * @param args program argument.\n   */\n  public static void main(String[] args) throws Exception {\n    var videos =\n        Map.of(\n            1, new Video(1, \"Avatar\", 178, \"epic science fiction film\", \"James Cameron\", \"English\"),\n            2,\n                new Video(\n                    2,\n                    \"Godzilla Resurgence\",\n                    120,\n                    \"Action & drama movie|\",\n                    \"Hideaki Anno\",\n                    \"Japanese\"),\n            3,\n                new Video(\n                    3, \"Interstellar\", 169, \"Adventure & Sci-Fi\", \"Christopher Nolan\", \"English\"));\n    var videoResource = new VideoResource(new FieldJsonMapper(), videos);\n\n    LOGGER.info(\"Retrieving full response from server:-\");\n    LOGGER.info(\"Get all video information:\");\n    var videoDetails = videoResource.getDetails(1);\n    LOGGER.info(videoDetails);\n\n    LOGGER.info(\"----------------------------------------------------------\");\n\n    LOGGER.info(\"Retrieving partial response from server:-\");\n    LOGGER.info(\"Get video @id, @title, @director:\");\n    var specificFieldsDetails = videoResource.getDetails(3, \"id\", \"title\", \"director\");\n    LOGGER.info(specificFieldsDetails);\n\n    LOGGER.info(\"Get video @id, @length:\");\n    var videoLength = videoResource.getDetails(3, \"id\", \"length\");\n    LOGGER.info(videoLength);\n  }\n}\n"
  },
  {
    "path": "partial-response/src/main/java/com/iluwatar/partialresponse/FieldJsonMapper.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.partialresponse;\n\nimport java.lang.reflect.Field;\nimport java.util.StringJoiner;\n\n/** Map a video to json. */\npublic class FieldJsonMapper {\n\n  /**\n   * Gets json of required fields from video.\n   *\n   * @param video object containing video information\n   * @param fields fields information to get\n   * @return json of required fields from video\n   */\n  public String toJson(Video video, String[] fields) throws Exception {\n    var json = new StringJoiner(\",\", \"{\", \"}\");\n\n    var i = 0;\n    var fieldsLength = fields.length;\n    while (i < fieldsLength) {\n      json.add(getString(video, Video.class.getDeclaredField(fields[i])));\n      i++;\n    }\n\n    return json.toString();\n  }\n\n  private String getString(Video video, Field declaredField) throws IllegalAccessException {\n    declaredField.setAccessible(true);\n    var value = declaredField.get(video);\n    if (declaredField.get(video) instanceof Integer) {\n      return \"\\\"\" + declaredField.getName() + \"\\\"\" + \": \" + value;\n    }\n    return \"\\\"\" + declaredField.getName() + \"\\\"\" + \": \" + \"\\\"\" + value.toString() + \"\\\"\";\n  }\n}\n"
  },
  {
    "path": "partial-response/src/main/java/com/iluwatar/partialresponse/Video.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.partialresponse;\n\n/**\n * {@link Video} is an entity to serve from server.It contains all video related information. Video\n * is a record class.\n */\npublic record Video(\n    Integer id,\n    String title,\n    Integer length,\n    String description,\n    String director,\n    String language) {\n  /**\n   * ToString.\n   *\n   * @return json representation of video\n   */\n  @Override\n  public String toString() {\n    return \"{\"\n        + \"\\\"id\\\": \"\n        + id\n        + \",\"\n        + \"\\\"title\\\": \\\"\"\n        + title\n        + \"\\\",\"\n        + \"\\\"length\\\": \"\n        + length\n        + \",\"\n        + \"\\\"description\\\": \\\"\"\n        + description\n        + \"\\\",\"\n        + \"\\\"director\\\": \\\"\"\n        + director\n        + \"\\\",\"\n        + \"\\\"language\\\": \\\"\"\n        + language\n        + \"\\\"\"\n        + \"}\";\n  }\n}\n"
  },
  {
    "path": "partial-response/src/main/java/com/iluwatar/partialresponse/VideoResource.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.partialresponse;\n\nimport java.util.Map;\n\n/**\n * The resource record class which serves video information. This class act as server in the demo.\n * Which has all video details.\n *\n * @param fieldJsonMapper map object to json.\n * @param videos initialize resource with existing videos. Act as database.\n */\npublic record VideoResource(FieldJsonMapper fieldJsonMapper, Map<Integer, Video> videos) {\n  /**\n   * Get Details.\n   *\n   * @param id video id\n   * @param fields fields to get information about\n   * @return full response if no fields specified else partial response for given field.\n   */\n  public String getDetails(Integer id, String... fields) throws Exception {\n    if (fields.length == 0) {\n      return videos.get(id).toString();\n    }\n    return fieldJsonMapper.toJson(videos.get(id), fields);\n  }\n}\n"
  },
  {
    "path": "partial-response/src/test/java/com/iluwatar/partialresponse/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.partialresponse;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    Assertions.assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "partial-response/src/test/java/com/iluwatar/partialresponse/FieldJsonMapperTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.partialresponse;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\n/** tests {@link FieldJsonMapper}. */\nclass FieldJsonMapperTest {\n  private static FieldJsonMapper mapper;\n\n  @BeforeAll\n  static void setUp() {\n    mapper = new FieldJsonMapper();\n  }\n\n  @Test\n  void shouldReturnJsonForSpecifiedFieldsInVideo() throws Exception {\n    var fields = new String[] {\"id\", \"title\", \"length\"};\n    var video =\n        new Video(\n            2, \"Godzilla Resurgence\", 120, \"Action & drama movie|\", \"Hideaki Anno\", \"Japanese\");\n\n    var jsonFieldResponse = mapper.toJson(video, fields);\n\n    var expectedDetails = \"{\\\"id\\\": 2,\\\"title\\\": \\\"Godzilla Resurgence\\\",\\\"length\\\": 120}\";\n    Assertions.assertEquals(expectedDetails, jsonFieldResponse);\n  }\n}\n"
  },
  {
    "path": "partial-response/src/test/java/com/iluwatar/partialresponse/VideoResourceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.partialresponse;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\n\nimport java.util.Map;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\n/** tests {@link VideoResource}. */\n@ExtendWith(MockitoExtension.class)\nclass VideoResourceTest {\n  @Mock private static FieldJsonMapper fieldJsonMapper;\n\n  private static VideoResource resource;\n\n  @BeforeEach\n  void setUp() {\n    var videos =\n        Map.of(\n            1, new Video(1, \"Avatar\", 178, \"epic science fiction film\", \"James Cameron\", \"English\"),\n            2,\n                new Video(\n                    2,\n                    \"Godzilla Resurgence\",\n                    120,\n                    \"Action & drama movie|\",\n                    \"Hideaki Anno\",\n                    \"Japanese\"),\n            3,\n                new Video(\n                    3, \"Interstellar\", 169, \"Adventure & Sci-Fi\", \"Christopher Nolan\", \"English\"));\n    resource = new VideoResource(fieldJsonMapper, videos);\n  }\n\n  @Test\n  void shouldGiveVideoDetailsById() throws Exception {\n    var actualDetails = resource.getDetails(1);\n\n    var expectedDetails =\n        \"{\\\"id\\\": 1,\\\"title\\\": \\\"Avatar\\\",\\\"length\\\": 178,\\\"description\\\": \"\n            + \"\\\"epic science fiction film\\\",\\\"director\\\": \\\"James Cameron\\\",\\\"language\\\": \\\"English\\\"}\";\n    Assertions.assertEquals(expectedDetails, actualDetails);\n  }\n\n  @Test\n  void shouldGiveSpecifiedFieldsInformationOfVideo() throws Exception {\n    var fields = new String[] {\"id\", \"title\", \"length\"};\n\n    var expectedDetails = \"{\\\"id\\\": 1,\\\"title\\\": \\\"Avatar\\\",\\\"length\\\": 178}\";\n    Mockito.when(fieldJsonMapper.toJson(any(Video.class), eq(fields))).thenReturn(expectedDetails);\n\n    var actualFieldsDetails = resource.getDetails(2, fields);\n\n    Assertions.assertEquals(expectedDetails, actualFieldsDetails);\n  }\n\n  @Test\n  void shouldAllSpecifiedFieldsInformationOfVideo() throws Exception {\n    var fields = new String[] {\"id\", \"title\", \"length\", \"description\", \"director\", \"language\"};\n\n    var expectedDetails =\n        \"{\\\"id\\\": 1,\\\"title\\\": \\\"Avatar\\\",\\\"length\\\": 178,\\\"description\\\": \"\n            + \"\\\"epic science fiction film\\\",\\\"director\\\": \\\"James Cameron\\\",\\\"language\\\": \\\"English\\\"}\";\n    Mockito.when(fieldJsonMapper.toJson(any(Video.class), eq(fields))).thenReturn(expectedDetails);\n\n    var actualFieldsDetails = resource.getDetails(1, fields);\n\n    Assertions.assertEquals(expectedDetails, actualFieldsDetails);\n  }\n}\n"
  },
  {
    "path": "pipeline/README.md",
    "content": "---\ntitle: \"Pipeline Pattern in Java: Streamlining Data Processing with Modular Components\"\nshortTitle: Pipeline\ndescription: \"Master the Pipeline design pattern in Java with our comprehensive guide. Learn how to implement data processing in discrete stages for improved code scalability and flexibility. Ideal for developers looking to advance their software engineering skills.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - API design\n  - Data processing\n  - Decoupling\n  - Extensibility\n  - Functional decomposition\n  - Scalability\n---\n\n## Also known as\n\n* Chain of Operations\n* Processing Pipeline\n\n## Intent of Pipeline Design Pattern\n\nThe Pipeline design pattern in Java is engineered to facilitate data processing across discrete stages, enhancing modular development and operational efficiency.\n\n## Detailed Explanation of Pipeline Pattern with Real-World Examples\n\nReal-world example\n\n> A practical example of the Java Pipeline design pattern can be seen in assembly lines, such as those in car manufacturing, illustrating its efficiency and scalability.\n>\n> In this analogy, the car manufacturing process is divided into several discrete stages, each stage handling a specific part of the car assembly. For example:\n>\n> 1. **Chassis Assembly:** The base frame of the car is assembled.\n> 2. **Engine Installation:** The engine is installed onto the chassis.\n> 3. **Painting:** The car is painted.\n> 4. **Interior Assembly:** The interior, including seats and dashboard, is installed.\n> 5. **Quality Control:** The finished car is inspected for defects.\n>\n> In the Java Pipeline pattern, each stage functions independently and sequentially, ensuring smooth data flow and easy modifications. The output of one stage (e.g., a partially assembled car) becomes the input for the next stage. This modular approach allows for easy maintenance, scalability (e.g., adding more workers to a stage), and flexibility (e.g., replacing a stage with a more advanced version). Just like in a software pipeline, changes in one stage do not affect the others, facilitating continuous improvements and efficient production.\n\nIn plain words\n\n> Pipeline pattern is an assembly line where partial results are passed from one stage to another.\n\nWikipedia says\n\n> In software engineering, a pipeline consists of a chain of processing elements (processes, threads, coroutines, functions, etc.), arranged so that the output of each element is the input of the next; the name is by analogy to a physical pipeline.\n\nFlowchart\n\n![Pipeline flowchart](./etc/pipeline-flowchart.png)\n\n## Programmatic Example of Pipeline Pattern in Java\n\nLet's create a string processing pipeline example. The stages of our pipeline are called `Handler`s.\n\n```java\ninterface Handler<I, O> {\n    O process(I input);\n}\n```\n\nIn our string processing example we have 3 different concrete `Handler`s.\n\n```java\nclass RemoveAlphabetsHandler implements Handler<String, String> {\n  // ...\n}\n\nclass RemoveDigitsHandler implements Handler<String, String> {\n  // ...\n}\n\nclass ConvertToCharArrayHandler implements Handler<String, char[]> {\n  // ...\n}\n```\n\nHere is the `Pipeline` that will gather and execute the handlers one by one.\n\n```java\nclass Pipeline<I, O> {\n\n    private final Handler<I, O> currentHandler;\n\n    Pipeline(Handler<I, O> currentHandler) {\n        this.currentHandler = currentHandler;\n    }\n\n    <K> Pipeline<I, K> addHandler(Handler<O, K> newHandler) {\n        return new Pipeline<>(input -> newHandler.process(currentHandler.process(input)));\n    }\n\n    O execute(I input) {\n        return currentHandler.process(input);\n    }\n}\n```\n\nAnd here's the `Pipeline` in action processing the string.\n\n```java\npublic static void main(String[] args) {\n    LOGGER.info(\"Creating pipeline\");\n    var filters = new Pipeline<>(new RemoveAlphabetsHandler())\n            .addHandler(new RemoveDigitsHandler())\n            .addHandler(new ConvertToCharArrayHandler());\n    var input = \"GoYankees123!\";\n    LOGGER.info(\"Executing pipeline with input: {}\", input);\n    var output = filters.execute(input);\n    LOGGER.info(\"Pipeline output: {}\", output);\n}\n```\n\nConsole output:\n\n```\n07:34:27.069 [main] INFO com.iluwatar.pipeline.App -- Creating pipeline\n07:34:27.072 [main] INFO com.iluwatar.pipeline.App -- Executing pipeline with input: GoYankees123!\n07:34:27.074 [main] INFO com.iluwatar.pipeline.RemoveAlphabetsHandler -- Current handler: class com.iluwatar.pipeline.RemoveAlphabetsHandler, input is GoYankees123! of type class java.lang.String, output is 123!, of type class java.lang.String\n07:34:27.075 [main] INFO com.iluwatar.pipeline.RemoveDigitsHandler -- Current handler: class com.iluwatar.pipeline.RemoveDigitsHandler, input is 123! of type class java.lang.String, output is !, of type class java.lang.String\n07:34:27.075 [main] INFO com.iluwatar.pipeline.ConvertToCharArrayHandler -- Current handler: class com.iluwatar.pipeline.ConvertToCharArrayHandler, input is ! of type class java.lang.String, output is [!], of type class [Ljava.lang.Character;\n07:34:27.075 [main] INFO com.iluwatar.pipeline.App -- Pipeline output: [!]\n```\n\n## When to Use the Pipeline Pattern in Java\n\nUse the Pipeline pattern when you want to\n\n* When you need to process data in a sequence of stages.\n* When each stage of processing is independent and can be easily replaced or reordered.\n* When you want to improve the scalability and maintainability of data processing code.\n\n## Pipeline Pattern Java Tutorials\n\n* [The Pipeline design pattern (in Java) (Medium)](https://medium.com/@deepakbapat/the-pipeline-design-pattern-in-java-831d9ce2fe21)\n* [The Pipeline Pattern — for fun and profit (Aaron Weatherall)](https://medium.com/@aaronweatherall/the-pipeline-pattern-for-fun-and-profit-9b5f43a98130)\n* [Pipelines (Microsoft)](https://docs.microsoft.com/en-us/previous-versions/msp-n-p/ff963548(v=pandp.10))\n\n## Real-World Applications of Pipeline Pattern in Java\n\n* Data transformation and ETL (Extract, Transform, Load) processes.\n* Compilers for processing source code through various stages such as lexical analysis, syntax analysis, semantic analysis, and code generation.\n* Image processing applications where multiple filters are applied sequentially.\n* Logging frameworks where messages pass through multiple handlers for formatting, filtering, and output.\n\n## Benefits and Trade-offs of Pipeline Pattern\n\nBenefits:\n\n* Decoupling: Each stage of the pipeline is a separate component, making the system more modular and easier to maintain.\n* Reusability: Individual stages can be reused in different pipelines.\n* Extensibility: New stages can be added without modifying existing ones.\n* Scalability: Pipelines can be parallelized by running different stages on different processors or threads.\n\nTrade-offs:\n\n* Complexity: Managing the flow of data through multiple stages can introduce complexity.\n* Performance Overhead: Each stage introduces some performance overhead due to context switching and data transfer between stages.\n* Debugging Difficulty: Debugging pipelines can be more challenging since the data flows through multiple components.\n\n## Related Java Design Patterns\n\n* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/): Both patterns involve passing data through a series of handlers, but in Chain of Responsibility, handlers can decide not to pass the data further.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Both patterns involve adding behavior dynamically, but Decorator wraps additional behavior around objects, whereas Pipeline processes data in discrete steps.\n* [Composite](https://java-design-patterns.com/patterns/composite/): Like Pipeline, Composite also involves hierarchical processing, but Composite is more about part-whole hierarchies.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "pipeline/etc/pipeline.urm.puml",
    "content": "@startuml\npackage com.iluwatar.pipeline {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  ~class ConvertToCharArrayHandler {\n    - LOGGER : Logger {static}\n    ~ ConvertToCharArrayHandler()\n    + process(input : String) : char[]\n  }\n  ~interface Handler<I, O> {\n    + process(I) : O {abstract}\n  }\n  ~class Pipeline<I, O> {\n    - currentHandler : Handler<I, O>\n    ~ Pipeline<I, O>(currentHandler : Handler<I, O>)\n    ~ addHandler(newHandler : Handler<O, K>) : Pipeline<I, K>\n    ~ execute(input : I) : O\n  }\n  ~class RemoveAlphabetsHandler {\n    - LOGGER : Logger {static}\n    ~ RemoveAlphabetsHandler()\n    + process(input : String) : String\n  }\n  ~class RemoveDigitsHandler {\n    - LOGGER : Logger {static}\n    ~ RemoveDigitsHandler()\n    + process(input : String) : String\n  }\n}\nPipeline -->  \"-currentHandler\" Handler\nConvertToCharArrayHandler ..|> Handler \nRemoveAlphabetsHandler ..|> Handler \nRemoveDigitsHandler ..|> Handler \n@enduml"
  },
  {
    "path": "pipeline/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>pipeline</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.pipeline.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "pipeline/src/main/java/com/iluwatar/pipeline/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pipeline;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Pipeline pattern uses ordered stages to process a sequence of input values. Each implemented\n * task is represented by a stage of the pipeline. You can think of pipelines as similar to assembly\n * lines in a factory, where each item in the assembly line is constructed in stages. The partially\n * assembled item is passed from one assembly stage to another. The outputs of the assembly line\n * occur in the same order as that of the inputs.\n *\n * <p>Classes used in this example are suffixed with \"Handlers\", and synonymously refers to the\n * \"stage\".\n */\n@Slf4j\npublic class App {\n  /**\n   * Specify the initial input type for the first stage handler and the expected output type of the\n   * last stage handler as type parameters for Pipeline. Use the fluent builder by calling\n   * addHandler to add more stage handlers on the pipeline.\n   */\n  public static void main(String[] args) {\n    /*\n     Suppose we wanted to pass through a String to a series of filtering stages and convert it\n     as a char array on the last stage.\n\n     - Stage handler 1 (pipe): Removing the alphabets, accepts a String input and returns the\n     processed String output. This will be used by the next handler as its input.\n\n     - Stage handler 2 (pipe): Removing the digits, accepts a String input and returns the\n     processed String output. This shall also be used by the last handler we have.\n\n     - Stage handler 3 (pipe): Converting the String input to a char array handler. We would\n     be returning a different type in here since that is what's specified by the requirement.\n     This means that at any stages along the pipeline, the handler can return any type of data\n     as long as it fulfills the requirements for the next handler's input.\n\n     Suppose we wanted to add another handler after ConvertToCharArrayHandler. That handler\n     then is expected to receive an input of char[] array since that is the type being returned\n     by the previous handler, ConvertToCharArrayHandler.\n    */\n    LOGGER.info(\"Creating pipeline\");\n    var filters =\n        new Pipeline<>(new RemoveAlphabetsHandler())\n            .addHandler(new RemoveDigitsHandler())\n            .addHandler(new ConvertToCharArrayHandler());\n    var input = \"GoYankees123!\";\n    LOGGER.info(\"Executing pipeline with input: {}\", input);\n    var output = filters.execute(input);\n    LOGGER.info(\"Pipeline output: {}\", output);\n  }\n}\n"
  },
  {
    "path": "pipeline/src/main/java/com/iluwatar/pipeline/ConvertToCharArrayHandler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pipeline;\n\nimport java.util.Arrays;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** Stage handler that converts an input String to its char[] array counterpart. */\nclass ConvertToCharArrayHandler implements Handler<String, char[]> {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(ConvertToCharArrayHandler.class);\n\n  @Override\n  public char[] process(String input) {\n    var characters = input.toCharArray();\n    var string = Arrays.toString(characters);\n    LOGGER.info(\n        String.format(\n            \"Current handler: %s, input is %s of type %s, output is %s, of type %s\",\n            ConvertToCharArrayHandler.class, input, String.class, string, Character[].class));\n\n    return characters;\n  }\n}\n"
  },
  {
    "path": "pipeline/src/main/java/com/iluwatar/pipeline/Handler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pipeline;\n\n/**\n * Forms a contract to all stage handlers to accept a certain type of input and return a processed\n * output.\n *\n * @param <I> the input type of the handler\n * @param <O> the processed output type of the handler\n */\ninterface Handler<I, O> {\n  O process(I input);\n}\n"
  },
  {
    "path": "pipeline/src/main/java/com/iluwatar/pipeline/Pipeline.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pipeline;\n\n/**\n * Main Pipeline class that initially sets the current handler. Processed output of the initial\n * handler is then passed as the input to the next stage handlers.\n *\n * @param <I> the type of the input for the first stage handler\n * @param <O> the final stage handler's output type\n */\nclass Pipeline<I, O> {\n\n  private final Handler<I, O> currentHandler;\n\n  Pipeline(Handler<I, O> currentHandler) {\n    this.currentHandler = currentHandler;\n  }\n\n  <K> Pipeline<I, K> addHandler(Handler<O, K> newHandler) {\n    return new Pipeline<>(input -> newHandler.process(currentHandler.process(input)));\n  }\n\n  O execute(I input) {\n    return currentHandler.process(input);\n  }\n}\n"
  },
  {
    "path": "pipeline/src/main/java/com/iluwatar/pipeline/RemoveAlphabetsHandler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pipeline;\n\nimport java.util.function.IntPredicate;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Stage handler that returns a new instance of String without the alphabet characters of the input\n * string.\n */\nclass RemoveAlphabetsHandler implements Handler<String, String> {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(RemoveAlphabetsHandler.class);\n\n  @Override\n  public String process(String input) {\n    var inputWithoutAlphabets = new StringBuilder();\n    var isAlphabetic = (IntPredicate) Character::isAlphabetic;\n    input\n        .chars()\n        .filter(isAlphabetic.negate())\n        .mapToObj(x -> (char) x)\n        .forEachOrdered(inputWithoutAlphabets::append);\n\n    var inputWithoutAlphabetsStr = inputWithoutAlphabets.toString();\n    LOGGER.info(\n        String.format(\n            \"Current handler: %s, input is %s of type %s, output is %s, of type %s\",\n            RemoveAlphabetsHandler.class,\n            input,\n            String.class,\n            inputWithoutAlphabetsStr,\n            String.class));\n\n    return inputWithoutAlphabetsStr;\n  }\n}\n"
  },
  {
    "path": "pipeline/src/main/java/com/iluwatar/pipeline/RemoveDigitsHandler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pipeline;\n\nimport java.util.function.IntPredicate;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Stage handler that returns a new instance of String without the digit characters of the input\n * string.\n */\nclass RemoveDigitsHandler implements Handler<String, String> {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(RemoveDigitsHandler.class);\n\n  @Override\n  public String process(String input) {\n    var inputWithoutDigits = new StringBuilder();\n    var isDigit = (IntPredicate) Character::isDigit;\n    input\n        .chars()\n        .filter(isDigit.negate())\n        .mapToObj(x -> (char) x)\n        .forEachOrdered(inputWithoutDigits::append);\n\n    var inputWithoutDigitsStr = inputWithoutDigits.toString();\n    LOGGER.info(\n        String.format(\n            \"Current handler: %s, input is %s of type %s, output is %s, of type %s\",\n            RemoveDigitsHandler.class, input, String.class, inputWithoutDigitsStr, String.class));\n\n    return inputWithoutDigitsStr;\n  }\n}\n"
  },
  {
    "path": "pipeline/src/test/java/com/iluwatar/pipeline/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pipeline;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application Test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "pipeline/src/test/java/com/iluwatar/pipeline/PipelineTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.pipeline;\n\nimport static org.junit.jupiter.api.Assertions.assertArrayEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test for {@link Pipeline} */\nclass PipelineTest {\n\n  @Test\n  void testAddHandlersToPipeline() {\n    var filters =\n        new Pipeline<>(new RemoveAlphabetsHandler())\n            .addHandler(new RemoveDigitsHandler())\n            .addHandler(new ConvertToCharArrayHandler());\n\n    assertArrayEquals(\n        new char[] {'#', '!', '(', '&', '%', '#', '!'}, filters.execute(\"#H!E(L&L0O%THE3R#34E!\"));\n  }\n}\n"
  },
  {
    "path": "poison-pill/README.md",
    "content": "---\ntitle: \"Poison Pill Pattern in Java: Gracefully Terminating Multithreaded Processes\"\nshortTitle: Poison Pill\ndescription: \"Explore the Poison Pill design pattern in Java, used for gracefully shutting down multi-threaded applications. Understand its intent, applicability, and see a real-world example. Perfect for developers looking to enhance concurrency and messaging systems.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Decoupling\n  - Fault tolerance\n  - Messaging\n  - Thread management\n---\n\n## Also known as\n\n* Shutdown Signal\n\n## Intent of Poison Pill Design Pattern\n\nThe Poison Pill design pattern is used to gracefully shut down a service or a producer-consumer system by sending a special message (the \"poison pill\") to message queue which indicates that no more messages will be sent, allowing the consumers to terminate.\n\n## Detailed Explanation of Poison Pill Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy for the Poison Pill design pattern is the use of a \"closed\" sign in a retail store. When the store is ready to close for the day, the manager places a \"closed\" sign on the door. This sign acts as a signal to any new customers that no more customers will be admitted, but it doesn't immediately force out the customers already inside. The store staff will then attend to the remaining customers, allowing them to complete their purchases before finally locking up and turning off the lights. Similarly, in the Poison Pill pattern, a special \"poison pill\" message signals consumers to stop accepting new tasks while allowing them to finish processing the current tasks before shutting down gracefully. \n\nIn plain words\n\n> Poison Pill is a known message structure that ends the message exchange.   \n\nSequence diagram\n\n![Poison Pill sequence diagram](./etc/poison-pill-sequence-diagram.png)\n\n## Programmatic Example of Poison Pill Pattern in Java\n\nIn this Java example, the Poison Pill serves as a shutdown signal within message queues, demonstrating effective thread management and consumer communication.\n\nLet's define the message structure first. There's interface `Message` and implementation `SimpleMessage`.\n\n```java\npublic interface Message {\n    \n  // Other properties and methods...\n\n  enum Headers {\n    DATE, SENDER\n  }\n\n  void addHeader(Headers header, String value);\n\n  String getHeader(Headers header);\n\n  Map<Headers, String> getHeaders();\n\n  void setBody(String body);\n\n  String getBody();\n}\n\npublic class SimpleMessage implements Message {\n\n  private final Map<Headers, String> headers = new HashMap<>();\n  private String body;\n\n  @Override\n  public void addHeader(Headers header, String value) {\n    headers.put(header, value);\n  }\n\n  @Override\n  public String getHeader(Headers header) {\n    return headers.get(header);\n  }\n\n  @Override\n  public Map<Headers, String> getHeaders() {\n    return Collections.unmodifiableMap(headers);\n  }\n\n  @Override\n  public void setBody(String body) {\n    this.body = body;\n  }\n\n  @Override\n  public String getBody() {\n    return body;\n  }\n}\n```\n\nTo pass messages we are using message queues. Here we define the types related to the message queue: `MqPublishPoint`, `MqSubscribePoint` and `MessageQueue`. `SimpleMessageQueue` implements all these interfaces.\n\n```java\npublic interface MqPublishPoint {\n  void put(Message msg) throws InterruptedException;\n}\n\npublic interface MqSubscribePoint {\n  Message take() throws InterruptedException;\n}\n\npublic interface MessageQueue extends MqPublishPoint, MqSubscribePoint {}\n\npublic class SimpleMessageQueue implements MessageQueue {\n\n  private final BlockingQueue<Message> queue;\n\n  public SimpleMessageQueue(int bound) {\n    queue = new ArrayBlockingQueue<>(bound);\n  }\n\n  @Override\n  public void put(Message msg) throws InterruptedException {\n    queue.put(msg);\n  }\n\n  @Override\n  public Message take() throws InterruptedException {\n    return queue.take();\n  }\n}\n```\n\nNext, we need message `Producer` and `Consumer`. Internally they use the message queues from above. It's important to notice that when `Producer` stops, it sends out the poison pill to inform `Consumer` that the messaging has finished. \n\n```java\npublic class Producer {\n\n  // Other properties and methods...\n\n  public void send(String body) {\n    if (isStopped) {\n      throw new IllegalStateException(String.format(\n          \"Producer %s was stopped and fail to deliver requested message [%s].\", body, name));\n    }\n    var msg = new SimpleMessage();\n    msg.addHeader(Headers.DATE, new Date().toString());\n    msg.addHeader(Headers.SENDER, name);\n    msg.setBody(body);\n\n    try {\n      queue.put(msg);\n    } catch (InterruptedException e) {\n      // allow thread to exit\n      LOGGER.error(\"Exception caught.\", e);\n    }\n  }\n\n  public void stop() {\n    isStopped = true;\n    try {\n      queue.put(Message.POISON_PILL);\n    } catch (InterruptedException e) {\n      // allow thread to exit\n      LOGGER.error(\"Exception caught.\", e);\n    }\n  }\n}\n\npublic class Consumer {\n\n  // Other properties and methods...\n\n  public void consume() {\n    while (true) {\n      try {\n        var msg = queue.take();\n        if (Message.POISON_PILL.equals(msg)) {\n          LOGGER.info(\"Consumer {} receive request to terminate.\", name);\n          break;\n        }\n        var sender = msg.getHeader(Headers.SENDER);\n        var body = msg.getBody();\n        LOGGER.info(\"Message [{}] from [{}] received by [{}]\", body, sender, name);\n      } catch (InterruptedException e) {\n        // allow thread to exit\n        LOGGER.error(\"Exception caught.\", e);\n        return;\n      }\n    }\n  }\n}\n```\n\nFinally, we are ready to present the whole example in action.\n\n```java\n  public static void main(String[] args) {\n    var queue = new SimpleMessageQueue(10000);\n\n    final var producer = new Producer(\"PRODUCER_1\", queue);\n    final var consumer = new Consumer(\"CONSUMER_1\", queue);\n\n    new Thread(consumer::consume).start();\n\n    new Thread(() -> {\n        producer.send(\"hand shake\");\n        producer.send(\"some very important information\");\n        producer.send(\"bye!\");\n        producer.stop();\n    }).start();\n}\n```\n\nProgram output:\n\n```\n07:43:01.518 [Thread-0] INFO com.iluwatar.poison.pill.Consumer -- Message [hand shake] from [PRODUCER_1] received by [CONSUMER_1]\n07:43:01.520 [Thread-0] INFO com.iluwatar.poison.pill.Consumer -- Message [some very important information] from [PRODUCER_1] received by [CONSUMER_1]\n07:43:01.520 [Thread-0] INFO com.iluwatar.poison.pill.Consumer -- Message [bye!] from [PRODUCER_1] received by [CONSUMER_1]\n07:43:01.520 [Thread-0] INFO com.iluwatar.poison.pill.Consumer -- Consumer CONSUMER_1 receive request to terminate.\n```\n\n## When to Use the Poison Pill Pattern in Java\n\nUse the Poison Pill idiom when:\n\n* Systems require robust fault tolerance and seamless consumer shutdown in multithreaded environments.\n* In producer-consumer scenarios where consumers need to be informed about the end of message processing.\n* To ensure that consumers can finish processing remaining messages before shutting down.\n\n## Real-World Applications of Poison Pill Pattern in Java\n\n* Java ExecutorService shutdown using a special task to signal shutdown.\n* Messaging systems where a specific message indicates the end of the queue processing.\n* [Akka framework](https://doc.akka.io/japi/akka/2.5/akka/actor/typed/internal/PoisonPill.html)\n\n## Benefits and Trade-offs of Poison Pill Pattern\n\nBenefits:\n\n* Simplifies the shutdown process of consumers.\n* Ensures that all pending tasks are completed before termination.\n* Decouples the shutdown logic from the main processing logic.\n\nTrade-offs:\n\n* Requires consumers to check for the poison pill, adding some overhead.\n* If not managed properly, could lead to consumers not recognizing the poison pill, causing indefinite blocking.\n\n## Related Java Design Patterns\n\n* [Producer-Consumer](https://java-design-patterns.com/patterns/producer-consumer/): Works in tandem with the Poison Pill pattern to handle the communication and shutdown of consumers.\n* Message Queue: Often uses poison pills to signal the end of message processing in the queue.\n* [Observer](https://java-design-patterns.com/patterns/observer/): Can be used to notify subscribers about the shutdown event.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n"
  },
  {
    "path": "poison-pill/etc/poison-pill.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.Producer\" project=\"poison-pill\" \n    file=\"/poison-pill/src/main/java/com/iluwatar/Producer.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"153\" width=\"182\" x=\"158\" y=\"209\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"2\" language=\"java\" name=\"com.iluwatar.MQPublishPoint\" project=\"poison-pill\" \n    file=\"/poison-pill/src/main/java/com/iluwatar/MQPublishPoint.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"453\" y=\"283\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.SimpleMessageQueue\" project=\"poison-pill\" \n    file=\"/poison-pill/src/main/java/com/iluwatar/SimpleMessageQueue.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"627\" y=\"115\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"4\" language=\"java\" name=\"com.iluwatar.MessageQueue\" project=\"poison-pill\" \n    file=\"/poison-pill/src/main/java/com/iluwatar/MessageQueue.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"627\" y=\"283\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"5\" language=\"java\" name=\"com.iluwatar.MQSubscribePoint\" project=\"poison-pill\" \n    file=\"/poison-pill/src/main/java/com/iluwatar/MQSubscribePoint.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"821\" y=\"282\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.Consumer\" project=\"poison-pill\" \n    file=\"/poison-pill/src/main/java/com/iluwatar/Consumer.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1055\" y=\"282\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <generalization id=\"7\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </generalization>  \n  <realization id=\"8\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <generalization id=\"9\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </generalization>  \n  <association id=\"10\">    \n    <end type=\"SOURCE\" refId=\"6\" navigable=\"false\">      \n      <attribute id=\"11\" name=\"queue\"/>      \n      <multiplicity id=\"12\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"13\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"14\" name=\"queue\"/>      \n      <multiplicity id=\"15\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "poison-pill/etc/poison-pill.urm.puml",
    "content": "@startuml\npackage com.iluwatar.poison.pill {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Consumer {\n    - LOGGER : Logger {static}\n    - name : String\n    - queue : MqSubscribePoint\n    + Consumer(name : String, queue : MqSubscribePoint)\n    + consume()\n  }\n  interface Message {\n    + POISON_PILL : Message {static}\n    + addHeader(Headers, String) {abstract}\n    + getBody() : String {abstract}\n    + getHeader(Headers) : String {abstract}\n    + getHeaders() : Map<Headers, String> {abstract}\n    + setBody(String) {abstract}\n  }\n  enum Headers {\n    + DATE {static}\n    + SENDER {static}\n    + valueOf(name : String) : Headers {static}\n    + values() : Headers[] {static}\n  }\n  interface MessageQueue {\n  }\n  interface MqPublishPoint {\n    + put(Message) {abstract}\n  }\n  interface MqSubscribePoint {\n    + take() : Message {abstract}\n  }\n  class Producer {\n    - LOGGER : Logger {static}\n    - isStopped : boolean\n    - name : String\n    - queue : MqPublishPoint\n    + Producer(name : String, queue : MqPublishPoint)\n    + send(body : String)\n    + stop()\n  }\n  class SimpleMessage {\n    - body : String\n    - headers : Map<Headers, String>\n    + SimpleMessage()\n    + addHeader(header : Headers, value : String)\n    + getBody() : String\n    + getHeader(header : Headers) : String\n    + getHeaders() : Map<Headers, String>\n    + setBody(body : String)\n  }\n  class SimpleMessageQueue {\n    - queue : BlockingQueue<Message>\n    + SimpleMessageQueue(bound : int)\n    + put(msg : Message)\n    + take() : Message\n  }\n}\nSimpleMessageQueue -->  \"-queue\" Message\nHeaders ..+ Message\nConsumer -->  \"-queue\" MqSubscribePoint\nProducer -->  \"-queue\" MqPublishPoint\nMessage -->  \"-POISON_PILL\" Message\nMessageQueue --|> MqPublishPoint \nMessageQueue --|> MqSubscribePoint \nSimpleMessage ..|> Message \nSimpleMessageQueue ..|> MessageQueue \n@enduml"
  },
  {
    "path": "poison-pill/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>poison-pill</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.poison.pill.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "poison-pill/src/main/java/com/iluwatar/poison/pill/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\n/**\n * One of the possible approaches to terminate Producer-Consumer pattern is using the Poison Pill\n * idiom. If you use Poison Pill as the termination signal then Producer is responsible to notify\n * Consumer that the exchange is over and reject any further messages. The Consumer receiving Poison\n * Pill will stop reading messages from the queue. You must also ensure that the Poison Pill will be\n * the last message that will be read from the queue (if you have prioritized queue then this can be\n * tricky).\n *\n * <p>In simple cases the Poison Pill can be just a null-reference, but holding a unique separate\n * shared object-marker (with name \"Poison\" or \"Poison Pill\") is more clear and self describing.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var queue = new SimpleMessageQueue(10000);\n\n    final var producer = new Producer(\"PRODUCER_1\", queue);\n    final var consumer = new Consumer(\"CONSUMER_1\", queue);\n\n    new Thread(consumer::consume).start();\n\n    new Thread(\n            () -> {\n              producer.send(\"hand shake\");\n              producer.send(\"some very important information\");\n              producer.send(\"bye!\");\n              producer.stop();\n            })\n        .start();\n  }\n}\n"
  },
  {
    "path": "poison-pill/src/main/java/com/iluwatar/poison/pill/Consumer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\nimport com.iluwatar.poison.pill.Message.Headers;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Class responsible for receiving and handling submitted to the queue messages. */\n@Slf4j\npublic class Consumer {\n\n  private final MqSubscribePoint queue;\n  private final String name;\n\n  public Consumer(String name, MqSubscribePoint queue) {\n    this.name = name;\n    this.queue = queue;\n  }\n\n  /** Consume message. */\n  public void consume() {\n    while (true) {\n      try {\n        var msg = queue.take();\n        if (Message.POISON_PILL.equals(msg)) {\n          LOGGER.info(\"Consumer {} receive request to terminate.\", name);\n          break;\n        }\n        var sender = msg.getHeader(Headers.SENDER);\n        var body = msg.getBody();\n        LOGGER.info(\"Message [{}] from [{}] received by [{}]\", body, sender, name);\n      } catch (InterruptedException e) {\n        // allow thread to exit\n        LOGGER.error(\"Exception caught.\", e);\n        return;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "poison-pill/src/main/java/com/iluwatar/poison/pill/Message.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\nimport java.util.Map;\n\n/**\n * Interface that implements the Message pattern and represents an inbound or outbound message as\n * part of an {@link Producer}-{@link Consumer} exchange.\n */\npublic interface Message {\n\n  Message POISON_PILL =\n      new Message() {\n\n        @Override\n        public void addHeader(Headers header, String value) {\n          throw poison();\n        }\n\n        @Override\n        public String getHeader(Headers header) {\n          throw poison();\n        }\n\n        @Override\n        public Map<Headers, String> getHeaders() {\n          throw poison();\n        }\n\n        @Override\n        public void setBody(String body) {\n          throw poison();\n        }\n\n        @Override\n        public String getBody() {\n          throw poison();\n        }\n\n        private RuntimeException poison() {\n          return new UnsupportedOperationException(\"Poison\");\n        }\n      };\n\n  /** Enumeration of Type of Headers. */\n  enum Headers {\n    DATE,\n    SENDER\n  }\n\n  void addHeader(Headers header, String value);\n\n  String getHeader(Headers header);\n\n  Map<Headers, String> getHeaders();\n\n  void setBody(String body);\n\n  String getBody();\n}\n"
  },
  {
    "path": "poison-pill/src/main/java/com/iluwatar/poison/pill/MessageQueue.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\n/**\n * Represents abstraction of channel (or pipe) that bounds {@link Producer} and {@link Consumer}.\n */\npublic interface MessageQueue extends MqPublishPoint, MqSubscribePoint {}\n"
  },
  {
    "path": "poison-pill/src/main/java/com/iluwatar/poison/pill/MqPublishPoint.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\n/** Endpoint to publish {@link Message} to queue. */\npublic interface MqPublishPoint {\n\n  void put(Message msg) throws InterruptedException;\n}\n"
  },
  {
    "path": "poison-pill/src/main/java/com/iluwatar/poison/pill/MqSubscribePoint.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\n/** Endpoint to retrieve {@link Message} from queue. */\npublic interface MqSubscribePoint {\n\n  Message take() throws InterruptedException;\n}\n"
  },
  {
    "path": "poison-pill/src/main/java/com/iluwatar/poison/pill/Producer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\nimport com.iluwatar.poison.pill.Message.Headers;\nimport java.util.Date;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Class responsible for producing unit of work that can be expressed as message and submitted to\n * queue.\n */\n@Slf4j\npublic class Producer {\n\n  private final MqPublishPoint queue;\n  private final String name;\n  private boolean isStopped;\n\n  /** Constructor. */\n  public Producer(String name, MqPublishPoint queue) {\n    this.name = name;\n    this.queue = queue;\n    this.isStopped = false;\n  }\n\n  /** Send message to queue. */\n  public void send(String body) {\n    if (isStopped) {\n      throw new IllegalStateException(\n          String.format(\n              \"Producer %s was stopped and fail to deliver requested message [%s].\", body, name));\n    }\n    var msg = new SimpleMessage();\n    msg.addHeader(Headers.DATE, new Date().toString());\n    msg.addHeader(Headers.SENDER, name);\n    msg.setBody(body);\n\n    try {\n      queue.put(msg);\n    } catch (InterruptedException e) {\n      // allow thread to exit\n      LOGGER.error(\"Exception caught.\", e);\n    }\n  }\n\n  /** Stop system by sending poison pill. */\n  public void stop() {\n    isStopped = true;\n    try {\n      queue.put(Message.POISON_PILL);\n    } catch (InterruptedException e) {\n      // allow thread to exit\n      LOGGER.error(\"Exception caught.\", e);\n    }\n  }\n}\n"
  },
  {
    "path": "poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessage.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/** {@link Message} basic implementation. */\npublic class SimpleMessage implements Message {\n\n  private final Map<Headers, String> headers = new HashMap<>();\n  private String body;\n\n  @Override\n  public void addHeader(Headers header, String value) {\n    headers.put(header, value);\n  }\n\n  @Override\n  public String getHeader(Headers header) {\n    return headers.get(header);\n  }\n\n  @Override\n  public Map<Headers, String> getHeaders() {\n    return Collections.unmodifiableMap(headers);\n  }\n\n  @Override\n  public void setBody(String body) {\n    this.body = body;\n  }\n\n  @Override\n  public String getBody() {\n    return body;\n  }\n}\n"
  },
  {
    "path": "poison-pill/src/main/java/com/iluwatar/poison/pill/SimpleMessageQueue.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.BlockingQueue;\n\n/** Bounded blocking queue wrapper. */\npublic class SimpleMessageQueue implements MessageQueue {\n\n  private final BlockingQueue<Message> queue;\n\n  public SimpleMessageQueue(int bound) {\n    queue = new ArrayBlockingQueue<>(bound);\n  }\n\n  @Override\n  public void put(Message msg) throws InterruptedException {\n    queue.put(msg);\n  }\n\n  @Override\n  public Message take() throws InterruptedException {\n    return queue.take();\n  }\n}\n"
  },
  {
    "path": "poison-pill/src/test/java/com/iluwatar/poison/pill/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.time.LocalDateTime;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/** ConsumerTest */\nclass ConsumerTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(Consumer.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  @Test\n  void testConsume() throws Exception {\n    final var messages =\n        List.of(\n            createMessage(\"you\", \"Hello!\"),\n            createMessage(\"me\", \"Hi!\"),\n            Message.POISON_PILL,\n            createMessage(\"late_for_the_party\", \"Hello? Anyone here?\"));\n\n    final var queue = new SimpleMessageQueue(messages.size());\n    for (final var message : messages) {\n      queue.put(message);\n    }\n\n    new Consumer(\"NSA\", queue).consume();\n\n    assertTrue(appender.logContains(\"Message [Hello!] from [you] received by [NSA]\"));\n    assertTrue(appender.logContains(\"Message [Hi!] from [me] received by [NSA]\"));\n    assertTrue(appender.logContains(\"Consumer NSA receive request to terminate.\"));\n  }\n\n  /**\n   * Create a new message from the given sender with the given message body\n   *\n   * @param sender The sender's name\n   * @param message The message body\n   * @return The message instance\n   */\n  private static Message createMessage(final String sender, final String message) {\n    final var msg = new SimpleMessage();\n    msg.addHeader(Message.Headers.SENDER, sender);\n    msg.addHeader(Message.Headers.DATE, LocalDateTime.now().toString());\n    msg.setBody(message);\n    return msg;\n  }\n\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender(Class clazz) {\n      ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public boolean logContains(String message) {\n      return log.stream().map(ILoggingEvent::getFormattedMessage).anyMatch(message::equals);\n    }\n  }\n}\n"
  },
  {
    "path": "poison-pill/src/test/java/com/iluwatar/poison/pill/PoisonMessageTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\nimport static com.iluwatar.poison.pill.Message.Headers;\nimport static com.iluwatar.poison.pill.Message.POISON_PILL;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nimport org.junit.jupiter.api.Test;\n\n/** PoisonMessageTest */\nclass PoisonMessageTest {\n\n  @Test\n  void testAddHeader() {\n    assertThrows(\n        UnsupportedOperationException.class, () -> POISON_PILL.addHeader(Headers.SENDER, \"sender\"));\n  }\n\n  @Test\n  void testGetHeader() {\n    assertThrows(UnsupportedOperationException.class, () -> POISON_PILL.getHeader(Headers.SENDER));\n  }\n\n  @Test\n  void testGetHeaders() {\n    assertThrows(UnsupportedOperationException.class, POISON_PILL::getHeaders);\n  }\n\n  @Test\n  void testSetBody() {\n    assertThrows(UnsupportedOperationException.class, () -> POISON_PILL.setBody(\"Test message.\"));\n  }\n\n  @Test\n  void testGetBody() {\n    assertThrows(UnsupportedOperationException.class, POISON_PILL::getBody);\n  }\n}\n"
  },
  {
    "path": "poison-pill/src/test/java/com/iluwatar/poison/pill/ProducerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.fail;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport org.junit.jupiter.api.Test;\nimport org.mockito.ArgumentCaptor;\n\n/** ProducerTest */\nclass ProducerTest {\n\n  @Test\n  void testSend() throws Exception {\n    final var publishPoint = mock(MqPublishPoint.class);\n    final var producer = new Producer(\"producer\", publishPoint);\n    verifyNoMoreInteractions(publishPoint);\n\n    producer.send(\"Hello!\");\n\n    final var messageCaptor = ArgumentCaptor.forClass(Message.class);\n    verify(publishPoint).put(messageCaptor.capture());\n\n    final var message = messageCaptor.getValue();\n    assertNotNull(message);\n    assertEquals(\"producer\", message.getHeader(Message.Headers.SENDER));\n    assertNotNull(message.getHeader(Message.Headers.DATE));\n    assertEquals(\"Hello!\", message.getBody());\n\n    verifyNoMoreInteractions(publishPoint);\n  }\n\n  @Test\n  void testStop() throws Exception {\n    final var publishPoint = mock(MqPublishPoint.class);\n    final var producer = new Producer(\"producer\", publishPoint);\n    verifyNoMoreInteractions(publishPoint);\n\n    producer.stop();\n    verify(publishPoint).put(eq(Message.POISON_PILL));\n\n    try {\n      producer.send(\"Hello!\");\n      fail(\"Expected 'IllegalStateException' at this point, since the producer has stopped!\");\n    } catch (IllegalStateException e) {\n      assertNotNull(e);\n      assertNotNull(e.getMessage());\n      assertEquals(\n          \"Producer Hello! was stopped and fail to deliver requested message [producer].\",\n          e.getMessage());\n    }\n\n    verifyNoMoreInteractions(publishPoint);\n  }\n}\n"
  },
  {
    "path": "poison-pill/src/test/java/com/iluwatar/poison/pill/SimpleMessageTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.poison.pill;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** SimpleMessageTest */\nclass SimpleMessageTest {\n\n  @Test\n  void testGetHeaders() {\n    final var message = new SimpleMessage();\n    assertNotNull(message.getHeaders());\n    assertTrue(message.getHeaders().isEmpty());\n\n    final var senderName = \"test\";\n    message.addHeader(Message.Headers.SENDER, senderName);\n    assertNotNull(message.getHeaders());\n    assertFalse(message.getHeaders().isEmpty());\n    assertEquals(senderName, message.getHeaders().get(Message.Headers.SENDER));\n  }\n\n  @Test\n  void testUnModifiableHeaders() {\n    final var message = new SimpleMessage();\n    final var headers = message.getHeaders();\n    assertThrows(\n        UnsupportedOperationException.class, () -> headers.put(Message.Headers.SENDER, \"test\"));\n  }\n}\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n  <project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <groupId>com.iluwatar</groupId>\n  <artifactId>java-design-patterns</artifactId>\n  <version>1.26.0-SNAPSHOT</version>\n  <packaging>pom</packaging>\n  <inceptionYear>2014-2022</inceptionYear>\n  <name>Java Design Patterns</name>\n  <description>Java Design Patterns</description>\n  <properties>\n    <!-- General properties -->\n    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n\n    <!-- Spring Boot related dependencies. Keep these in sync! -->\n    <spring-boot.version>3.4.4</spring-boot.version>\n    <junit.version>5.11.4</junit.version>\n    <mockito.version>5.14.2</mockito.version>\n    <logback.version>1.5.18</logback.version>\n    <slf4j.version>2.0.17</slf4j.version>\n\n    <!-- Other dependencies -->\n    <jacoco.version>0.8.13</jacoco.version>\n    <commons-dbcp.version>1.4</commons-dbcp.version>\n    <htmlunit.version>4.17.0</htmlunit.version>\n    <gson.version>2.11.0</gson.version>\n    <guice.version>6.0.0</guice.version>\n    <system-lambda.version>1.1.0</system-lambda.version>\n    <lombok.version>1.18.38</lombok.version>\n    <mongo.version>5.4.0</mongo.version>\n    <bson.version>5.4.0</bson.version>\n    <h2.version>2.3.232</h2.version>\n\n    <!-- Plugins -->\n    <maven-surefire-plugin.version>3.5.2</maven-surefire-plugin.version>\n    <license-maven-plugin.version>5.0.0</license-maven-plugin.version>\n    <maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>\n\n    <!-- SonarCloud -->\n    <sonar-maven-plugin.version>5.1.0.4751</sonar-maven-plugin.version>\n    <sonar.host.url>https://sonarcloud.io</sonar.host.url>\n    <sonar.organization>iluwatar</sonar.organization>\n    <sonar.projectKey>iluwatar_java-design-patterns</sonar.projectKey>\n    <sonar.moduleKey>${project.artifactId}</sonar.moduleKey>\n    <sonar.projectName>Java Design Patterns</sonar.projectName>\n  </properties>\n  <modules>\n    <module>abstract-document</module>\n    <module>abstract-factory</module>\n    <module>active-object</module>\n    <module>acyclic-visitor</module>\n    <module>adapter</module>\n    <module>ambassador</module>\n    <module>anti-corruption-layer</module>\n    <module>arrange-act-assert</module>\n    <module>async-method-invocation</module>\n    <module>balking</module>\n    <module>bloc</module>\n    <module>bridge</module>\n    <module>builder</module>\n    <module>business-delegate</module>\n    <module>bytecode</module>\n    <module>caching</module>\n    <module>callback</module>\n    <module>chain-of-responsibility</module>\n    <module>circuit-breaker</module>\n    <module>clean-architecture</module>\n    <module>client-session</module>\n    <module>collecting-parameter</module>\n    <module>collection-pipeline</module>\n    <module>combinator</module>\n    <module>command</module>\n    <module>command-query-responsibility-segregation</module>\n    <module>commander</module>\n    <module>component</module>\n    <module>composite</module>\n    <module>composite-entity</module>\n    <module>composite-view</module>\n    <module>context-object</module>\n    <module>converter</module>\n    <module>curiously-recurring-template-pattern</module>\n    <module>currying</module>\n      <module>dao-factory</module>\n    <module>data-access-object</module>\n    <module>data-bus</module>\n    <module>data-locality</module>\n    <module>data-mapper</module>\n    <module>data-transfer-object</module>\n    <module>decorator</module>\n    <module>delegation</module>\n    <module>dependency-injection</module>\n    <module>dirty-flag</module>\n    <module>domain-model</module>\n    <module>double-buffer</module>\n    <module>double-checked-locking</module>\n    <module>double-dispatch</module>\n    <module>dynamic-proxy</module>\n    <module>event-aggregator</module>\n    <module>event-based-asynchronous</module>\n    <module>event-driven-architecture</module>\n    <module>event-queue</module>\n    <module>event-sourcing</module>\n    <module>execute-around</module>\n    <module>extension-objects</module>\n    <module>facade</module>\n    <module>factory</module>\n    <module>factory-kit</module>\n    <module>factory-method</module>\n    <module>fanout-fanin</module>\n    <module>feature-toggle</module>\n    <module>filterer</module>\n    <module>fluent-interface</module>\n    <module>flux</module>\n    <module>flyweight</module>\n    <module>front-controller</module>\n    <module>function-composition</module>\n    <module>game-loop</module>\n    <module>gateway</module>\n    <module>guarded-suspension</module>\n    <module>half-sync-half-async</module>\n    <module>health-check</module>\n    <module>hexagonal-architecture</module>\n    <module>identity-map</module>\n    <module>intercepting-filter</module>\n    <module>interpreter</module>\n    <module>iterator</module>\n    <module>layered-architecture</module>\n    <module>lazy-loading</module>\n    <module>leader-election</module>\n    <module>leader-followers</module>\n    <module>lockable-object</module>\n    <module>map-reduce</module>\n    <module>marker-interface</module>\n    <module>master-worker</module>\n    <module>mediator</module>\n    <module>memento</module>\n    <module>metadata-mapping</module>\n    <module>microservices-aggregrator</module>\n    <module>microservices-api-gateway</module>\n    <module>microservices-client-side-ui-composition</module>\n    <module>microservices-distributed-tracing</module>\n    <module>microservices-idempotent-consumer</module>\n    <module>microservices-log-aggregation</module>\n    <module>microservices-self-registration</module>\n    <module>model-view-controller</module>\n    <module>model-view-intent</module>\n    <module>model-view-presenter</module>\n    <module>model-view-viewmodel</module>\n    <module>monad</module>\n    <module>money</module>\n    <module>monitor</module>\n    <module>monolithic-architecture</module>\n    <module>monostate</module>\n    <module>multiton</module>\n    <module>mute-idiom</module>\n    <module>notification</module>\n    <module>null-object</module>\n    <module>object-mother</module>\n    <module>object-pool</module>\n    <module>observer</module>\n    <module>optimistic-offline-lock</module>\n    <module>page-controller</module>\n    <module>page-object</module>\n    <module>parameter-object</module>\n    <module>partial-response</module>\n    <module>pipeline</module>\n    <module>poison-pill</module>\n    <module>presentation-model</module>\n    <module>private-class-data</module>\n    <module>producer-consumer</module>\n    <module>promise</module>\n    <module>property</module>\n    <module>prototype</module>\n    <module>proxy</module>\n    <module>publish-subscribe</module>\n    <module>queue-based-load-leveling</module>\n    <module>reactor</module>\n    <module>registry</module>\n    <module>repository</module>\n    <module>resource-acquisition-is-initialization</module>\n    <module>retry</module>\n    <module>role-object</module>\n    <module>saga</module>\n    <module>separated-interface</module>\n    <module>serialized-entity</module>\n    <module>serialized-lob</module>\n    <module>servant</module>\n    <module>server-session</module>\n    <module>service-layer</module>\n    <module>service-locator</module>\n    <module>service-stub</module>\n    <module>service-to-worker</module>\n    <module>session-facade</module>\n    <module>sharding</module>\n    <module>single-table-inheritance</module>\n    <module>singleton</module>\n    <module>spatial-partition</module>\n    <module>special-case</module>\n    <module>specification</module>\n    <module>state</module>\n    <module>step-builder</module>\n    <module>strangler</module>\n    <module>strategy</module>\n    <module>subclass-sandbox</module>\n    <module>table-inheritance</module>\n    <module>table-module</module>\n    <module>template-method</module>\n    <module>templateview</module>\n    <module>thread-pool-executor</module>\n    <module>throttling</module>\n    <module>tolerant-reader</module>\n    <module>trampoline</module>\n    <module>transaction-script</module>\n    <module>twin</module>\n    <module>type-object</module>\n    <module>unit-of-work</module>\n    <module>update-method</module>\n    <module>value-object</module>\n    <module>version-number</module>\n    <module>view-helper</module>\n    <module>virtual-proxy</module>\n    <module>visitor</module>\n    <module>backpressure</module>\n    <module>actor-model</module>\n    <module>rate-limiting-pattern</module>\n  </modules>\n  <repositories>\n    <repository>\n      <id>jitpack.io</id>\n      <url>https://jitpack.io</url>\n    </repository>\n  </repositories>\n  <dependencyManagement>\n    <dependencies>\n      <dependency>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter</artifactId>\n        <version>${spring-boot.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-web</artifactId>\n        <version>${spring-boot.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-actuator</artifactId>\n        <version>${spring-boot.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-data-jpa</artifactId>\n        <version>${spring-boot.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-test</artifactId>\n        <scope>test</scope>\n        <version>${spring-boot.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>commons-dbcp</groupId>\n        <artifactId>commons-dbcp</artifactId>\n        <version>${commons-dbcp.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>org.htmlunit</groupId>\n        <artifactId>htmlunit</artifactId>\n        <version>${htmlunit.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>com.google.code.gson</groupId>\n        <artifactId>gson</artifactId>\n        <version>${gson.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>com.google.inject</groupId>\n        <artifactId>guice</artifactId>\n        <version>${guice.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>com.github.stefanbirkner</groupId>\n        <artifactId>system-lambda</artifactId>\n        <version>${system-lambda.version}</version>\n        <scope>test</scope>\n      </dependency>\n      <dependency>\n        <groupId>org.junit.jupiter</groupId>\n        <artifactId>junit-jupiter-engine</artifactId>\n        <version>${junit.version}</version>\n        <scope>test</scope>\n      </dependency>\n      <dependency>\n        <groupId>org.junit.jupiter</groupId>\n        <artifactId>junit-jupiter-params</artifactId>\n        <version>${junit.version}</version>\n        <scope>test</scope>\n      </dependency>\n      <dependency>\n        <groupId>org.junit.jupiter</groupId>\n        <artifactId>junit-jupiter-migrationsupport</artifactId>\n        <version>${junit.version}</version>\n        <scope>test</scope>\n      </dependency>\n      <dependency>\n        <groupId>org.slf4j</groupId>\n        <artifactId>slf4j-api</artifactId>\n        <version>${slf4j.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>ch.qos.logback</groupId>\n        <artifactId>logback-classic</artifactId>\n        <version>${logback.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>org.mockito</groupId>\n        <artifactId>mockito-core</artifactId>\n        <version>${mockito.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>org.mongodb</groupId>\n        <artifactId>bson</artifactId>\n        <version>${bson.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>org.mongodb</groupId>\n        <artifactId>mongodb-driver-legacy</artifactId>\n        <version>${mongo.version}</version>\n      </dependency>\n      <dependency>\n        <groupId>com.h2database</groupId>\n        <artifactId>h2</artifactId>\n        <version>${h2.version}</version>\n      </dependency>\n    </dependencies>\n  </dependencyManagement>\n  <dependencies>\n    <dependency>\n      <groupId>org.projectlombok</groupId>\n      <artifactId>lombok</artifactId>\n      <version>${lombok.version}</version>\n      <scope>provided</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <pluginManagement>\n      <plugins>\n        <plugin>\n          <groupId>org.apache.maven.plugins</groupId>\n          <artifactId>maven-compiler-plugin</artifactId>\n          <version>${maven-compiler-plugin.version}</version>\n          <configuration>\n            <source>21</source>\n            <target>21</target>\n            <annotationProcessorPaths>\n              <path>\n                <groupId>org.projectlombok</groupId>\n                <artifactId>lombok</artifactId>\n                <version>${lombok.version}</version>\n              </path>\n            </annotationProcessorPaths>\n          </configuration>\n        </plugin>\n        <plugin>\n          <groupId>org.apache.maven.plugins</groupId>\n          <artifactId>maven-surefire-plugin</artifactId>\n          <version>${maven-surefire-plugin.version}</version>\n        </plugin>\n        <plugin>\n          <groupId>org.springframework.boot</groupId>\n          <artifactId>spring-boot-maven-plugin</artifactId>\n        </plugin>\n        <!-- Maven assembly plugin template for all child project to follow -->\n        <plugin>\n          <groupId>org.apache.maven.plugins</groupId>\n          <artifactId>maven-assembly-plugin</artifactId>\n          <executions>\n            <execution>\n              <phase>package</phase>\n              <goals>\n                <goal>single</goal>\n              </goals>\n              <configuration>\n                <descriptorRefs>\n                  <descriptorRef>jar-with-dependencies</descriptorRef>\n                </descriptorRefs>\n                <!-- below two line make sure the fat jar is sharing the same name as of project name -->\n                <finalName>${project.artifactId}-${project.version}</finalName>\n                <appendAssemblyId>false</appendAssemblyId>\n              </configuration>\n            </execution>\n          </executions>\n        </plugin>\n        <plugin>\n          <groupId>org.sonarsource.scanner.maven</groupId>\n          <artifactId>sonar-maven-plugin</artifactId>\n          <version>${sonar-maven-plugin.version}</version>\n        </plugin>\n      </plugins>\n    </pluginManagement>\n    <plugins>\n      <plugin>\n        <groupId>com.mycila</groupId>\n        <artifactId>license-maven-plugin</artifactId>\n        <version>${license-maven-plugin.version}</version>\n        <configuration>\n          <licenseSets>\n            <licenseSet>\n              <multi>\n                <preamble><![CDATA[This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).]]></preamble>\n                <header>com/mycila/maven/plugin/license/templates/MIT.txt</header>\n              </multi>\n              <excludes>\n                <exclude>**/README</exclude>\n                <exclude>src/test/resources/**</exclude>\n                <exclude>src/main/resources/**</exclude>\n                <exclude>checkstyle-suppressions.xml</exclude>\n              </excludes>\n            </licenseSet>\n          </licenseSets>\n          <properties>\n            <owner>Ilkka Seppälä</owner>\n            <email>iluwatar@gmail.com</email>\n          </properties>\n        </configuration>\n        <executions>\n          <execution>\n            <id>install-format</id>\n            <phase>install</phase>\n            <goals>\n              <goal>format</goal>\n            </goals>\n          </execution>\n        </executions>\n      </plugin>\n      <plugin>\n        <groupId>org.jacoco</groupId>\n        <artifactId>jacoco-maven-plugin</artifactId>\n        <version>${jacoco.version}</version>\n        <executions>\n          <execution>\n            <id>prepare-agent</id>\n            <goals>\n              <goal>prepare-agent</goal>\n            </goals>\n          </execution>\n          <execution>\n            <id>report</id>\n            <goals>\n              <goal>report</goal>\n            </goals>\n          </execution>\n        </executions>\n      </plugin>\n      <plugin>\n        <groupId>com.diffplug.spotless</groupId>\n        <artifactId>spotless-maven-plugin</artifactId>\n        <version>2.44.4</version> <!-- Use latest version -->\n        <executions>\n          <execution>\n            <goals>\n              <goal>check</goal>     <!-- Run to check formatting -->\n              <goal>apply</goal>     <!-- Run to format automatically -->\n            </goals>\n          </execution>\n        </executions>\n        <configuration>\n          <java>\n            <googleJavaFormat>\n              <version>1.17.0</version> <!-- Optional: choose the GJF version -->\n            </googleJavaFormat>\n          </java>\n        </configuration>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "presentation-model/README.md",
    "content": "---\ntitle: \"Presentation Model Pattern in Java: Enhancing UI Design with Robust Data Management\"\nshortTitle: Presentation Model\ndescription: \"Explore the Presentation Model Pattern at Java Design Patterns. Learn how it separates UI from business logic to enhance flexibility, maintainability, and testability. Ideal for Java developers interested in robust design solutions.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - Decoupling\n  - Encapsulation\n  - Presentation\n  - Testing\n---\n\n## Also known as\n\n* Application Model\n\n## Intent of Presentation Model Design Pattern\n\nThe Presentation Model pattern separates the logic of the user interface (UI) from the business logic by creating a model that represents the data and behavior of the UI independently.\n\n## Detailed Explanation of Presentation Model Pattern with Real-World Examples\n\nReal-world example\n\n> An analogous real-world example of the Presentation Model design pattern is the relationship between a scriptwriter, an actor, and a director in a theater production. The scriptwriter creates the script (analogous to the business logic), which the actor then interprets and performs on stage (analogous to the user interface). The director acts as the intermediary, ensuring that the actor's performance aligns with the script and the vision of the play (similar to the Presentation Model coordinating the UI and the business logic). This separation allows the script to be rewritten without changing the actor's techniques or the director's interpretation, ensuring flexibility and maintainability.\n\nIn plain words\n\n> The Presentation Model design pattern separates the UI logic from the business logic by creating an intermediate model that represents the data and behavior of the UI independently, enhancing testability, maintainability, and flexibility.\n\nArchitecture diagram\n\n![Presentation Model Architecture Diagram](./etc/presentation-model-architecture-diagram.png)\n\n## Programmatic Example of Presentation Model Pattern in Java\n\nThe Presentation Model design pattern is a pattern that separates the responsibility of managing the state and behavior of the GUI in a separate model class. This model class is not tied to the view and can be used to test the GUI behavior independently of the GUI itself.\n\nLet's take a look at the code provided and see how it implements the Presentation Model pattern.\n\nFirst, we have the `Album` class. This class represents the data model in our application. It contains properties like `title`, `artist`, `isClassical`, and `composer`.\n\n```java\n@Setter\n@Getter\n@AllArgsConstructor\npublic class Album {\n    private String title;\n    private String artist;\n    private boolean isClassical;\n    private String composer;\n}\n```\n\nNext, we have the `DisplayedAlbums` class. This class is responsible for managing a collection of `Album` objects.\n\n```java\n@Slf4j\n@Getter\npublic class DisplayedAlbums {\n    private final List<Album> albums;\n\n    public DisplayedAlbums() {\n        this.albums = new ArrayList<>();\n    }\n\n    public void addAlbums(final String title,\n                          final String artist, final boolean isClassical,\n                          final String composer) {\n        if (isClassical) {\n            this.albums.add(new Album(title, artist, true, composer));\n        } else {\n            this.albums.add(new Album(title, artist, false, \"\"));\n        }\n    }\n}\n```\n\nThe `PresentationModel` class is where the Presentation Model pattern is implemented. This class is responsible for managing the state and behavior of the GUI. It contains a reference to the `DisplayedAlbums` object and provides methods for interacting with the selected album.\n\n```java\npublic class PresentationModel {\n    \n    private final DisplayedAlbums data;\n    private int selectedAlbumNumber;\n    private Album selectedAlbum;\n\n    public PresentationModel(final DisplayedAlbums dataOfAlbums) {\n        this.data = dataOfAlbums;\n        this.selectedAlbumNumber = 1;\n        this.selectedAlbum = this.data.getAlbums().get(0);\n    }\n\n    // other methods...\n}\n```\n\nThe `App` class is the entry point of the application. It creates a `View` object and calls its `createView` method to start the GUI.\n\n```java\npublic final class App {\n    public static void main(final String[] args) {\n        var view = new View();\n        view.createView();\n    }\n}\n```\n\nIn this example, the `PresentationModel` class is the Presentation Model. It separates the GUI's state and behavior from the `View` class, allowing the GUI to be tested independently from the actual GUI components.\n\n## When to Use the Presentation Model Pattern in Java\n\nUse the Presentation Model Pattern when\n\n* Use when you want to decouple the UI from the underlying business logic to allow for easier testing, maintenance, and the ability to support multiple views or platforms.\n* Ideal for applications where the UI changes frequently or needs to be different across various platforms while keeping the core logic intact.\n\n## Real-World Applications of Presentation Model Pattern in Java\n\nThe Presentation Model pattern is used in:\n\n* JavaFX applications: Utilizing JavaFX properties and bindings to create a clear separation between the UI and business logic.\n* Swing applications: Employing a Presentation Model to decouple Swing components from the application logic, enhancing testability and flexibility.\n* Android apps: Implementing MVVM architecture using ViewModel classes to manage UI-related data and lifecycle-aware components.\n\n## Benefits and Trade-offs of Presentation Model Pattern\n\nBenefits:\n\n* Decoupling: Enhances [separation of concerns](https://java-design-patterns.com/principles/#separation-of-concerns), making the system more modular and testable.\n* Testability: Facilitates unit testing of UI logic without the need for actual UI components.\n* Maintainability: Simplifies maintenance by isolating changes to the UI or business logic.\n* Flexibility: Supports multiple views for the same model, making it easier to adapt the UI for different platforms.\n\nTrade-offs:\n\n* Complexity: Can introduce additional layers and complexity in the application architecture.\n* Learning Curve: May require a deeper understanding of binding mechanisms and state management.\n\n## Related Java Design Patterns\n\n* [Model-View-Controller (MVC)](https://java-design-patterns.com/patterns/model-view-controller/): Similar in that it separates concerns, but Presentation Model encapsulates more of the view logic.\n* [Model-View-Presenter (MVP)](https://java-design-patterns.com/patterns/model-view-presenter/): Another UI pattern focusing on separation of concerns, but with a different interaction model.\n* [Observer](https://java-design-patterns.com/patterns/observer/): Often used within the Presentation Model to update the UI when the model changes.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Presentation Model (Martin Fowler)](https://martinfowler.com/eaaDev/PresentationModel.html)\n"
  },
  {
    "path": "presentation-model/etc/presentation-model.urm.puml",
    "content": "@startuml\npackage com.iluwatar.presentationmodel {\n  class Album {\n    ~ artist : String\n    ~ composer : String\n    ~ isClassical : boolean\n    ~ rowId : int\n    ~ title : String\n    + Album(rowId : int, title : String, artist : String, isClassical : boolean, composer : String)\n  }\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class DsAlbum {\n    + albums : List<Album>\n    + albumsCache : List<Album>\n    + DsAlbum()\n    + acceptChanges()\n    + addAlbums(rowId : int, title : String, artist : String, isClassical : boolean, composer : String)\n  }\n  class PresentationMod {\n    - data : DsAlbum\n    - selectedAlbum : Album\n    - selectedAlbumNumber : int\n    + PresentationMod(data : DsAlbum)\n    + albumDataSet() : DsAlbum {static}\n    + getAlbumList() : String[]\n    + getArtist() : String\n    + getComposer() : String\n    + getIsClassical() : boolean\n    + getTitle() : String\n    + setArtist(value : String)\n    + setComposer(value : String)\n    + setIsClassical(value : boolean)\n    + setSelectedAlbumNumber(selectedAlbumNumber : int)\n    + setTitle(value : String)\n  }\n  class View {\n    ~ albumList : JList<String>\n    ~ apply : JButton\n    ~ cancel : JButton\n    ~ chkClassical : JCheckBox\n    ~ model : PresentationMod\n    ~ notLoadView : boolean\n    ~ txtArtist : TextField\n    ~ txtComposer : TextField\n    ~ txtTitle : TextField\n    + View()\n    + createView()\n    + loadFromPMod()\n    + saveToPMod()\n  }\n}\nPresentationMod -->  \"-selectedAlbum\" Album\nView -->  \"-model\" PresentationMod\nDsAlbum -->  \"-albums\" Album\nPresentationMod -->  \"-data\" DsAlbum\n@enduml"
  },
  {
    "path": "presentation-model/etc/presentation.urm.puml",
    "content": "@startuml\npackage com.iluwatar.presentationmodel {\n  class Album {\n    - artist : String\n    - composer : String\n    - isClassical : boolean\n    - title : String\n    + Album(title : String, artist : String, isClassical : boolean, composer : String)\n    + getArtist() : String\n    + getComposer() : String\n    + getTitle() : String\n    + isClassical() : boolean\n    + setArtist(artist : String)\n    + setClassical(isClassical : boolean)\n    + setComposer(composer : String)\n    + setTitle(title : String)\n  }\n  class App {\n    - LOGGER : Logger {static}\n    - App()\n    + main(args : String[]) {static}\n  }\n  class DisplayedAlbums {\n    - LOGGER : Logger {static}\n    - albums : List<Album>\n    + DisplayedAlbums()\n    + addAlbums(title : String, artist : String, isClassical : boolean, composer : String)\n    + getAlbums() : List<Album>\n  }\n  class PresentationModel {\n    - LOGGER : Logger {static}\n    - data : DisplayedAlbums\n    - selectedAlbum : Album\n    - selectedAlbumNumber : int\n    + PresentationModel(dataOfAlbums : DisplayedAlbums)\n    + albumDataSet() : DisplayedAlbums {static}\n    + getAlbumList() : String[]\n    + getArtist() : String\n    + getComposer() : String\n    + getIsClassical() : boolean\n    + getTitle() : String\n    + setArtist(value : String)\n    + setComposer(value : String)\n    + setIsClassical(value : boolean)\n    + setSelectedAlbumNumber(albumNumber : int)\n    + setTitle(value : String)\n  }\n  class View {\n    ~ HEIGHT : int {static}\n    ~ HEIGHT_TXT : int {static}\n    ~ LOCATION_X : int {static}\n    ~ LOCATION_Y : int {static}\n    - LOGGER : Logger {static}\n    ~ WIDTH : int {static}\n    ~ WIDTH_TXT : int {static}\n    - albumList : JList<String>\n    - apply : JButton\n    - cancel : JButton\n    - chkClassical : JCheckBox\n    - model : PresentationModel\n    - txtArtist : TextField\n    - txtComposer : TextField\n    - txtTitle : TextField\n    + View()\n    + createView()\n    + getAlbumList() : JList<String>\n    + getApply() : JButton\n    + getCancel() : JButton\n    + getChkClassical() : JCheckBox\n    + getModel() : PresentationModel\n    + getTxtArtist() : TextField\n    + getTxtComposer() : TextField\n    + getTxtTitle() : TextField\n    + loadFromPMod()\n    + saveToPMod()\n  }\n}\nDisplayedAlbums -->  \"-albums\" Album\nView -->  \"-model\" PresentationModel\nPresentationModel -->  \"-data\" DisplayedAlbums\nPresentationModel -->  \"-selectedAlbum\" Album\n@enduml"
  },
  {
    "path": "presentation-model/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>presentation-model</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <!-- Maven assembly plugin is invoked with default setting which we have\n            in parent pom and specifying the class having main method -->\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.presentationmodel.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "presentation-model/src/main/java/com/iluwatar/presentationmodel/Album.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.presentationmodel;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** A class used to store the information of album. */\n@Setter\n@Getter\n@AllArgsConstructor\npublic class Album {\n  /** the title of the album. */\n  private String title;\n\n  /** the artist name of the album. */\n  private String artist;\n\n  /** is the album classical, true or false. */\n  private boolean isClassical;\n\n  /** only when the album is classical, composer can have content. */\n  private String composer;\n}\n"
  },
  {
    "path": "presentation-model/src/main/java/com/iluwatar/presentationmodel/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.presentationmodel;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Presentation model pattern is used to divide the presentation and controlling. This demo is a\n * used to information of some albums with GUI.\n */\n@Slf4j\npublic final class App {\n  /** the constructor. */\n  private App() {}\n\n  /**\n   * main method.\n   *\n   * @param args args\n   */\n  public static void main(final String[] args) {\n    var view = new View();\n    view.createView();\n  }\n}\n"
  },
  {
    "path": "presentation-model/src/main/java/com/iluwatar/presentationmodel/DisplayedAlbums.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.presentationmodel;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/** a class used to deal with albums. */\n@Slf4j\n@Getter\npublic class DisplayedAlbums {\n  /** albums a list of albums. */\n  private final List<Album> albums;\n\n  /** a constructor method. */\n  public DisplayedAlbums() {\n    this.albums = new ArrayList<>();\n  }\n\n  /**\n   * a method used to add a new album to album list.\n   *\n   * @param title the title of the album.\n   * @param artist the artist name of the album.\n   * @param isClassical is the album classical, true or false.\n   * @param composer only when the album is classical, composer can have content.\n   */\n  public void addAlbums(\n      final String title, final String artist, final boolean isClassical, final String composer) {\n    if (isClassical) {\n      this.albums.add(new Album(title, artist, true, composer));\n    } else {\n      this.albums.add(new Album(title, artist, false, \"\"));\n    }\n  }\n}\n"
  },
  {
    "path": "presentation-model/src/main/java/com/iluwatar/presentationmodel/PresentationModel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.presentationmodel;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** The class between view and albums, it is used to control the data. */\n@Slf4j\npublic class PresentationModel {\n  /** the data of all albums that will be shown. */\n  private final DisplayedAlbums data;\n\n  /** the no of selected album. */\n  private int selectedAlbumNumber;\n\n  /** the selected album. */\n  private Album selectedAlbum;\n\n  /**\n   * Generates a set of data for testing.\n   *\n   * @return a instance of DsAlbum which store the data.\n   */\n  public static DisplayedAlbums albumDataSet() {\n    var titleList =\n        new String[] {\n          \"HQ\", \"The Rough Dancer and Cyclical Night\",\n          \"The Black Light\", \"Symphony No.5\"\n        };\n    var artistList =\n        new String[] {\n          \"Roy Harper\", \"Astor Piazzola\",\n          \"The Black Light\", \"CBSO\"\n        };\n    var isClassicalList = new boolean[] {false, false, false, true};\n    var composerList = new String[] {null, null, null, \"Sibelius\"};\n\n    var result = new DisplayedAlbums();\n    for (var i = 1; i <= titleList.length; i++) {\n      result.addAlbums(\n          titleList[i - 1], artistList[i - 1], isClassicalList[i - 1], composerList[i - 1]);\n    }\n    return result;\n  }\n\n  /**\n   * constructor method.\n   *\n   * @param dataOfAlbums the data of all the albums\n   */\n  public PresentationModel(final DisplayedAlbums dataOfAlbums) {\n    this.data = dataOfAlbums;\n    this.selectedAlbumNumber = 1;\n    this.selectedAlbum = this.data.getAlbums().get(0);\n  }\n\n  /**\n   * Changes the value of selectedAlbumNumber.\n   *\n   * @param albumNumber the number of album which is shown on the view.\n   */\n  public void setSelectedAlbumNumber(final int albumNumber) {\n    LOGGER.info(\"Change select number from {} to {}\", this.selectedAlbumNumber, albumNumber);\n    this.selectedAlbumNumber = albumNumber;\n    this.selectedAlbum = data.getAlbums().get(this.selectedAlbumNumber - 1);\n  }\n\n  /**\n   * get the title of selected album.\n   *\n   * @return the tile of selected album.\n   */\n  public String getTitle() {\n    return selectedAlbum.getTitle();\n  }\n\n  /**\n   * set the title of selected album.\n   *\n   * @param value the title which user want to user.\n   */\n  public void setTitle(final String value) {\n    LOGGER.info(\"Change album title from {} to {}\", selectedAlbum.getTitle(), value);\n    selectedAlbum.setTitle(value);\n  }\n\n  /**\n   * get the artist of selected album.\n   *\n   * @return the artist of selected album.\n   */\n  public String getArtist() {\n    return selectedAlbum.getArtist();\n  }\n\n  /**\n   * set the name of artist.\n   *\n   * @param value the name want artist to be.\n   */\n  public void setArtist(final String value) {\n    LOGGER.info(\"Change album artist from {} to {}\", selectedAlbum.getArtist(), value);\n    selectedAlbum.setArtist(value);\n  }\n\n  /**\n   * Gets a boolean value which represents whether the album is classical.\n   *\n   * @return is the album classical.\n   */\n  public boolean getIsClassical() {\n    return selectedAlbum.isClassical();\n  }\n\n  /**\n   * set the isClassical of album.\n   *\n   * @param value is the album classical.\n   */\n  public void setIsClassical(final boolean value) {\n    LOGGER.info(\"Change album isClassical from {} to {}\", selectedAlbum.isClassical(), value);\n    selectedAlbum.setClassical(value);\n  }\n\n  /**\n   * get is classical of the selected album.\n   *\n   * @return is the album classical.\n   */\n  public String getComposer() {\n    return selectedAlbum.isClassical() ? selectedAlbum.getComposer() : \"\";\n  }\n\n  /**\n   * Sets the name of composer when the album is classical.\n   *\n   * @param value the name of composer.\n   */\n  public void setComposer(final String value) {\n    if (selectedAlbum.isClassical()) {\n      LOGGER.info(\"Change album composer from {} to {}\", selectedAlbum.getComposer(), value);\n      selectedAlbum.setComposer(value);\n    } else {\n      LOGGER.info(\"Composer can not be changed\");\n    }\n  }\n\n  /**\n   * Gets a list of albums.\n   *\n   * @return the names of all the albums.\n   */\n  public String[] getAlbumList() {\n    var result = new String[data.getAlbums().size()];\n    for (var i = 0; i < result.length; i++) {\n      result[i] = data.getAlbums().get(i).getTitle();\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "presentation-model/src/main/java/com/iluwatar/presentationmodel/View.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.presentationmodel;\n\nimport java.awt.TextField;\nimport java.awt.event.MouseAdapter;\nimport java.awt.event.MouseEvent;\nimport javax.swing.Box;\nimport javax.swing.JButton;\nimport javax.swing.JCheckBox;\nimport javax.swing.JFrame;\nimport javax.swing.JList;\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Generates the GUI of albums. */\n@Getter\n@Slf4j\npublic class View {\n  /** the model that controls this view. */\n  private final PresentationModel model;\n\n  /** the filed to show and modify title. */\n  private TextField txtTitle;\n\n  /** the filed to show and modify the name of artist. */\n  private TextField txtArtist;\n\n  /** the checkbox for is classical. */\n  private JCheckBox chkClassical;\n\n  /** the filed to show and modify composer. */\n  private TextField txtComposer;\n\n  /** a list to show all the name of album. */\n  private JList<String> albumList;\n\n  /** a button to apply of all the change. */\n  private JButton apply;\n\n  /** roll back the change. */\n  private JButton cancel;\n\n  /** the value of the text field size. */\n  static final int WIDTH_TXT = 200;\n\n  static final int HEIGHT_TXT = 50;\n\n  /** the value of the GUI size and location. */\n  static final int LOCATION_X = 200;\n\n  static final int LOCATION_Y = 200;\n  static final int WIDTH = 500;\n  static final int HEIGHT = 300;\n\n  /** constructor method. */\n  public View() {\n    model = new PresentationModel(PresentationModel.albumDataSet());\n  }\n\n  /** save the data to PresentationModel. */\n  public void saveToMod() {\n    LOGGER.info(\"Save data to PresentationModel\");\n    model.setArtist(txtArtist.getText());\n    model.setTitle(txtTitle.getText());\n    model.setIsClassical(chkClassical.isSelected());\n    model.setComposer(txtComposer.getText());\n  }\n\n  /** load the data from PresentationModel. */\n  public void loadFromMod() {\n    LOGGER.info(\"Load data from PresentationModel\");\n    txtArtist.setText(model.getArtist());\n    txtTitle.setText(model.getTitle());\n    chkClassical.setSelected(model.getIsClassical());\n    txtComposer.setEditable(model.getIsClassical());\n    txtComposer.setText(model.getComposer());\n  }\n\n  /** initialize the GUI. */\n  public void createView() {\n    var frame = new JFrame(\"Album\");\n    var b1 = Box.createHorizontalBox();\n\n    frame.add(b1);\n    albumList = new JList<>(model.getAlbumList());\n    albumList.addMouseListener(\n        new MouseAdapter() {\n          @Override\n          public void mouseClicked(final MouseEvent e) {\n            model.setSelectedAlbumNumber(albumList.getSelectedIndex() + 1);\n            loadFromMod();\n          }\n        });\n    b1.add(albumList);\n\n    var b2 = Box.createVerticalBox();\n    b1.add(b2);\n\n    txtArtist = new TextField();\n    txtTitle = new TextField();\n\n    txtArtist.setSize(WIDTH_TXT, HEIGHT_TXT);\n    txtTitle.setSize(WIDTH_TXT, HEIGHT_TXT);\n\n    chkClassical = new JCheckBox();\n    txtComposer = new TextField();\n    chkClassical.addActionListener(\n        itemEvent -> {\n          txtComposer.setEditable(chkClassical.isSelected());\n          if (!chkClassical.isSelected()) {\n            txtComposer.setText(\"\");\n          }\n        });\n    txtComposer.setSize(WIDTH_TXT, HEIGHT_TXT);\n    txtComposer.setEditable(model.getIsClassical());\n\n    apply = new JButton(\"Apply\");\n    apply.addMouseListener(\n        new MouseAdapter() {\n          @Override\n          public void mouseClicked(final MouseEvent e) {\n            saveToMod();\n            loadFromMod();\n          }\n        });\n    cancel = new JButton(\"Cancel\");\n    cancel.addMouseListener(\n        new MouseAdapter() {\n          @Override\n          public void mouseClicked(final MouseEvent e) {\n            loadFromMod();\n          }\n        });\n\n    b2.add(txtArtist);\n    b2.add(txtTitle);\n\n    b2.add(chkClassical);\n    b2.add(txtComposer);\n\n    b2.add(apply);\n    b2.add(cancel);\n\n    frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);\n    frame.setBounds(LOCATION_X, LOCATION_Y, WIDTH, HEIGHT);\n    frame.setVisible(true);\n  }\n}\n"
  },
  {
    "path": "presentation-model/src/test/java/com/iluwatar/presentationmodel/AlbumTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.presentationmodel;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\nclass AlbumTest {\n  @Test\n  void testSetTitle() {\n    Album album = new Album(\"a\", \"b\", false, \"\");\n    album.setTitle(\"b\");\n    assertEquals(\"b\", album.getTitle());\n  }\n\n  @Test\n  void testSetArtist() {\n    Album album = new Album(\"a\", \"b\", false, \"\");\n    album.setArtist(\"c\");\n    assertEquals(\"c\", album.getArtist());\n  }\n\n  @Test\n  void testSetClassical() {\n    Album album = new Album(\"a\", \"b\", false, \"\");\n    album.setClassical(true);\n    assertTrue(album.isClassical());\n  }\n\n  @Test\n  void testSetComposer() {\n    Album album = new Album(\"a\", \"b\", false, \"\");\n    album.setClassical(true);\n    album.setComposer(\"w\");\n    assertEquals(\"w\", album.getComposer());\n  }\n}\n"
  },
  {
    "path": "presentation-model/src/test/java/com/iluwatar/presentationmodel/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.presentationmodel;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/**\n * Issue: Add at least one assertion to this test case.\n *\n * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link App}\n * throws an exception.\n */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "presentation-model/src/test/java/com/iluwatar/presentationmodel/DisplayedAlbumsTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.presentationmodel;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\nclass DisplayedAlbumsTest {\n  @Test\n  void testAdd_true() {\n    DisplayedAlbums displayedAlbums = new DisplayedAlbums();\n    displayedAlbums.addAlbums(\"title\", \"artist\", true, \"composer\");\n    assertEquals(\"composer\", displayedAlbums.getAlbums().get(0).getComposer());\n  }\n\n  @Test\n  void testAdd_false() {\n    DisplayedAlbums displayedAlbums = new DisplayedAlbums();\n    displayedAlbums.addAlbums(\"title\", \"artist\", false, \"composer\");\n    assertEquals(\"\", displayedAlbums.getAlbums().get(0).getComposer());\n  }\n}\n"
  },
  {
    "path": "presentation-model/src/test/java/com/iluwatar/presentationmodel/PresentationTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.presentationmodel;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.Arrays;\nimport org.junit.jupiter.api.Test;\n\nclass PresentationTest {\n  String[] albumList = {\n    \"HQ\", \"The Rough Dancer and Cyclical Night\", \"The Black Light\", \"Symphony No.5\"\n  };\n\n  @Test\n  void testCreateAlbumList() {\n    PresentationModel model = new PresentationModel(PresentationModel.albumDataSet());\n    String[] list = model.getAlbumList();\n    assertEquals(Arrays.toString(albumList), Arrays.toString(list));\n  }\n\n  @Test\n  void testSetSelectedAlbumNumber_1() {\n    PresentationModel model = new PresentationModel(PresentationModel.albumDataSet());\n    final int selectId = 2;\n    model.setSelectedAlbumNumber(selectId);\n    assertEquals(albumList[selectId - 1], model.getTitle());\n  }\n\n  @Test\n  void testSetSelectedAlbumNumber_2() {\n    PresentationModel model = new PresentationModel(PresentationModel.albumDataSet());\n    final int selectId = 4;\n    model.setSelectedAlbumNumber(selectId);\n    assertEquals(albumList[selectId - 1], model.getTitle());\n  }\n\n  @Test\n  void testSetTitle_1() {\n    PresentationModel model = new PresentationModel(PresentationModel.albumDataSet());\n    String testTitle = \"TestTile\";\n    model.setTitle(testTitle);\n    assertEquals(testTitle, model.getTitle());\n  }\n\n  @Test\n  void testSetTitle_2() {\n    PresentationModel model = new PresentationModel(PresentationModel.albumDataSet());\n    String testTitle = \"\";\n    model.setTitle(testTitle);\n    assertEquals(testTitle, model.getTitle());\n  }\n\n  @Test\n  void testSetArtist_1() {\n    PresentationModel model = new PresentationModel(PresentationModel.albumDataSet());\n    String testArtist = \"TestArtist\";\n    model.setArtist(testArtist);\n    assertEquals(testArtist, model.getArtist());\n  }\n\n  @Test\n  void testSetArtist_2() {\n    PresentationModel model = new PresentationModel(PresentationModel.albumDataSet());\n    String testArtist = \"\";\n    model.setArtist(testArtist);\n    assertEquals(testArtist, model.getArtist());\n  }\n\n  @Test\n  void testSetIsClassical() {\n    PresentationModel model = new PresentationModel(PresentationModel.albumDataSet());\n    model.setIsClassical(true);\n    assertTrue(model.getIsClassical());\n  }\n\n  @Test\n  void testSetComposer_false() {\n    PresentationModel model = new PresentationModel(PresentationModel.albumDataSet());\n    String testComposer = \"TestComposer\";\n\n    model.setIsClassical(false);\n    model.setComposer(testComposer);\n    assertEquals(\"\", model.getComposer());\n  }\n\n  @Test\n  void testSetComposer_true() {\n    PresentationModel model = new PresentationModel(PresentationModel.albumDataSet());\n    String testComposer = \"TestComposer\";\n\n    model.setIsClassical(true);\n    model.setComposer(testComposer);\n    assertEquals(testComposer, model.getComposer());\n  }\n}\n"
  },
  {
    "path": "presentation-model/src/test/java/com/iluwatar/presentationmodel/ViewTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.presentationmodel;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\nclass ViewTest {\n  String[] albumList = {\n    \"HQ\", \"The Rough Dancer and Cyclical Night\", \"The Black Light\", \"Symphony No.5\"\n  };\n\n  @Test\n  void testSave_setArtistAndTitle() {\n    View view = new View();\n    view.createView();\n    String testTitle = \"testTitle\";\n    String testArtist = \"testArtist\";\n    view.getTxtArtist().setText(testArtist);\n    view.getTxtTitle().setText(testTitle);\n    view.saveToMod();\n    view.loadFromMod();\n    assertEquals(testTitle, view.getModel().getTitle());\n    assertEquals(testArtist, view.getModel().getArtist());\n  }\n\n  @Test\n  void testSave_setClassicalAndComposer() {\n    View view = new View();\n    view.createView();\n    boolean isClassical = true;\n    String testComposer = \"testComposer\";\n    view.getChkClassical().setSelected(isClassical);\n    view.getTxtComposer().setText(testComposer);\n    view.saveToMod();\n    view.loadFromMod();\n    assertTrue(view.getModel().getIsClassical());\n    assertEquals(testComposer, view.getModel().getComposer());\n  }\n\n  @Test\n  void testLoad_1() {\n    View view = new View();\n    view.createView();\n    view.getModel().setSelectedAlbumNumber(2);\n    view.loadFromMod();\n    assertEquals(albumList[1], view.getModel().getTitle());\n  }\n\n  @Test\n  void testLoad_2() {\n    View view = new View();\n    view.createView();\n    view.getModel().setSelectedAlbumNumber(4);\n    view.loadFromMod();\n    assertEquals(albumList[3], view.getModel().getTitle());\n  }\n}\n"
  },
  {
    "path": "private-class-data/README.md",
    "content": "---\ntitle: \"Private Class Data Pattern in Java: Safeguarding Data Integrity with Encapsulation\"\nshortTitle: Private Class Data\ndescription: \"Explore the Private Class Data pattern in Java, ideal for enhancing data security and integrity in object-oriented programming. Learn how it prevents unintended data manipulation with encapsulation.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Abstraction\n  - Encapsulation\n  - Security\n---\n\n## Also known as\n\n* Data Hiding\n* Encapsulation\n\n## Intent of Private Class Data Design Pattern\n\nThe Private Class Data design pattern in Java focuses on restricting access to the internal state of an object, enhancing security and reducing risks of data corruption through controlled method access.\n\n## Detailed Explanation of Private Class Data Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy for the Private Class Data pattern is the way a bank protects customer account information. Just like a class with private fields, a bank keeps sensitive data such as account balances, transaction history, and personal information private and only accessible through specific methods. Customers interact with their accounts through well-defined interfaces such as ATMs or online banking portals, which enforce security and validation rules, ensuring that unauthorized access or modifications are prevented. This controlled access mechanism ensures the integrity and security of the data, similar to how Private Class Data protects and manages access to class attributes in software design.\n\nIn plain words\n\n> Private class data pattern prevents manipulation of data that is meant to be immutable by separating the data from the methods that use it into a class that maintains the data state.\n\nWikipedia says\n\n> Private class data is a design pattern in computer programming used to encapsulate class attributes and their manipulation.\n\nMind map\n\n![Private Class Data mind map](./etc/private-class-data-mind-map.png)\n\nFlowchart\n\n![Private Class Data flowchart](./etc/private-class-data-flowchart.png)\n\n## Programmatic Example of Private Class Data Pattern in Java\n\nImagine you are cooking a stew for your family dinner. You want to stop your family members from tasting the stew while you're still preparing it. If they do, there might not be enough stew left for dinner.\n\nFirst, we have a `Stew` class where its data is not protected by private class data, making the stew's ingredient mutable to class methods. \n\n```java\n@Slf4j\npublic class Stew {\n    \n  private int numPotatoes;\n  private int numCarrots;\n  private int numMeat;\n  private int numPeppers;\n  \n  public Stew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) {\n    this.numPotatoes = numPotatoes;\n    this.numCarrots = numCarrots;\n    this.numMeat = numMeat;\n    this.numPeppers = numPeppers;\n  }\n  \n  public void mix() {\n    LOGGER.info(\"Mixing the stew we find: {} potatoes, {} carrots, {} meat and {} peppers\",\n        numPotatoes, numCarrots, numMeat, numPeppers);\n  }\n  \n  public void taste() {\n    LOGGER.info(\"Tasting the stew\");\n    if (numPotatoes > 0) {\n      numPotatoes--;\n    }\n    if (numCarrots > 0) {\n      numCarrots--;\n    }\n    if (numMeat > 0) {\n      numMeat--;\n    }\n    if (numPeppers > 0) {\n      numPeppers--;\n    }\n  }\n}\n```\n\nNow, we have `ImmutableStew` class, where its data is protected by `StewData` record. The methods in `ImmutableStew` are unable to manipulate the data of the `StewData` class.\n\n```java\npublic record StewData(int numPotatoes, int numCarrots, int numMeat, int numPeppers) {}\n\n@Slf4j\npublic class ImmutableStew {\n    \n  private final StewData data;\n  \n  public ImmutableStew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) {\n    data = new StewData(numPotatoes, numCarrots, numMeat, numPeppers);\n  }\n  \n  public void mix() {\n    LOGGER\n        .info(\"Mixing the immutable stew we find: {} potatoes, {} carrots, {} meat and {} peppers\",\n            data.getNumPotatoes(), data.getNumCarrots(), data.getNumMeat(), data.getNumPeppers());\n  }\n}\n```\n\nLet's try creating an instance of each class and call their methods:\n\n```java\npublic static void main(String[] args) {\n    // stew is mutable\n    var stew = new Stew(1, 2, 3, 4);\n    stew.mix();\n    stew.taste();\n    stew.mix();\n\n    // immutable stew protected with Private Class Data pattern\n    var immutableStew = new ImmutableStew(2, 4, 3, 6);\n    immutableStew.mix();\n}\n```\n\nProgram output:\n\n```\n08:00:08.210 [main] INFO com.iluwatar.privateclassdata.Stew -- Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers\n08:00:08.212 [main] INFO com.iluwatar.privateclassdata.Stew -- Tasting the stew\n08:00:08.212 [main] INFO com.iluwatar.privateclassdata.Stew -- Mixing the stew we find: 0 potatoes, 1 carrots, 2 meat and 3 peppers\n08:00:08.213 [main] INFO com.iluwatar.privateclassdata.ImmutableStew -- Mixing the immutable stew we find: 2 potatoes, 4 carrots, 3 meat and 6 peppers\n```\n\n## When to Use the Private Class Data Pattern in Java\n\nUse the Private Class Data pattern when\n\n* When you want to protect the integrity of an object’s state.\n* When you need to limit the visibility of the internal data of an object to prevent unintended modification.\n* In scenarios where multiple classes need to share access to some common data without exposing it directly.\n\n## Real-World Applications of Private Class Data Pattern in Java\n\n* Java Beans, where properties are accessed via getters and setters.\n* In many Java libraries where the internal state is hidden from the user to ensure consistency and security.\n* Enterprise applications where sensitive data needs to be protected from direct access.\n\n## Benefits and Trade-offs of Private Class Data Pattern\n\nBenefits:\n\n* Enhanced Security: Reduces the risk of unintended data corruption by encapsulating the data.\n* Ease of Maintenance: Changes to the internal representation of data do not affect external code.\n* Improved Abstraction: Users interact with a simplified interface without worrying about the complexities of data management.\n\nTrade-offs:\n\n* Performance Overhead: Additional method calls (getters/setters) can introduce slight performance overhead.\n* Complexity: May increase the complexity of the class design due to the additional layer of methods for data access.\n\n## Related Java Design Patterns\n\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): Both patterns restrict access to the underlying object but Proxy controls access to the object itself, while Private Class Data controls access to the data.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Ensures that a class has only one instance and provides a global point of access to it; often used to manage shared data with controlled access.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Adds behavior to an object without altering its structure; can be combined with Private Class Data to manage additional state privately.\n\n## References and Credits\n\n* [Clean Code: A Handbook of Agile Software Craftsmanship](https://amzn.to/3UJTZJk)\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n"
  },
  {
    "path": "private-class-data/etc/private-class-data.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \r\n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \r\n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.Stew\" project=\"private-class-data\" \r\n    file=\"/private-class-data/src/main/java/com/iluwatar/Stew.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"189\" width=\"113\" x=\"157\" y=\"57\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.ImmutableStew\" project=\"private-class-data\" \r\n    file=\"/private-class-data/src/main/java/com/iluwatar/ImmutableStew.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"377\" y=\"106\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.StewData\" project=\"private-class-data\" \r\n    file=\"/private-class-data/src/main/java/com/iluwatar/StewData.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"377\" y=\"398\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <association id=\"4\">    \r\n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \r\n      <attribute id=\"5\" name=\"data\"/>      \r\n      <multiplicity id=\"6\" minimum=\"0\" maximum=\"1\"/>    \r\n    </end>    \r\n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \r\n    <display labels=\"true\" multiplicity=\"true\"/>  \r\n  </association>  \r\n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \r\n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \r\n  </classifier-display>  \r\n  <association-display labels=\"true\" multiplicity=\"true\"/>\r\n</class-diagram>"
  },
  {
    "path": "private-class-data/etc/private-class-data.urm.puml",
    "content": "@startuml\npackage com.iluwatar.privateclassdata {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class ImmutableStew {\n    - LOGGER : Logger {static}\n    - data : StewData\n    + ImmutableStew(numPotatoes : int, numCarrots : int, numMeat : int, numPeppers : int)\n    + mix()\n  }\n  class Stew {\n    - LOGGER : Logger {static}\n    - numCarrots : int\n    - numMeat : int\n    - numPeppers : int\n    - numPotatoes : int\n    + Stew(numPotatoes : int, numCarrots : int, numMeat : int, numPeppers : int)\n    + mix()\n    + taste()\n  }\n  class StewData {\n    - numCarrots : int\n    - numMeat : int\n    - numPeppers : int\n    - numPotatoes : int\n    + StewData(numPotatoes : int, numCarrots : int, numMeat : int, numPeppers : int)\n    + getNumCarrots() : int\n    + getNumMeat() : int\n    + getNumPeppers() : int\n    + getNumPotatoes() : int\n  }\n}\nImmutableStew -->  \"-data\" StewData\n@enduml"
  },
  {
    "path": "private-class-data/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>private-class-data</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.privateclassdata.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "private-class-data/src/main/java/com/iluwatar/privateclassdata/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.privateclassdata;\n\n/**\n * The Private Class Data design pattern seeks to reduce exposure of attributes by limiting their\n * visibility. It reduces the number of class attributes by encapsulating them in single data\n * object. It allows the class designer to remove write privilege of attributes that are intended to\n * be set only during construction, even from methods of the target class.\n *\n * <p>In the example we have normal {@link Stew} class with some ingredients given in constructor.\n * Then we have methods to enumerate the ingredients and to taste the stew. The method for tasting\n * the stew alters the private members of the {@link Stew} class.\n *\n * <p>The problem is solved with the Private Class Data pattern. We introduce {@link ImmutableStew}\n * class that contains {@link StewData}. The private data members of {@link Stew} are now in {@link\n * StewData} and cannot be altered by {@link ImmutableStew} methods.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    // stew is mutable\n    var stew = new Stew(1, 2, 3, 4);\n    stew.mix();\n    stew.taste();\n    stew.mix();\n\n    // immutable stew protected with Private Class Data pattern\n    var immutableStew = new ImmutableStew(2, 4, 3, 6);\n    immutableStew.mix();\n  }\n}\n"
  },
  {
    "path": "private-class-data/src/main/java/com/iluwatar/privateclassdata/ImmutableStew.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.privateclassdata;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Immutable stew class, protected with Private Class Data pattern. */\n@Slf4j\npublic class ImmutableStew {\n\n  private final StewData data;\n\n  public ImmutableStew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) {\n    data = new StewData(numPotatoes, numCarrots, numMeat, numPeppers);\n  }\n\n  /** Mix the stew. */\n  public void mix() {\n    LOGGER.info(\n        \"Mixing the immutable stew we find: {} potatoes, {} carrots, {} meat and {} peppers\",\n        data.numPotatoes(),\n        data.numCarrots(),\n        data.numMeat(),\n        data.numPeppers());\n  }\n}\n"
  },
  {
    "path": "private-class-data/src/main/java/com/iluwatar/privateclassdata/Stew.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.privateclassdata;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Mutable stew class. */\n@Slf4j\npublic class Stew {\n\n  private int numPotatoes;\n  private int numCarrots;\n  private int numMeat;\n  private int numPeppers;\n\n  /** Constructor. */\n  public Stew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) {\n    this.numPotatoes = numPotatoes;\n    this.numCarrots = numCarrots;\n    this.numMeat = numMeat;\n    this.numPeppers = numPeppers;\n  }\n\n  /** Mix the stew. */\n  public void mix() {\n    LOGGER.info(\n        \"Mixing the stew we find: {} potatoes, {} carrots, {} meat and {} peppers\",\n        numPotatoes,\n        numCarrots,\n        numMeat,\n        numPeppers);\n  }\n\n  /** Taste the stew. */\n  public void taste() {\n    LOGGER.info(\"Tasting the stew\");\n    if (numPotatoes > 0) {\n      numPotatoes--;\n    }\n    if (numCarrots > 0) {\n      numCarrots--;\n    }\n    if (numMeat > 0) {\n      numMeat--;\n    }\n    if (numPeppers > 0) {\n      numPeppers--;\n    }\n  }\n}\n"
  },
  {
    "path": "private-class-data/src/main/java/com/iluwatar/privateclassdata/StewData.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.privateclassdata;\n\n/** Stew ingredients. */\npublic record StewData(int numPotatoes, int numCarrots, int numMeat, int numPeppers) {}\n"
  },
  {
    "path": "private-class-data/src/test/java/com/iluwatar/privateclassdata/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.privateclassdata;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "private-class-data/src/test/java/com/iluwatar/privateclassdata/ImmutableStewTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.privateclassdata;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.privateclassdata.utils.InMemoryAppender;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** ImmutableStewTest */\nclass ImmutableStewTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /** Verify if mixing the stew doesn't change the internal state */\n  @Test\n  void testMix() {\n    var stew = new Stew(1, 2, 3, 4);\n    var expectedMessage = \"Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers\";\n\n    for (var i = 0; i < 20; i++) {\n      stew.mix();\n      assertEquals(expectedMessage, appender.getLastMessage());\n    }\n\n    assertEquals(20, appender.getLogSize());\n  }\n\n  /** Verify if tasting the stew actually removes one of each ingredient */\n  @Test\n  void testDrink() {\n    final var stew = new Stew(1, 2, 3, 4);\n    stew.mix();\n\n    assertEquals(\n        \"Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers\",\n        appender.getLastMessage());\n\n    stew.taste();\n    assertEquals(\"Tasting the stew\", appender.getLastMessage());\n\n    stew.mix();\n    assertEquals(\n        \"Mixing the stew we find: 0 potatoes, 1 carrots, 2 meat and 3 peppers\",\n        appender.getLastMessage());\n  }\n}\n"
  },
  {
    "path": "private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.privateclassdata;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.privateclassdata.utils.InMemoryAppender;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** StewTest */\nclass StewTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /** Verify if mixing the stew doesn't change the internal state */\n  @Test\n  void testMix() {\n    final var stew = new ImmutableStew(1, 2, 3, 4);\n    final var expectedMessage =\n        \"Mixing the immutable stew we find: 1 potatoes, \" + \"2 carrots, 3 meat and 4 peppers\";\n\n    for (var i = 0; i < 20; i++) {\n      stew.mix();\n      assertEquals(expectedMessage, appender.getLastMessage());\n    }\n\n    assertEquals(20, appender.getLogSize());\n  }\n}\n"
  },
  {
    "path": "private-class-data/src/test/java/com/iluwatar/privateclassdata/utils/InMemoryAppender.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.privateclassdata.utils;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.slf4j.LoggerFactory;\n\n/** InMemory Log Appender Util. */\npublic class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n  private final List<ILoggingEvent> log = new LinkedList<>();\n\n  public InMemoryAppender() {\n    ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n    start();\n  }\n\n  @Override\n  protected void append(ILoggingEvent eventObject) {\n    log.add(eventObject);\n  }\n\n  public int getLogSize() {\n    return log.size();\n  }\n\n  public String getLastMessage() {\n    return log.get(log.size() - 1).getFormattedMessage();\n  }\n}\n"
  },
  {
    "path": "producer-consumer/README.md",
    "content": "---\ntitle: \"Producer-Consumer Pattern in Java: Streamlining Production and Consumption Processes\"\nshortTitle: Producer-Consumer\ndescription: \"Explore the Producer-Consumer pattern, a fundamental concept in Java for managing concurrent data production and consumption with buffer management. Ideal for improving system design and performance.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Asynchronous\n  - Buffering\n  - Decoupling\n  - Messaging\n  - Synchronization\n  - Thread management\n---\n\n## Also known as\n\n* Bounded Buffer\n* Consumer-Producer\n\n## Intent of Producer-Consumer Design Pattern\n\nThe Producer-Consumer design pattern, a critical component for concurrent Java applications, is used to decouple the tasks of producing and consuming data, enabling a producer to generate data and a consumer to process that data concurrently without direct dependency on each other.\n\n## Detailed Explanation of Producer-Consumer Pattern with Real-World Examples\n\nReal-world example\n\n> In a typical car manufacturing setup, the Producer-Consumer pattern facilitates synchronous operations, ensuring efficient assembly and installation processes. Imagine a car manufacturing plant where different stages of production occur. The \"producer\" could be the station that assembles car engines, while the \"consumer\" could be the station that installs the engines into car bodies. The engines are placed onto a conveyor belt (acting as a buffer) once they are assembled. The installation station takes engines off the conveyor belt to install them into cars. This allows the engine assembly and engine installation processes to operate independently, with the conveyor belt managing the synchronization between these two stages. If the assembly station produces engines faster than the installation station can install them, the excess engines are temporarily stored on the conveyor belt. Conversely, if the installation station needs engines but the assembly station is temporarily halted, it can still work on the engines available on the belt.\n\nIn plain words\n\n> It provides a way to share data between multiple loops running at different rates.\n\nWikipedia says\n\n> Dijkstra wrote about the case: \"We consider two processes, which are called the 'producer' and the 'consumer' respectively. The producer is a cyclic process that produces a certain portion of information, that has to be processed by the consumer. The consumer is also a cyclic process that needs to process the next portion of information, as has been produced by the producer. We assume the two processes to be connected for this purpose via a buffer with unbounded capacity.\"\n\nSequence diagram\n\n![Producer-Consumer sequence diagram](./etc/producer-consumer-sequence-diagram.png)\n\n## Programmatic Example of Producer-Consumer Pattern in Java\n\nConsider a manufacturing process of item, the producer will need to pause the production when manufacturing pipeline is full and the consumer will need to pause the consumption of item when the manufacturing pipeline is empty. We can separate the process of production and consumption which work together and pause at separate times.\n\nIn this Java example, `Producers` generate items stored in `ItemQueue`, demonstrating efficient thread management and data synchronization essential for high-performance Java applications.\n\nWe have a simple `Item` record. They are stored in `ItemQueue`.\n\n```java\npublic record Item(String producer, int id) {}\n```\n\n```java\npublic class ItemQueue {\n\n    private final BlockingQueue<Item> queue;\n\n    public ItemQueue() {\n        queue = new LinkedBlockingQueue<>(5);\n    }\n\n    public void put(Item item) throws InterruptedException {\n        queue.put(item);\n    }\n\n    public Item take() throws InterruptedException {\n        return queue.take();\n    }\n}\n```\n\n`Producer` produces items to the `ItemQueue`.\n\n```java\npublic class Producer {\n\n  private static final SecureRandom RANDOM = new SecureRandom();\n  private final ItemQueue queue;\n  private final String name;\n  private int itemId;\n\n  public Producer(String name, ItemQueue queue) {\n    this.name = name;\n    this.queue = queue;\n  }\n\n  public void produce() throws InterruptedException {\n\n    var item = new Item(name, itemId++);\n    queue.put(item);\n    Thread.sleep(RANDOM.nextInt(2000));\n  }\n}\n```\n\nThen, we have the `Consumer` class that takes items from the `ItemQueue`.\n\n```java\n@Slf4j\npublic class Consumer {\n\n  private final ItemQueue queue;\n  private final String name;\n\n  public Consumer(String name, ItemQueue queue) {\n    this.name = name;\n    this.queue = queue;\n  }\n\n  public void consume() throws InterruptedException {\n    var item = queue.take();\n    LOGGER.info(\"Consumer [{}] consume item [{}] produced by [{}]\", name,\n        item.getId(), item.getProducer());\n\n  }\n}\n``` \n\nNow, during the manufacturing pipeline, we can instantiate objects from both the `Producer` and `Consumer` classes as they produce and consume items from the queue.\n\n```java\n  public static void main(String[] args) {\n\n    var queue = new ItemQueue();\n\n    var executorService = Executors.newFixedThreadPool(5);\n    for (var i = 0; i < 2; i++) {\n\n        final var producer = new Producer(\"Producer_\" + i, queue);\n        executorService.submit(() -> {\n            while (true) {\n                producer.produce();\n            }\n        });\n    }\n\n    for (var i = 0; i < 3; i++) {\n        final var consumer = new Consumer(\"Consumer_\" + i, queue);\n        executorService.submit(() -> {\n            while (true) {\n                consumer.consume();\n            }\n        });\n    }\n\n    executorService.shutdown();\n    try {\n        executorService.awaitTermination(10, TimeUnit.SECONDS);\n        executorService.shutdownNow();\n    } catch (InterruptedException e) {\n        LOGGER.error(\"Error waiting for ExecutorService shutdown\");\n    }\n}\n```\n\nProgram output:\n\n```\n08:10:08.008 [pool-1-thread-3] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_0] consume item [0] produced by [Producer_1]\n08:10:08.008 [pool-1-thread-4] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_1] consume item [0] produced by [Producer_0]\n08:10:08.517 [pool-1-thread-5] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_2] consume item [1] produced by [Producer_0]\n08:10:08.952 [pool-1-thread-3] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_0] consume item [1] produced by [Producer_1]\n08:10:09.208 [pool-1-thread-4] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_1] consume item [2] produced by [Producer_0]\n08:10:09.354 [pool-1-thread-5] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_2] consume item [2] produced by [Producer_1]\n08:10:10.214 [pool-1-thread-3] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_0] consume item [3] produced by [Producer_1]\n08:10:10.585 [pool-1-thread-4] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_1] consume item [3] produced by [Producer_0]\n08:10:11.530 [pool-1-thread-5] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_2] consume item [4] produced by [Producer_1]\n08:10:11.682 [pool-1-thread-3] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_0] consume item [4] produced by [Producer_0]\n08:10:11.781 [pool-1-thread-4] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_1] consume item [5] produced by [Producer_0]\n08:10:12.209 [pool-1-thread-5] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_2] consume item [5] produced by [Producer_1]\n08:10:13.045 [pool-1-thread-3] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_0] consume item [6] produced by [Producer_0]\n08:10:13.861 [pool-1-thread-4] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_1] consume item [6] produced by [Producer_1]\n08:10:14.739 [pool-1-thread-5] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_2] consume item [7] produced by [Producer_1]\n08:10:14.842 [pool-1-thread-3] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_0] consume item [7] produced by [Producer_0]\n08:10:15.975 [pool-1-thread-4] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_1] consume item [8] produced by [Producer_0]\n08:10:16.378 [pool-1-thread-5] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_2] consume item [8] produced by [Producer_1]\n08:10:16.967 [pool-1-thread-3] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_0] consume item [9] produced by [Producer_0]\n08:10:17.417 [pool-1-thread-4] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_1] consume item [9] produced by [Producer_1]\n08:10:17.483 [pool-1-thread-5] INFO com.iluwatar.producer.consumer.Consumer -- Consumer [Consumer_2] consume item [10] produced by [Producer_1]\n```\n\n## When to Use the Producer-Consumer Pattern in Java\n\n* When you need to manage a buffer or queue where producers add data and consumers take data, often in a multithreaded environment.\n* When decoupling the production and consumption of data is beneficial for the application's design, performance, or maintainability.\n* Suitable for scenarios requiring synchronized access to a shared resource or data structure.\n\n## Real-World Applications of Producer-Consumer Pattern in Java\n\n* Thread pools where worker threads act as consumers processing tasks produced by another thread.\n* Logging frameworks where log messages are produced by various parts of an application and consumed by a logging service.\n* Message queues in distributed systems for asynchronous communication between services.\n\n## Benefits and Trade-offs of Producer-Consumer Pattern\n\nBenefits:\n\n* Decoupling: Producers and consumers can operate independently, simplifying the system design.\n* Improved Performance: Allows multiple producer and consumer threads to work concurrently, improving throughput.\n* Flexibility: Easily extendable to add more producers or consumers without significant changes to the existing system.\n\nTrade-offs:\n\n* Complexity: Requires careful handling of synchronization and potential deadlocks.\n* Resource Management: Properly managing the buffer size to avoid overflow or underflow conditions.\n\n## Related Java Design Patterns\n\n* [Observer](https://java-design-patterns.com/patterns/observer/): While both deal with notifying or handling events, the Observer pattern is more about event subscription and notification, whereas Producer-Consumer focuses on decoupled data production and consumption.\n* [Thread Pool](https://java-design-patterns.com/patterns/thread-pool/): Uses a similar decoupling approach where tasks are produced and consumed by a pool of worker threads.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n"
  },
  {
    "path": "producer-consumer/etc/producer-consumer.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.producer.consumer.Item\" project=\"producer-consumer\" \n    file=\"/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Item.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"415\" y=\"378\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.producer.consumer.Producer\" project=\"producer-consumer\" \n    file=\"/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"150\" y=\"191\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.producer.consumer.Consumer\" project=\"producer-consumer\" \n    file=\"/producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"675\" y=\"186\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.producer.consumer.ItemQueue\" project=\"producer-consumer\" \n    file=\"/producer-consumer/src/main/java/com/iluwatar/producer/consumer/ItemQueue.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"415\" y=\"187\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"5\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"6\" name=\"queue\"/>      \n      <multiplicity id=\"7\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"8\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"9\" name=\"queue\"/>      \n      <multiplicity id=\"10\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"11\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"12\" name=\"queue\"/>      \n      <multiplicity id=\"13\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "producer-consumer/etc/producer-consumer.urm.puml",
    "content": "@startuml\npackage com.iluwatar.producer.consumer {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Consumer {\n    - LOGGER : Logger {static}\n    - name : String\n    - queue : ItemQueue\n    + Consumer(name : String, queue : ItemQueue)\n    + consume()\n  }\n  class Item {\n    - id : int\n    - producer : String\n    + Item(producer : String, id : int)\n    + getId() : int\n    + getProducer() : String\n  }\n  class ItemQueue {\n    - queue : BlockingQueue<Item>\n    + ItemQueue()\n    + put(item : Item)\n    + take() : Item\n  }\n  class Producer {\n    - RANDOM : Random {static}\n    - itemId : int\n    - name : String\n    - queue : ItemQueue\n    + Producer(name : String, queue : ItemQueue)\n    + produce()\n  }\n}\nConsumer -->  \"-queue\" ItemQueue\nProducer -->  \"-queue\" ItemQueue\nItemQueue -->  \"-queue\" Item\n@enduml"
  },
  {
    "path": "producer-consumer/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>producer-consumer</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.producer.consumer.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "producer-consumer/src/main/java/com/iluwatar/producer/consumer/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.producer.consumer;\n\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Producer Consumer Design pattern is a classic concurrency or threading pattern which reduces\n * coupling between Producer and Consumer by separating Identification of work with Execution of\n * Work.\n *\n * <p>In producer consumer design pattern a shared queue is used to control the flow and this\n * separation allows you to code producer and consumer separately. It also addresses the issue of\n * different timing require to produce item or consuming item. by using producer consumer pattern\n * both Producer and Consumer Thread can work with different speed.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var queue = new ItemQueue();\n\n    var executorService = Executors.newFixedThreadPool(5);\n    for (var i = 0; i < 2; i++) {\n\n      final var producer = new Producer(\"Producer_\" + i, queue);\n      executorService.submit(\n          () -> {\n            while (true) {\n              producer.produce();\n            }\n          });\n    }\n\n    for (var i = 0; i < 3; i++) {\n      final var consumer = new Consumer(\"Consumer_\" + i, queue);\n      executorService.submit(\n          () -> {\n            while (true) {\n              consumer.consume();\n            }\n          });\n    }\n\n    executorService.shutdown();\n    try {\n      executorService.awaitTermination(10, TimeUnit.SECONDS);\n      executorService.shutdownNow();\n    } catch (InterruptedException e) {\n      LOGGER.error(\"Error waiting for ExecutorService shutdown\");\n    }\n  }\n}\n"
  },
  {
    "path": "producer-consumer/src/main/java/com/iluwatar/producer/consumer/Consumer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.producer.consumer;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Class responsible for consume the {@link Item} produced by {@link Producer}. */\n@Slf4j\npublic class Consumer {\n\n  private final ItemQueue queue;\n\n  private final String name;\n\n  public Consumer(String name, ItemQueue queue) {\n    this.name = name;\n    this.queue = queue;\n  }\n\n  /** Consume item from the queue. */\n  public void consume() throws InterruptedException {\n    var item = queue.take();\n    LOGGER.info(\n        \"Consumer [{}] consume item [{}] produced by [{}]\", name, item.id(), item.producer());\n  }\n}\n"
  },
  {
    "path": "producer-consumer/src/main/java/com/iluwatar/producer/consumer/Item.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.producer.consumer;\n\n/** Class take part of an {@link Producer}-{@link Consumer} exchange. */\npublic record Item(String producer, int id) {}\n"
  },
  {
    "path": "producer-consumer/src/main/java/com/iluwatar/producer/consumer/ItemQueue.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.producer.consumer;\n\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.LinkedBlockingQueue;\n\n/** Class as a channel for {@link Producer}-{@link Consumer} exchange. */\npublic class ItemQueue {\n\n  private final BlockingQueue<Item> queue;\n\n  public ItemQueue() {\n\n    queue = new LinkedBlockingQueue<>(5);\n  }\n\n  public void put(Item item) throws InterruptedException {\n\n    queue.put(item);\n  }\n\n  public Item take() throws InterruptedException {\n\n    return queue.take();\n  }\n}\n"
  },
  {
    "path": "producer-consumer/src/main/java/com/iluwatar/producer/consumer/Producer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.producer.consumer;\n\nimport java.security.SecureRandom;\n\n/**\n * Class responsible for producing unit of work that can be expressed as {@link Item} and submitted\n * to queue.\n */\npublic class Producer {\n\n  private static final SecureRandom RANDOM = new SecureRandom();\n\n  private final ItemQueue queue;\n\n  private final String name;\n\n  private int itemId;\n\n  public Producer(String name, ItemQueue queue) {\n    this.name = name;\n    this.queue = queue;\n  }\n\n  /** Put item in the queue. */\n  public void produce() throws InterruptedException {\n\n    var item = new Item(name, itemId++);\n    queue.put(item);\n    Thread.sleep(RANDOM.nextInt(2000));\n  }\n}\n"
  },
  {
    "path": "producer-consumer/src/test/java/com/iluwatar/producer/consumer/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.producer.consumer;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.producer.consumer;\n\nimport static org.mockito.Mockito.reset;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\nimport org.junit.jupiter.api.Test;\n\n/** ConsumerTest */\nclass ConsumerTest {\n\n  private static final int ITEM_COUNT = 5;\n\n  @Test\n  void testConsume() throws Exception {\n    final var queue = spy(new ItemQueue());\n    for (var id = 0; id < ITEM_COUNT; id++) {\n      queue.put(new Item(\"producer\", id));\n    }\n\n    reset(queue); // Don't count the preparation above as interactions with the queue\n    final var consumer = new Consumer(\"consumer\", queue);\n\n    for (var id = 0; id < ITEM_COUNT; id++) {\n      consumer.consume();\n    }\n\n    verify(queue, times(ITEM_COUNT)).take();\n  }\n}\n"
  },
  {
    "path": "producer-consumer/src/test/java/com/iluwatar/producer/consumer/ProducerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.producer.consumer;\n\nimport static java.time.Duration.ofMillis;\nimport static org.junit.jupiter.api.Assertions.assertTimeout;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport org.junit.jupiter.api.Test;\n\n/** ProducerTest */\nclass ProducerTest {\n\n  @Test\n  void testProduce() {\n    assertTimeout(\n        ofMillis(6000),\n        () -> {\n          final var queue = mock(ItemQueue.class);\n          final var producer = new Producer(\"producer\", queue);\n\n          producer.produce();\n          verify(queue).put(any(Item.class));\n\n          verifyNoMoreInteractions(queue);\n        });\n  }\n}\n"
  },
  {
    "path": "promise/README.md",
    "content": "---\ntitle: \"Promise Pattern in Java: Streamlining Async Tasks for Better Performance\"\nshortTitle: Promise\ndescription: \"Explore the Promise design pattern in Java, ideal for managing asynchronous operations efficiently. Learn how it enhances code readability and maintainability with practical examples and detailed explanations.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Asynchronous\n  - Decoupling\n  - Messaging\n  - Synchronization\n  - Thread management\n---\n\n## Also known as\n\n* Deferred\n* Future\n\n## Intent of Promise Design Pattern\n\nThe Promise design pattern is used to handle asynchronous operations by providing a placeholder for a result that is initially unknown but will be resolved in the future.\n\n## Detailed Explanation of Promise Pattern with Real-World Examples\n\nReal-world example\n\n> In an online pizza ordering system, when a customer places an order, the system immediately acknowledges the order and provides a tracking number (the promise). The pizza preparation and delivery process happens asynchronously in the background. The customer can check the status of their order at any time using the tracking number. Once the pizza is prepared and out for delivery, the customer receives a notification (promise resolved) about the delivery status. If there are any issues, such as an unavailable ingredient or delivery delay, the customer is notified about the error (promise rejected).\n> \n> This analogy illustrates how the Promise design pattern manages asynchronous tasks, decoupling the initial request from the eventual outcome, and handling both results and errors efficiently.\n\nIn plain words\n\n> Promise is a placeholder for an asynchronous operation that is ongoing.\n\nWikipedia says\n\n> In computer science, future, promise, delay, and deferred refer to constructs used for synchronizing program execution in some concurrent programming languages. They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is not yet complete.\n\nSequence diagram\n\n![Promise sequence diagram](./etc/promise-sequence-diagram.png)\n\n## Programmatic Example of Promise Pattern in Java\n\nThe Promise design pattern is a software design pattern that's often used in concurrent programming to handle asynchronous operations. It represents a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason.\n\nIn the provided example, a Promise is used to download files and perform operations like line counting and character frequency analysis asynchronously, showcasing the pattern's utility in practical applications.\n\n```java\n@Slf4j\npublic class App {\n\n  private static final String DEFAULT_URL =\n      \"https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/promise/README.md\";\n  private final ExecutorService executor;\n\n  private App() {\n    // Create a thread pool with 2 threads\n    executor = Executors.newFixedThreadPool(2);\n  }\n\n  public static void main(String[] args) {\n    var app = new App();\n    app.promiseUsage();\n  }\n\n  private void promiseUsage() {\n    calculateLineCount();\n    calculateLowestFrequencyChar();\n  }\n\n  private void calculateLowestFrequencyChar() {\n    // Create a promise to calculate the lowest frequency character\n    lowestFrequencyChar().thenAccept(\n        charFrequency -> {\n          LOGGER.info(\"Char with lowest frequency is: {}\", charFrequency);\n        }\n    );\n  }\n\n  private void calculateLineCount() {\n    // Create a promise to calculate the line count\n    countLines().thenAccept(\n        count -> {\n          LOGGER.info(\"Line count is: {}\", count);\n        }\n    );\n  }\n\n  private Promise<Character> lowestFrequencyChar() {\n    // Create a promise to calculate the character frequency and then find the lowest frequency character\n    return characterFrequency().thenApply(Utility::lowestFrequencyChar);\n  }\n\n  private Promise<Map<Character, Long>> characterFrequency() {\n    // Create a promise to download a file and then calculate the character frequency\n    return download(DEFAULT_URL).thenApply(Utility::characterFrequency);\n  }\n\n  private Promise<Integer> countLines() {\n    // Create a promise to download a file and then count the lines\n    return download(DEFAULT_URL).thenApply(Utility::countLines);\n  }\n\n  private Promise<String> download(String urlString) {\n    // Create a promise to download a file\n    return new Promise<String>()\n        .fulfillInAsync(\n            () -> Utility.downloadFile(urlString), executor)\n        .onError(\n            throwable -> {\n              LOGGER.error(\"An error occurred: \", throwable);\n            }\n        );\n  }\n}\n```\n\nIn this code, the `Promise` class is used to create promises for various operations. The `thenApply` method is used to chain promises, meaning that the result of one promise is used as the input for the next promise. The `thenAccept` method is used to handle the result of a promise. The `fulfillInAsync` method is used to fulfill a promise asynchronously, and the `onError` method is used to handle any errors that occur while fulfilling the promise.\n\nProgram output:\n\n```\n08:19:33.036 [pool-1-thread-2] INFO com.iluwatar.promise.Utility -- Downloading contents from url: https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/promise/README.md\n08:19:33.036 [pool-1-thread-1] INFO com.iluwatar.promise.Utility -- Downloading contents from url: https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/promise/README.md\n08:19:33.419 [pool-1-thread-2] INFO com.iluwatar.promise.Utility -- File downloaded at: /var/folders/sg/9_st37nn5hq_bfhp8hw2dcrw0000gp/T/promise_pattern12403918065536844551.tmp\n08:19:33.419 [pool-1-thread-1] INFO com.iluwatar.promise.Utility -- File downloaded at: /var/folders/sg/9_st37nn5hq_bfhp8hw2dcrw0000gp/T/promise_pattern11215446820862558571.tmp\n08:19:33.419 [pool-1-thread-1] INFO com.iluwatar.promise.App -- Line count is: 164\n08:19:33.426 [pool-1-thread-2] INFO com.iluwatar.promise.App -- Char with lowest frequency is: ’\n```\n\n## When to Use the Promise Pattern in Java\n\n* When you need to perform asynchronous tasks and handle their results or errors at a later point.\n* In scenarios where tasks can be executed in parallel and their outcomes need to be handled once they are completed.\n* Suitable for improving the readability and maintainability of asynchronous code.\n\n## Promise Pattern Java Tutorials\n\n* [Functional-Style Callbacks Using Java 8's CompletableFuture (InfoQ)](https://www.infoq.com/articles/Functional-Style-Callbacks-Using-CompletableFuture)\n* [Guide To CompletableFuture (Baeldung)](https://www.baeldung.com/java-completablefuture)\n* [You are missing the point to Promises (Domenic Denicola)](https://gist.github.com/domenic/3889970)\n\n## Real-World Applications of Promise Pattern in Java\n\n* Java's CompletableFuture and Future classes.\n* JavaScript’s Promise object for managing asynchronous operations.\n* Many asynchronous frameworks and libraries such as RxJava and Vert.x.\n* [Guava ListenableFuture](https://github.com/google/guava/wiki/ListenableFutureExplained)\n\n## Benefits and Trade-offs of Promise Pattern\n\nBenefits:\n\n* Improved Readability: Simplifies complex asynchronous code, making it easier to understand and maintain.\n* Decoupling: Decouples the code that initiates the asynchronous operation from the code that processes the result.\n* Error Handling: Provides a unified way to handle both results and errors from asynchronous operations.\n\nTrade-offs:\n\n* Complexity: Can add complexity to the codebase if overused or misused.\n* Debugging: Asynchronous code can be harder to debug compared to synchronous code due to the non-linear flow of execution.\n\n## Related Java Design Patterns\n\n* [Observer](https://java-design-patterns.com/patterns/observer/): Promises can be used in conjunction with the Observer pattern to notify subscribers about the completion of asynchronous operations.\n* [Callback](https://java-design-patterns.com/patterns/callback/): Promises often replace callback mechanisms by providing a more structured and readable way to handle asynchronous results.\n* [Async Method Invocation](https://java-design-patterns.com/patterns/async-method-invocation/): Promises are often used to handle the results of asynchronous method invocations, allowing for non-blocking execution and result handling.\n\n## References and Credits\n\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Java 8 in Action: Lambdas, Streams, and functional-style programming](https://amzn.to/3QCmGXs)\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n* [Modern Java in Action: Lambdas, streams, functional and reactive programming](https://amzn.to/3VhwetF)\n"
  },
  {
    "path": "promise/etc/promise.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.10\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" \n  generalizations=\"true\" realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" \n  router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.promise.Promise\" project=\"promise\" \n    file=\"/promise/src/main/java/com/iluwatar/promise/Promise.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"524\" y=\"541\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"false\" protected=\"true\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"2\" language=\"java\" name=\"java.util.concurrent.Future\" project=\"async-method-invocation\" \n    file=\"/usr/lib/java/jdk1.8.0_45/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"527\" y=\"94\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.promise.PromiseSupport\" project=\"promise\" \n    file=\"/promise/src/main/java/com/iluwatar/promise/PromiseSupport.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"524\" y=\"313\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"false\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"false\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"4\" language=\"java\" name=\"java.util.concurrent.Executor\" project=\"async-method-invocation\" \n    file=\"/usr/lib/java/jdk1.8.0_45/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"798\" y=\"541\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"5\" language=\"java\" name=\"java.util.concurrent.Callable\" project=\"async-method-invocation\" \n    file=\"/usr/lib/java/jdk1.8.0_45/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"847\" y=\"345\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"6\" language=\"java\" name=\"java.util.function.Consumer\" project=\"async-method-invocation\" \n    file=\"/usr/lib/java/jdk1.8.0_45/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"158\" y=\"336\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"7\" language=\"java\" name=\"java.util.function.Function\" project=\"async-method-invocation\" \n    file=\"/usr/lib/java/jdk1.8.0_45/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"166\" y=\"546\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"false\"/>    \n    </display>  \n  </interface>  \n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.promise.App\" project=\"promise\" \n    file=\"/promise/src/main/java/com/iluwatar/promise/App.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"801\" y=\"189\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <dependency id=\"9\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </dependency>  \n  <dependency id=\"10\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </dependency>  \n  <dependency id=\"11\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </dependency>  \n  <generalization id=\"12\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </generalization>  \n  <dependency id=\"13\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </dependency>  \n  <dependency id=\"14\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </dependency>  \n  <realization id=\"15\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "promise/etc/promise.urm.puml",
    "content": "@startuml\npackage com.iluwatar.promise {\n  class App {\n    - DEFAULT_URL : String {static}\n    - LOGGER : Logger {static}\n    - executor : ExecutorService\n    - stopLatch : CountDownLatch\n    - App()\n    - calculateLineCount()\n    - calculateLowestFrequencyChar()\n    - characterFrequency() : Promise<Map<Character, Integer>>\n    - countLines() : Promise<Integer>\n    - download(urlString : String) : Promise<String>\n    - lowestFrequencyChar() : Promise<Character>\n    + main(args : String[]) {static}\n    - promiseUsage()\n    - stop()\n    - taskCompleted()\n  }\n  class Promise<T> {\n    - exceptionHandler : Consumer<? super Throwable>\n    - fulfillmentAction : Runnable\n    + Promise<T>()\n    + fulfill(value : T)\n    + fulfillExceptionally(exception : Exception)\n    + fulfillInAsync(task : Callable<T>, executor : Executor) : Promise<T>\n    - handleException(exception : Exception)\n    + onError(exceptionHandler : Consumer<? super Throwable>) : Promise<T>\n    - postFulfillment()\n    + thenAccept(action : Consumer<? super T>) : Promise<Void>\n    + thenApply(func : Function<? super T, V>) : Promise<V>\n  }\n  -class ConsumeAction {\n    - action : Consumer<? super T>\n    - dest : Promise<Void>\n    - src : Promise<T>\n    - ConsumeAction(src : Promise<T>, dest : Promise<T>, action : Consumer<T>)\n    + run()\n  }\n  -class TransformAction<V> {\n    - dest : Promise<V>\n    - func : Function<? super T, V>\n    - src : Promise<T>\n    - TransformAction<V>(src : Promise<T>, dest : Promise<T>, func : Function<T, R>)\n    + run()\n  }\n  ~class PromiseSupport<T> {\n    - COMPLETED : int {static}\n    - FAILED : int {static}\n    - LOGGER : Logger {static}\n    - RUNNING : int {static}\n    - exception : Exception\n    - lock : Object\n    - state : int\n    - value : T\n    ~ PromiseSupport<T>()\n    + cancel(mayInterruptIfRunning : boolean) : boolean\n    ~ fulfill(value : T)\n    ~ fulfillExceptionally(exception : Exception)\n    + get() : T\n    + get(timeout : long, unit : TimeUnit) : T\n    + isCancelled() : boolean\n    + isDone() : boolean\n  }\n  class Utility {\n    - LOGGER : Logger {static}\n    + Utility()\n    + characterFrequency(fileLocation : String) : Map<Character, Integer> {static}\n    + countLines(fileLocation : String) : Integer {static}\n    + downloadFile(urlString : String) : String {static}\n    + lowestFrequencyChar(charFrequency : Map<Character, Integer>) : Character {static}\n  }\n}\nTransformAction --+ Promise\nTransformAction -->  \"-src\" Promise\nConsumeAction --+ Promise\nConsumeAction -->  \"-src\" Promise\nPromise --|> PromiseSupport \n@enduml"
  },
  {
    "path": "promise/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>promise</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.promise.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "promise/src/main/java/com/iluwatar/promise/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.promise;\n\nimport java.util.Map;\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Promise object is used for asynchronous computations. A Promise represents an operation that\n * hasn't completed yet, but is expected in the future.\n *\n * <p>A Promise represents a proxy for a value not necessarily known when the promise is created. It\n * allows you to associate dependent promises to an asynchronous action's eventual success value or\n * failure reason. This lets asynchronous methods return values like synchronous methods: instead of\n * the final value, the asynchronous method returns a promise of having a value at some point in the\n * future.\n *\n * <p>Promises provide a few advantages over callback objects:\n *\n * <ul>\n *   <li>Functional composition and error handling\n *   <li>Prevents callback hell and provides callback aggregation\n * </ul>\n *\n * <p>In this application the usage of promise is demonstrated with two examples:\n *\n * <ul>\n *   <li>Count Lines: In this example a file is downloaded and its line count is calculated. The\n *       calculated line count is then consumed and printed on console.\n *   <li>Lowest Character Frequency: In this example a file is downloaded and its lowest frequency\n *       character is found and printed on console. This happens via a chain of promises, we start\n *       with a file download promise, then a promise of character frequency, then a promise of\n *       lowest frequency character which is finally consumed and result is printed on console.\n * </ul>\n *\n * @see CompletableFuture\n */\n@Slf4j\npublic class App {\n\n  private static final String DEFAULT_URL =\n      \"https://raw.githubusercontent.com/iluwatar/java-design-patterns/master/promise/README.md\";\n  private final ExecutorService executor;\n  private final CountDownLatch stopLatch;\n\n  private App() {\n    executor = Executors.newFixedThreadPool(2);\n    stopLatch = new CountDownLatch(2);\n  }\n\n  /**\n   * Program entry point.\n   *\n   * @param args arguments\n   * @throws InterruptedException if main thread is interrupted.\n   */\n  public static void main(String[] args) throws InterruptedException {\n    var app = new App();\n    try {\n      app.promiseUsage();\n    } finally {\n      app.stop();\n    }\n  }\n\n  private void promiseUsage() {\n    calculateLineCount();\n\n    calculateLowestFrequencyChar();\n  }\n\n  /*\n   * Calculate the lowest frequency character and when that promise is fulfilled,\n   * consume the result in a Consumer<Character>\n   */\n  private void calculateLowestFrequencyChar() {\n    lowestFrequencyChar()\n        .thenAccept(\n            charFrequency -> {\n              LOGGER.info(\"Char with lowest frequency is: {}\", charFrequency);\n              taskCompleted();\n            });\n  }\n\n  /*\n   * Calculate the line count and when that promise is fulfilled, consume the result\n   * in a Consumer<Integer>\n   */\n  private void calculateLineCount() {\n    countLines()\n        .thenAccept(\n            count -> {\n              LOGGER.info(\"Line count is: {}\", count);\n              taskCompleted();\n            });\n  }\n\n  /*\n   * Calculate the character frequency of a file and when that promise is fulfilled,\n   * then promise to apply function to calculate the lowest character frequency.\n   */\n  private Promise<Character> lowestFrequencyChar() {\n    return characterFrequency().thenApply(Utility::lowestFrequencyChar);\n  }\n\n  /*\n   * Download the file at DEFAULT_URL and when that promise is fulfilled,\n   * then promise to apply function to calculate character frequency.\n   */\n  private Promise<Map<Character, Long>> characterFrequency() {\n    return download(DEFAULT_URL).thenApply(Utility::characterFrequency);\n  }\n\n  /*\n   * Download the file at DEFAULT_URL and when that promise is fulfilled,\n   * then promise to apply function to count lines in that file.\n   */\n  private Promise<Integer> countLines() {\n    return download(DEFAULT_URL).thenApply(Utility::countLines);\n  }\n\n  /*\n   * Return a promise to provide the local absolute path of the file downloaded in background.\n   * This is an async method and does not wait until the file is downloaded.\n   */\n  private Promise<String> download(String urlString) {\n    return new Promise<String>()\n        .fulfillInAsync(() -> Utility.downloadFile(urlString), executor)\n        .onError(\n            throwable -> {\n              LOGGER.error(\"An error occurred: \", throwable);\n              taskCompleted();\n            });\n  }\n\n  private void stop() throws InterruptedException {\n    stopLatch.await();\n    executor.shutdownNow();\n  }\n\n  private void taskCompleted() {\n    stopLatch.countDown();\n  }\n}\n"
  },
  {
    "path": "promise/src/main/java/com/iluwatar/promise/Promise.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.promise;\n\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Executor;\nimport java.util.function.Consumer;\nimport java.util.function.Function;\n\n/**\n * A Promise represents a proxy for a value not necessarily known when the promise is created. It\n * allows you to associate dependent promises to an asynchronous action's eventual success value or\n * failure reason. This lets asynchronous methods return values like synchronous methods: instead of\n * the final value, the asynchronous method returns a promise of having a value at some point in the\n * future.\n *\n * @param <T> type of result.\n */\npublic class Promise<T> extends PromiseSupport<T> {\n\n  private Runnable fulfillmentAction;\n  private Consumer<? super Throwable> exceptionHandler;\n\n  /** Creates a promise that will be fulfilled in the future. */\n  public Promise() {\n    // Empty constructor\n  }\n\n  /**\n   * Fulfills the promise with the provided value.\n   *\n   * @param value the fulfilled value that can be accessed using {@link #get()}.\n   */\n  @Override\n  public void fulfill(T value) {\n    super.fulfill(value);\n    postFulfillment();\n  }\n\n  /**\n   * Fulfills the promise with exception due to error in execution.\n   *\n   * @param exception the exception will be wrapped in {@link ExecutionException} when accessing the\n   *     value using {@link #get()}.\n   */\n  @Override\n  public void fulfillExceptionally(Exception exception) {\n    super.fulfillExceptionally(exception);\n    handleException(exception);\n    postFulfillment();\n  }\n\n  private void handleException(Exception exception) {\n    if (exceptionHandler == null) {\n      return;\n    }\n    exceptionHandler.accept(exception);\n  }\n\n  private void postFulfillment() {\n    if (fulfillmentAction == null) {\n      return;\n    }\n    fulfillmentAction.run();\n  }\n\n  /**\n   * Executes the task using the executor in other thread and fulfills the promise returned once the\n   * task completes either successfully or with an exception.\n   *\n   * @param task the task that will provide the value to fulfill the promise.\n   * @param executor the executor in which the task should be run.\n   * @return a promise that represents the result of running the task provided.\n   */\n  public Promise<T> fulfillInAsync(final Callable<T> task, Executor executor) {\n    executor.execute(\n        () -> {\n          try {\n            fulfill(task.call());\n          } catch (Exception ex) {\n            fulfillExceptionally(ex);\n          }\n        });\n    return this;\n  }\n\n  /**\n   * Returns a new promise that, when this promise is fulfilled normally, is fulfilled with result\n   * of this promise as argument to the action provided.\n   *\n   * @param action action to be executed.\n   * @return a new promise.\n   */\n  public Promise<Void> thenAccept(Consumer<? super T> action) {\n    var dest = new Promise<Void>();\n    fulfillmentAction = new ConsumeAction(this, dest, action);\n    return dest;\n  }\n\n  /**\n   * Set the exception handler on this promise.\n   *\n   * @param exceptionHandler a consumer that will handle the exception occurred while fulfilling the\n   *     promise.\n   * @return this\n   */\n  public Promise<T> onError(Consumer<? super Throwable> exceptionHandler) {\n    this.exceptionHandler = exceptionHandler;\n    return this;\n  }\n\n  /**\n   * Returns a new promise that, when this promise is fulfilled normally, is fulfilled with result\n   * of this promise as argument to the function provided.\n   *\n   * @param func function to be executed.\n   * @return a new promise.\n   */\n  public <V> Promise<V> thenApply(Function<? super T, V> func) {\n    Promise<V> dest = new Promise<>();\n    fulfillmentAction = new TransformAction<>(this, dest, func);\n    return dest;\n  }\n\n  /**\n   * Accesses the value from source promise and calls the consumer, then fulfills the destination\n   * promise.\n   */\n  private class ConsumeAction implements Runnable {\n\n    private final Promise<T> src;\n    private final Promise<Void> dest;\n    private final Consumer<? super T> action;\n\n    private ConsumeAction(Promise<T> src, Promise<Void> dest, Consumer<? super T> action) {\n      this.src = src;\n      this.dest = dest;\n      this.action = action;\n    }\n\n    @Override\n    public void run() {\n      try {\n        action.accept(src.get());\n        dest.fulfill(null);\n      } catch (Throwable throwable) {\n        dest.fulfillExceptionally((Exception) throwable.getCause());\n      }\n    }\n  }\n\n  /**\n   * Accesses the value from source promise, then fulfills the destination promise using the\n   * transformed value. The source value is transformed using the transformation function.\n   */\n  private class TransformAction<V> implements Runnable {\n\n    private final Promise<T> src;\n    private final Promise<V> dest;\n    private final Function<? super T, V> func;\n\n    private TransformAction(Promise<T> src, Promise<V> dest, Function<? super T, V> func) {\n      this.src = src;\n      this.dest = dest;\n      this.func = func;\n    }\n\n    @Override\n    public void run() {\n      try {\n        dest.fulfill(func.apply(src.get()));\n      } catch (Throwable throwable) {\n        dest.fulfillExceptionally((Exception) throwable.getCause());\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "promise/src/main/java/com/iluwatar/promise/PromiseSupport.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.promise;\n\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * A really simplified implementation of future that allows completing it successfully with a value\n * or exceptionally with an exception.\n */\nclass PromiseSupport<T> implements Future<T> {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(PromiseSupport.class);\n\n  private static final int RUNNING = 1;\n  private static final int FAILED = 2;\n  private static final int COMPLETED = 3;\n\n  private final Object lock;\n\n  private volatile int state = RUNNING;\n  private T value;\n  private Exception exception;\n\n  PromiseSupport() {\n    this.lock = new Object();\n  }\n\n  void fulfill(T value) {\n    this.value = value;\n    this.state = COMPLETED;\n    synchronized (lock) {\n      lock.notifyAll();\n    }\n  }\n\n  void fulfillExceptionally(Exception exception) {\n    this.exception = exception;\n    this.state = FAILED;\n    synchronized (lock) {\n      lock.notifyAll();\n    }\n  }\n\n  @Override\n  public boolean cancel(boolean mayInterruptIfRunning) {\n    return false;\n  }\n\n  @Override\n  public boolean isCancelled() {\n    return false;\n  }\n\n  @Override\n  public boolean isDone() {\n    return state > RUNNING;\n  }\n\n  @Override\n  public T get() throws InterruptedException, ExecutionException {\n    synchronized (lock) {\n      while (state == RUNNING) {\n        lock.wait();\n      }\n    }\n    if (state == COMPLETED) {\n      return value;\n    }\n    throw new ExecutionException(exception);\n  }\n\n  @Override\n  public T get(long timeout, TimeUnit unit) throws ExecutionException {\n    synchronized (lock) {\n      while (state == RUNNING) {\n        try {\n          lock.wait(unit.toMillis(timeout));\n        } catch (InterruptedException e) {\n          LOGGER.warn(\"Interrupted!\", e);\n          Thread.currentThread().interrupt();\n        }\n      }\n    }\n\n    if (state == COMPLETED) {\n      return value;\n    }\n    throw new ExecutionException(exception);\n  }\n}\n"
  },
  {
    "path": "promise/src/main/java/com/iluwatar/promise/Utility.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.promise;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileReader;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.net.URL;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Utility to perform various operations. */\n@Slf4j\npublic class Utility {\n\n  /**\n   * Calculates character frequency of the file provided.\n   *\n   * @param fileLocation location of the file.\n   * @return a map of character to its frequency, an empty map if file does not exist.\n   */\n  public static Map<Character, Long> characterFrequency(String fileLocation) {\n    try (var bufferedReader = new BufferedReader(new FileReader(fileLocation))) {\n      return bufferedReader\n          .lines()\n          .flatMapToInt(String::chars)\n          .mapToObj(x -> (char) x)\n          .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));\n    } catch (IOException ex) {\n      LOGGER.error(\"An error occurred: \", ex);\n    }\n    return Collections.emptyMap();\n  }\n\n  /**\n   * Return the character with the lowest frequency, if exists.\n   *\n   * @return the character, {@code Optional.empty()} otherwise.\n   */\n  public static Character lowestFrequencyChar(Map<Character, Long> charFrequency) {\n    return charFrequency.entrySet().stream()\n        .min(Comparator.comparingLong(Entry::getValue))\n        .map(Entry::getKey)\n        .orElseThrow();\n  }\n\n  /**\n   * Count the number of lines in a file.\n   *\n   * @return number of lines, 0 if file does not exist.\n   */\n  public static Integer countLines(String fileLocation) {\n    try (var bufferedReader = new BufferedReader(new FileReader(fileLocation))) {\n      return (int) bufferedReader.lines().count();\n    } catch (IOException ex) {\n      LOGGER.error(\"An error occurred: \", ex);\n    }\n    return 0;\n  }\n\n  /**\n   * Downloads the contents from the given urlString, and stores it in a temporary directory.\n   *\n   * @return the absolute path of the file downloaded.\n   */\n  public static String downloadFile(String urlString) throws IOException {\n    LOGGER.info(\"Downloading contents from url: {}\", urlString);\n    var url = new URL(urlString);\n    var file = File.createTempFile(\"promise_pattern\", null);\n    try (var bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));\n        var writer = new FileWriter(file)) {\n      String line;\n      while ((line = bufferedReader.readLine()) != null) {\n        writer.write(line);\n        writer.write(\"\\n\");\n      }\n      LOGGER.info(\"File downloaded at: {}\", file.getAbsolutePath());\n      return file.getAbsolutePath();\n    }\n  }\n}\n"
  },
  {
    "path": "promise/src/test/java/com/iluwatar/promise/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.promise;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(null));\n  }\n}\n"
  },
  {
    "path": "promise/src/test/java/com/iluwatar/promise/PromiseTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.promise;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\n\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.Consumer;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests Promise class. */\nclass PromiseTest {\n\n  private Executor executor;\n  private Promise<Integer> promise;\n\n  @BeforeEach\n  void setUp() {\n    executor = Executors.newSingleThreadExecutor();\n    promise = new Promise<>();\n  }\n\n  @Test\n  void promiseIsFulfilledWithTheResultantValueOfExecutingTheTask()\n      throws InterruptedException, ExecutionException {\n    promise.fulfillInAsync(new NumberCrunchingTask(), executor);\n\n    assertEquals(NumberCrunchingTask.CRUNCHED_NUMBER, promise.get());\n    assertTrue(promise.isDone());\n    assertFalse(promise.isCancelled());\n  }\n\n  @Test\n  void promiseIsFulfilledWithAnExceptionIfTaskThrowsAnException() throws InterruptedException {\n    testWaitingForeverForPromiseToBeFulfilled();\n    testWaitingSomeTimeForPromiseToBeFulfilled();\n  }\n\n  private void testWaitingForeverForPromiseToBeFulfilled() throws InterruptedException {\n    var promise = new Promise<Integer>();\n    promise.fulfillInAsync(\n        () -> {\n          throw new RuntimeException(\"Barf!\");\n        },\n        executor);\n\n    try {\n      promise.get();\n      fail(\"Fetching promise should result in exception if the task threw an exception\");\n    } catch (ExecutionException ex) {\n      assertTrue(promise.isDone());\n      assertFalse(promise.isCancelled());\n    }\n\n    try {\n      promise.get(1000, TimeUnit.SECONDS);\n      fail(\"Fetching promise should result in exception if the task threw an exception\");\n    } catch (ExecutionException ex) {\n      assertTrue(promise.isDone());\n      assertFalse(promise.isCancelled());\n    }\n  }\n\n  private void testWaitingSomeTimeForPromiseToBeFulfilled() throws InterruptedException {\n    var promise = new Promise<Integer>();\n    promise.fulfillInAsync(\n        () -> {\n          throw new RuntimeException(\"Barf!\");\n        },\n        executor);\n\n    try {\n      promise.get(1000, TimeUnit.SECONDS);\n      fail(\"Fetching promise should result in exception if the task threw an exception\");\n    } catch (ExecutionException ex) {\n      assertTrue(promise.isDone());\n      assertFalse(promise.isCancelled());\n    }\n\n    try {\n      promise.get();\n      fail(\"Fetching promise should result in exception if the task threw an exception\");\n    } catch (ExecutionException ex) {\n      assertTrue(promise.isDone());\n      assertFalse(promise.isCancelled());\n    }\n  }\n\n  @Test\n  void dependentPromiseIsFulfilledAfterTheConsumerConsumesTheResultOfThisPromise()\n      throws InterruptedException, ExecutionException {\n    var dependentPromise =\n        promise\n            .fulfillInAsync(new NumberCrunchingTask(), executor)\n            .thenAccept(value -> assertEquals(NumberCrunchingTask.CRUNCHED_NUMBER, value));\n\n    dependentPromise.get();\n    assertTrue(dependentPromise.isDone());\n    assertFalse(dependentPromise.isCancelled());\n  }\n\n  @Test\n  void dependentPromiseIsFulfilledWithAnExceptionIfConsumerThrowsAnException()\n      throws InterruptedException {\n    var dependentPromise =\n        promise\n            .fulfillInAsync(new NumberCrunchingTask(), executor)\n            .thenAccept(\n                value -> {\n                  throw new RuntimeException(\"Barf!\");\n                });\n\n    try {\n      dependentPromise.get();\n      fail(\n          \"Fetching dependent promise should result in exception \"\n              + \"if the action threw an exception\");\n    } catch (ExecutionException ex) {\n      assertTrue(promise.isDone());\n      assertFalse(promise.isCancelled());\n    }\n\n    try {\n      dependentPromise.get(1000, TimeUnit.SECONDS);\n      fail(\n          \"Fetching dependent promise should result in exception \"\n              + \"if the action threw an exception\");\n    } catch (ExecutionException ex) {\n      assertTrue(promise.isDone());\n      assertFalse(promise.isCancelled());\n    }\n  }\n\n  @Test\n  void dependentPromiseIsFulfilledAfterTheFunctionTransformsTheResultOfThisPromise()\n      throws InterruptedException, ExecutionException {\n    var dependentPromise =\n        promise\n            .fulfillInAsync(new NumberCrunchingTask(), executor)\n            .thenApply(\n                value -> {\n                  assertEquals(NumberCrunchingTask.CRUNCHED_NUMBER, value);\n                  return String.valueOf(value);\n                });\n\n    assertEquals(String.valueOf(NumberCrunchingTask.CRUNCHED_NUMBER), dependentPromise.get());\n    assertTrue(dependentPromise.isDone());\n    assertFalse(dependentPromise.isCancelled());\n  }\n\n  @Test\n  void dependentPromiseIsFulfilledWithAnExceptionIfTheFunctionThrowsException()\n      throws InterruptedException {\n    var dependentPromise =\n        promise\n            .fulfillInAsync(new NumberCrunchingTask(), executor)\n            .thenApply(\n                value -> {\n                  throw new RuntimeException(\"Barf!\");\n                });\n\n    try {\n      dependentPromise.get();\n      fail(\n          \"Fetching dependent promise should result in exception \"\n              + \"if the function threw an exception\");\n    } catch (ExecutionException ex) {\n      assertTrue(promise.isDone());\n      assertFalse(promise.isCancelled());\n    }\n\n    try {\n      dependentPromise.get(1000, TimeUnit.SECONDS);\n      fail(\n          \"Fetching dependent promise should result in exception \"\n              + \"if the function threw an exception\");\n    } catch (ExecutionException ex) {\n      assertTrue(promise.isDone());\n      assertFalse(promise.isCancelled());\n    }\n  }\n\n  @Test\n  void fetchingAnAlreadyFulfilledPromiseReturnsTheFulfilledValueImmediately()\n      throws ExecutionException {\n    var promise = new Promise<Integer>();\n    promise.fulfill(NumberCrunchingTask.CRUNCHED_NUMBER);\n\n    Integer result = promise.get(1000, TimeUnit.SECONDS);\n    assertEquals(NumberCrunchingTask.CRUNCHED_NUMBER, result);\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Test\n  void exceptionHandlerIsCalledWhenPromiseIsFulfilledExceptionally() {\n    var promise = new Promise<>();\n    var exceptionHandler = mock(Consumer.class);\n    promise.onError(exceptionHandler);\n\n    var exception = new Exception(\"barf!\");\n    promise.fulfillExceptionally(exception);\n\n    verify(exceptionHandler).accept(eq(exception));\n  }\n\n  private static class NumberCrunchingTask implements Callable<Integer> {\n\n    private static final Integer CRUNCHED_NUMBER = Integer.MAX_VALUE;\n\n    @Override\n    public Integer call() throws Exception {\n      // Do number crunching\n      Thread.sleep(100);\n      return CRUNCHED_NUMBER;\n    }\n  }\n}\n"
  },
  {
    "path": "property/README.md",
    "content": "---\ntitle: \"Property Pattern in Java: Enhancing Flexibility with Dynamic Attribute Management\"\nshortTitle: Property\ndescription: \"Explore how the Property design pattern facilitates dynamic property management in Java objects, enabling runtime modifications without altering class structure. Ideal for developers looking to enhance flexibility and maintainability in their code.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Abstraction\n  - Encapsulation\n  - Interface\n  - Object composition\n  - Polymorphism\n---\n\n## Also known as\n\n* Dynamic Properties\n* Property Bag\n\n## Intent of Property Design Pattern\n\nThe Property design pattern in Java allows dynamic addition, removal, or modification of object properties, offering a flexible solution for developers to customize object attributes at runtime.\n\n## Detailed Explanation of Property Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a custom burger ordering system at a restaurant. Each burger starts with a basic configuration (bun, patty), but customers can add or remove various ingredients (cheese, lettuce, tomato, sauces) as they wish. The restaurant's ordering system uses the Property design pattern to handle this flexibility. Each burger object dynamically updates its list of properties (ingredients) based on customer choices, allowing for a wide variety of custom burgers without needing a fixed class structure for every possible combination. This ensures the system can adapt to any new ingredient without altering the core burger class.\n\nIn plain words\n\n> Define and manage a dynamic set of properties for an object, allowing customization without altering its structure.\n\nSequence diagram\n\n![Property sequence diagram](./etc/property-sequence-diagram.png)\n\n## Programmatic Example of Property Pattern in Java\n\nThe Property design pattern, also known as Prototype inheritance, is a pattern that allows objects to be created from other objects, forming object hierarchies. This pattern is particularly useful when you want to create a new object that is a slight variation of an existing object.\n\nIn the given code, the Property pattern is used to create different types of characters, each with their own unique properties.\n\n```java\n// The Character class represents a character in a game. It has a type and a set of properties.\npublic class Character {\n  private Type type;\n  private Map<Stats, Integer> properties;\n\n  // The Character can be created with a type and a prototype. The new character will have the same properties as the prototype.\n  public Character(Type type, Character prototype) {\n    this.type = type;\n    this.properties = new HashMap<>(prototype.properties);\n  }\n\n  // Properties can be added or modified using the set method.\n  public void set(Stats stat, int value) {\n    properties.put(stat, value);\n  }\n\n  // Properties can be removed using the remove method.\n  public void remove(Stats stat) {\n    properties.remove(stat);\n  }\n\n  // The has method checks if a property is present.\n  public boolean has(Stats stat) {\n    return properties.containsKey(stat);\n  }\n\n  // The get method retrieves the value of a property.\n  public Integer get(Stats stat) {\n    return properties.get(stat);\n  }\n}\n\n// The Stats enum represents the different properties a character can have.\npublic enum Stats {\n  STRENGTH, AGILITY, ARMOR, ATTACK_POWER, INTELLECT, SPIRIT, RAGE, ENERGY\n}\n\n// The Type enum represents the different types of characters.\npublic enum Type {\n  MAGE, WARRIOR, ROGUE\n}\n```\n\nIn the `main` method, we create a prototype character and then create different types of characters based on the prototype:\n\n```java\npublic static void main(String[] args) {\n  // Create a prototype character with default properties\n  var charProto = new Character();\n  charProto.set(Stats.STRENGTH, 10);\n  charProto.set(Stats.AGILITY, 10);\n  charProto.set(Stats.ARMOR, 10);\n  charProto.set(Stats.ATTACK_POWER, 10);\n\n  // Create a mage character based on the prototype and add mage-specific properties\n  var mageProto = new Character(Type.MAGE, charProto);\n  mageProto.set(Stats.INTELLECT, 15);\n  mageProto.set(Stats.SPIRIT, 10);\n\n  // Create a warrior character based on the prototype and add warrior-specific properties\n  var warProto = new Character(Type.WARRIOR, charProto);\n  warProto.set(Stats.RAGE, 15);\n  warProto.set(Stats.ARMOR, 15); // boost default armor for warrior\n\n  // Create a rogue character based on the prototype and add rogue-specific properties\n  var rogueProto = new Character(Type.ROGUE, charProto);\n  rogueProto.set(Stats.ENERGY, 15);\n  rogueProto.set(Stats.AGILITY, 15); // boost default agility for rogue\n\n  // Create specific characters based on the prototypes\n  var mag = new Character(\"Player_1\", mageProto);\n  var warrior = new Character(\"Player_2\", warProto);\n  var rogue = new Character(\"Player_3\", rogueProto);\n}\n```\n\nProgram output:\n\n```\n08:27:52.567 [main] INFO com.iluwatar.property.App -- Player: Player_1\nCharacter type: MAGE\nStats:\n  - AGILITY:10\n  - STRENGTH:10\n  - ATTACK_POWER:10\n  - ARMOR:8\n  - INTELLECT:15\n  - SPIRIT:10\n\n08:27:52.569 [main] INFO com.iluwatar.property.App -- Player: Player_2\nCharacter type: WARRIOR\nStats:\n  - AGILITY:10\n  - STRENGTH:10\n  - ATTACK_POWER:10\n  - ARMOR:15\n  - RAGE:15\n\n08:27:52.569 [main] INFO com.iluwatar.property.App -- Player: Player_3\nCharacter type: ROGUE\nStats:\n  - AGILITY:15\n  - STRENGTH:10\n  - ATTACK_POWER:10\n  - ARMOR:10\n  - ENERGY:15\n\n08:27:52.569 [main] INFO com.iluwatar.property.App -- Player: Player_4\nCharacter type: ROGUE\nStats:\n  - AGILITY:15\n  - STRENGTH:10\n  - ATTACK_POWER:12\n  - ARMOR:10\n  - ENERGY:15\n```\n\nThis way, we can easily create new characters with different properties without having to create a new class for each type of character.\n\n## When to Use the Property Pattern in Java\n\nUse the Property pattern when\n\n* When you need to manage a flexible set of properties without altering the class structure.\n* When properties need to be added or removed dynamically at runtime.\n* When different instances of a class need different properties.\n\n## Real-World Applications of Property Pattern in Java\n\n* Configurations in applications where different entities require different sets of configurable parameters.\n* Game development where game entities (like characters or objects) need various attributes that can change during gameplay.\n* User profile management systems where user profiles can have dynamic attributes.\n\n## Benefits and Trade-offs of Property Pattern\n\nBenefits:\n\nEmploying the Property design pattern enhances\n\n* Flexibility: Allows for the dynamic addition, removal, and modification of properties.\n* Decoupling: Reduces dependencies between classes and their properties.\n* Ease of Use: Simplifies the management of properties in large systems.\n\nTrade-offs:\n\n* Performance Overhead: Dynamic property management can introduce runtime overhead.\n* Complexity: May increase the complexity of the code, making it harder to maintain and understand.\n* Type Safety: Reduces type safety since properties are often managed as generic key-value pairs.\n\n## Related Java Design Patterns\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): Composite allows a tree structure of objects where each node can be a complex or simple object. Property pattern can be seen as a flattened version, managing properties without hierarchy.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Both patterns enhance an object's behavior, but the Property pattern focuses on adding properties dynamically, while the Decorator adds responsibilities.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Like the Property pattern, the Strategy pattern allows dynamic behavior changes, but Strategy is about changing the algorithm used by an object.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n"
  },
  {
    "path": "property/etc/property.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <enumeration id=\"1\" language=\"java\" name=\"com.iluwatar.property.Character.Type\" project=\"property\" \n    file=\"/property/src/main/java/com/iluwatar/property/Character.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"142\" width=\"144\" x=\"285\" y=\"594\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <enumeration id=\"2\" language=\"java\" name=\"com.iluwatar.property.Stats\" project=\"property\" \n    file=\"/property/src/main/java/com/iluwatar/property/Stats.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"232\" width=\"170\" x=\"205\" y=\"268\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.property.Character\" project=\"property\" \n    file=\"/property/src/main/java/com/iluwatar/property/Character.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"286\" width=\"206\" x=\"415\" y=\"268\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"4\" language=\"java\" name=\"com.iluwatar.property.Prototype\" project=\"property\" \n    file=\"/property/src/main/java/com/iluwatar/property/Prototype.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"142\" width=\"152\" x=\"469\" y=\"594\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <association id=\"5\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"6\" name=\"type\"/>      \n      <multiplicity id=\"7\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"8\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"9\" name=\"prototype\"/>      \n      <multiplicity id=\"10\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <nesting id=\"11\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </nesting>  \n  <realization id=\"12\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "property/etc/property.urm.puml",
    "content": "@startuml\npackage com.iluwatar.property {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Character {\n    - name : String\n    - properties : Map<Stats, Integer>\n    - prototype : Prototype\n    - type : Type\n    + Character()\n    + Character(name : String, prototype : Character)\n    + Character(type : Type, prototype : Prototype)\n    + get(stat : Stats) : Integer\n    + has(stat : Stats) : boolean\n    + name() : String\n    + remove(stat : Stats)\n    + set(stat : Stats, val : Integer)\n    + toString() : String\n    + type() : Type\n  }\n  enum Type {\n    + MAGE {static}\n    + ROGUE {static}\n    + WARRIOR {static}\n    + valueOf(name : String) : Type {static}\n    + values() : Type[] {static}\n  }\n  interface Prototype {\n    + get(Stats) : Integer {abstract}\n    + has(Stats) : boolean {abstract}\n    + remove(Stats) {abstract}\n    + set(Stats, Integer) {abstract}\n  }\n  enum Stats {\n    + AGILITY {static}\n    + ARMOR {static}\n    + ATTACK_POWER {static}\n    + ENERGY {static}\n    + INTELLECT {static}\n    + RAGE {static}\n    + SPIRIT {static}\n    + STRENGTH {static}\n    + valueOf(name : String) : Stats {static}\n    + values() : Stats[] {static}\n  }\n}\nCharacter -->  \"-prototype\" Prototype\nType ..+ Character\nCharacter -->  \"-type\" Type\nCharacter ..|> Prototype \n@enduml"
  },
  {
    "path": "property/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>property</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.property.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "property/src/main/java/com/iluwatar/property/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.property;\n\nimport com.iluwatar.property.Character.Type;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Property pattern is also known as Prototype inheritance.\n *\n * <p>In prototype inheritance instead of classes, as opposite to Java class inheritance, objects\n * are used to create another objects and object hierarchies. Hierarchies are created using\n * prototype chain through delegation: every object has link to parent object. Any base (parent)\n * object can be amended at runtime (by adding or removal of some property), and all child objects\n * will be affected as result.\n *\n * <p>In this example we demonstrate {@link Character} instantiation using the Property pattern.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    /* set up */\n    var charProto = new Character();\n    charProto.set(Stats.STRENGTH, 10);\n    charProto.set(Stats.AGILITY, 10);\n    charProto.set(Stats.ARMOR, 10);\n    charProto.set(Stats.ATTACK_POWER, 10);\n\n    var mageProto = new Character(Type.MAGE, charProto);\n    mageProto.set(Stats.INTELLECT, 15);\n    mageProto.set(Stats.SPIRIT, 10);\n\n    var warProto = new Character(Type.WARRIOR, charProto);\n    warProto.set(Stats.RAGE, 15);\n    warProto.set(Stats.ARMOR, 15); // boost default armor for warrior\n\n    var rogueProto = new Character(Type.ROGUE, charProto);\n    rogueProto.set(Stats.ENERGY, 15);\n    rogueProto.set(Stats.AGILITY, 15); // boost default agility for rogue\n\n    /* usage */\n    var mag = new Character(\"Player_1\", mageProto);\n    mag.set(Stats.ARMOR, 8);\n    LOGGER.info(mag.toString());\n\n    var warrior = new Character(\"Player_2\", warProto);\n    LOGGER.info(warrior.toString());\n\n    var rogue = new Character(\"Player_3\", rogueProto);\n    LOGGER.info(rogue.toString());\n\n    var rogueDouble = new Character(\"Player_4\", rogue);\n    rogueDouble.set(Stats.ATTACK_POWER, 12);\n    LOGGER.info(rogueDouble.toString());\n  }\n}\n"
  },
  {
    "path": "property/src/main/java/com/iluwatar/property/Character.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.property;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/** Represents Character in game and his abilities (base stats). */\npublic class Character implements Prototype {\n\n  /** Enumeration of Character types. */\n  public enum Type {\n    WARRIOR,\n    MAGE,\n    ROGUE\n  }\n\n  private final Prototype prototype;\n  private final Map<Stats, Integer> properties = new HashMap<>();\n\n  private String name;\n  private Type type;\n\n  /** Constructor. */\n  public Character() {\n    this.prototype =\n        new Prototype() { // Null-value object\n          @Override\n          public Integer get(Stats stat) {\n            return null;\n          }\n\n          @Override\n          public boolean has(Stats stat) {\n            return false;\n          }\n\n          @Override\n          public void set(Stats stat, Integer val) {\n            // Does Nothing\n          }\n\n          @Override\n          public void remove(Stats stat) {\n            // Does Nothing.\n          }\n        };\n  }\n\n  public Character(Type type, Prototype prototype) {\n    this.type = type;\n    this.prototype = prototype;\n  }\n\n  /** Constructor. */\n  public Character(String name, Character prototype) {\n    this.name = name;\n    this.type = prototype.type;\n    this.prototype = prototype;\n  }\n\n  public String name() {\n    return name;\n  }\n\n  public Type type() {\n    return type;\n  }\n\n  @Override\n  public Integer get(Stats stat) {\n    var containsValue = properties.containsKey(stat);\n    if (containsValue) {\n      return properties.get(stat);\n    } else {\n      return prototype.get(stat);\n    }\n  }\n\n  @Override\n  public boolean has(Stats stat) {\n    return get(stat) != null;\n  }\n\n  @Override\n  public void set(Stats stat, Integer val) {\n    properties.put(stat, val);\n  }\n\n  @Override\n  public void remove(Stats stat) {\n    properties.put(stat, null);\n  }\n\n  @Override\n  public String toString() {\n    var builder = new StringBuilder();\n    if (name != null) {\n      builder.append(\"Player: \").append(name).append('\\n');\n    }\n\n    if (type != null) {\n      builder.append(\"Character type: \").append(type.name()).append('\\n');\n    }\n\n    builder.append(\"Stats:\\n\");\n    for (var stat : Stats.values()) {\n      var value = this.get(stat);\n      if (value == null) {\n        continue;\n      }\n      builder.append(\" - \").append(stat.name()).append(':').append(value).append('\\n');\n    }\n    return builder.toString();\n  }\n}\n"
  },
  {
    "path": "property/src/main/java/com/iluwatar/property/Prototype.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.property;\n\n/** Interface for prototype inheritance. */\npublic interface Prototype {\n\n  Integer get(Stats stat);\n\n  boolean has(Stats stat);\n\n  void set(Stats stat, Integer val);\n\n  void remove(Stats stat);\n}\n"
  },
  {
    "path": "property/src/main/java/com/iluwatar/property/Stats.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.property;\n\n/** All possible attributes that Character can have. */\npublic enum Stats {\n  AGILITY,\n  STRENGTH,\n  ATTACK_POWER,\n  ARMOR,\n  INTELLECT,\n  SPIRIT,\n  ENERGY,\n  RAGE\n}\n"
  },
  {
    "path": "property/src/test/java/com/iluwatar/property/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.property;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "property/src/test/java/com/iluwatar/property/CharacterTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.property;\n\nimport static com.iluwatar.property.Character.Type;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.Arrays;\nimport org.junit.jupiter.api.Test;\n\n/** CharacterTest */\nclass CharacterTest {\n\n  @Test\n  void testPrototypeStats() {\n    final var prototype = new Character();\n\n    for (final var stat : Stats.values()) {\n      assertFalse(prototype.has(stat));\n      assertNull(prototype.get(stat));\n\n      final var expectedValue = stat.ordinal();\n      prototype.set(stat, expectedValue);\n      assertTrue(prototype.has(stat));\n      assertEquals(expectedValue, prototype.get(stat));\n\n      prototype.remove(stat);\n      assertFalse(prototype.has(stat));\n      assertNull(prototype.get(stat));\n    }\n  }\n\n  @Test\n  void testCharacterStats() {\n    final var prototype = new Character();\n    Arrays.stream(Stats.values()).forEach(stat -> prototype.set(stat, stat.ordinal()));\n\n    final var mage = new Character(Type.MAGE, prototype);\n    for (final var stat : Stats.values()) {\n      final var expectedValue = stat.ordinal();\n      assertTrue(mage.has(stat));\n      assertEquals(expectedValue, mage.get(stat));\n    }\n  }\n\n  @Test\n  void testToString() {\n    final var prototype = new Character();\n    prototype.set(Stats.ARMOR, 1);\n    prototype.set(Stats.AGILITY, 2);\n    prototype.set(Stats.INTELLECT, 3);\n    var message =\n        \"\"\"\n            Stats:\n             - AGILITY:2\n             - ARMOR:1\n             - INTELLECT:3\n            \"\"\";\n    assertEquals(message, prototype.toString());\n\n    final var stupid = new Character(Type.ROGUE, prototype);\n    stupid.remove(Stats.INTELLECT);\n    String expectedStupidString =\n        \"\"\"\n            Character type: ROGUE\n            Stats:\n             - AGILITY:2\n             - ARMOR:1\n            \"\"\";\n    assertEquals(expectedStupidString, stupid.toString());\n\n    final var weak = new Character(\"weak\", prototype);\n    weak.remove(Stats.ARMOR);\n    String expectedWeakString =\n        \"\"\"\n            Player: weak\n            Stats:\n             - AGILITY:2\n             - INTELLECT:3\n            \"\"\";\n    assertEquals(expectedWeakString, weak.toString());\n  }\n\n  @Test\n  void testName() {\n    final var prototype = new Character();\n    prototype.set(Stats.ARMOR, 1);\n    prototype.set(Stats.INTELLECT, 2);\n    assertNull(prototype.name());\n\n    final var stupid = new Character(Type.ROGUE, prototype);\n    stupid.remove(Stats.INTELLECT);\n    assertNull(stupid.name());\n\n    final var weak = new Character(\"weak\", prototype);\n    weak.remove(Stats.ARMOR);\n    assertEquals(\"weak\", weak.name());\n  }\n\n  @Test\n  void testType() {\n    final var prototype = new Character();\n    prototype.set(Stats.ARMOR, 1);\n    prototype.set(Stats.INTELLECT, 2);\n    assertNull(prototype.type());\n\n    final var stupid = new Character(Type.ROGUE, prototype);\n    stupid.remove(Stats.INTELLECT);\n    assertEquals(Type.ROGUE, stupid.type());\n\n    final var weak = new Character(\"weak\", prototype);\n    weak.remove(Stats.ARMOR);\n    assertNull(weak.type());\n  }\n}\n"
  },
  {
    "path": "prototype/README.md",
    "content": "---\ntitle: \"Prototype Pattern in Java: Mastering Object Cloning for Efficient Instantiation\"\nshortTitle: Prototype\ndescription: \"Explore the Prototype design pattern in Java with a comprehensive guide on its implementation, advantages, and real-world applications. Learn how to efficiently clone objects and manage object creation in your Java applications.\"\ncategory: Creational\nlanguage: en\ntag: \n  - Gang of Four\n  - Instantiation\n  - Object composition\n  - Polymorphism\n---\n\n## Also known as \n\n* Clone\n\n## Intent of Prototype Design Pattern\n\nThe Prototype pattern is used to specify the kinds of objects to create using a prototypical instance, and create new instances through object cloning.\n\n## Detailed Explanation of Prototype Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a company that manufactures custom-designed furniture. Instead of creating each piece from scratch every time an order is placed, they keep prototypes of their most popular designs. When a customer places an order for a specific design, the company simply clones the prototype of that design and makes the necessary customizations. This approach saves time and resources as the basic structure and design details are already in place, allowing the company to quickly fulfill orders with consistent quality.\n>\n> In this scenario, the furniture prototypes act like object prototypes in software, enabling efficient creation of new, customized pieces based on existing models.\n\nIn plain words\n\n> Create an object based on an existing object through cloning.\n\nWikipedia says\n\n> The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects.\n\nSequence diagram\n\n![Prototype sequence diagram](./etc/prototype-sequence-diagram.png)\n\n## Programmatic Example of Prototype Pattern in Java\n\nIn Java, the prototype pattern is recommended to be implemented as follows. First, create an interface with a method for cloning objects. In this example, `Prototype` interface accomplishes this with its `copy` method.\n\n```java\npublic abstract class Prototype<T> implements Cloneable {\n    @SneakyThrows\n    public T copy() {\n        return (T) super.clone();\n    }\n}\n```\n\nOur example contains a hierarchy of different creatures. For example, let's look at `Beast` and `OrcBeast` classes.\n\n```java\n@EqualsAndHashCode(callSuper = false)\n@NoArgsConstructor\npublic abstract class Beast extends Prototype<Beast> {\n  public Beast(Beast source) {}\n}\n```\n\n```java\n@EqualsAndHashCode(callSuper = false)\n@RequiredArgsConstructor\npublic class OrcBeast extends Beast {\n\n  private final String weapon;\n\n  public OrcBeast(OrcBeast orcBeast) {\n    super(orcBeast);\n    this.weapon = orcBeast.weapon;\n  }\n\n  @Override\n  public String toString() {\n    return \"Orcish wolf attacks with \" + weapon;\n  }\n}\n```\n\nWe don't want to go into too many details, but the full example contains also base classes `Mage` and `Warlord` and there are specialized implementations of those for elves and orcs.\n\nTo take full advantage of the prototype pattern, we create `HeroFactory` and `HeroFactoryImpl` classes to produce different kinds of creatures from prototypes.\n\n```java\npublic interface HeroFactory {\n  Mage createMage();\n  Warlord createWarlord();\n  Beast createBeast();\n}\n```\n\n```java\n@RequiredArgsConstructor\npublic class HeroFactoryImpl implements HeroFactory {\n\n  private final Mage mage;\n  private final Warlord warlord;\n  private final Beast beast;\n\n  public Mage createMage() {\n    return mage.copy();\n  }\n\n  public Warlord createWarlord() {\n    return warlord.copy();\n  }\n\n  public Beast createBeast() {\n    return beast.copy();\n  }\n}\n```\n\nNow, we are able to show the full prototype pattern in action producing new creatures by cloning existing instances.\n\n```java\npublic static void main(String[] args) {\n    var factory = new HeroFactoryImpl(\n            new ElfMage(\"cooking\"),\n            new ElfWarlord(\"cleaning\"),\n            new ElfBeast(\"protecting\")\n    );\n    var mage = factory.createMage();\n    var warlord = factory.createWarlord();\n    var beast = factory.createBeast();\n    LOGGER.info(mage.toString());\n    LOGGER.info(warlord.toString());\n    LOGGER.info(beast.toString());\n\n    factory = new HeroFactoryImpl(\n            new OrcMage(\"axe\"),\n            new OrcWarlord(\"sword\"),\n            new OrcBeast(\"laser\")\n    );\n    mage = factory.createMage();\n    warlord = factory.createWarlord();\n    beast = factory.createBeast();\n    LOGGER.info(mage.toString());\n    LOGGER.info(warlord.toString());\n    LOGGER.info(beast.toString());\n}\n```\n\nHere's the console output from running the example.\n\n```\n08:36:19.012 [main] INFO com.iluwatar.prototype.App -- Elven mage helps in cooking\n08:36:19.013 [main] INFO com.iluwatar.prototype.App -- Elven warlord helps in cleaning\n08:36:19.014 [main] INFO com.iluwatar.prototype.App -- Elven eagle helps in protecting\n08:36:19.014 [main] INFO com.iluwatar.prototype.App -- Orcish mage attacks with axe\n08:36:19.014 [main] INFO com.iluwatar.prototype.App -- Orcish warlord attacks with sword\n08:36:19.014 [main] INFO com.iluwatar.prototype.App -- Orcish wolf attacks with laser\n```\n\n## When to Use the Prototype Pattern in Java\n\n* When the classes to instantiate are specified at run-time, for example, by dynamic loading.\n* To avoid building a class hierarchy of factories that parallels the class hierarchy of products.\n* When instances of a class can have one of only a few different combinations of state. It may be more convenient to install a corresponding number of prototypes and clone them rather than instantiating the class manually, each time with the appropriate state.\n* When object creation is expensive compared to cloning.\n* When the concrete classes to instantiate are unknown until runtime.\n\n## Real-World Applications of Prototype Pattern in Java\n\n* In Java, the `Object.clone()` method is a classic implementation of the Prototype pattern.\n* GUI libraries often use prototypes for creating buttons, windows, and other widgets.\n* In game development, creating multiple objects (like enemy characters) with similar attributes.\n\n## Benefits and Trade-offs of Prototype Pattern\n\nBenefits:\n\nLeveraging the Prototype pattern in Java applications\n\n* Hides the complexities of instantiating new objects.\n* Reduces the number of classes.\n* Allows adding and removing objects at runtime.\n\nTrade-offs:\n\n* Requires implementing a cloning mechanism which might be complex.\n* Deep cloning can be difficult to implement correctly, especially if the classes have complex object graphs with circular references.\n\n## Related Java Design Patterns\n\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): Both involve creating objects, but Prototype uses cloning of a prototype instance whereas Abstract Factory creates objects using factory methods.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Singleton can use a prototype for creating instances if it allows cloning of its single instance.\n* [Composite](https://java-design-patterns.com/patterns/composite/): Prototypes are often used within composites to allow for dynamic creation of component trees.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n"
  },
  {
    "path": "prototype/etc/prototype.urm.puml",
    "content": "@startuml\npackage com.iluwatar.prototype {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  abstract class Beast {\n    + Beast()\n    + Beast(source : Beast)\n    + copy() : Beast {abstract}\n    + equals(obj : Object) : boolean\n  }\n  class ElfBeast {\n    - helpType : String\n    + ElfBeast(elfBeast : ElfBeast)\n    + ElfBeast(helpType : String)\n    + copy() : ElfBeast\n    + equals(obj : Object) : boolean\n    + toString() : String\n  }\n  class ElfMage {\n    - helpType : String\n    + ElfMage(elfMage : ElfMage)\n    + ElfMage(helpType : String)\n    + copy() : ElfMage\n    + equals(obj : Object) : boolean\n    + toString() : String\n  }\n  class ElfWarlord {\n    - helpType : String\n    + ElfWarlord(elfWarlord : ElfWarlord)\n    + ElfWarlord(helpType : String)\n    + copy() : ElfWarlord\n    + equals(obj : Object) : boolean\n    + toString() : String\n  }\n  interface HeroFactory {\n    + createBeast() : Beast {abstract}\n    + createMage() : Mage {abstract}\n    + createWarlord() : Warlord {abstract}\n  }\n  class HeroFactoryImpl {\n    - beast : Beast\n    - mage : Mage\n    - warlord : Warlord\n    + HeroFactoryImpl(mage : Mage, warlord : Warlord, beast : Beast)\n    + createBeast() : Beast\n    + createMage() : Mage\n    + createWarlord() : Warlord\n  }\n  abstract class Mage {\n    + Mage()\n    + Mage(source : Mage)\n    + copy() : Mage {abstract}\n    + equals(obj : Object) : boolean\n  }\n  class OrcBeast {\n    - weapon : String\n    + OrcBeast(orcBeast : OrcBeast)\n    + OrcBeast(weapon : String)\n    + copy() : OrcBeast\n    + equals(obj : Object) : boolean\n    + toString() : String\n  }\n  class OrcMage {\n    - weapon : String\n    + OrcMage(orcMage : OrcMage)\n    + OrcMage(weapon : String)\n    + copy() : OrcMage\n    + equals(obj : Object) : boolean\n    + toString() : String\n  }\n  class OrcWarlord {\n    - weapon : String\n    + OrcWarlord(orcWarlord : OrcWarlord)\n    + OrcWarlord(weapon : String)\n    + copy() : OrcWarlord\n    + equals(obj : Object) : boolean\n    + toString() : String\n  }\n  interface Prototype {\n    + copy() : Object {abstract}\n  }\n  abstract class Warlord {\n    + Warlord()\n    + Warlord(source : Warlord)\n    + copy() : Warlord {abstract}\n    + equals(obj : Object) : boolean\n  }\n}\nHeroFactoryImpl -->  \"-beast\" Beast\nHeroFactoryImpl -->  \"-warlord\" Warlord\nHeroFactoryImpl -->  \"-mage\" Mage\nBeast ..|> Prototype \nElfBeast --|> Beast \nElfMage --|> Mage \nElfWarlord --|> Warlord \nHeroFactoryImpl ..|> HeroFactory \nMage ..|> Prototype \nOrcBeast --|> Beast \nOrcMage --|> Mage \nOrcWarlord --|> Warlord \nWarlord ..|> Prototype \n@enduml"
  },
  {
    "path": "prototype/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>prototype</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-params</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.prototype.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Prototype pattern is a creational design pattern in software development. It is used when the\n * type of objects to create is determined by a prototypical instance, which is cloned to produce\n * new objects. This pattern is used to: - avoid subclasses of an object creator in the client\n * application, like the abstract factory pattern, does. - avoid the inherent cost of creating a new\n * object in the standard way (e.g., using the 'new' keyword)\n *\n * <p>In this example we have a factory class ({@link HeroFactoryImpl}) producing objects by cloning\n * the existing ones. The factory's prototype objects are given as constructor parameters.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var factory =\n        new HeroFactoryImpl(\n            new ElfMage(\"cooking\"), new ElfWarlord(\"cleaning\"), new ElfBeast(\"protecting\"));\n    var mage = factory.createMage();\n    var warlord = factory.createWarlord();\n    var beast = factory.createBeast();\n    LOGGER.info(mage.toString());\n    LOGGER.info(warlord.toString());\n    LOGGER.info(beast.toString());\n\n    factory =\n        new HeroFactoryImpl(new OrcMage(\"axe\"), new OrcWarlord(\"sword\"), new OrcBeast(\"laser\"));\n    mage = factory.createMage();\n    warlord = factory.createWarlord();\n    beast = factory.createBeast();\n    LOGGER.info(mage.toString());\n    LOGGER.info(warlord.toString());\n    LOGGER.info(beast.toString());\n  }\n}\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/Beast.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.NoArgsConstructor;\n\n/** Beast. */\n@EqualsAndHashCode(callSuper = false)\n@NoArgsConstructor\npublic abstract class Beast extends Prototype<Beast> {\n\n  public Beast(Beast source) {}\n}\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/ElfBeast.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.RequiredArgsConstructor;\n\n/** ElfBeast. */\n@EqualsAndHashCode(callSuper = true)\n@RequiredArgsConstructor\npublic class ElfBeast extends Beast {\n\n  private final String helpType;\n\n  public ElfBeast(ElfBeast elfBeast) {\n    super(elfBeast);\n    this.helpType = elfBeast.helpType;\n  }\n\n  @Override\n  public String toString() {\n    return \"Elven eagle helps in \" + helpType;\n  }\n}\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/ElfMage.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.RequiredArgsConstructor;\n\n/** ElfMage. */\n@EqualsAndHashCode(callSuper = true)\n@RequiredArgsConstructor\npublic class ElfMage extends Mage {\n\n  private final String helpType;\n\n  public ElfMage(ElfMage elfMage) {\n    super(elfMage);\n    this.helpType = elfMage.helpType;\n  }\n\n  @Override\n  public String toString() {\n    return \"Elven mage helps in \" + helpType;\n  }\n}\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/ElfWarlord.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.RequiredArgsConstructor;\n\n/** ElfWarlord. */\n@EqualsAndHashCode(callSuper = true)\n@RequiredArgsConstructor\npublic class ElfWarlord extends Warlord {\n\n  private final String helpType;\n\n  public ElfWarlord(ElfWarlord elfWarlord) {\n    super(elfWarlord);\n    this.helpType = elfWarlord.helpType;\n  }\n\n  @Override\n  public String toString() {\n    return \"Elven warlord helps in \" + helpType;\n  }\n}\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/HeroFactory.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\n/** Interface for the factory class. */\npublic interface HeroFactory {\n\n  Mage createMage();\n\n  Warlord createWarlord();\n\n  Beast createBeast();\n}\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/HeroFactoryImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport lombok.RequiredArgsConstructor;\n\n/** Concrete factory class. */\n@RequiredArgsConstructor\npublic class HeroFactoryImpl implements HeroFactory {\n\n  private final Mage mage;\n  private final Warlord warlord;\n  private final Beast beast;\n\n  /** Create mage. */\n  public Mage createMage() {\n    return mage.copy();\n  }\n\n  /** Create warlord. */\n  public Warlord createWarlord() {\n    return warlord.copy();\n  }\n\n  /** Create beast. */\n  public Beast createBeast() {\n    return beast.copy();\n  }\n}\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/Mage.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.NoArgsConstructor;\n\n/** Mage. */\n@EqualsAndHashCode(callSuper = false)\n@NoArgsConstructor\npublic abstract class Mage extends Prototype<Mage> {\n\n  public Mage(Mage source) {}\n}\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/OrcBeast.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.RequiredArgsConstructor;\n\n/** OrcBeast. */\n@EqualsAndHashCode(callSuper = false)\n@RequiredArgsConstructor\npublic class OrcBeast extends Beast {\n\n  private final String weapon;\n\n  public OrcBeast(OrcBeast orcBeast) {\n    super(orcBeast);\n    this.weapon = orcBeast.weapon;\n  }\n\n  @Override\n  public String toString() {\n    return \"Orcish wolf attacks with \" + weapon;\n  }\n}\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/OrcMage.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.RequiredArgsConstructor;\n\n/** OrcMage. */\n@EqualsAndHashCode(callSuper = true)\n@RequiredArgsConstructor\npublic class OrcMage extends Mage {\n\n  private final String weapon;\n\n  public OrcMage(OrcMage orcMage) {\n    super(orcMage);\n    this.weapon = orcMage.weapon;\n  }\n\n  @Override\n  public String toString() {\n    return \"Orcish mage attacks with \" + weapon;\n  }\n}\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/OrcWarlord.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.RequiredArgsConstructor;\n\n/** OrcWarlord. */\n@EqualsAndHashCode(callSuper = true)\n@RequiredArgsConstructor\npublic class OrcWarlord extends Warlord {\n\n  private final String weapon;\n\n  public OrcWarlord(OrcWarlord orcWarlord) {\n    super(orcWarlord);\n    this.weapon = orcWarlord.weapon;\n  }\n\n  @Override\n  public String toString() {\n    return \"Orcish warlord attacks with \" + weapon;\n  }\n}\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/Prototype.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport lombok.SneakyThrows;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Prototype. */\n@Slf4j\npublic abstract class Prototype<T> implements Cloneable {\n\n  /** Object a shallow copy of this object or null if this object is not Cloneable. */\n  @SuppressWarnings(\"unchecked\")\n  @SneakyThrows\n  public T copy() {\n    return (T) super.clone();\n  }\n}\n"
  },
  {
    "path": "prototype/src/main/java/com/iluwatar/prototype/Warlord.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport lombok.EqualsAndHashCode;\nimport lombok.NoArgsConstructor;\n\n/** Warlord. */\n@EqualsAndHashCode(callSuper = false)\n@NoArgsConstructor\npublic abstract class Warlord extends Prototype<Warlord> {\n\n  public Warlord(Warlord source) {}\n}\n"
  },
  {
    "path": "prototype/src/test/java/com/iluwatar/prototype/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.prototype;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNotSame;\nimport static org.junit.jupiter.api.Assertions.assertSame;\n\nimport java.util.Collection;\nimport java.util.List;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\n/**\n * PrototypeTest\n *\n * @param <P> Prototype\n */\nclass PrototypeTest<P extends Prototype<P>> {\n  static Collection<Object[]> dataProvider() {\n    return List.of(\n        new Object[] {new OrcBeast(\"axe\"), \"Orcish wolf attacks with axe\"},\n        new Object[] {new OrcMage(\"sword\"), \"Orcish mage attacks with sword\"},\n        new Object[] {new OrcWarlord(\"laser\"), \"Orcish warlord attacks with laser\"},\n        new Object[] {new ElfBeast(\"cooking\"), \"Elven eagle helps in cooking\"},\n        new Object[] {new ElfMage(\"cleaning\"), \"Elven mage helps in cleaning\"},\n        new Object[] {new ElfWarlord(\"protecting\"), \"Elven warlord helps in protecting\"});\n  }\n\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testPrototype(P testedPrototype, String expectedToString) {\n    assertEquals(expectedToString, testedPrototype.toString());\n\n    final var clone = testedPrototype.copy();\n    assertNotNull(clone);\n    assertNotSame(clone, testedPrototype);\n    assertSame(testedPrototype.getClass(), clone.getClass());\n    assertEquals(clone, testedPrototype);\n  }\n}\n"
  },
  {
    "path": "proxy/README.md",
    "content": "---\ntitle: \"Proxy Pattern in Java: Enhancing Security and Control with Smart Proxies\"\nshortTitle: Proxy\ndescription: \"Explore the Proxy design pattern in Java with detailed examples. Learn how it provides controlled access, facilitates lazy initialization, and ensures security. Ideal for developers looking to implement advanced Java techniques.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Decoupling\n  - Encapsulation\n  - Gang of Four\n  - Lazy initialization\n  - Proxy\n  - Security\n  - Wrapping\n---\n\n## Also known as\n\n* Surrogate\n\n## Intent of Proxy Design Pattern\n\nThe Proxy pattern in Java provides a surrogate or placeholder to effectively control access to an object, enhancing security and resource management.\n\n## Detailed Explanation of Proxy Pattern with Real-World Examples\n\nReal-world example\n\n> In a real-world scenario, consider a security guard at a gated community. The security guard acts as a proxy for the residents. When a visitor arrives, the guard checks the visitor's credentials and permissions before allowing them access to the community. If the visitor is authorized, the guard grants entry; if not, entry is denied. This ensures that only authorized individuals can access the community, much like a Proxy design pattern controls access to a specific object.\n\nIn plain words\n\n> Utilizing the Java Proxy pattern, a class encapsulates the functionality of another, streamlining access control and operation efficiency.\n\nWikipedia says\n\n> A proxy, in its most general form, is a class functioning as an interface to something else. A proxy is a wrapper or agent object that is being called by the client to access the real serving object behind the scenes. Use of the proxy can simply be forwarding to the real object, or can provide additional logic. In the proxy extra functionality can be provided, for example caching when operations on the real object are resource intensive, or checking preconditions before operations on the real object are invoked.\n\nSequence diagram\n\n![Proxy sequence diagram](./etc/proxy-sequence-diagram.png)\n\n## Programmatic Example of Proxy Pattern in Java\n\nImagine a tower where the local wizards go to study their spells. The ivory tower can only be accessed through a proxy which ensures that only the first three wizards can enter. Here the proxy represents the functionality of the tower and adds access control to it.\n\nFirst, we have the `WizardTower` interface and the `IvoryTower` class.\n\n```java\npublic interface WizardTower {\n  void enter(Wizard wizard);\n}\n```\n\n```java\n@Slf4j\npublic class IvoryTower implements WizardTower {\n  public void enter(Wizard wizard) {\n    LOGGER.info(\"{} enters the tower.\", wizard);\n  }\n}\n```\n\nThen a simple `Wizard` class.\n\n```java\npublic class Wizard {\n\n  private final String name;\n\n  public Wizard(String name) {\n    this.name = name;\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n}\n```\n\nThen we have the `WizardTowerProxy` to add access control to `WizardTower`.\n\n```java\n@Slf4j\npublic class WizardTowerProxy implements WizardTower {\n\n  private static final int NUM_WIZARDS_ALLOWED = 3;\n  private int numWizards;\n  private final WizardTower tower;\n\n  public WizardTowerProxy(WizardTower tower) {\n    this.tower = tower;\n  }\n\n  @Override\n  public void enter(Wizard wizard) {\n    if (numWizards < NUM_WIZARDS_ALLOWED) {\n      tower.enter(wizard);\n      numWizards++;\n    } else {\n      LOGGER.info(\"{} is not allowed to enter!\", wizard);\n    }\n  }\n}\n```\n\nAnd here is the tower entering scenario.\n\n```java\n  public static void main(String[] args) {\n\n    var proxy = new WizardTowerProxy(new IvoryTower());\n    proxy.enter(new Wizard(\"Red wizard\"));\n    proxy.enter(new Wizard(\"White wizard\"));\n    proxy.enter(new Wizard(\"Black wizard\"));\n    proxy.enter(new Wizard(\"Green wizard\"));\n    proxy.enter(new Wizard(\"Brown wizard\"));\n}\n```\n\nProgram output:\n\n```\n08:42:06.183 [main] INFO com.iluwatar.proxy.IvoryTower -- Red wizard enters the tower.\n08:42:06.186 [main] INFO com.iluwatar.proxy.IvoryTower -- White wizard enters the tower.\n08:42:06.186 [main] INFO com.iluwatar.proxy.IvoryTower -- Black wizard enters the tower.\n08:42:06.186 [main] INFO com.iluwatar.proxy.WizardTowerProxy -- Green wizard is not allowed to enter!\n08:42:06.186 [main] INFO com.iluwatar.proxy.WizardTowerProxy -- Brown wizard is not allowed to enter!\n```\n\n## When to Use the Proxy Pattern in Java\n\nProxy is applicable whenever there is a need for a more versatile or sophisticated reference to an object than a simple pointer. Here are several common situations in which the Proxy pattern is applicable. Typically, the proxy pattern is used to\n\n* Control access to another object\n* Lazy initialization\n* Implement logging\n* Facilitate network connection\n* Count references to an object\n* Provide a local representation for an object that is in a different address space.\n\n## Real-World Applications of Proxy Pattern in Java\n\n* Virtual Proxies: In applications that need heavy resources like large images or complex calculations, virtual proxies can be used to instantiate objects only when needed.\n* Remote Proxies: Used in remote method invocation (RMI) to manage interactions with remote objects.\n* Protection Proxies: Control access to the original object to ensure proper authorization.\n* [java.lang.reflect.Proxy](http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html)\n* [Apache Commons Proxy](https://commons.apache.org/proper/commons-proxy/)\n* Mocking frameworks [Mockito](https://site.mockito.org/),[Powermock](https://powermock.github.io/), [EasyMock](https://easymock.org/)\n* [UIAppearance](https://developer.apple.com/documentation/uikit/uiappearance)\n\n## Benefits and Trade-offs of Proxy Pattern\n\nBenefits:\n\n* Controlled Access: Proxies control access to the real object, allowing for checks, logging, or other operations.\n* Lazy Initialization: Proxies can delay the creation and initialization of resource-intensive objects until they are needed.\n* Remote Proxy Handling: Simplifies interaction with remote objects by handling the network communication.\n\nTrade-offs:\n\n* Overhead: Adding a proxy introduces additional layers that might add overhead.\n* Complexity: Increases the complexity of the system by adding more classes.\n\n## Related Java Design Patterns\n\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): The Adapter pattern changes the interface of an existing object, whereas Proxy provides the same interface as the original object.\n* [Ambassador](https://java-design-patterns.com/patterns/ambassador/): Ambassador is similar to Proxy as it acts as an intermediary, especially in remote communications, enhancing access control and monitoring.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Both Decorator and Proxy patterns provide a level of indirection, but the Decorator pattern adds responsibilities to objects dynamically, while Proxy controls access.\n* [Facade](https://java-design-patterns.com/patterns/facade/): Facade provides a simplified interface to a complex subsystem, while Proxy controls access to a particular object.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n"
  },
  {
    "path": "proxy/etc/proxy.urm.puml",
    "content": "@startuml\npackage com.iluwatar.proxy {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class IvoryTower {\n    - LOGGER : Logger {static}\n    + IvoryTower()\n    + enter(wizard : Wizard)\n  }\n  class Wizard {\n    - name : String\n    + Wizard(name : String)\n    + toString() : String\n  }\n  interface WizardTower {\n    + enter(Wizard) {abstract}\n  }\n  class WizardTowerProxy {\n    - LOGGER : Logger {static}\n    - NUM_WIZARDS_ALLOWED : int {static}\n    - numWizards : int\n    - tower : WizardTower\n    + WizardTowerProxy(tower : WizardTower)\n    + enter(wizard : Wizard)\n  }\n}\nWizardTowerProxy -->  \"-tower\" WizardTower\nIvoryTower ..|> WizardTower \nWizardTowerProxy ..|> WizardTower \n@enduml"
  },
  {
    "path": "proxy/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>proxy</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.proxy.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "proxy/src/main/java/com/iluwatar/proxy/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.proxy;\n\n/**\n * A proxy, in its most general form, is a class functioning as an interface to something else. The\n * proxy could interface to anything: a network connection, a large object in memory, a file, or\n * some other resource that is expensive or impossible to duplicate. In short, a proxy is a wrapper\n * or agent object that is being called by the client to access the real serving object behind the\n * scenes.\n *\n * <p>The Proxy design pattern allows you to provide an interface to other objects by creating a\n * wrapper class as the proxy. The wrapper class, which is the proxy, can add additional\n * functionality to the object of interest without changing the object's code.\n *\n * <p>In this example the proxy ({@link WizardTowerProxy}) controls access to the actual object (\n * {@link IvoryTower}).\n */\npublic class App {\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n\n    var proxy = new WizardTowerProxy(new IvoryTower());\n    proxy.enter(new Wizard(\"Red wizard\"));\n    proxy.enter(new Wizard(\"White wizard\"));\n    proxy.enter(new Wizard(\"Black wizard\"));\n    proxy.enter(new Wizard(\"Green wizard\"));\n    proxy.enter(new Wizard(\"Brown wizard\"));\n  }\n}\n"
  },
  {
    "path": "proxy/src/main/java/com/iluwatar/proxy/IvoryTower.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.proxy;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** The object to be proxied. */\n@Slf4j\npublic class IvoryTower implements WizardTower {\n\n  public void enter(Wizard wizard) {\n    LOGGER.info(\"{} enters the tower.\", wizard);\n  }\n}\n"
  },
  {
    "path": "proxy/src/main/java/com/iluwatar/proxy/Wizard.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.proxy;\n\nimport lombok.RequiredArgsConstructor;\n\n/** Wizard. */\n@RequiredArgsConstructor\npublic class Wizard {\n\n  private final String name;\n\n  @Override\n  public String toString() {\n    return name;\n  }\n}\n"
  },
  {
    "path": "proxy/src/main/java/com/iluwatar/proxy/WizardTower.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.proxy;\n\n/** WizardTower interface. */\npublic interface WizardTower {\n\n  void enter(Wizard wizard);\n}\n"
  },
  {
    "path": "proxy/src/main/java/com/iluwatar/proxy/WizardTowerProxy.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.proxy;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** The proxy controlling access to the {@link IvoryTower}. */\n@Slf4j\npublic class WizardTowerProxy implements WizardTower {\n\n  private static final int NUM_WIZARDS_ALLOWED = 3;\n\n  private int numWizards;\n\n  private final WizardTower tower;\n\n  public WizardTowerProxy(WizardTower tower) {\n    this.tower = tower;\n  }\n\n  @Override\n  public void enter(Wizard wizard) {\n    if (numWizards < NUM_WIZARDS_ALLOWED) {\n      tower.enter(wizard);\n      numWizards++;\n    } else {\n      LOGGER.info(\"{} is not allowed to enter!\", wizard);\n    }\n  }\n}\n"
  },
  {
    "path": "proxy/src/test/java/com/iluwatar/proxy/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.proxy;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "proxy/src/test/java/com/iluwatar/proxy/IvoryTowerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.proxy;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.proxy.utils.InMemoryAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for {@link IvoryTower} */\nclass IvoryTowerTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender(IvoryTower.class);\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  @Test\n  void testEnter() {\n    final var wizards =\n        List.of(\n            new Wizard(\"Gandalf\"),\n            new Wizard(\"Dumbledore\"),\n            new Wizard(\"Oz\"),\n            new Wizard(\"Merlin\"));\n\n    var tower = new IvoryTower();\n    wizards.forEach(tower::enter);\n\n    assertTrue(appender.logContains(\"Gandalf enters the tower.\"));\n    assertTrue(appender.logContains(\"Dumbledore enters the tower.\"));\n    assertTrue(appender.logContains(\"Oz enters the tower.\"));\n    assertTrue(appender.logContains(\"Merlin enters the tower.\"));\n    assertEquals(4, appender.getLogSize());\n  }\n}\n"
  },
  {
    "path": "proxy/src/test/java/com/iluwatar/proxy/WizardTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.proxy;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for {@link Wizard} */\nclass WizardTest {\n\n  @Test\n  void testToString() {\n    List.of(\"Gandalf\", \"Dumbledore\", \"Oz\", \"Merlin\")\n        .forEach(name -> assertEquals(name, new Wizard(name).toString()));\n  }\n}\n"
  },
  {
    "path": "proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.proxy;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.proxy.utils.InMemoryAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for {@link WizardTowerProxy} */\nclass WizardTowerProxyTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  @Test\n  void testEnter() {\n    final var wizards =\n        List.of(\n            new Wizard(\"Gandalf\"),\n            new Wizard(\"Dumbledore\"),\n            new Wizard(\"Oz\"),\n            new Wizard(\"Merlin\"));\n\n    final var proxy = new WizardTowerProxy(new IvoryTower());\n    wizards.forEach(proxy::enter);\n\n    assertTrue(appender.logContains(\"Gandalf enters the tower.\"));\n    assertTrue(appender.logContains(\"Dumbledore enters the tower.\"));\n    assertTrue(appender.logContains(\"Oz enters the tower.\"));\n    assertTrue(appender.logContains(\"Merlin is not allowed to enter!\"));\n    assertEquals(4, appender.getLogSize());\n  }\n}\n"
  },
  {
    "path": "proxy/src/test/java/com/iluwatar/proxy/utils/InMemoryAppender.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.proxy.utils;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.slf4j.LoggerFactory;\n\n/** InMemory Log Appender Util. */\npublic class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n  private final List<ILoggingEvent> log = new LinkedList<>();\n\n  public InMemoryAppender(Class<?> clazz) {\n    ((Logger) LoggerFactory.getLogger(clazz)).addAppender(this);\n    start();\n  }\n\n  public InMemoryAppender() {\n    ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n    start();\n  }\n\n  @Override\n  protected void append(ILoggingEvent eventObject) {\n    log.add(eventObject);\n  }\n\n  public boolean logContains(String message) {\n    return log.stream().map(ILoggingEvent::getFormattedMessage).anyMatch(message::equals);\n  }\n\n  public int getLogSize() {\n    return log.size();\n  }\n}\n"
  },
  {
    "path": "publish-subscribe/README.md",
    "content": "---\ntitle: \"Publish-Subscribe Pattern in Java: Decoupling components with asynchronous communication\"\nshortTitle: Publish-Subscribe\ndescription: \"Explore the Publish-Subscribe design pattern in Java with detailed examples. Learn how it helps to create loosely coupled, scalable, and flexible systems by allowing components to communicate asynchronously without knowing each other directly.\"\ncategory: Messaging\nlanguage: en\ntag:\n    - Architecture\n    - Asynchronous\n    - Decoupling\n    - Event-driven\n    - Messaging\n    - Microservices\n    - Publish/subscribe\n    - Scalability\n---\n\n## Intent of the Publish-Subscribe Design Pattern\n\nDefines a one-to-many dependency between objects, enabling automatic notification of multiple subscribers when a publisher's state changes or an event occurs.\n\n## Detailed Explanation of Publish-Subscribe Pattern with Real-World Examples\n\nReal-world example\n\n> An analogous real-world example of the Publish-Subscribe pattern is a news broadcasting system. A news agency (publisher) broadcasts breaking news stories without knowing who specifically receives them. Subscribers, such as television stations, news websites, or mobile news apps, independently decide which types of news they want to receive (e.g., sports, politics, weather) and are automatically notified whenever relevant events occur. This approach keeps the news agency unaware of subscribers' specifics, allowing flexible and scalable distribution of information.\n\nIn plain words\n\n> The Publish-Subscribe design pattern allows senders (publishers) to broadcast messages to multiple receivers (subscribers) without knowing who they are, enabling loose coupling and asynchronous communication in a system.\n\nWikipedia says\n\n> In software architecture, publish–subscribe or pub/sub is a messaging pattern where publishers categorize messages into classes that are received by subscribers.\nThis is contrasted to the typical messaging pattern model where publishers send messages directly to subscribers. Similarly, subscribers express interest in one or more classes and only receive messages that are of interest, without knowledge of which publishers, if any, there are. Publish–subscribe is a sibling of the message queue paradigm, and is typically one part of a larger message-oriented middleware system.\nMost messaging systems support both the pub/sub and message queue models in their API; e.g., Java Message Service (JMS).\n\nSequence diagram\n\n![Publish-Subscribe sequence diagram](./etc/publish-subscribe-sequence-diagram.png)\n\n## Programmatic Example of Publish-Subscribe Pattern in Java\n\nFirst, we identify events that trigger the publisher-subscriber interactions. Common examples include:\n\n* Sending alerts based on weather events, like earthquakes, floods, and tornadoes.\n* Sending notifications based on temperature changes.\n* Sending emails to customer support when support tickets are created.\n\n### Defining the Message\n\nWe start with a simple message class encapsulating the information sent from publishers to subscribers.\n\n```java\npublic record Message(Object content) {\n}\n```\n\n### Defining Topics\n\nA Topic represents an event category that subscribers can register to and publishers can publish messages to. Each topic has:\n\n* A unique identifier or name (e.g., WEATHER, TEMPERATURE, CUSTOMER_SUPPORT).\n* A collection of subscribers listening to this topic.\n\nSubscribers can dynamically subscribe or unsubscribe.\n\n```java\n@Getter\n@Setter\n@RequiredArgsConstructor\npublic class Topic {\n\n  private final String topicName;\n  private final Set<Subscriber> subscribers = new CopyOnWriteArraySet<>();\n\n  public void addSubscriber(Subscriber subscriber) {\n    subscribers.add(subscriber);\n  }\n\n  public void removeSubscriber(Subscriber subscriber) {\n    subscribers.remove(subscriber);\n  }\n\n  public void publish(Message message) {\n    for (Subscriber subscriber : subscribers) {\n      CompletableFuture.runAsync(() -> subscriber.onMessage(message));\n    }\n  }\n}\n```\n\n### Publisher Implementation\n\nThe Publisher maintains a collection of topics it can publish to.\n\n* Before publishing, a topic must be registered.\n* Upon publishing, it forwards messages to subscribers of the corresponding topic.\n\n```java\npublic class PublisherImpl implements Publisher {\n\n    private static final Logger logger = LoggerFactory.getLogger(PublisherImpl.class);\n    private final Set<Topic> topics = new HashSet<>();\n\n    @Override\n    public void registerTopic(Topic topic) {\n        topics.add(topic);\n    }\n\n    @Override\n    public void publish(Topic topic, Message message) {\n        if (!topics.contains(topic)) {\n            logger.error(\"This topic is not registered: {}\", topic.getName());\n            return;\n        }\n        topic.publish(message);\n    }\n}\n```\n\n### Defining Subscribers\n\nSubscribers implement an interface that handles incoming messages.\n\n* Each subscriber processes messages according to specific logic.\n* Subscribers can be registered to multiple topics.\n\n```java\npublic interface Subscriber {\n    void onMessage(Message message);\n}\n```\n\nSubscriber examples:\n\n* WeatherSubscriber: handles alerts for weather events or temperature changes.\n* CustomerSupportSubscriber: handles support tickets by sending emails.\n* DelayedWeatherSubscriber: simulates delayed processing for demonstrating asynchronous behavior.\n\n### Example Usage (Invocation)\n\nHere's how all components connect:\n\n1. Create Publisher\n2. Register Topics with Publisher\n3. Create Subscribers and Subscribe to Relevant Topics\n4. Publish Messages\n5. Manage Subscriptions Dynamically\n\n```java\npublic static void main(String[] args) throws InterruptedException {\n\n    final String topicWeather = \"WEATHER\";\n    final String topicTemperature = \"TEMPERATURE\";\n    final String topicCustomerSupport = \"CUSTOMER_SUPPORT\";\n\n    // 1. create the publisher.\n    Publisher publisher = new PublisherImpl();\n\n    // 2. define the topics and register on publisher\n    Topic weatherTopic = new Topic(topicWeather);\n    publisher.registerTopic(weatherTopic);\n\n    Topic temperatureTopic = new Topic(topicTemperature);\n    publisher.registerTopic(temperatureTopic);\n\n    Topic supportTopic = new Topic(topicCustomerSupport);\n    publisher.registerTopic(supportTopic);\n\n    // 3. Create the subscribers and subscribe to the relevant topics\n    // weatherSub1 will subscribe to two topics WEATHER and TEMPERATURE.\n    Subscriber weatherSub1 = new WeatherSubscriber();\n    weatherTopic.addSubscriber(weatherSub1);\n    temperatureTopic.addSubscriber(weatherSub1);\n\n    // weatherSub2 will subscribe to WEATHER topic\n    Subscriber weatherSub2 = new WeatherSubscriber();\n    weatherTopic.addSubscriber(weatherSub2);\n\n    // delayedWeatherSub will subscribe to WEATHER topic\n    // NOTE :: DelayedWeatherSubscriber has a 0.2 sec delay of processing message.\n    Subscriber delayedWeatherSub = new DelayedWeatherSubscriber();\n    weatherTopic.addSubscriber(delayedWeatherSub);\n\n    // subscribe the customer support subscribers to the CUSTOMER_SUPPORT topic.\n    Subscriber supportSub1 = new CustomerSupportSubscriber();\n    supportTopic.addSubscriber(supportSub1);\n    Subscriber supportSub2 = new CustomerSupportSubscriber();\n    supportTopic.addSubscriber(supportSub2);\n\n    // 4. publish message from each topic\n    publisher.publish(weatherTopic, new Message(\"earthquake\"));\n    publisher.publish(temperatureTopic, new Message(\"23C\"));\n    publisher.publish(supportTopic, new Message(\"support@test.de\"));\n\n    // 5. unregister subscriber from TEMPERATURE topic\n    temperatureTopic.removeSubscriber(weatherSub1);\n\n    // 6. publish message under TEMPERATURE topic\n    publisher.publish(temperatureTopic, new Message(\"0C\"));\n\n    /*\n     * Finally, we wait for the subscribers to consume messages to check the output.\n     * The output can change on each run, depending on how long the execution on each\n     * subscriber would take\n     * Expected behavior:\n     * - weatherSub1 will consume earthquake and 23C\n     * - weatherSub2 will consume earthquake\n     * - delayedWeatherSub will take longer and consume earthquake\n     * - supportSub1, supportSub2 will consume support@test.de\n     * - the message 0C will not be consumed because weatherSub1 unsubscribed from TEMPERATURE topic\n     */\n    TimeUnit.SECONDS.sleep(2);\n}\n```\n\n### Program output\n\nOutput may vary due to asynchronous subscriber processing:\n\n```\n14:01:45.599 [ForkJoinPool.commonPool-worker-6] INFO com.iluwatar.publish.subscribe.subscriber.CustomerSupportSubscriber -- Customer Support Subscriber: 1416331388 sent the email to: support@test.de\n14:01:45.599 [ForkJoinPool.commonPool-worker-4] INFO com.iluwatar.publish.subscribe.subscriber.WeatherSubscriber -- Weather Subscriber: 1949521124 issued message: 23C\n14:01:45.599 [ForkJoinPool.commonPool-worker-2] INFO com.iluwatar.publish.subscribe.subscriber.WeatherSubscriber -- Weather Subscriber: 60629172 issued message: earthquake\n14:01:45.599 [ForkJoinPool.commonPool-worker-5] INFO com.iluwatar.publish.subscribe.subscriber.CustomerSupportSubscriber -- Customer Support Subscriber: 1807508804 sent the email to: support@test.de\n14:01:45.599 [ForkJoinPool.commonPool-worker-1] INFO com.iluwatar.publish.subscribe.subscriber.WeatherSubscriber -- Weather Subscriber: 1949521124 issued message: earthquake\n14:01:47.600 [ForkJoinPool.commonPool-worker-3] INFO com.iluwatar.publish.subscribe.subscriber.DelayedWeatherSubscriber -- Delayed Weather Subscriber: 2085808749 issued message: earthquake\n```\n\nThis demonstrates:\n\n* Subscribers reacting independently to messages published to subscribed topics.\n* Dynamic subscription management allows changing which subscribers listen to specific topics.\n* The asynchronous and loosely coupled nature of the publish-subscribe pattern in Java applications.\n\n## When to Use the Publish-Subscribe Pattern\n\n* When an application requires loose coupling between event producers and consumers.\n* In scenarios where multiple subscribers independently react to the same event.\n* When developing scalable, asynchronous messaging systems, particularly within microservices architectures.\n\n## Real-World Applications of Publish-Subscribe Pattern in Java\n\n* Java Message Service (JMS) implementations (ActiveMQ, RabbitMQ)\n* Apache Kafka (used extensively in Java-based microservices)\n* Spring Framework's event publishing and listening mechanisms\n* Google Cloud Pub/Sub in Java applications\n* AWS Simple Notification Service (SNS) with Java SDK\n\n## Benefits and Trade-offs of Publish-Subscribe Pattern\n\nBenefits:\n\n* Loose coupling between publishers and subscribers promotes flexibility.\n* Improved scalability and maintainability as new subscribers can be easily added.\n* Supports asynchronous communication, enhancing system responsiveness.\n\nTrade-offs:\n\n* Increased complexity due to asynchronous message handling and debugging difficulties.\n* Potential message delivery delays and inconsistency if the infrastructure isn't reliable.\n* Risk of message flooding, requiring proper infrastructure and consumer management.\n\n## Related Java Design Patterns\n\n* [Observer Pattern](https://java-design-patterns.com/patterns/observer/): Both patterns establish a publisher-subscriber relationship; however, Observer typically works within a single application boundary synchronously, whereas Publish-Subscribe is often distributed and asynchronous.\n* [Mediator Pattern](https://java-design-patterns.com/patterns/mediator/): Mediator encapsulates interactions between objects in a centralized manner, whereas Publish-Subscribe provides decentralized, loosely-coupled interactions.\n\n## References and Credits\n\n* [Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions](https://amzn.to/3WcFVui)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects](https://amzn.to/3UgC24V)\n* [Publisher-Subscriber Pattern (Microsoft)](https://learn.microsoft.com/en-us/azure/architecture/patterns/publisher-subscriber)\n"
  },
  {
    "path": "publish-subscribe/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>publish-subscribe</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n    </dependencies>\n\n</project>"
  },
  {
    "path": "publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe;\n\nimport com.iluwatar.publish.subscribe.model.Message;\nimport com.iluwatar.publish.subscribe.model.Topic;\nimport com.iluwatar.publish.subscribe.publisher.Publisher;\nimport com.iluwatar.publish.subscribe.publisher.PublisherImpl;\nimport com.iluwatar.publish.subscribe.subscriber.CustomerSupportSubscriber;\nimport com.iluwatar.publish.subscribe.subscriber.DelayedWeatherSubscriber;\nimport com.iluwatar.publish.subscribe.subscriber.Subscriber;\nimport com.iluwatar.publish.subscribe.subscriber.WeatherSubscriber;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * The Publish and Subscribe pattern is a messaging paradigm used in software architecture with\n * several key points:\n * <li>Decoupling of publishers and subscribers: Publishers and subscribers operate independently,\n *     and there's no direct link between them. This enhances the scalability and * modularity of\n *     applications.\n * <li>Event-driven communication: The pattern facilitates event-driven architectures by allowing\n *     publishers to broadcast events without concerning themselves with who receives the events.\n * <li>Dynamic subscription: Subscribers can dynamically choose to listen for specific events or\n *     messages they are interested in, often by subscribing to a particular topic or channel.\n * <li>Asynchronous processing: The pattern inherently supports asynchronous message processing,\n *     enabling efficient handling of events and improving application responsiveness.\n * <li>Scalability: By decoupling senders and receivers, the pattern can support a large number of\n *     publishers and subscribers, making it suitable for scalable systems.\n * <li>Flexibility and adaptability: New subscribers or publishers can be added to the system\n *     without significant changes to the existing components, making the system highly adaptable to\n *     evolving requirements.\n *\n *     <p>In this example we will create three topics WEATHER, TEMPERATURE and CUSTOMER_SUPPORT.\n *     Then we will register those topics in the {@link Publisher}. After that we will create two\n *     {@link WeatherSubscriber}s, one {@link DelayedWeatherSubscriber} and two {@link\n *     CustomerSupportSubscriber}.The subscribers will subscribe to the relevant topics. One {@link\n *     WeatherSubscriber} will subscribe to two topics (WEATHER, TEMPERATURE). {@link\n *     DelayedWeatherSubscriber} has a delay in message processing. Now we can publish the three\n *     {@link Topic}s with different content in the {@link Message}s. And we can observe the output\n *     in the log where, one {@link WeatherSubscriber} will output the message with weather and the\n *     other {@link WeatherSubscriber} will output weather and temperature. {@link\n *     CustomerSupportSubscriber}s will output the message with customer support email. {@link\n *     DelayedWeatherSubscriber} has a delay in processing and will output the message at last. Each\n *     subscriber is only listening to the subscribed topics.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) throws InterruptedException {\n\n    final String topicWeather = \"WEATHER\";\n    final String topicTemperature = \"TEMPERATURE\";\n    final String topicCustomerSupport = \"CUSTOMER_SUPPORT\";\n\n    // 1. create the publisher.\n    Publisher publisher = new PublisherImpl();\n\n    // 2. define the topics and register on publisher\n    Topic weatherTopic = new Topic(topicWeather);\n    publisher.registerTopic(weatherTopic);\n\n    Topic temperatureTopic = new Topic(topicTemperature);\n    publisher.registerTopic(temperatureTopic);\n\n    Topic supportTopic = new Topic(topicCustomerSupport);\n    publisher.registerTopic(supportTopic);\n\n    // 3. Create the subscribers and subscribe to the relevant topics\n    // weatherSub1 will subscribe to two topics WEATHER and TEMPERATURE.\n    Subscriber weatherSub1 = new WeatherSubscriber();\n    weatherTopic.addSubscriber(weatherSub1);\n    temperatureTopic.addSubscriber(weatherSub1);\n\n    // weatherSub2 will subscribe to WEATHER topic\n    Subscriber weatherSub2 = new WeatherSubscriber();\n    weatherTopic.addSubscriber(weatherSub2);\n\n    // delayedWeatherSub will subscribe to WEATHER topic\n    // NOTE :: DelayedWeatherSubscriber has a 0.2 sec delay of processing message.\n    Subscriber delayedWeatherSub = new DelayedWeatherSubscriber();\n    weatherTopic.addSubscriber(delayedWeatherSub);\n\n    // subscribe the customer support subscribers to the CUSTOMER_SUPPORT topic.\n    Subscriber supportSub1 = new CustomerSupportSubscriber();\n    supportTopic.addSubscriber(supportSub1);\n    Subscriber supportSub2 = new CustomerSupportSubscriber();\n    supportTopic.addSubscriber(supportSub2);\n\n    // 4. publish message from each topic\n    publisher.publish(weatherTopic, new Message(\"earthquake\"));\n    publisher.publish(temperatureTopic, new Message(\"23C\"));\n    publisher.publish(supportTopic, new Message(\"support@test.de\"));\n\n    // 5. unregister subscriber from TEMPERATURE topic\n    temperatureTopic.removeSubscriber(weatherSub1);\n\n    // 6. publish message under TEMPERATURE topic\n    publisher.publish(temperatureTopic, new Message(\"0C\"));\n\n    /*\n     * Finally, we wait for the subscribers to consume messages to check the output.\n     * The output can change on each run, depending on how long the execution on each\n     * subscriber would take\n     * Expected behavior:\n     * - weatherSub1 will consume earthquake and 23C\n     * - weatherSub2 will consume earthquake\n     * - delayedWeatherSub will take longer and consume earthquake\n     * - supportSub1, supportSub2 will consume support@test.de\n     * - the message 0C will not be consumed because weatherSub1 unsubscribed from TEMPERATURE topic\n     */\n    TimeUnit.SECONDS.sleep(2);\n  }\n}\n"
  },
  {
    "path": "publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/model/Message.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe.model;\n\n/** This class represents a Message that holds the published content. */\npublic record Message(Object content) {}\n"
  },
  {
    "path": "publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/model/Topic.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe.model;\n\nimport com.iluwatar.publish.subscribe.subscriber.Subscriber;\nimport java.util.Set;\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.CopyOnWriteArraySet;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\nimport lombok.Setter;\n\n/** This class represents a Topic that topic name and subscribers. */\n@Getter\n@Setter\n@RequiredArgsConstructor\npublic class Topic {\n\n  private final String topicName;\n  private final Set<Subscriber> subscribers = new CopyOnWriteArraySet<>();\n\n  /**\n   * Add a subscriber to the list of subscribers.\n   *\n   * @param subscriber subscriber to add\n   */\n  public void addSubscriber(Subscriber subscriber) {\n    subscribers.add(subscriber);\n  }\n\n  /**\n   * Remove a subscriber from the list of subscribers.\n   *\n   * @param subscriber subscriber to remove\n   */\n  public void removeSubscriber(Subscriber subscriber) {\n    subscribers.remove(subscriber);\n  }\n\n  /**\n   * Publish a message to subscribers.\n   *\n   * @param message message with content to publish\n   */\n  public void publish(Message message) {\n    for (Subscriber subscriber : subscribers) {\n      CompletableFuture.runAsync(() -> subscriber.onMessage(message));\n    }\n  }\n}\n"
  },
  {
    "path": "publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/publisher/Publisher.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe.publisher;\n\nimport com.iluwatar.publish.subscribe.model.Message;\nimport com.iluwatar.publish.subscribe.model.Topic;\n\n/** This class represents a Publisher. */\npublic interface Publisher {\n\n  /**\n   * Register a topic in the publisher.\n   *\n   * @param topic the topic to be registered\n   */\n  void registerTopic(Topic topic);\n\n  /**\n   * Register a topic in the publisher.\n   *\n   * @param topic the topic to publish the message under\n   * @param message message with content to be published\n   */\n  void publish(Topic topic, Message message);\n}\n"
  },
  {
    "path": "publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/publisher/PublisherImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe.publisher;\n\nimport com.iluwatar.publish.subscribe.model.Message;\nimport com.iluwatar.publish.subscribe.model.Topic;\nimport java.util.HashSet;\nimport java.util.Set;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** This class is an implementation of the Publisher. */\npublic class PublisherImpl implements Publisher {\n\n  private static final Logger logger = LoggerFactory.getLogger(PublisherImpl.class);\n  private final Set<Topic> topics = new HashSet<>();\n\n  @Override\n  public void registerTopic(Topic topic) {\n    topics.add(topic);\n  }\n\n  @Override\n  public void publish(Topic topic, Message message) {\n    if (!topics.contains(topic)) {\n      logger.error(\"This topic is not registered: {}\", topic.getTopicName());\n      return;\n    }\n    topic.publish(message);\n  }\n}\n"
  },
  {
    "path": "publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/subscriber/CustomerSupportSubscriber.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe.subscriber;\n\nimport com.iluwatar.publish.subscribe.model.Message;\nimport lombok.extern.slf4j.Slf4j;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** This class subscribes to CUSTOMER_SUPPORT topic. */\n@Slf4j\npublic class CustomerSupportSubscriber implements Subscriber {\n\n  private static final Logger logger = LoggerFactory.getLogger(CustomerSupportSubscriber.class);\n\n  @Override\n  public void onMessage(Message message) {\n    if (message.content() instanceof String content) {\n      logger.info(\n          \"Customer Support Subscriber: {} sent the email to: {}\", this.hashCode(), content);\n    } else {\n      logger.error(\n          \"Unknown content type: {} expected: {}\",\n          message.content().getClass().getSimpleName(),\n          String.class.getSimpleName());\n    }\n  }\n}\n"
  },
  {
    "path": "publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/subscriber/DelayedWeatherSubscriber.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe.subscriber;\n\nimport com.iluwatar.publish.subscribe.model.Message;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** This class subscribes to WEATHER topic. */\n@Slf4j\npublic class DelayedWeatherSubscriber implements Subscriber {\n\n  private static final Logger logger = LoggerFactory.getLogger(DelayedWeatherSubscriber.class);\n\n  @Override\n  public void onMessage(Message message) {\n    if (message.content() instanceof String content) {\n      processData();\n      logger.info(\"Delayed Weather Subscriber: {} issued message: {}\", this.hashCode(), content);\n    } else {\n      logger.error(\n          \"Unknown content type: {} expected: {}\",\n          message.content().getClass().getSimpleName(),\n          String.class.getSimpleName());\n    }\n  }\n\n  /** create an artificial delay to mimic the persistence and timeouts in real world. */\n  private void processData() {\n    try {\n      TimeUnit.MILLISECONDS.sleep(2000);\n    } catch (InterruptedException e) {\n      logger.error(\"Interrupted!\", e);\n      Thread.currentThread().interrupt();\n    }\n  }\n}\n"
  },
  {
    "path": "publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/subscriber/Subscriber.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe.subscriber;\n\nimport com.iluwatar.publish.subscribe.model.Message;\n\n/** This class represents a Subscriber. */\npublic interface Subscriber {\n\n  /**\n   * On message method will trigger when the subscribed event is published.\n   *\n   * @param message the message contains the content of the published event\n   */\n  void onMessage(Message message);\n}\n"
  },
  {
    "path": "publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/subscriber/WeatherSubscriber.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe.subscriber;\n\nimport com.iluwatar.publish.subscribe.model.Message;\nimport lombok.extern.slf4j.Slf4j;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** This class subscribes to WEATHER or TEMPERATURE topic. */\n@Slf4j\npublic class WeatherSubscriber implements Subscriber {\n\n  private static final Logger logger = LoggerFactory.getLogger(WeatherSubscriber.class);\n\n  @Override\n  public void onMessage(Message message) {\n    if (message.content() instanceof String content) {\n      logger.info(\"Weather Subscriber: {} issued message: {}\", this.hashCode(), content);\n    } else {\n      logger.error(\n          \"Unknown content type: {} expected: {}\",\n          message.content().getClass().getSimpleName(),\n          String.class.getSimpleName());\n    }\n  }\n}\n"
  },
  {
    "path": "publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/LoggerExtension.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.read.ListAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.extension.AfterEachCallback;\nimport org.junit.jupiter.api.extension.BeforeEachCallback;\nimport org.junit.jupiter.api.extension.ExtensionContext;\nimport org.slf4j.LoggerFactory;\n\npublic class LoggerExtension implements BeforeEachCallback, AfterEachCallback {\n\n  private final ListAppender<ILoggingEvent> listAppender = new ListAppender<>();\n  private final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);\n\n  @Override\n  public void afterEach(ExtensionContext extensionContext) throws Exception {\n    listAppender.stop();\n    listAppender.list.clear();\n    logger.detachAppender(listAppender);\n  }\n\n  @Override\n  public void beforeEach(ExtensionContext extensionContext) throws Exception {\n    logger.addAppender(listAppender);\n    listAppender.start();\n  }\n\n  public List<String> getMessages() {\n    return listAppender.list.stream().map(e -> e.getMessage()).toList();\n  }\n\n  public List<String> getFormattedMessages() {\n    return listAppender.list.stream().map(e -> e.getFormattedMessage()).toList();\n  }\n}\n"
  },
  {
    "path": "publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/model/MessageTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe.model;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertInstanceOf;\n\nimport org.junit.jupiter.api.Test;\n\nclass MessageTest {\n\n  @Test\n  void testMessage() {\n    final String content = \"some content\";\n    Message message = new Message(content);\n    assertInstanceOf(String.class, message.content());\n    assertEquals(content, String.valueOf(message.content()));\n  }\n}\n"
  },
  {
    "path": "publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/model/TopicTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe.model;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertInstanceOf;\n\nimport com.iluwatar.publish.subscribe.subscriber.Subscriber;\nimport com.iluwatar.publish.subscribe.subscriber.WeatherSubscriber;\nimport java.lang.reflect.Field;\nimport java.util.Set;\nimport org.junit.jupiter.api.Test;\n\nclass TopicTest {\n\n  private static final String TOPIC_WEATHER = \"WEATHER\";\n\n  @Test\n  void testTopic() {\n    Topic topic = new Topic(TOPIC_WEATHER);\n    assertEquals(TOPIC_WEATHER, topic.getTopicName());\n  }\n\n  @Test\n  void testSubscribing() throws NoSuchFieldException, IllegalAccessException {\n\n    Topic topic = new Topic(TOPIC_WEATHER);\n    Subscriber sub = new WeatherSubscriber();\n    topic.addSubscriber(sub);\n\n    Field field = topic.getClass().getDeclaredField(\"subscribers\");\n    field.setAccessible(true);\n    Object value = field.get(topic);\n    assertInstanceOf(Set.class, value);\n\n    Set<?> subscribers = (Set<?>) field.get(topic);\n    assertEquals(1, subscribers.size());\n\n    topic.removeSubscriber(sub);\n    assertEquals(0, subscribers.size());\n  }\n}\n"
  },
  {
    "path": "publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/publisher/PublisherTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe.publisher;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertInstanceOf;\n\nimport com.iluwatar.publish.subscribe.LoggerExtension;\nimport com.iluwatar.publish.subscribe.model.Message;\nimport com.iluwatar.publish.subscribe.model.Topic;\nimport java.lang.reflect.Field;\nimport java.util.Set;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.RegisterExtension;\n\nclass PublisherTest {\n\n  @RegisterExtension public LoggerExtension loggerExtension = new LoggerExtension();\n\n  private static final String TOPIC_WEATHER = \"WEATHER\";\n  private static final String TOPIC_CUSTOMER_SUPPORT = \"CUSTOMER_SUPPORT\";\n\n  @Test\n  void testRegisterTopic() throws NoSuchFieldException, IllegalAccessException {\n    Topic topic = new Topic(TOPIC_CUSTOMER_SUPPORT);\n    Publisher publisher = new PublisherImpl();\n    publisher.registerTopic(topic);\n\n    Field field = publisher.getClass().getDeclaredField(\"topics\");\n    field.setAccessible(true);\n    Object value = field.get(publisher);\n    assertInstanceOf(Set.class, value);\n\n    Set<?> topics = (Set<?>) field.get(publisher);\n    assertEquals(1, topics.size());\n  }\n\n  @Test\n  void testPublish() {\n    Topic topic = new Topic(TOPIC_WEATHER);\n    Publisher publisher = new PublisherImpl();\n    publisher.registerTopic(topic);\n\n    Message message = new Message(\"weather\");\n    assertDoesNotThrow(() -> publisher.publish(topic, message));\n  }\n\n  @Test\n  void testPublishUnregisteredTopic() {\n    Topic topic = new Topic(TOPIC_WEATHER);\n    Publisher publisher = new PublisherImpl();\n    publisher.registerTopic(topic);\n\n    Topic topicUnregistered = new Topic(TOPIC_CUSTOMER_SUPPORT);\n    Message message = new Message(\"support\");\n    publisher.publish(topicUnregistered, message);\n    assertEquals(\n        \"This topic is not registered: CUSTOMER_SUPPORT\",\n        loggerExtension.getFormattedMessages().getFirst());\n  }\n}\n"
  },
  {
    "path": "publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/subscriber/SubscriberTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.publish.subscribe.subscriber;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.publish.subscribe.LoggerExtension;\nimport com.iluwatar.publish.subscribe.model.Message;\nimport com.iluwatar.publish.subscribe.model.Topic;\nimport com.iluwatar.publish.subscribe.publisher.Publisher;\nimport com.iluwatar.publish.subscribe.publisher.PublisherImpl;\nimport java.util.Optional;\nimport java.util.concurrent.TimeUnit;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.RegisterExtension;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\npublic class SubscriberTest {\n\n  private static final Logger logger = LoggerFactory.getLogger(SubscriberTest.class);\n  @RegisterExtension public LoggerExtension loggerExtension = new LoggerExtension();\n\n  private static final String TOPIC_WEATHER = \"WEATHER\";\n  private static final String TOPIC_TEMPERATURE = \"TEMPERATURE\";\n  private static final String TOPIC_CUSTOMER_SUPPORT = \"CUSTOMER_SUPPORT\";\n\n  @Test\n  void testSubscribeToMultipleTopics() {\n\n    Topic topicWeather = new Topic(TOPIC_WEATHER);\n    Topic topicTemperature = new Topic(TOPIC_TEMPERATURE);\n    Subscriber weatherSubscriber = new WeatherSubscriber();\n\n    topicWeather.addSubscriber(weatherSubscriber);\n    topicTemperature.addSubscriber(weatherSubscriber);\n\n    Publisher publisher = new PublisherImpl();\n    publisher.registerTopic(topicWeather);\n    publisher.registerTopic(topicTemperature);\n\n    publisher.publish(topicWeather, new Message(\"earthquake\"));\n    publisher.publish(topicTemperature, new Message(\"-2C\"));\n\n    waitForOutput();\n    assertEquals(2, loggerExtension.getFormattedMessages().size());\n  }\n\n  @Test\n  void testOnlyReceiveSubscribedTopic() {\n\n    Topic weatherTopic = new Topic(TOPIC_WEATHER);\n    Subscriber weatherSubscriber = new WeatherSubscriber();\n    weatherTopic.addSubscriber(weatherSubscriber);\n\n    Topic customerSupportTopic = new Topic(TOPIC_CUSTOMER_SUPPORT);\n    Publisher publisher = new PublisherImpl();\n    publisher.registerTopic(weatherTopic);\n    publisher.registerTopic(customerSupportTopic);\n\n    publisher.publish(customerSupportTopic, new Message(\"support@test.de\"));\n\n    waitForOutput();\n    assertEquals(0, loggerExtension.getFormattedMessages().size());\n  }\n\n  @Test\n  void testMultipleSubscribersOnSameTopic() {\n\n    Topic weatherTopic = new Topic(TOPIC_WEATHER);\n    Subscriber weatherSubscriber1 = new WeatherSubscriber();\n    weatherTopic.addSubscriber(weatherSubscriber1);\n\n    Subscriber weatherSubscriber2 = new WeatherSubscriber();\n    weatherTopic.addSubscriber(weatherSubscriber2);\n\n    Publisher publisher = new PublisherImpl();\n    publisher.registerTopic(weatherTopic);\n\n    publisher.publish(weatherTopic, new Message(\"tornado\"));\n\n    waitForOutput();\n    assertEquals(2, loggerExtension.getFormattedMessages().size());\n    assertEquals(\n        \"Weather Subscriber: \" + weatherSubscriber1.hashCode() + \" issued message: tornado\",\n        getMessage(weatherSubscriber1.hashCode()));\n    assertEquals(\n        \"Weather Subscriber: \" + weatherSubscriber2.hashCode() + \" issued message: tornado\",\n        getMessage(weatherSubscriber2.hashCode()));\n  }\n\n  @Test\n  void testMultipleSubscribersOnDifferentTopics() {\n\n    Topic weatherTopic = new Topic(TOPIC_WEATHER);\n    Subscriber weatherSubscriber = new WeatherSubscriber();\n    weatherTopic.addSubscriber(weatherSubscriber);\n\n    Topic customerSupportTopic = new Topic(TOPIC_CUSTOMER_SUPPORT);\n    Subscriber customerSupportSubscriber = new CustomerSupportSubscriber();\n    customerSupportTopic.addSubscriber(customerSupportSubscriber);\n\n    Publisher publisher = new PublisherImpl();\n    publisher.registerTopic(weatherTopic);\n    publisher.registerTopic(customerSupportTopic);\n\n    publisher.publish(weatherTopic, new Message(\"flood\"));\n    publisher.publish(customerSupportTopic, new Message(\"support@test.at\"));\n\n    waitForOutput();\n    assertEquals(2, loggerExtension.getFormattedMessages().size());\n    assertEquals(\n        \"Weather Subscriber: \" + weatherSubscriber.hashCode() + \" issued message: flood\",\n        getMessage(weatherSubscriber.hashCode()));\n    assertEquals(\n        \"Customer Support Subscriber: \"\n            + customerSupportSubscriber.hashCode()\n            + \" sent the email to: support@test.at\",\n        getMessage(customerSupportSubscriber.hashCode()));\n  }\n\n  @Test\n  void testInvalidContentOnTopics() {\n\n    Topic weatherTopic = new Topic(TOPIC_WEATHER);\n    Subscriber weatherSubscriber = new WeatherSubscriber();\n    weatherTopic.addSubscriber(weatherSubscriber);\n\n    Topic customerSupportTopic = new Topic(TOPIC_CUSTOMER_SUPPORT);\n    Subscriber customerSupportSubscriber = new CustomerSupportSubscriber();\n    customerSupportTopic.addSubscriber(customerSupportSubscriber);\n\n    Publisher publisher = new PublisherImpl();\n    publisher.registerTopic(weatherTopic);\n    publisher.registerTopic(customerSupportTopic);\n\n    publisher.publish(weatherTopic, new Message(123));\n    publisher.publish(customerSupportTopic, new Message(34.56));\n\n    waitForOutput();\n    assertTrue(loggerExtension.getFormattedMessages().getFirst().contains(\"Unknown content type\"));\n    assertTrue(loggerExtension.getFormattedMessages().get(1).contains(\"Unknown content type\"));\n  }\n\n  @Test\n  void testUnsubscribe() {\n\n    Topic weatherTopic = new Topic(TOPIC_WEATHER);\n    Subscriber weatherSubscriber = new WeatherSubscriber();\n    weatherTopic.addSubscriber(weatherSubscriber);\n\n    Publisher publisher = new PublisherImpl();\n    publisher.registerTopic(weatherTopic);\n\n    publisher.publish(weatherTopic, new Message(\"earthquake\"));\n\n    weatherTopic.removeSubscriber(weatherSubscriber);\n    publisher.publish(weatherTopic, new Message(\"tornado\"));\n\n    waitForOutput();\n    assertEquals(1, loggerExtension.getFormattedMessages().size());\n    assertTrue(loggerExtension.getFormattedMessages().getFirst().contains(\"earthquake\"));\n    assertFalse(loggerExtension.getFormattedMessages().getFirst().contains(\"tornado\"));\n  }\n\n  private String getMessage(int subscriberHash) {\n    Optional<String> message =\n        loggerExtension.getFormattedMessages().stream()\n            .filter(str -> str.contains(String.valueOf(subscriberHash)))\n            .findFirst();\n    assertTrue(message.isPresent());\n    return message.get();\n  }\n\n  private void waitForOutput() {\n    try {\n      TimeUnit.SECONDS.sleep(1);\n    } catch (InterruptedException e) {\n      logger.error(\"Interrupted!\", e);\n      Thread.currentThread().interrupt();\n    }\n  }\n}\n"
  },
  {
    "path": "queue-based-load-leveling/README.md",
    "content": "---\ntitle: \"Queue-Based Load Leveling Pattern in Java: Balancing Workloads for Scalable Performance\"\nshortTitle: Queue-Based Load Leveling\ndescription: \"Master the Queue-Based Load Leveling pattern in Java with our comprehensive guide. Learn how to enhance system resilience, manage workload efficiently, and prevent overload with effective asynchronous buffering techniques.\"\ncategory: Resilience\nlanguage: en\ntag:\n  - Asynchronous\n  - Buffering\n  - Decoupling\n  - Fault tolerance\n  - Messaging\n  - Scalability\n  - Synchronization\n  - Thread management\n---\n\n## Also known as\n\n* Load Leveling\n* Message Queuing\n\n## Intent of Queue-Based Load Leveling Design Pattern\n\nThe Queue-Based Load Leveling pattern expertly manages system load balancing in Java by utilizing a queue to efficiently distribute the workload among producers and consumers, enhancing system performance and scalability.\n\n## Detailed Explanation of Queue-Based Load Leveling Pattern with Real-World Examples\n\nReal-world example\n\n> In a practical scenario, akin to a bustling restaurant, Queue-Based Load Leveling serves as a system optimization strategy, where orders are systematically queued to maintain high service quality and efficiency. During peak hours, if all customers were served immediately, the kitchen would be overwhelmed, leading to long wait times and potential mistakes in orders. To manage this, the restaurant implements a queue-based load leveling system using a ticketing machine. \n>\n> When customers place orders, they receive a ticket number and their order is placed in a queue. The kitchen staff then processes orders one at a time in the order they were received. This ensures that the kitchen can handle the workload at a manageable pace, preventing overload and maintaining service quality. Customers wait comfortably knowing their order is in line and will be handled efficiently, even during the busiest times.\n\nIn plain words\n\n> Queue-Based Load Leveling is a design pattern that uses a queue to manage and balance the workload between producers and consumers, preventing system overload and ensuring smooth processing.\n\nWikipedia says\n\n> Message Queues are essential components for inter-process communication (IPC) and inter-thread communication, using queues to manage the passing of messages. They help in decoupling producers and consumers, allowing asynchronous processing, which is a key aspect of the Queue-Based Load Leveling pattern.\n\nFlowchart\n\n![Queue-Based Load Leveling flowchart](./etc/queue-based-load-leveling-flowchart.png)\n\n## Programmatic Example of Queue-Based Load Leveling Pattern in Java\n\nThe Queue-Based Load Leveling pattern helps to manage high-volume, sporadic bursts of tasks that can overwhelm a system. It uses a queue as a buffer to hold tasks, decoupling the task generation from task processing. Tasks are processed at a controlled rate, ensuring optimal load management and fault tolerance, crucial for maintaining robust system architecture.\n\nFirst, let's look at the `MessageQueue` and `Message` classes. The `MessageQueue` acts as a buffer, storing messages until they are retrieved by the `ServiceExecutor`. The `Message` represents the tasks to be processed.\n\n```java\npublic class Message {\n  // Message details\n}\n```\n\n```java\npublic class MessageQueue {\n  private Queue<Message> queue;\n\n  public MessageQueue() {\n    queue = new LinkedList<>();\n  }\n\n  // Method to add a message to the queue\n  public void addMessage(Message message) {\n    queue.add(message);\n  }\n\n  // Method to retrieve a message from the queue\n  public Message getMessage() {\n    return queue.poll();\n  }\n}\n```\n\nNext, we have the `TaskGenerator` class. This class represents the task producers. It generates tasks and submits them to the `MessageQueue`.\n\n```java\npublic class TaskGenerator implements Runnable {\n    \n  private MessageQueue msgQueue;\n  private int taskCount;\n\n  public TaskGenerator(MessageQueue msgQueue, int taskCount) {\n    this.msgQueue = msgQueue;\n    this.taskCount = taskCount;\n  }\n\n  @Override\n  public void run() {\n    for (int i = 0; i < taskCount; i++) {\n      Message message = new Message(); // Create a new message\n      msgQueue.addMessage(message); // Add the message to the queue\n    }\n  }\n}\n```\n\nThe `ServiceExecutor` class represents the task consumer. It retrieves tasks from the `MessageQueue` and processes them.\n\n```java\npublic class ServiceExecutor implements Runnable {\n    \n  private MessageQueue msgQueue;\n\n  public ServiceExecutor(MessageQueue msgQueue) {\n    this.msgQueue = msgQueue;\n  }\n\n  @Override\n  public void run() {\n    while (true) {\n      Message message = msgQueue.getMessage(); // Retrieve a message from the queue\n      if (message != null) {\n        // Process the message\n      } else {\n        // No more messages to process\n        break;\n      }\n    }\n  }\n}\n```\n\nFinally, we have the `App` class which sets up the `TaskGenerator` and `ServiceExecutor` threads and submits them to an `ExecutorService`.\n\n```java\npublic class App {\n  public static void main(String[] args) {\n    var msgQueue = new MessageQueue();\n\n    final var taskRunnable1 = new TaskGenerator(msgQueue, 5);\n    final var taskRunnable2 = new TaskGenerator(msgQueue, 1);\n    final var taskRunnable3 = new TaskGenerator(msgQueue, 2);\n\n    final var srvRunnable = new ServiceExecutor(msgQueue);\n\n    ExecutorService executor = Executors.newFixedThreadPool(2);\n    executor.submit(taskRunnable1);\n    executor.submit(taskRunnable2);\n    executor.submit(taskRunnable3);\n    executor.submit(srvRunnable);\n\n    executor.shutdown();\n  }\n}\n```\n\nIn this example, the `TaskGenerator` threads generate tasks at a variable rate and submit them to the `MessageQueue`. The `ServiceExecutor` retrieves the tasks from the queue and processes them at its own pace, preventing the system from being overwhelmed by peak loads.\n\nRunning the application produces the following console output:\n\n```\n[main] INFO App - Submitting TaskGenerators and ServiceExecutor threads.\n[main] INFO App - Initiating shutdown. Executor will shutdown only after all the Threads are completed.\n[pool-1-thread-2] INFO TaskGenerator - Message-1 submitted by pool-1-thread-2\n[pool-1-thread-1] INFO TaskGenerator - Message-5 submitted by pool-1-thread-1\n[pool-1-thread-1] INFO TaskGenerator - Message-4 submitted by pool-1-thread-1\n[pool-1-thread-2] INFO TaskGenerator - Message-2 submitted by pool-1-thread-2\n[pool-1-thread-1] INFO TaskGenerator - Message-3 submitted by pool-1-thread-1\n[pool-1-thread-2] INFO TaskGenerator - Message-1 submitted by pool-1-thread-2\n[pool-1-thread-1] INFO TaskGenerator - Message-2 submitted by pool-1-thread-1\n[pool-1-thread-2] INFO ServiceExecutor - Message-1 submitted by pool-1-thread-2 is served.\n[pool-1-thread-1] INFO TaskGenerator - Message-1 submitted by pool-1-thread-1\n[pool-1-thread-2] INFO ServiceExecutor - Message-5 submitted by pool-1-thread-1 is served.\n[pool-1-thread-2] INFO ServiceExecutor - Message-4 submitted by pool-1-thread-1 is served.\n[pool-1-thread-2] INFO ServiceExecutor - Message-2 submitted by pool-1-thread-2 is served.\n[pool-1-thread-2] INFO ServiceExecutor - Message-3 submitted by pool-1-thread-1 is served.\n[pool-1-thread-2] INFO ServiceExecutor - Message-1 submitted by pool-1-thread-2 is served.\n[pool-1-thread-2] INFO ServiceExecutor - Message-2 submitted by pool-1-thread-1 is served.\n[pool-1-thread-2] INFO ServiceExecutor - Message-1 submitted by pool-1-thread-1 is served.\n[pool-1-thread-2] INFO ServiceExecutor - Service Executor: Waiting for Messages to serve .. \n[pool-1-thread-2] INFO ServiceExecutor - Service Executor: Waiting for Messages to serve .. \n[pool-1-thread-2] INFO ServiceExecutor - Service Executor: Waiting for Messages to serve .. \n[pool-1-thread-2] INFO ServiceExecutor - Service Executor: Waiting for Messages to serve .. \n[main] INFO App - Executor was shut down and Exiting.\n[pool-1-thread-2] ERROR ServiceExecutor - sleep interrupted\n```\n\n## When to Use the Queue-Based Load Leveling Pattern in Java\n\n* When there are variable workloads, and you need to ensure that peak loads do not overwhelm the system\n* In distributed systems where tasks are produced at a different rate than they are consumed\n* For decoupling producers and consumers in an asynchronous messaging system\n\n## Real-World Applications of Queue-Based Load Leveling Pattern in Java\n\n* Amazon Web Services (AWS) Simple Queue Service (SQS)\n* RabbitMQ\n* Java Message Service (JMS) in enterprise Java applications\n\n## Benefits and Trade-offs of Queue-Based Load Leveling Pattern\n\nBenefits:\n\n* Decouples the producers and consumers, allowing each to operate at its own pace\n* Increases system resilience and fault tolerance by preventing overload conditions\n* Enhances scalability by allowing more consumers to be added to handle increased load\n\nTrade-offs:\n\n* Adds complexity to the system architecture\n* May introduce latency as messages need to be queued and dequeued\n* Requires additional components (queues) to be managed and monitored\n\n## Related Java Design Patterns\n\n* Asynchronous Messaging: Queue-Based Load Leveling uses asynchronous messaging to decouple producers and consumers\n* [Circuit Breaker](https://java-design-patterns.com/patterns/circuit-breaker/): Often used in conjunction with Queue-Based Load Leveling to prevent system overloads by temporarily halting message processing\n* [Producer-Consumer](https://java-design-patterns.com/patterns/producer-consumer/): Queue-Based Load Leveling is a specific application of the Producer-Consumer pattern where the queue serves as the intermediary\n* [Retry](https://java-design-patterns.com/patterns/retry/): Works with Queue-Based Load Leveling to handle transient failures by retrying failed operations\n\n## References and Credits\n\n* [Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems](https://amzn.to/3y6yv1z)\n* [Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions](https://amzn.to/3WcFVui)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Queue-Based Load Leveling - Microsoft](https://docs.microsoft.com/en-us/azure/architecture/patterns/queue-based-load-leveling)\n"
  },
  {
    "path": "queue-based-load-leveling/etc/queue-based-load-leveling.urm.puml",
    "content": "@startuml\npackage com.iluwatar.queue.load.leveling {\n  class App {\n    - LOGGER : Logger {static}\n    - SHUTDOWN_TIME : int {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Message {\n    - msg : String\n    + Message(msg : String)\n    + getMsg() : String\n    + toString() : String\n  }\n  class MessageQueue {\n    - LOGGER : Logger {static}\n    - blkQueue : BlockingQueue<Message>\n    + MessageQueue()\n    + retrieveMsg() : Message\n    + submitMsg(msg : Message)\n  }\n  class ServiceExecutor {\n    - LOGGER : Logger {static}\n    - msgQueue : MessageQueue\n    + ServiceExecutor(msgQueue : MessageQueue)\n    + run()\n  }\n  interface Task {\n    + submit(Message) {abstract}\n  }\n  class TaskGenerator {\n    - LOGGER : Logger {static}\n    - msgCount : int\n    - msgQueue : MessageQueue\n    + TaskGenerator(msgQueue : MessageQueue, msgCount : int)\n    + run()\n    + submit(msg : Message)\n  }\n}\nMessageQueue -->  \"-blkQueue\" Message\nServiceExecutor -->  \"-msgQueue\" MessageQueue\nTaskGenerator -->  \"-msgQueue\" MessageQueue\nTaskGenerator ..|> Task \n@enduml"
  },
  {
    "path": "queue-based-load-leveling/etc/queue-load-leveling.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.11\" icons=\"true\" always-add-relationships=\"false\" generalizations=\"true\" realizations=\"true\" \n  associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"org.queue.load.leveling.TaskGenerator\" project=\"queue-load-leveling\" \n    file=\"/queue-load-leveling/src/main/java/org/queue/load/leveling/TaskGenerator.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"470\" y=\"213\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"2\" language=\"java\" name=\"org.queue.load.leveling.Task\" project=\"queue-load-leveling\" \n    file=\"/queue-load-leveling/src/main/java/org/queue/load/leveling/Task.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"426\" y=\"389\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"3\" language=\"java\" name=\"org.queue.load.leveling.MessageQueue\" project=\"queue-load-leveling\" \n    file=\"/queue-load-leveling/src/main/java/org/queue/load/leveling/MessageQueue.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"661\" y=\"419\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"org.queue.load.leveling.Message\" project=\"queue-load-leveling\" \n    file=\"/queue-load-leveling/src/main/java/org/queue/load/leveling/Message.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"594\" y=\"657\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"org.queue.load.leveling.ServiceExecutor\" project=\"queue-load-leveling\" \n    file=\"/queue-load-leveling/src/main/java/org/queue/load/leveling/ServiceExecutor.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"775\" y=\"193\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <realization id=\"6\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </realization>  \n  <association id=\"7\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"8\" name=\"msgQueue\"/>      \n      <multiplicity id=\"9\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"10\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"11\" name=\"blkQueue\"/>      \n      <multiplicity id=\"12\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"13\">    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"14\" name=\"msgQueue\"/>      \n      <multiplicity id=\"15\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "queue-based-load-leveling/etc/queue-load-leveling.urm.puml",
    "content": "@startuml\npackage com.iluwatar.queue.load.leveling {\n  class App {\n    - LOGGER : Logger {static}\n    - SHUTDOWN_TIME : int {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Message {\n    - msg : String\n    + Message(msg : String)\n    + getMsg() : String\n    + toString() : String\n  }\n  class MessageQueue {\n    - LOGGER : Logger {static}\n    - blkQueue : BlockingQueue<Message>\n    + MessageQueue()\n    + retrieveMsg() : Message\n    + submitMsg(msg : Message)\n  }\n  class ServiceExecutor {\n    - LOGGER : Logger {static}\n    - msgQueue : MessageQueue\n    + ServiceExecutor(msgQueue : MessageQueue)\n    + run()\n  }\n  interface Task {\n    + submit(Message) {abstract}\n  }\n  class TaskGenerator {\n    - LOGGER : Logger {static}\n    - msgCount : int\n    - msgQueue : MessageQueue\n    + TaskGenerator(msgQueue : MessageQueue, msgCount : int)\n    + run()\n    + submit(msg : Message)\n  }\n}\nMessageQueue -->  \"-blkQueue\" Message\nServiceExecutor -->  \"-msgQueue\" MessageQueue\nTaskGenerator -->  \"-msgQueue\" MessageQueue\nTaskGenerator ..|> Task \n@enduml"
  },
  {
    "path": "queue-based-load-leveling/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>queue-based-load-leveling</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.queue.load.leveling.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "queue-based-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.queue.load.leveling;\n\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Many solutions in the cloud involve running tasks that invoke services. In this environment, if a\n * service is subjected to intermittent heavy loads, it can cause performance or reliability issues.\n *\n * <p>A service could be a component that is part of the same solution as the tasks that utilize it,\n * or it could be a third-party service providing access to frequently used resources such as a\n * cache or a storage service. If the same service is utilized by a number of tasks running\n * concurrently, it can be difficult to predict the volume of requests to which the service might be\n * subjected at any given point in time.\n *\n * <p>We will build a queue-based-load-leveling to solve above problem. Refactor the solution and\n * introduce a queue between the task and the service. The task and the service run asynchronously.\n * The task posts a message containing the data required by the service to a queue. The queue acts\n * as a buffer, storing the message until it is retrieved by the service. The service retrieves the\n * messages from the queue and processes them. Requests from a number of tasks, which can be\n * generated at a highly variable rate, can be passed to the service through the same message queue.\n *\n * <p>The queue effectively decouples the tasks from the service, and the service can handle the\n * messages at its own pace irrespective of the volume of requests from concurrent tasks.\n * Additionally, there is no delay to a task if the service is not available at the time it posts a\n * message to the queue.\n *\n * <p>In this example we have a class {@link MessageQueue} to hold the message {@link Message}\n * objects. All the worker threads {@link TaskGenerator} will submit the messages to the\n * MessageQueue. The service executor class {@link ServiceExecutor} will pick up one task at a time\n * from the Queue and execute them.\n */\n@Slf4j\npublic class App {\n\n  // Executor shut down time limit.\n  private static final int SHUTDOWN_TIME = 15;\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    // An Executor that provides methods to manage termination and methods that can\n    // produce a Future for tracking progress of one or more asynchronous tasks.\n    ExecutorService executor = null;\n\n    try {\n      // Create a MessageQueue object.\n      var msgQueue = new MessageQueue();\n\n      LOGGER.info(\"Submitting TaskGenerators and ServiceExecutor threads.\");\n\n      // Create three TaskGenerator threads. Each of them will submit different number of jobs.\n      final var taskRunnable1 = new TaskGenerator(msgQueue, 5);\n      final var taskRunnable2 = new TaskGenerator(msgQueue, 1);\n      final var taskRunnable3 = new TaskGenerator(msgQueue, 2);\n\n      // Create e service which should process the submitted jobs.\n      final var srvRunnable = new ServiceExecutor(msgQueue);\n\n      // Create a ThreadPool of 2 threads and\n      // submit all Runnable task for execution to executor\n      executor = Executors.newFixedThreadPool(2);\n      executor.submit(taskRunnable1);\n      executor.submit(taskRunnable2);\n      executor.submit(taskRunnable3);\n\n      // submitting serviceExecutor thread to the Executor service.\n      executor.submit(srvRunnable);\n\n      // Initiates an orderly shutdown.\n      LOGGER.info(\n          \"Initiating shutdown.\"\n              + \" Executor will shutdown only after all the Threads are completed.\");\n      executor.shutdown();\n\n      // Wait for SHUTDOWN_TIME seconds for all the threads to complete\n      // their tasks and then shut down the executor and then exit.\n      if (!executor.awaitTermination(SHUTDOWN_TIME, TimeUnit.SECONDS)) {\n        LOGGER.info(\"Executor was shut down and Exiting.\");\n        executor.shutdownNow();\n      }\n    } catch (Exception e) {\n      LOGGER.error(e.getMessage());\n    }\n  }\n}\n"
  },
  {
    "path": "queue-based-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/Message.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.queue.load.leveling;\n\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/** Message class with only one parameter. */\n@Getter\n@RequiredArgsConstructor\npublic class Message {\n  private final String msg;\n\n  @Override\n  public String toString() {\n    return msg;\n  }\n}\n"
  },
  {
    "path": "queue-based-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/MessageQueue.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.queue.load.leveling;\n\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.BlockingQueue;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * MessageQueue class. In this class we will create a Blocking Queue and submit/retrieve all the\n * messages from it.\n */\n@Slf4j\npublic class MessageQueue {\n\n  private final BlockingQueue<Message> blkQueue;\n\n  // Default constructor when called creates Blocking Queue object.\n  public MessageQueue() {\n    this.blkQueue = new ArrayBlockingQueue<>(1024);\n  }\n\n  /**\n   * All the TaskGenerator threads will call this method to insert the Messages in to the Blocking\n   * Queue.\n   */\n  public void submitMsg(Message msg) {\n    try {\n      if (null != msg) {\n        blkQueue.add(msg);\n      }\n    } catch (Exception e) {\n      LOGGER.error(e.getMessage());\n    }\n  }\n\n  /**\n   * All the messages will be retrieved by the ServiceExecutor by calling this method and process\n   * them. Retrieves and removes the head of this queue, or returns null if this queue is empty.\n   */\n  public Message retrieveMsg() {\n    try {\n      return blkQueue.poll();\n    } catch (Exception e) {\n      LOGGER.error(e.getMessage());\n    }\n    return null;\n  }\n}\n"
  },
  {
    "path": "queue-based-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/ServiceExecutor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.queue.load.leveling;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * ServiceExecuotr class. This class will pick up Messages one by one from the Blocking Queue and\n * process them.\n */\n@Slf4j\npublic class ServiceExecutor implements Runnable {\n\n  private final MessageQueue msgQueue;\n\n  public ServiceExecutor(MessageQueue msgQueue) {\n    this.msgQueue = msgQueue;\n  }\n\n  /** The ServiceExecutor thread will retrieve each message and process it. */\n  public void run() {\n    try {\n      while (!Thread.currentThread().isInterrupted()) {\n        var msg = msgQueue.retrieveMsg();\n\n        if (null != msg) {\n          LOGGER.info(msg + \" is served.\");\n        } else {\n          LOGGER.info(\"Service Executor: Waiting for Messages to serve .. \");\n        }\n\n        Thread.sleep(1000);\n      }\n    } catch (Exception e) {\n      LOGGER.error(e.getMessage());\n    }\n  }\n}\n"
  },
  {
    "path": "queue-based-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/Task.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.queue.load.leveling;\n\n/** Task Interface. */\npublic interface Task {\n  void submit(Message msg);\n}\n"
  },
  {
    "path": "queue-based-load-leveling/src/main/java/com/iluwatar/queue/load/leveling/TaskGenerator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.queue.load.leveling;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * TaskGenerator class. Each TaskGenerator thread will be a Worker which submits messages to the\n * queue. We need to mention the message count for each of the TaskGenerator threads.\n */\n@Slf4j\npublic class TaskGenerator implements Task, Runnable {\n\n  // MessageQueue reference using which we will submit our messages.\n  private final MessageQueue msgQueue;\n\n  // Total message count that a TaskGenerator will submit.\n  private final int msgCount;\n\n  // Parameterized constructor.\n  public TaskGenerator(MessageQueue msgQueue, int msgCount) {\n    this.msgQueue = msgQueue;\n    this.msgCount = msgCount;\n  }\n\n  /** Submit messages to the Blocking Queue. */\n  public void submit(Message msg) {\n    try {\n      this.msgQueue.submitMsg(msg);\n    } catch (Exception e) {\n      LOGGER.error(e.getMessage());\n    }\n  }\n\n  /**\n   * Each TaskGenerator thread will submit all the messages to the Queue. After every message\n   * submission TaskGenerator thread will sleep for 1 second.\n   */\n  public void run() {\n    var count = this.msgCount;\n\n    try {\n      while (count > 0) {\n        var statusMsg = \"Message-\" + count + \" submitted by \" + Thread.currentThread().getName();\n        this.submit(new Message(statusMsg));\n\n        LOGGER.info(statusMsg);\n\n        // reduce the message count.\n        count--;\n\n        // Make the current thread to sleep after every Message submission.\n        Thread.sleep(1000);\n      }\n    } catch (Exception e) {\n      LOGGER.error(e.getMessage());\n    }\n  }\n}\n"
  },
  {
    "path": "queue-based-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.queue.load.leveling;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application Test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "queue-based-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/MessageQueueTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.queue.load.leveling;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test case for submitting and retrieving messages from Blocking Queue. */\nclass MessageQueueTest {\n\n  @Test\n  void messageQueueTest() {\n\n    var msgQueue = new MessageQueue();\n\n    // submit message\n    msgQueue.submitMsg(new Message(\"MessageQueue Test\"));\n\n    // retrieve message\n    assertEquals(\"MessageQueue Test\", msgQueue.retrieveMsg().getMsg());\n  }\n}\n"
  },
  {
    "path": "queue-based-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/MessageTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.queue.load.leveling;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test case for creating and checking the Message. */\nclass MessageTest {\n\n  @Test\n  void messageTest() {\n\n    // Parameterized constructor test.\n    var testMsg = \"Message Test\";\n    var msg = new Message(testMsg);\n    assertEquals(testMsg, msg.getMsg());\n  }\n}\n"
  },
  {
    "path": "queue-based-load-leveling/src/test/java/com/iluwatar/queue/load/leveling/TaskGenSrvExeTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.queue.load.leveling;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport org.junit.jupiter.api.Test;\n\n/**\n * Test case for submitting Message to Blocking Queue by TaskGenerator and retrieve the message by\n * ServiceExecutor.\n */\nclass TaskGenSrvExeTest {\n\n  @Test\n  void taskGeneratorTest() {\n    var msgQueue = new MessageQueue();\n\n    // Create a task generator thread with 1 job to submit.\n    var taskRunnable = new TaskGenerator(msgQueue, 1);\n    var taskGenThr = new Thread(taskRunnable);\n    taskGenThr.start();\n\n    assertNotNull(taskGenThr);\n\n    // Create a service executor thread.\n    var srvRunnable = new ServiceExecutor(msgQueue);\n    var srvExeThr = new Thread(srvRunnable);\n    srvExeThr.start();\n\n    assertNotNull(srvExeThr);\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/README.md",
    "content": "---\ntitle: \"Rate Limiting Pattern in Java: Controlling System Overload Gracefully\"\nshortTitle: Rate Limiting\ndescription: \"Explore multiple rate limiting strategies in Java—Token Bucket, Fixed Window, and Adaptive Limiting. Learn with diagrams, programmatic examples, and real-world simulation.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Resilience\n  - System Overload Protection\n  - API Throttling\n  - Concurrency\n  - Cloud Patterns\n---\n\n## Also known as\n\n- Throttling\n- Request Limiting\n- API Rate Limiting\n\n---\n\n## Intent of Rate Limiting Design Pattern\n\nTo regulate the number of requests sent to a service in a specific time window, avoiding resource exhaustion and ensuring system stability. This is especially useful in distributed and cloud-native architectures.\n\n---\n\n## Detailed Explanation of Rate Limiting with Real-World Examples\n\n### Real-world example\n\nImagine you're entering a concert hall that only allows 50 people per minute. If too many fans arrive at once, the gate staff slows down entry, allowing only a few at a time. This prevents overcrowding and ensures safety. Similarly, the rate limiter controls how many requests are processed to avoid overloading a server.\n\n### In plain words\n\nRegulate the number of requests a system handles within a time frame to protect availability and performance.\n\n\n### AWS says\n\n> \"API Gateway limits the steady-state rate and burst rate of requests that it allows for each method in your REST APIs. When request rates exceed these limits, API Gateway begins to throttle requests.\"\n\n— [API Gateway quotas and important notes - AWS Documentation](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-request-throttling.html)\n\n---\n\n## Architecture Diagram\n\n![UML Class Diagram](etc/UMLClassDiagram.png)\n\nThis UML shows the key components:\n- `RateLimiter` interface\n- `TokenBucketRateLimiter`, `FixedWindowRateLimiter`, `AdaptiveRateLimiter`\n- Supporting exception classes\n- `FindCustomerRequest` as a rate-limited operation\n\n---\n\n## Flowcharts\n\n### 1. Token Bucket Strategy\n\n![Token Bucket Rate Limiter](etc/TokenBucketRateLimiter.png)\n\n### 2. Fixed Window Strategy\n\n![Fixed Window Rate Limiter](etc/FixedWindowRateLimiter.png)\n\n### 3. Adaptive Rate Limiting Strategy\n\n![Adaptive Rate Limiter](etc/AdaptiveRateLimiter.png)\n\n---\n\n### Programmatic Example of Rate Limiter Pattern in Java\n\nThe **Rate Limiter** design pattern helps protect systems from overload by restricting the number of operations that can be performed in a given time window. It is especially useful when accessing shared resources, APIs, or services that are sensitive to spikes in traffic.\n\nThis implementation demonstrates three strategies for rate limiting:\n\n- **Token Bucket Rate Limiter**\n- **Fixed Window Rate Limiter**\n- **Adaptive Rate Limiter**\n\nLet’s walk through the key components.\n\n---\n\n#### 1. Token Bucket Rate Limiter\n\nThe token bucket allows short bursts followed by a steady rate. Tokens are added periodically and requests are only allowed if a token is available.\n\n```java\npublic class TokenBucketRateLimiter implements RateLimiter {\n  private final int capacity;\n  private final int refillRate;\n  private final ConcurrentHashMap<String, TokenBucket> buckets = new ConcurrentHashMap<>();\n  private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);\n\n  public TokenBucketRateLimiter(int capacity, int refillRate) {\n    this.capacity = capacity;\n    this.refillRate = refillRate;\n    scheduler.scheduleAtFixedRate(this::refillBuckets, 1, 1, TimeUnit.SECONDS);\n  }\n\n  @Override\n  public void check(String serviceName, String operationName) throws RateLimitException {\n    String key = serviceName + \":\" + operationName;\n    TokenBucket bucket = buckets.computeIfAbsent(key, k -> new TokenBucket(capacity));\n    if (!bucket.tryConsume()) {\n      throw new ThrottlingException(serviceName, operationName, 1000);\n    }\n  }\n\n  private void refillBuckets() {\n    buckets.forEach((k, b) -> b.refill(refillRate));\n  }\n\n  private static class TokenBucket {\n    private final int capacity;\n    private final AtomicInteger tokens;\n\n    TokenBucket(int capacity) {\n      this.capacity = capacity;\n      this.tokens = new AtomicInteger(capacity);\n    }\n\n    boolean tryConsume() {\n      while (true) {\n        int current = tokens.get();\n        if (current <= 0) return false;\n        if (tokens.compareAndSet(current, current - 1)) return true;\n      }\n    }\n\n    void refill(int amount) {\n      tokens.getAndUpdate(current -> Math.min(current + amount, capacity));\n    }\n  }\n}\n```\n\n---\n\n#### 2. Fixed Window Rate Limiter\n\nThis strategy uses a simple counter within a fixed time window.\n\n```java\npublic class FixedWindowRateLimiter implements RateLimiter {\n  private final int limit;\n  private final long windowMillis;\n  private final ConcurrentHashMap<String, WindowCounter> counters = new ConcurrentHashMap<>();\n\n  public FixedWindowRateLimiter(int limit, long windowSeconds) {\n    this.limit = limit;\n    this.windowMillis = TimeUnit.SECONDS.toMillis(windowSeconds);\n  }\n\n  @Override\n  public synchronized void check(String serviceName, String operationName) throws RateLimitException {\n    String key = serviceName + \":\" + operationName;\n    WindowCounter counter = counters.computeIfAbsent(key, k -> new WindowCounter());\n\n    if (!counter.tryIncrement()) {\n      throw new RateLimitException(\"Rate limit exceeded for \" + key, windowMillis);\n    }\n  }\n\n  private class WindowCounter {\n    private AtomicInteger count = new AtomicInteger(0);\n    private volatile long windowStart = System.currentTimeMillis();\n\n    synchronized boolean tryIncrement() {\n      long now = System.currentTimeMillis();\n      if (now - windowStart > windowMillis) {\n        count.set(0);\n        windowStart = now;\n      }\n      return count.incrementAndGet() <= limit;\n    }\n  }\n}\n```\n\n---\n\n#### 3. Adaptive Rate Limiter\n\nThis version adjusts the rate based on system health, reducing the rate when throttling occurs and recovering periodically.\n\n```java\npublic class AdaptiveRateLimiter implements RateLimiter {\n  private final int initialLimit;\n  private final int maxLimit;\n  private final AtomicInteger currentLimit;\n  private final ConcurrentHashMap<String, RateLimiter> limiters = new ConcurrentHashMap<>();\n  private final ScheduledExecutorService healthChecker = Executors.newScheduledThreadPool(1);\n\n  public AdaptiveRateLimiter(int initialLimit, int maxLimit) {\n    this.initialLimit = initialLimit;\n    this.maxLimit = maxLimit;\n    this.currentLimit = new AtomicInteger(initialLimit);\n    healthChecker.scheduleAtFixedRate(this::adjustLimits, 10, 10, TimeUnit.SECONDS);\n  }\n\n  @Override\n  public void check(String serviceName, String operationName) throws RateLimitException {\n    String key = serviceName + \":\" + operationName;\n    int current = currentLimit.get();\n    RateLimiter limiter = limiters.computeIfAbsent(key, k -> new TokenBucketRateLimiter(current, current));\n\n    try {\n      limiter.check(serviceName, operationName);\n    } catch (RateLimitException e) {\n      currentLimit.updateAndGet(curr -> Math.max(initialLimit, curr / 2));\n      throw e;\n    }\n  }\n\n  private void adjustLimits() {\n    currentLimit.updateAndGet(curr -> Math.min(maxLimit, curr + (initialLimit / 2)));\n  }\n}\n```\n\n---\n\n#### 4. Simulated Demo Using All Limiters\n\n```java\npublic final class App {\n  public static void main(String[] args) {\n    TokenBucketRateLimiter tb = new TokenBucketRateLimiter(2, 1);\n    FixedWindowRateLimiter fw = new FixedWindowRateLimiter(3, 1);\n    AdaptiveRateLimiter ar = new AdaptiveRateLimiter(2, 6);\n\n    ExecutorService executor = Executors.newFixedThreadPool(3);\n    for (int i = 1; i <= 3; i++) {\n      executor.submit(createClientTask(i, tb, fw, ar));\n    }\n  }\n\n  private static Runnable createClientTask(int clientId, RateLimiter tb, RateLimiter fw, RateLimiter ar) {\n    return () -> {\n      String[] services = {\"s3\", \"dynamodb\", \"lambda\"};\n      String[] operations = {\"GetObject\", \"PutObject\", \"Query\", \"Scan\", \"PutItem\", \"Invoke\", \"ListFunctions\"};\n      Random random = new Random();\n\n      while (true) {\n        String service = services[random.nextInt(services.length)];\n        String operation = operations[random.nextInt(operations.length)];\n        try {\n          switch (service) {\n            case \"s3\" -> tb.check(service, operation);\n            case \"dynamodb\" -> fw.check(service, operation);\n            case \"lambda\" -> ar.check(service, operation);\n          }\n          System.out.printf(\"Client %d: %s.%s - ALLOWED%n\", clientId, service, operation);\n        } catch (RateLimitException e) {\n          System.out.printf(\"Client %d: %s.%s - THROTTLED%n\", clientId, service, operation);\n        }\n\n        try {\n          Thread.sleep(30 + random.nextInt(50));\n        } catch (InterruptedException e) {\n          Thread.currentThread().interrupt();\n        }\n      }\n    };\n  }\n}\n```\n\n---\n\nThis example highlights how the Rate Limiter pattern supports various throttling techniques and how they respond under simulated traffic pressure, making it invaluable for building scalable, resilient systems.\n\n## When to Use Rate Limiting\n\n- APIs receiving unpredictable traffic\n- Shared cloud resources (e.g., DB, compute)\n- Services requiring fair client usage\n- Preventing DoS or abuse\n\n---\n\n## Real-World Applications\n\n- **AWS API Gateway**\n- **Google Cloud Functions**\n- **Netflix Zuul API Gateway**\n- **Stripe API Throttling**\n\n---\n\n## Benefits and Trade-offs\n\n### Benefits\n\n- Protects backend from overload\n- Fair distribution of resources\n- Better user experience under load\n\n### Trade-offs\n\n- May delay valid requests\n- Requires tuning of limits\n- Could create bottlenecks if misused\n\n---\n\n## Related Java Design Patterns\n\n- [Circuit Breaker](https://java-design-patterns.com/patterns/circuit-breaker/)\n- [Retry](https://java-design-patterns.com/patterns/retry/)\n- [Throttling Queue](https://java-design-patterns.com/patterns/throttling/)\n\n---\n\n## References and Credits\n\n- [Microsoft Cloud Design Patterns](https://learn.microsoft.com/en-us/azure/architecture/patterns/throttling)\n- [AWS API Gateway Throttling](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-request-throttling.html)\n- *Designing Data-Intensive Applications* by Martin Kleppmann\n- [Resilience4j](https://resilience4j.readme.io/)\n- Java Design Patterns Project: [java-design-patterns](https://github.com/iluwatar/java-design-patterns)\n"
  },
  {
    "path": "rate-limiting-pattern/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>rate-limiter</artifactId>\n\n    <properties>\n        <maven.compiler.source>22</maven.compiler.source>\n        <maven.compiler.target>22</maven.compiler.target>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <junit.jupiter.version>5.11.1</junit.jupiter.version>\n        <junit.platform.version>1.11.1</junit.platform.version>\n    </properties>\n\n    <dependencies>\n        <!-- JUnit 5 API and Engine -->\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter</artifactId>\n            <version>${junit.jupiter.version}</version>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <version>5.12.0</version>\n            <scope>test</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n            <version>2.0.9</version>\n        </dependency>\n\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n            <version>1.4.11</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.assertj</groupId>\n            <artifactId>assertj-core</artifactId>\n            <version>3.24.2</version>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>com.diffplug.spotless</groupId>\n                <artifactId>spotless-maven-plugin</artifactId>\n                <version>2.44.2</version>\n                <executions>\n                    <execution>\n                        <goals>\n                            <goal>check</goal> <!-- Fails the build if formatting is off -->\n                            <goal>apply</goal> <!-- Automatically formats code -->\n                        </goals>\n                    </execution>\n                </executions>\n                <configuration>\n                    <java>\n                        <googleJavaFormat />\n                    </java>\n                </configuration>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-surefire-plugin</artifactId>\n                <version>3.1.2</version>\n                <configuration>\n                    <useModulePath>false</useModulePath> <!-- for Java 17+ compatibility -->\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "rate-limiting-pattern/src/main/java/com/iluwatar/rate/limiting/pattern/AdaptiveRateLimiter.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/** Adaptive rate limiter that adjusts limits based on system health. */\npublic class AdaptiveRateLimiter implements RateLimiter {\n  private final int initialLimit;\n  private final int maxLimit;\n  private final AtomicInteger currentLimit;\n  private final ConcurrentHashMap<String, RateLimiter> limiters = new ConcurrentHashMap<>();\n  private final ScheduledExecutorService healthChecker = Executors.newScheduledThreadPool(1);\n\n  public AdaptiveRateLimiter(int initialLimit, int maxLimit) {\n    this.initialLimit = initialLimit;\n    this.maxLimit = maxLimit;\n    this.currentLimit = new AtomicInteger(initialLimit);\n    // Periodically increase limit to recover if system appears healthy\n    healthChecker.scheduleAtFixedRate(this::adjustLimits, 10, 10, TimeUnit.SECONDS);\n  }\n\n  @Override\n  public void check(String serviceName, String operationName) throws RateLimitException {\n    String key = serviceName + \":\" + operationName;\n    int current = currentLimit.get();\n\n    // Reuse or create TokenBucket for this key using currentLimit\n    RateLimiter limiter =\n        limiters.computeIfAbsent(key, k -> new TokenBucketRateLimiter(current, current));\n\n    try {\n      limiter.check(serviceName, operationName);\n      System.out.printf(\n          \"[Adaptive] Allowed %s.%s - CurrentLimit: %d%n\", serviceName, operationName, current);\n    } catch (RateLimitException e) {\n      // On throttling, reduce system limit to reduce load\n      currentLimit.updateAndGet(curr -> Math.max(initialLimit, curr / 2));\n      System.out.printf(\n          \"[Adaptive] Throttled %s.%s - Decreasing limit to %d%n\",\n          serviceName, operationName, currentLimit.get());\n      throw e;\n    }\n  }\n\n  // Periodic recovery mechanism to raise limits when the system is under control\n  private void adjustLimits() {\n    int updated = currentLimit.updateAndGet(curr -> Math.min(maxLimit, curr + (initialLimit / 2)));\n    System.out.printf(\"[Adaptive] Health check passed - Increasing limit to %d%n\", updated);\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/main/java/com/iluwatar/rate/limiting/pattern/App.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport java.security.SecureRandom;\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * The <em>Rate Limiter</em> pattern is a key defensive strategy used to prevent system overload and\n * ensure fair usage of shared services. This demo showcases how different rate limiting techniques\n * can regulate traffic in distributed systems.\n *\n * <p>Specifically, this simulation implements three rate limiter strategies:\n *\n * <ul>\n *   <li><b>Token Bucket</b> – Allows short bursts followed by steady request rates.\n *   <li><b>Fixed Window</b> – Enforces a strict limit per discrete time window (e.g., 3\n *       requests/sec).\n *   <li><b>Adaptive</b> – Dynamically scales limits based on system health, simulating elastic\n *       backoff.\n * </ul>\n *\n * <p>Each simulated service (e.g., S3, DynamoDB, Lambda) is governed by one of these limiters.\n * Multiple concurrent client threads issue randomized requests to these services over a fixed\n * duration. Each request is either:\n *\n * <ul>\n *   <li><b>ALLOWED</b> – Permitted under the current rate limit\n *   <li><b>THROTTLED</b> – Rejected due to quota exhaustion\n *   <li><b>FAILED</b> – Dropped due to transient service failure\n * </ul>\n *\n * <p>Statistics are printed every few seconds, and the simulation exits gracefully after a fixed\n * runtime, offering a clear view into how each limiter behaves under pressure.\n *\n * <p><b>Relation to AWS API Gateway:</b><br>\n * This implementation mirrors the throttling behavior described in the <a\n * href=\"https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-request-throttling.html\">\n * AWS API Gateway Request Throttling documentation</a>, where limits are applied per second and\n * over longer durations (burst and rate limits). The <code>TokenBucketRateLimiter</code> mimics\n * burst capacity, the <code>FixedWindowRateLimiter</code> models steady rate enforcement, and the\n * <code>AdaptiveRateLimiter</code> reflects elasticity in real-world systems like AWS Lambda under\n * variable load.\n */\npublic final class App {\n  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n  private static final int RUN_DURATION_SECONDS = 10;\n  private static final int SHUTDOWN_TIMEOUT_SECONDS = 5;\n\n  static final AtomicInteger successfulRequests = new AtomicInteger();\n  static final AtomicInteger throttledRequests = new AtomicInteger();\n  static final AtomicInteger failedRequests = new AtomicInteger();\n  static final AtomicBoolean running = new AtomicBoolean(true);\n  private static final String DIVIDER_LINE = \"====================================\";\n\n  public static void main(String[] args) {\n    LOGGER.info(\"Starting Rate Limiter Demo\");\n    LOGGER.info(DIVIDER_LINE);\n\n    ExecutorService executor = Executors.newFixedThreadPool(3);\n    ScheduledExecutorService statsPrinter = Executors.newSingleThreadScheduledExecutor();\n\n    try {\n      TokenBucketRateLimiter tb = new TokenBucketRateLimiter(2, 1);\n      FixedWindowRateLimiter fw = new FixedWindowRateLimiter(3, 1);\n      AdaptiveRateLimiter ar = new AdaptiveRateLimiter(2, 6);\n\n      statsPrinter.scheduleAtFixedRate(App::printStats, 2, 2, TimeUnit.SECONDS);\n\n      for (int i = 1; i <= 3; i++) {\n        executor.submit(createClientTask(i, tb, fw, ar));\n      }\n\n      Thread.sleep(RUN_DURATION_SECONDS * 1000L);\n      LOGGER.info(\"Shutting down the demo...\");\n    } catch (InterruptedException e) {\n      Thread.currentThread().interrupt();\n    } finally {\n      running.set(false);\n      shutdownExecutor(executor, \"mainExecutor\");\n      shutdownExecutor(statsPrinter, \"statsPrinter\");\n      printFinalStats();\n      LOGGER.info(\"Demo completed.\");\n    }\n  }\n\n  private static void shutdownExecutor(ExecutorService service, String name) {\n    service.shutdown();\n    try {\n      if (!service.awaitTermination(SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {\n        service.shutdownNow();\n        LOGGER.warn(\"Forced shutdown of {}\", name);\n      }\n    } catch (InterruptedException e) {\n      service.shutdownNow();\n      Thread.currentThread().interrupt();\n    }\n  }\n\n  static Runnable createClientTask(\n      int clientId, RateLimiter s3Limiter, RateLimiter dynamoDbLimiter, RateLimiter lambdaLimiter) {\n\n    return () -> {\n      String[] services = {\"s3\", \"dynamodb\", \"lambda\"};\n      String[] operations = {\n        \"GetObject\", \"PutObject\", \"Query\", \"Scan\", \"PutItem\", \"Invoke\", \"ListFunctions\"\n      };\n      SecureRandom random = new SecureRandom(); // ✅ Safe & compliant for SonarCloud\n\n      while (running.get() && !Thread.currentThread().isInterrupted()) {\n        try {\n          String service = services[random.nextInt(services.length)];\n          String operation = operations[random.nextInt(operations.length)];\n\n          switch (service) {\n            case \"s3\" -> makeRequest(clientId, s3Limiter, service, operation);\n            case \"dynamodb\" -> makeRequest(clientId, dynamoDbLimiter, service, operation);\n            case \"lambda\" -> makeRequest(clientId, lambdaLimiter, service, operation);\n            default -> LOGGER.warn(\"Unknown service: {}\", service);\n          }\n\n          Thread.sleep(30L + random.nextInt(50));\n        } catch (InterruptedException e) {\n          Thread.currentThread().interrupt();\n        }\n      }\n    };\n  }\n\n  static void makeRequest(int clientId, RateLimiter limiter, String service, String operation) {\n    try {\n      limiter.check(service, operation);\n      successfulRequests.incrementAndGet();\n      LOGGER.info(\"Client {}: {}.{} - ALLOWED\", clientId, service, operation);\n    } catch (ThrottlingException e) {\n      throttledRequests.incrementAndGet();\n      LOGGER.warn(\n          \"Client {}: {}.{} - THROTTLED (Retry in {}ms)\",\n          clientId,\n          service,\n          operation,\n          e.getRetryAfterMillis());\n    } catch (ServiceUnavailableException e) {\n      failedRequests.incrementAndGet();\n      LOGGER.warn(\"Client {}: {}.{} - SERVICE UNAVAILABLE\", clientId, service, operation);\n    } catch (Exception e) {\n      failedRequests.incrementAndGet();\n      LOGGER.error(\"Client {}: {}.{} - ERROR: {}\", clientId, service, operation, e.getMessage());\n    }\n  }\n\n  static void printStats() {\n    if (!running.get()) return;\n    LOGGER.info(\"=== Current Statistics ===\");\n    LOGGER.info(\"Successful Requests: {}\", successfulRequests.get());\n    LOGGER.info(\"Throttled Requests : {}\", throttledRequests.get());\n    LOGGER.info(\"Failed Requests    : {}\", failedRequests.get());\n    LOGGER.info(DIVIDER_LINE);\n  }\n\n  static void printFinalStats() {\n    LOGGER.info(\"Final Statistics\");\n    LOGGER.info(DIVIDER_LINE);\n    LOGGER.info(\"Successful Requests: {}\", successfulRequests.get());\n    LOGGER.info(\"Throttled Requests : {}\", throttledRequests.get());\n    LOGGER.info(\"Failed Requests    : {}\", failedRequests.get());\n    LOGGER.info(DIVIDER_LINE);\n  }\n\n  static void resetCountersForTesting() {\n    successfulRequests.set(0);\n    throttledRequests.set(0);\n    failedRequests.set(0);\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/main/java/com/iluwatar/rate/limiting/pattern/FindCustomerRequest.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\n/**\n * A rate-limited customer lookup operation. This class wraps the rate limiting logic and represents\n * an executable business request.\n */\npublic class FindCustomerRequest implements RateLimitOperation<String> {\n  private final String customerId;\n  private final RateLimiter rateLimiter;\n\n  public FindCustomerRequest(String customerId, RateLimiter rateLimiter) {\n    this.customerId = customerId;\n    this.rateLimiter = rateLimiter;\n  }\n\n  @Override\n  public String getServiceName() {\n    return \"CustomerService\";\n  }\n\n  @Override\n  public String getOperationName() {\n    return \"FindCustomer\";\n  }\n\n  @Override\n  public String execute() throws RateLimitException {\n    // Ensure the operation respects the assigned rate limiter\n    rateLimiter.check(getServiceName(), getOperationName());\n\n    // Simulate actual operation\n    try {\n      Thread.sleep(50); // Simulate processing time\n      return \"Customer-\" + customerId;\n    } catch (InterruptedException e) {\n      Thread.currentThread().interrupt();\n      throw new ServiceUnavailableException(getServiceName(), 1000);\n    }\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/main/java/com/iluwatar/rate/limiting/pattern/FixedWindowRateLimiter.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Implements a fixed window rate limiter. It allows up to 'limit' number of requests within a time\n * window of fixed size.\n */\npublic class FixedWindowRateLimiter implements RateLimiter {\n  private final int limit;\n  private final long windowMillis;\n  private final ConcurrentHashMap<String, WindowCounter> counters = new ConcurrentHashMap<>();\n\n  public FixedWindowRateLimiter(int limit, long windowSeconds) {\n    this.limit = limit;\n    this.windowMillis = TimeUnit.SECONDS.toMillis(windowSeconds);\n  }\n\n  @Override\n  public synchronized void check(String serviceName, String operationName)\n      throws RateLimitException {\n    String key = serviceName + \":\" + operationName;\n    WindowCounter counter = counters.computeIfAbsent(key, k -> new WindowCounter());\n\n    if (!counter.tryIncrement()) {\n      System.out.printf(\n          \"[FixedWindow] Throttled %s.%s - Limit %d reached in window%n\",\n          serviceName, operationName, limit);\n      throw new RateLimitException(\"Rate limit exceeded for \" + key, windowMillis);\n    } else {\n      System.out.printf(\n          \"[FixedWindow] Allowed %s.%s - Count within window%n\", serviceName, operationName);\n    }\n  }\n\n  /** Tracks the count of requests within the current window. */\n  private class WindowCounter {\n    private AtomicInteger count = new AtomicInteger(0);\n    private volatile long windowStart = System.currentTimeMillis();\n\n    synchronized boolean tryIncrement() {\n      long now = System.currentTimeMillis();\n      // Reset window if expired\n      if (now - windowStart > windowMillis) {\n        count.set(0);\n        windowStart = now;\n      }\n      // Enforce the request limit within window\n      return count.incrementAndGet() <= limit;\n    }\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/main/java/com/iluwatar/rate/limiting/pattern/RateLimitException.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\n/** Base exception for rate limiting errors. */\npublic class RateLimitException extends Exception {\n  private final long retryAfterMillis;\n\n  public RateLimitException(String message, long retryAfterMillis) {\n    super(message);\n    this.retryAfterMillis = retryAfterMillis;\n  }\n\n  public long getRetryAfterMillis() {\n    return retryAfterMillis;\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/main/java/com/iluwatar/rate/limiting/pattern/RateLimitOperation.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\n/** Represents a business operation that needs rate limiting. Supports type-safe return values. */\npublic interface RateLimitOperation<T> {\n  String getServiceName();\n\n  String getOperationName();\n\n  T execute() throws RateLimitException;\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/main/java/com/iluwatar/rate/limiting/pattern/RateLimiter.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\n/** Base interface for all rate limiter strategies. */\npublic interface RateLimiter {\n  /**\n   * Checks if a request is allowed under current rate limits\n   *\n   * @param serviceName Service being called (e.g., \"dynamodb\")\n   * @param operationName Operation being performed (e.g., \"Query\")\n   * @throws RateLimitException if request exceeds limits\n   */\n  void check(String serviceName, String operationName) throws RateLimitException;\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/main/java/com/iluwatar/rate/limiting/pattern/ServiceUnavailableException.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\n/** Exception for when a service is temporarily unavailable. */\npublic class ServiceUnavailableException extends RateLimitException {\n  private final String serviceName;\n\n  public ServiceUnavailableException(String serviceName, long retryAfterMillis) {\n    super(\"Service temporarily unavailable: \" + serviceName, retryAfterMillis);\n    this.serviceName = serviceName;\n  }\n\n  public String getServiceName() {\n    return serviceName;\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/main/java/com/iluwatar/rate/limiting/pattern/ThrottlingException.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\n/** Exception thrown when AWS-style throttling occurs. */\npublic class ThrottlingException extends RateLimitException {\n  private final String serviceName;\n  private final String errorCode;\n\n  public ThrottlingException(String serviceName, String operationName, long retryAfterMillis) {\n    super(\"AWS throttling error for \" + serviceName + \"/\" + operationName, retryAfterMillis);\n    this.serviceName = serviceName;\n    this.errorCode = \"ThrottlingException\";\n  }\n\n  public String getServiceName() {\n    return serviceName;\n  }\n\n  public String getErrorCode() {\n    return errorCode;\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/main/java/com/iluwatar/rate/limiting/pattern/TokenBucketRateLimiter.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Token Bucket rate limiter implementation. Allows requests to proceed as long as there are tokens\n * available in the bucket. Tokens are added at a fixed interval up to a defined capacity.\n */\npublic class TokenBucketRateLimiter implements RateLimiter {\n  private final int capacity;\n  private final int refillRate;\n  private final ConcurrentHashMap<String, TokenBucket> buckets = new ConcurrentHashMap<>();\n  private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);\n\n  public TokenBucketRateLimiter(int capacity, int refillRate) {\n    this.capacity = capacity;\n    this.refillRate = refillRate;\n    // Refill tokens in all buckets every second\n    scheduler.scheduleAtFixedRate(this::refillBuckets, 1, 1, TimeUnit.SECONDS);\n  }\n\n  @Override\n  public void check(String serviceName, String operationName) throws RateLimitException {\n    String key = serviceName + \":\" + operationName;\n    TokenBucket bucket = buckets.computeIfAbsent(key, k -> new TokenBucket(capacity));\n\n    if (!bucket.tryConsume()) {\n      System.out.printf(\n          \"[TokenBucket] Throttled %s.%s - No tokens available%n\", serviceName, operationName);\n      throw new ThrottlingException(serviceName, operationName, 1000);\n    } else {\n      System.out.printf(\n          \"[TokenBucket] Allowed %s.%s - Tokens remaining%n\", serviceName, operationName);\n    }\n  }\n\n  private void refillBuckets() {\n    buckets.forEach((k, b) -> b.refill(refillRate));\n  }\n\n  /** Inner class that represents the bucket holding tokens for each service-operation. */\n  private static class TokenBucket {\n    private final int capacity;\n    private final AtomicInteger tokens;\n\n    TokenBucket(int capacity) {\n      this.capacity = capacity;\n      this.tokens = new AtomicInteger(capacity);\n    }\n\n    boolean tryConsume() {\n      while (true) {\n        int current = tokens.get();\n        if (current <= 0) return false;\n        if (tokens.compareAndSet(current, current - 1)) return true;\n      }\n    }\n\n    void refill(int amount) {\n      tokens.getAndUpdate(current -> Math.min(current + amount, capacity));\n    }\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/test/java/com/iluwatar/rate/limiting/pattern/AdaptiveRateLimiterTest.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass AdaptiveRateLimiterTest {\n  @Test\n  void shouldDecreaseLimitWhenThrottled() throws Exception {\n    AdaptiveRateLimiter limiter = new AdaptiveRateLimiter(10, 20);\n\n    // Exceed initial limit\n    for (int i = 0; i < 11; i++) {\n      try {\n        limiter.check(\"test\", \"op\");\n      } catch (RateLimitException e) {\n        // Expected after 10 requests\n      }\n    }\n\n    // Verify limit was reduced\n    assertThrows(\n        RateLimitException.class,\n        () -> {\n          for (int i = 0; i < 6; i++) { // New limit should be 5 (10/2)\n            limiter.check(\"test\", \"op\");\n          }\n        });\n  }\n\n  @Test\n  void shouldGraduallyIncreaseLimitWhenHealthy() throws Exception {\n    AdaptiveRateLimiter limiter =\n        new AdaptiveRateLimiter(4, 10); // Start from 4 → expect 2 → expect increase to 4\n\n    // Force throttling to reduce limit\n    for (int i = 0; i < 5; i++) {\n      try {\n        limiter.check(\"test\", \"op\");\n      } catch (RateLimitException e) {\n        // Expected to throttle and reduce limit\n      }\n    }\n\n    // Wait for health check to increase limit\n    Thread.sleep(11000); // Wait slightly more than 10 seconds\n\n    // Allow up to 4 requests again (limit should've increased to 4)\n    for (int i = 0; i < 4; i++) {\n      limiter.check(\"test\", \"op\");\n    }\n\n    // 5th should throw exception again\n    assertThrows(RateLimitException.class, () -> limiter.check(\"test\", \"op\"));\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/test/java/com/iluwatar/rate/limiting/pattern/AppTest.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport static org.junit.jupiter.api.Assertions.*;\nimport static org.mockito.Mockito.*;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for {@link App}. */\nclass AppTest {\n\n  private RateLimiter mockLimiter;\n\n  @BeforeEach\n  void setUp() {\n    mockLimiter = mock(RateLimiter.class);\n    AppTestUtils.resetCounters(); // Ensures counters are clean before every test\n  }\n\n  @Test\n  void shouldAllowRequest() {\n    AppTestUtils.invokeMakeRequest(1, mockLimiter, \"s3\", \"GetObject\");\n    assertEquals(1, AppTestUtils.getSuccessfulRequests().get(), \"Successful count should be 1\");\n    assertEquals(0, AppTestUtils.getThrottledRequests().get(), \"Throttled count should be 0\");\n    assertEquals(0, AppTestUtils.getFailedRequests().get(), \"Failed count should be 0\");\n  }\n\n  @Test\n  void shouldHandleThrottlingException() throws Exception {\n    doThrow(new ThrottlingException(\"s3\", \"PutObject\", 1000)).when(mockLimiter).check(any(), any());\n    AppTestUtils.invokeMakeRequest(2, mockLimiter, \"s3\", \"PutObject\");\n    assertEquals(0, AppTestUtils.getSuccessfulRequests().get());\n    assertEquals(1, AppTestUtils.getThrottledRequests().get());\n    assertEquals(0, AppTestUtils.getFailedRequests().get());\n  }\n\n  @Test\n  void shouldHandleServiceUnavailableException() throws Exception {\n    doThrow(new ServiceUnavailableException(\"lambda\", 500)).when(mockLimiter).check(any(), any());\n    AppTestUtils.invokeMakeRequest(3, mockLimiter, \"lambda\", \"Invoke\");\n    assertEquals(0, AppTestUtils.getSuccessfulRequests().get());\n    assertEquals(0, AppTestUtils.getThrottledRequests().get());\n    assertEquals(1, AppTestUtils.getFailedRequests().get());\n  }\n\n  @Test\n  void shouldHandleGenericException() throws Exception {\n    doThrow(new RuntimeException(\"Unexpected\")).when(mockLimiter).check(any(), any());\n    AppTestUtils.invokeMakeRequest(4, mockLimiter, \"dynamodb\", \"Query\");\n    assertEquals(0, AppTestUtils.getSuccessfulRequests().get());\n    assertEquals(0, AppTestUtils.getThrottledRequests().get());\n    assertEquals(1, AppTestUtils.getFailedRequests().get());\n  }\n\n  @Test\n  void shouldRunMainMethodWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/test/java/com/iluwatar/rate/limiting/pattern/AppTestUtils.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport java.util.concurrent.atomic.AtomicInteger;\n\npublic class AppTestUtils {\n\n  public static void invokeMakeRequest(\n      int clientId, RateLimiter limiter, String service, String operation) {\n    App.makeRequest(clientId, limiter, service, operation);\n  }\n\n  public static void resetCounters() {\n    App.resetCountersForTesting();\n  }\n\n  public static AtomicInteger getSuccessfulRequests() {\n    return App.successfulRequests;\n  }\n\n  public static AtomicInteger getThrottledRequests() {\n    return App.throttledRequests;\n  }\n\n  public static AtomicInteger getFailedRequests() {\n    return App.failedRequests;\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/test/java/com/iluwatar/rate/limiting/pattern/ConcurrencyTests.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport org.junit.jupiter.api.Test;\n\nclass ConcurrencyTests {\n  @Test\n  void tokenBucketShouldHandleConcurrentRequests() throws Exception {\n    int threadCount = 10;\n    int requestLimit = 5;\n    RateLimiter limiter = new TokenBucketRateLimiter(requestLimit, requestLimit);\n    ExecutorService executor = Executors.newFixedThreadPool(threadCount);\n    CountDownLatch latch = new CountDownLatch(threadCount);\n\n    AtomicInteger successCount = new AtomicInteger();\n    AtomicInteger failureCount = new AtomicInteger();\n\n    for (int i = 0; i < threadCount; i++) {\n      executor.submit(\n          () -> {\n            try {\n              limiter.check(\"test\", \"op\");\n              successCount.incrementAndGet();\n            } catch (RateLimitException e) {\n              failureCount.incrementAndGet();\n            }\n            latch.countDown();\n          });\n    }\n\n    latch.await();\n    assertEquals(requestLimit, successCount.get());\n    assertEquals(threadCount - requestLimit, failureCount.get());\n  }\n\n  @Test\n  void adaptiveLimiterShouldAdjustUnderLoad() throws Exception {\n    AdaptiveRateLimiter limiter = new AdaptiveRateLimiter(10, 20);\n    ExecutorService executor = Executors.newFixedThreadPool(20);\n\n    // Flood with requests to trigger throttling\n    for (int i = 0; i < 30; i++) {\n      executor.submit(\n          () -> {\n            try {\n              limiter.check(\"test\", \"op\");\n            } catch (RateLimitException ignored) {\n            }\n          });\n    }\n\n    Thread.sleep(15000); // Wait for adjustment\n\n    // Verify new limit is in effect\n    int allowed = 0;\n    for (int i = 0; i < 20; i++) {\n      try {\n        limiter.check(\"test\", \"op\");\n        allowed++;\n      } catch (RateLimitException ignored) {\n      }\n    }\n\n    assertTrue(allowed > 5 && allowed < 15); // Should be between initial and max\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/test/java/com/iluwatar/rate/limiting/pattern/ExceptionTests.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass ExceptionTests {\n  @Test\n  void rateLimitExceptionShouldContainRetryInfo() {\n    RateLimitException exception = new RateLimitException(\"Test\", 1000);\n    assertEquals(1000, exception.getRetryAfterMillis());\n    assertEquals(\"Test\", exception.getMessage());\n  }\n\n  @Test\n  void throttlingExceptionShouldContainServiceInfo() {\n    ThrottlingException exception = new ThrottlingException(\"dynamodb\", \"Query\", 500);\n    assertEquals(\"dynamodb\", exception.getServiceName());\n    assertEquals(\"ThrottlingException\", exception.getErrorCode());\n  }\n\n  @Test\n  void serviceUnavailableExceptionShouldContainRetryInfo() {\n    ServiceUnavailableException exception = new ServiceUnavailableException(\"s3\", 2000);\n    assertEquals(\"s3\", exception.getServiceName());\n    assertEquals(2000, exception.getRetryAfterMillis());\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/test/java/com/iluwatar/rate/limiting/pattern/FindCustomerRequestTest.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass FindCustomerRequestTest implements RateLimitOperationTest<String> {\n\n  @Override\n  public RateLimitOperation<String> createOperation(RateLimiter limiter) {\n    return new FindCustomerRequest(\"123\", limiter);\n  }\n\n  @Test\n  void shouldExecuteWhenUnderRateLimit() throws Exception {\n    RateLimiter limiter = new TokenBucketRateLimiter(10, 10);\n    RateLimitOperation<String> request = createOperation(limiter);\n\n    String result = request.execute();\n    assertEquals(\"Customer-123\", result);\n  }\n\n  @Test\n  void shouldThrowWhenRateLimitExceeded() {\n    RateLimiter limiter = new TokenBucketRateLimiter(0, 0); // Always throttled\n    RateLimitOperation<String> request = createOperation(limiter);\n\n    assertThrows(RateLimitException.class, request::execute);\n  }\n\n  @Test\n  void shouldReturnCorrectServiceAndOperationNames() {\n    RateLimiter limiter = new TokenBucketRateLimiter(10, 10);\n    FindCustomerRequest request = new FindCustomerRequest(\"123\", limiter);\n\n    assertEquals(\"CustomerService\", request.getServiceName());\n    assertEquals(\"FindCustomer\", request.getOperationName());\n  }\n\n  // Reuse helper logic from the interface for coverage\n  @Test\n  void shouldExecuteUsingDefaultHelper() throws Exception {\n    RateLimiter limiter = new TokenBucketRateLimiter(5, 5);\n    shouldExecuteWhenUnderLimit(createOperation(limiter));\n  }\n\n  @Test\n  void shouldThrowServiceUnavailableOnInterruptedException() {\n    RateLimiter noOpLimiter = (service, operation) -> {}; // no throttling\n\n    FindCustomerRequest request =\n        new FindCustomerRequest(\"999\", noOpLimiter) {\n          @Override\n          public String execute() throws RateLimitException {\n            Thread.currentThread().interrupt(); // Simulate thread interruption\n            return super.execute(); // Should throw ServiceUnavailableException\n          }\n        };\n\n    assertThrows(ServiceUnavailableException.class, request::execute);\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/test/java/com/iluwatar/rate/limiting/pattern/FixedWindowRateLimiterTest.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.concurrent.TimeUnit;\nimport org.junit.jupiter.api.Test;\n\nclass FixedWindowRateLimiterTest extends RateLimiterTest {\n  @Override\n  protected RateLimiter createRateLimiter(int limit, long windowMillis) {\n    return new FixedWindowRateLimiter(limit, windowMillis / 1000);\n  }\n\n  @Test\n  void shouldResetCounterAfterWindow() throws Exception {\n    FixedWindowRateLimiter limiter =\n        new FixedWindowRateLimiter(1, 1); // 1 request per 1 second window\n\n    // First request should pass\n    limiter.check(\"test\", \"op\");\n\n    // Second request in same window should be throttled\n    assertThrows(RateLimitException.class, () -> limiter.check(\"test\", \"op\"));\n\n    // Wait a bit more than 1 second to ensure window resets\n    TimeUnit.MILLISECONDS.sleep(1100);\n\n    // After window reset, this should pass again\n    limiter.check(\"test\", \"op\");\n  }\n\n  @Test\n  void shouldNotAllowMoreThanLimitInWindow() throws Exception {\n    FixedWindowRateLimiter limiter = new FixedWindowRateLimiter(3, 1);\n    for (int i = 0; i < 3; i++) {\n      limiter.check(\"test\", \"op\");\n    }\n    assertThrows(RateLimitException.class, () -> limiter.check(\"test\", \"op\"));\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/test/java/com/iluwatar/rate/limiting/pattern/RateLimitOperationTest.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\ninterface RateLimitOperationTest<T> {\n\n  RateLimitOperation<T> createOperation(RateLimiter limiter);\n\n  @Test\n  default void shouldThrowWhenRateLimited() {\n    RateLimiter limiter = new TokenBucketRateLimiter(0, 0); // Always throttled\n    RateLimitOperation<T> operation = createOperation(limiter);\n    assertThrows(RateLimitException.class, operation::execute);\n  }\n\n  // ✅ No @Test here, just a helper method\n  default void shouldExecuteWhenUnderLimit(RateLimitOperation<T> operation) throws Exception {\n    assertNotNull(operation.execute());\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/test/java/com/iluwatar/rate/limiting/pattern/RateLimiterTest.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\npublic abstract class RateLimiterTest {\n  protected abstract RateLimiter createRateLimiter(int limit, long windowMillis);\n\n  @Test\n  void shouldAllowRequestsWithinLimit() throws Exception {\n    RateLimiter limiter = createRateLimiter(5, 1000);\n    for (int i = 0; i < 5; i++) {\n      limiter.check(\"test\", \"op\");\n    }\n  }\n\n  @Test\n  void shouldThrowWhenLimitExceeded() throws Exception {\n    RateLimiter limiter = createRateLimiter(2, 1000);\n    limiter.check(\"test\", \"op\");\n    limiter.check(\"test\", \"op\");\n    assertThrows(RateLimitException.class, () -> limiter.check(\"test\", \"op\"));\n  }\n}\n"
  },
  {
    "path": "rate-limiting-pattern/src/test/java/com/iluwatar/rate/limiting/pattern/TokenBucketRateLimiterTest.java",
    "content": "package com.iluwatar.rate.limiting.pattern;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.concurrent.TimeUnit;\nimport org.junit.jupiter.api.Test;\n\nclass TokenBucketRateLimiterTest extends RateLimiterTest {\n  @Override\n  protected RateLimiter createRateLimiter(int limit, long windowMillis) {\n    return new TokenBucketRateLimiter(limit, (int) (limit * 1000 / windowMillis));\n  }\n\n  @Test\n  void shouldAllowBurstRequests() throws Exception {\n    TokenBucketRateLimiter limiter = new TokenBucketRateLimiter(10, 5);\n    for (int i = 0; i < 10; i++) {\n      limiter.check(\"test\", \"op\");\n    }\n  }\n\n  @Test\n  void shouldRefillTokensAfterTime() throws Exception {\n    TokenBucketRateLimiter limiter = new TokenBucketRateLimiter(1, 1);\n    limiter.check(\"test\", \"op\");\n    assertThrows(RateLimitException.class, () -> limiter.check(\"test\", \"op\"));\n\n    TimeUnit.SECONDS.sleep(1);\n    limiter.check(\"test\", \"op\");\n  }\n\n  @Test\n  void shouldHandleMultipleServicesSeparately() throws Exception {\n    TokenBucketRateLimiter limiter = new TokenBucketRateLimiter(1, 1);\n    limiter.check(\"service1\", \"op\");\n    limiter.check(\"service2\", \"op\");\n    assertThrows(RateLimitException.class, () -> limiter.check(\"service1\", \"op\"));\n  }\n}\n"
  },
  {
    "path": "reactor/README.md",
    "content": "---\ntitle: \"Reactor Pattern in Java: Mastering Non-blocking Event-Driven Architectures\"\nshortTitle: Reactor\ndescription: \"Explore the Reactor pattern in Java: Learn how this concurrency model handles multiple simultaneous I/O operations using a single thread for improved performance and scalability. Ideal for developers building high-performance network applications.\"\ncategory: Concurrency\nlanguage: en\ntag:\n  - Asynchronous\n  - Event-driven\n  - Fault tolerance\n  - Messaging\n  - Reactive\n  - Scalability\n  - Synchronization\n  - Thread management\n---\n\n## Also known as\n\n* Dispatcher\n* Notifier\n\n## Intent of Reactor Design Pattern\n\nThe Reactor pattern is designed to handle concurrent service requests efficiently, using a single or limited number of threads, making it a cornerstone for asynchronous, event-driven systems.\n\n## Detailed Explanation of Reactor Pattern with Real-World Examples\n\nReal-world example\n\n> This design pattern is analogous to a head chef in a busy kitchen, demonstrating its ability to manage high-scalability demands and maintain efficient task distribution in multithreaded environments. Instead of each chef handling one order at a time, there is a head chef who acts as the dispatcher. The head chef receives all the orders and decides which chef will handle which part of each order, ensuring that all chefs are utilized efficiently. This way, the kitchen can handle many orders simultaneously, ensuring that dishes are prepared quickly and efficiently without any one chef becoming a bottleneck. This setup is analogous to the Reactor pattern, where the head chef dispatches tasks (events) to various chefs (event handlers) to process multiple tasks concurrently.\n\nIn plain words\n\n> The Reactor pattern efficiently handles multiple concurrent service requests by dispatching them to appropriate event handlers using a single or a limited number of threads.\n\nWikipedia says\n\n> The reactor software design pattern is an event handling strategy that can respond to many potential service requests concurrently. The pattern's key component is an event loop, running in a single thread or process, which demultiplexes incoming requests and dispatches them to the correct request handler.\n\nSequence diagram\n\n![Reactor Sequence diagram](./etc/reactor-sequence-diagram.png)\n\n## Programmatic Example of Reactor Pattern in Java\n\nThe Reactor design pattern is a concurrency model that efficiently handles multiple simultaneous I/O operations using a single or a limited number of threads. It is particularly useful in scenarios where an application needs to handle multiple clients sending service requests concurrently.\n\nIn the given code, the Reactor pattern is implemented using Java's NIO (Non-blocking I/O) framework. The key components of this pattern in the code are:\n\n1. **Reactor**: This is the event loop that demultiplexes the incoming requests and dispatches them to the appropriate handlers. In our example, `NioReactor` is the reactor.\n\n2. **Dispatcher**: This is responsible for managing the execution of the tasks that are triggered by the events. In our example, `Dispatcher` is the dispatcher and `ThreadPoolDispatcher` is a concrete implementation of it.\n\n3. **Handles**: These are resources that are managed by the reactor. They are associated with specific events and are used by the reactor to identify the event handlers to which the events should be dispatched. In our example, `AbstractNioChannel` represents a handle.\n\n4. **Event Handlers**: These are associated with specific handles and are responsible for handling the events that occur on those handles. In our example, `ChannelHandler` is an event handler and `LoggingHandler` is a concrete implementation of it.\n\n5. **Synchronous Event Demultiplexer**: This is a system-level component (not shown in the code) that provides a blocking call that waits for events to occur on any of the handles. In our example, this is part of the Java NIO framework.\n\n6. **Concrete Event Handlers**: These are application-specific implementations of the event handlers. In our example, `LoggingHandler` is a concrete event handler.\n\n7. **Initiation Dispatcher**: This is a component that initializes the association between event handlers and handles. In our example, this is done by the `registerChannel` method in the `NioReactor` class.\n\n**Part 1: Creating the Dispatcher**\n\nThe first part of our example involves creating a dispatcher. The dispatcher is responsible for managing the execution of the tasks that are triggered by the events.\n\n```java\n// Create a dispatcher\nDispatcher dispatcher = new ThreadPoolDispatcher(2);\n```\n\nIn this snippet, we're creating a `ThreadPoolDispatcher` with 2 threads. This dispatcher will use a thread pool to execute the tasks.\n\n**Part 2: Creating the Reactor**\n\nNext, we create a reactor with the dispatcher. The reactor is the core component of the Reactor pattern. It waits for events on multiple channels registered to it in an event loop and dispatches them to the appropriate handlers.\n\n```java\n// Create a reactor with the dispatcher\nNioReactor reactor = new NioReactor(dispatcher);\n```\n\nHere, we're creating a `NioReactor` and passing the dispatcher we created earlier to its constructor.\n\n**Part 3: Creating the Handler**\n\nNow, we create a handler for handling events. The handler is responsible for processing the events that occur on the channels.\n\n```java\n// Create a handler for handling events\nChannelHandler loggingHandler = new LoggingHandler();\n```\n\nIn this snippet, we're creating a `LoggingHandler`. This handler will log the events that occur on the channels.\n\n**Part 4: Registering Channels with the Reactor**\n\nNext, we register channels with the reactor. These channels are the sources of the events that the reactor will handle.\n\n```java\n// Register channels with the reactor\nreactor.registerChannel(new NioServerSocketChannel(16666, loggingHandler));\nreactor.registerChannel(new NioDatagramChannel(16668, loggingHandler));\n```\n\nHere, we're registering a `NioServerSocketChannel` and a `NioDatagramChannel` with the reactor. These channels are associated with the `LoggingHandler` we created earlier.\n\n**Part 5: Starting the Reactor**\n\nFinally, we start the reactor. Once started, the reactor begins to listen for events on the registered channels.\n\n```java\n// Start the reactor\nreactor.start();\n```\n\nIn this snippet, we're starting the reactor. From this point on, the reactor will start handling events from the registered channels.\n\n**Part 6: Creating the App Class**\n\nThe `App` class is the entry point of our application. It creates the reactor, registers the channels, and starts the reactor.\n\n```java\npublic class App {\n\n    public static void main(String[] args) {\n        // Create a dispatcher\n        Dispatcher dispatcher = new ThreadPoolDispatcher(2);\n\n        // Create a reactor with the dispatcher\n        NioReactor reactor = new NioReactor(dispatcher);\n\n        // Create a handler for handling events\n        ChannelHandler loggingHandler = new LoggingHandler();\n\n        // Register channels with the reactor\n        reactor.registerChannel(new NioServerSocketChannel(16666, loggingHandler));\n        reactor.registerChannel(new NioDatagramChannel(16668, loggingHandler));\n\n        // Start the reactor\n        reactor.start();\n    }\n}\n```\n\nIn this snippet, we're creating an instance of the `App` class. Inside the `main` method, we're following the same steps as before: creating a dispatcher, creating a reactor with the dispatcher, creating a handler, registering channels with the reactor, and finally starting the reactor.\n\nThis `App` class demonstrates how an application interacts with the reactor. It sets up the necessary components (dispatcher, reactor, handler, channels) and starts the reactor. Once the reactor is started, it will handle events from the registered channels using the specified handler.\n\nRunning the code produces the following output:\n\n```\n09:50:08.317 [main] INFO com.iluwatar.reactor.framework.NioServerSocketChannel -- Bound TCP socket at port: 16666\n09:50:08.320 [main] INFO com.iluwatar.reactor.framework.NioServerSocketChannel -- Bound TCP socket at port: 16667\n09:50:08.323 [main] INFO com.iluwatar.reactor.framework.NioDatagramChannel -- Bound UDP socket at port: 16668\n09:50:08.324 [main] INFO com.iluwatar.reactor.framework.NioDatagramChannel -- Bound UDP socket at port: 16669\n09:50:08.324 [pool-2-thread-1] INFO com.iluwatar.reactor.framework.NioReactor -- Reactor started, waiting for events...\n```\n\nThis concludes our detailed explanation of the Reactor design pattern. The Reactor pattern allows us to handle multiple simultaneous I/O operations efficiently using a single or a limited number of threads.\n\n## When to Use the Reactor Pattern in Java\n\nEmploy the Reactor pattern in scenarios requiring low-latency and high-throughput in server-side applications, making it an essential strategy for modern networking frameworks and web servers.\n\n## Real-World Applications of Reactor Pattern in Java\n\n* Netty: An asynchronous event-driven network application framework for rapid development of maintainable high-performance protocol servers and clients.\n* Akka: A toolkit and runtime for building concurrent, distributed, and fault-tolerant applications on the JVM.\n* Java NIO (New I/O): Provides non-blocking I/O operations, allowing a single thread to manage multiple channels.\n\n## Benefits and Trade-offs of Reactor Pattern\n\nBenefits:\n\n* Improves application performance by efficiently handling multiple simultaneous connections.\n* Reduces resource consumption by using a small number of threads to handle many I/O operations.\n* Enhances scalability by allowing applications to serve many clients with minimal threads.\n\nTrade-offs:\n\n* Increased complexity in managing state and event handling.\n* Debugging and maintaining asynchronous code can be challenging.\n* Potential difficulty in ensuring thread safety and avoiding race conditions.\n\n## Related Java Design Patterns\n\n* [Observer](https://java-design-patterns.com/patterns/observer/): Reactor uses the Observer pattern for handling events where event handlers are notified of changes.\n* Proactor: Similar to Reactor but handles asynchronous I/O completion rather than readiness.\n* [Command](https://java-design-patterns.com/patterns/command/): Encapsulates a request as an object, allowing parameterization and queuing of requests.\n  \n## References and Credits\n\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n* [Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects](https://amzn.to/3UgC24V)\n* [Reactive Programming with RxJava: Creating Asynchronous, Event-Based Applications](https://amzn.to/4dNTLJC)\n* [Scalable IO in Java - Doug Lea](http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf)\n* [Reactor - An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events (Douglas C. Schmidt)](https://www.dre.vanderbilt.edu/~schmidt/PDF/Reactor.pdf)\n"
  },
  {
    "path": "reactor/etc/reactor.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"true\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"java.nio.channels.Selector\" project=\"abstract-factory\" \n    file=\"/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"224\" width=\"188\" x=\"1120\" y=\"-50\"/>    \n    <display autosize=\"false\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"false\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.reactor.framework.NioReactor\" project=\"reactor\" \n    file=\"/reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"760\" y=\"19\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"3\" language=\"java\" name=\"com.iluwatar.reactor.framework.Dispatcher\" project=\"reactor\" \n    file=\"/reactor/src/main/java/com/iluwatar/reactor/framework/Dispatcher.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"569\" y=\"279\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.reactor.framework.SameThreadDispatcher\" project=\"reactor\" \n    file=\"/reactor/src/main/java/com/iluwatar/reactor/framework/SameThreadDispatcher.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"291\" y=\"562\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.reactor.framework.ThreadPoolDispatcher\" project=\"reactor\" \n    file=\"/reactor/src/main/java/com/iluwatar/reactor/framework/ThreadPoolDispatcher.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"115\" width=\"356\" x=\"341\" y=\"375\"/>    \n    <display autosize=\"false\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.reactor.framework.AbstractNioChannel\" project=\"reactor\" \n    file=\"/reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"935\" y=\"265\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.reactor.framework.NioServerSocketChannel\" project=\"reactor\" \n    file=\"/reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"836\" y=\"543\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.reactor.framework.NioDatagramChannel\" project=\"reactor\" \n    file=\"/reactor/src/main/java/com/iluwatar/reactor/framework/NioDatagramChannel.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1110\" y=\"539\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"9\" language=\"java\" name=\"java.nio.channels.ServerSocketChannel\" project=\"abstract-factory\" \n    file=\"/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"609\" y=\"540\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"false\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"false\" package=\"true\" protected=\"false\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"10\" language=\"java\" name=\"java.nio.channels.DatagramChannel\" project=\"abstract-factory\" \n    file=\"/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar\" binary=\"true\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1202\" y=\"395\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"false\" package=\"true\" protected=\"false\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"11\" language=\"java\" name=\"com.iluwatar.reactor.framework.ChannelHandler\" project=\"reactor\" \n    file=\"/reactor/src/main/java/com/iluwatar/reactor/framework/ChannelHandler.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"303\" y=\"-1\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"12\" language=\"java\" name=\"com.iluwatar.reactor.app.LoggingHandler\" project=\"reactor\" \n    file=\"/reactor/src/main/java/com/iluwatar/reactor/app/LoggingHandler.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"297\" y=\"147\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"13\" language=\"java\" name=\"com.iluwatar.reactor.app.App\" project=\"reactor\" \n    file=\"/reactor/src/main/java/com/iluwatar/reactor/app/App.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"133\" width=\"148\" x=\"123\" y=\"266\"/>    \n    <display autosize=\"false\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <association id=\"14\">    \n    <end type=\"SOURCE\" refId=\"13\" navigable=\"false\">      \n      <attribute id=\"15\" name=\"dispatcher\"/>      \n      <multiplicity id=\"16\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"17\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"18\" name=\"selector\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"19\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <dependency id=\"20\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"10\"/>  \n  </dependency>  \n  <generalization id=\"21\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </generalization>  \n  <realization id=\"22\">    \n    <bendpoint x=\"309\" y=\"348\"/>    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </realization>  \n  <dependency id=\"23\">    \n    <end type=\"SOURCE\" refId=\"13\"/>    \n    <end type=\"TARGET\" refId=\"12\"/>  \n  </dependency>  \n  <association id=\"24\">    \n    <end type=\"SOURCE\" refId=\"6\" navigable=\"false\">      \n      <attribute id=\"25\" name=\"handler\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"26\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"11\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <dependency id=\"27\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"9\"/>  \n  </dependency>  \n  <generalization id=\"28\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </generalization>  \n  <association id=\"29\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"30\" name=\"dispatcher\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"31\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"3\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"32\">    \n    <end type=\"SOURCE\" refId=\"12\"/>    \n    <end type=\"TARGET\" refId=\"11\"/>  \n  </realization>  \n  <association id=\"33\">    \n    <bendpoint x=\"460\" y=\"203\"/>    \n    <end type=\"SOURCE\" refId=\"13\" navigable=\"false\">      \n      <attribute id=\"34\" name=\"reactor\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"35\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"36\">    \n    <end type=\"SOURCE\" refId=\"6\" navigable=\"false\">      \n      <attribute id=\"37\" name=\"reactor\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </attribute>      \n      <multiplicity id=\"38\" minimum=\"0\" maximum=\"1\">        \n        <position height=\"0\" width=\"0\" x=\"0\" y=\"0\"/>      \n      </multiplicity>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"39\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "reactor/etc/reactor.urm.puml",
    "content": "@startuml\npackage com.iluwatar.reactor.framework {\n  abstract class AbstractNioChannel {\n    - channel : SelectableChannel\n    - channelToPendingWrites : Map<SelectableChannel, Queue<Object>>\n    - handler : ChannelHandler\n    - reactor : NioReactor\n    + AbstractNioChannel(handler : ChannelHandler, channel : SelectableChannel)\n    + bind() {abstract}\n    # doWrite(Object, SelectionKey) {abstract}\n    ~ flush(key : SelectionKey)\n    + getHandler() : ChannelHandler\n    + getInterestedOps() : int {abstract}\n    + getJavaChannel() : SelectableChannel\n    + read(SelectionKey) : Object {abstract}\n    ~ setReactor(reactor : NioReactor)\n    + write(data : Object, key : SelectionKey)\n  }\n  interface ChannelHandler {\n    + handleChannelRead(AbstractNioChannel, Object, SelectionKey) {abstract}\n  }\n  interface Dispatcher {\n    + onChannelReadEvent(AbstractNioChannel, Object, SelectionKey) {abstract}\n    + stop() {abstract}\n  }\n  class NioDatagramChannel {\n    - LOGGER : Logger {static}\n    - port : int\n    + NioDatagramChannel(port : int, handler : ChannelHandler)\n    + bind()\n    # doWrite(pendingWrite : Object, key : SelectionKey)\n    + getInterestedOps() : int\n    + getJavaChannel() : DatagramChannel\n    + read(key : SelectionKey) : DatagramPacket\n    + write(data : Object, key : SelectionKey)\n  }\n  class DatagramPacket {\n    - data : ByteBuffer\n    - receiver : SocketAddress\n    - sender : SocketAddress\n    + DatagramPacket(data : ByteBuffer)\n    + getData() : ByteBuffer\n    + getReceiver() : SocketAddress\n    + getSender() : SocketAddress\n    + setReceiver(receiver : SocketAddress)\n    + setSender(sender : SocketAddress)\n  }\n  class NioReactor {\n    - LOGGER : Logger {static}\n    - dispatcher : Dispatcher\n    - pendingCommands : Queue<Runnable>\n    - reactorMain : ExecutorService\n    - selector : Selector\n    + NioReactor(dispatcher : Dispatcher)\n    + changeOps(key : SelectionKey, interestedOps : int)\n    - dispatchReadEvent(key : SelectionKey, readObject : Object)\n    - eventLoop()\n    - onChannelAcceptable(key : SelectionKey)\n    - onChannelReadable(key : SelectionKey)\n    - onChannelWritable(key : SelectionKey) {static}\n    - processKey(key : SelectionKey)\n    - processPendingCommands()\n    + registerChannel(channel : AbstractNioChannel) : NioReactor\n    + start()\n    + stop()\n  }\n  ~class ChangeKeyOpsCommand {\n    - interestedOps : int\n    - key : SelectionKey\n    + ChangeKeyOpsCommand(this$0 : SelectionKey, key : int)\n    + run()\n    + toString() : String\n  }\n  class NioServerSocketChannel {\n    - LOGGER : Logger {static}\n    - port : int\n    + NioServerSocketChannel(port : int, handler : ChannelHandler)\n    + bind()\n    # doWrite(pendingWrite : Object, key : SelectionKey)\n    + getInterestedOps() : int\n    + getJavaChannel() : ServerSocketChannel\n    + read(key : SelectionKey) : ByteBuffer\n  }\n  class SameThreadDispatcher {\n    + SameThreadDispatcher()\n    + onChannelReadEvent(channel : AbstractNioChannel, readObject : Object, key : SelectionKey)\n    + stop()\n  }\n  class ThreadPoolDispatcher {\n    - executorService : ExecutorService\n    + ThreadPoolDispatcher(poolSize : int)\n    + onChannelReadEvent(channel : AbstractNioChannel, readObject : Object, key : SelectionKey)\n    + stop()\n  }\n}\npackage com.iluwatar.reactor.app {\n  class App {\n    - channels : List<AbstractNioChannel>\n    - dispatcher : Dispatcher\n    - reactor : NioReactor\n    + App(dispatcher : Dispatcher)\n    + main(args : String[]) {static}\n    + start()\n    + stop()\n    - tcpChannel(port : int, handler : ChannelHandler) : AbstractNioChannel\n    - udpChannel(port : int, handler : ChannelHandler) : AbstractNioChannel\n  }\n  class AppClient {\n    - LOGGER : Logger {static}\n    - service : ExecutorService\n    + AppClient()\n    - artificialDelayOf(millis : long) {static}\n    + main(args : String[]) {static}\n    + start()\n    + stop()\n  }\n  ~class TcpLoggingClient {\n    - clientName : String\n    - serverPort : int\n    + TcpLoggingClient(clientName : String, serverPort : int)\n    + run()\n    - sendLogRequests(writer : PrintWriter, inputStream : InputStream)\n  }\n  ~class UdpLoggingClient {\n    - clientName : String\n    - remoteAddress : InetSocketAddress\n    + UdpLoggingClient(clientName : String, port : int)\n    + run()\n  }\n  class LoggingHandler {\n    - ACK : byte[] {static}\n    - LOGGER : Logger {static}\n    + LoggingHandler()\n    - doLogging(data : ByteBuffer) {static}\n    + handleChannelRead(channel : AbstractNioChannel, readObject : Object, key : SelectionKey)\n    - sendReply(channel : AbstractNioChannel, incomingPacket : DatagramPacket, key : SelectionKey) {static}\n    - sendReply(channel : AbstractNioChannel, key : SelectionKey) {static}\n  }\n}\nAbstractNioChannel -->  \"-handler\" ChannelHandler\nUdpLoggingClient ..+ AppClient\nTcpLoggingClient ..+ AppClient\nAbstractNioChannel -->  \"-reactor\" NioReactor\nNioReactor -->  \"-dispatcher\" Dispatcher\nApp -->  \"-reactor\" NioReactor\nApp -->  \"-channels\" AbstractNioChannel\nDatagramPacket ..+ NioDatagramChannel\nApp -->  \"-dispatcher\" Dispatcher\nChangeKeyOpsCommand --+ NioReactor\nLoggingHandler ..|> ChannelHandler \nNioDatagramChannel --|> AbstractNioChannel \nNioServerSocketChannel --|> AbstractNioChannel \nSameThreadDispatcher ..|> Dispatcher \nThreadPoolDispatcher ..|> Dispatcher \n@enduml"
  },
  {
    "path": "reactor/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>reactor</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.reactor.app.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "reactor/src/main/java/com/iluwatar/reactor/app/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.reactor.app;\n\nimport com.iluwatar.reactor.framework.AbstractNioChannel;\nimport com.iluwatar.reactor.framework.ChannelHandler;\nimport com.iluwatar.reactor.framework.Dispatcher;\nimport com.iluwatar.reactor.framework.NioDatagramChannel;\nimport com.iluwatar.reactor.framework.NioReactor;\nimport com.iluwatar.reactor.framework.NioServerSocketChannel;\nimport com.iluwatar.reactor.framework.ThreadPoolDispatcher;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * This application demonstrates Reactor pattern. The example demonstrated is a Distributed Logging\n * Service where it listens on multiple TCP or UDP sockets for incoming log requests.\n *\n * <p><i>INTENT</i> <br>\n * The Reactor design pattern handles service requests that are delivered concurrently to an\n * application by one or more clients. The application can register specific handlers for processing\n * which are called by reactor on specific events.\n *\n * <p><i>PROBLEM</i> <br>\n * Server applications in a distributed system must handle multiple clients that send them service\n * requests. Following forces need to be resolved:\n *\n * <ul>\n *   <li>Availability\n *   <li>Efficiency\n *   <li>Programming Simplicity\n *   <li>Adaptability\n * </ul>\n *\n * <p><i>PARTICIPANTS</i> <br>\n *\n * <ul>\n *   <li>Synchronous Event De-multiplexer\n *       <p>{@link NioReactor} plays the role of synchronous event de-multiplexer. It waits for\n *       events on multiple channels registered to it in an event loop.\n *   <li>Initiation Dispatcher\n *       <p>{@link NioReactor} plays this role as the application specific {@link ChannelHandler}s\n *       are registered to the reactor.\n *   <li>Handle\n *       <p>{@link AbstractNioChannel} acts as a handle that is registered to the reactor. When any\n *       events occur on a handle, reactor calls the appropriate handler.\n *   <li>Event Handler\n *       <p>{@link ChannelHandler} acts as an event handler, which is bound to a channel and is\n *       called back when any event occurs on any of its associated handles. Application logic\n *       resides in event handlers.\n * </ul>\n *\n * The application utilizes single thread to listen for requests on all ports. It does not create a\n * separate thread for each client, which provides better scalability under load (number of clients\n * increase). The example uses Java NIO framework to implement the Reactor.\n */\npublic class App {\n\n  private NioReactor reactor;\n  private final List<AbstractNioChannel> channels = new ArrayList<>();\n  private final Dispatcher dispatcher;\n\n  /**\n   * Creates an instance of App which will use provided dispatcher for dispatching events on\n   * reactor.\n   *\n   * @param dispatcher the dispatcher that will be used to dispatch events.\n   */\n  public App(Dispatcher dispatcher) {\n    this.dispatcher = dispatcher;\n  }\n\n  /** App entry. */\n  public static void main(String[] args) throws IOException {\n    new App(new ThreadPoolDispatcher(2)).start();\n  }\n\n  /**\n   * Starts the NIO reactor.\n   *\n   * @throws IOException if any channel fails to bind.\n   */\n  public void start() throws IOException {\n    /*\n     * The application can customize its event dispatching mechanism.\n     */\n    reactor = new NioReactor(dispatcher);\n\n    /*\n     * This represents application specific business logic that dispatcher will call on appropriate\n     * events. These events are read events in our example.\n     */\n    var loggingHandler = new LoggingHandler();\n\n    /*\n     * Our application binds to multiple channels and uses same logging handler to handle incoming\n     * log requests.\n     */\n    reactor\n        .registerChannel(tcpChannel(16666, loggingHandler))\n        .registerChannel(tcpChannel(16667, loggingHandler))\n        .registerChannel(udpChannel(16668, loggingHandler))\n        .registerChannel(udpChannel(16669, loggingHandler))\n        .start();\n  }\n\n  /**\n   * Stops the NIO reactor. This is a blocking call.\n   *\n   * @throws InterruptedException if interrupted while stopping the reactor.\n   * @throws IOException if any I/O error occurs\n   */\n  public void stop() throws InterruptedException, IOException {\n    reactor.stop();\n    dispatcher.stop();\n    for (var channel : channels) {\n      channel.getJavaChannel().close();\n    }\n  }\n\n  private AbstractNioChannel tcpChannel(int port, ChannelHandler handler) throws IOException {\n    var channel = new NioServerSocketChannel(port, handler);\n    channel.bind();\n    channels.add(channel);\n    return channel;\n  }\n\n  private AbstractNioChannel udpChannel(int port, ChannelHandler handler) throws IOException {\n    var channel = new NioDatagramChannel(port, handler);\n    channel.bind();\n    channels.add(channel);\n    return channel;\n  }\n}\n"
  },
  {
    "path": "reactor/src/main/java/com/iluwatar/reactor/app/AppClient.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.reactor.app;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.PrintWriter;\nimport java.net.DatagramPacket;\nimport java.net.DatagramSocket;\nimport java.net.InetAddress;\nimport java.net.InetSocketAddress;\nimport java.net.Socket;\nimport java.net.UnknownHostException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Represents the clients of Reactor pattern. Multiple clients are run concurrently and send logging\n * requests to Reactor.\n */\n@Slf4j\npublic class AppClient {\n\n  private final ExecutorService service = Executors.newFixedThreadPool(4);\n\n  /**\n   * App client entry.\n   *\n   * @throws IOException if any I/O error occurs.\n   */\n  public static void main(String[] args) throws IOException {\n    var appClient = new AppClient();\n    appClient.start();\n  }\n\n  /**\n   * Starts the logging clients.\n   *\n   * @throws IOException if any I/O error occurs.\n   */\n  public void start() throws IOException {\n    LOGGER.info(\"Starting logging clients\");\n    service.execute(new TcpLoggingClient(\"Client 1\", 16666));\n    service.execute(new TcpLoggingClient(\"Client 2\", 16667));\n    service.execute(new UdpLoggingClient(\"Client 3\", 16668));\n    service.execute(new UdpLoggingClient(\"Client 4\", 16669));\n  }\n\n  /** Stops logging clients. This is a blocking call. */\n  public void stop() {\n    service.shutdown();\n    if (!service.isTerminated()) {\n      service.shutdownNow();\n      try {\n        service.awaitTermination(1000, TimeUnit.SECONDS);\n      } catch (InterruptedException e) {\n        LOGGER.error(\"exception awaiting termination\", e);\n      }\n    }\n    LOGGER.info(\"Logging clients stopped\");\n  }\n\n  private static void artificialDelayOf(long millis) {\n    try {\n      Thread.sleep(millis);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"sleep interrupted\", e);\n    }\n  }\n\n  /** A logging client that sends requests to Reactor on TCP socket. */\n  static class TcpLoggingClient implements Runnable {\n\n    private final int serverPort;\n    private final String clientName;\n\n    /**\n     * Creates a new TCP logging client.\n     *\n     * @param clientName the name of the client to be sent in logging requests.\n     * @param serverPort the port on which client will send logging requests.\n     */\n    public TcpLoggingClient(String clientName, int serverPort) {\n      this.clientName = clientName;\n      this.serverPort = serverPort;\n    }\n\n    @Override\n    public void run() {\n      try (var socket = new Socket(InetAddress.getLocalHost(), serverPort)) {\n        var outputStream = socket.getOutputStream();\n        var writer = new PrintWriter(outputStream);\n        sendLogRequests(writer, socket.getInputStream());\n      } catch (IOException e) {\n        LOGGER.error(\"error sending requests\", e);\n        throw new RuntimeException(e);\n      }\n    }\n\n    private void sendLogRequests(PrintWriter writer, InputStream inputStream) throws IOException {\n      for (var i = 0; i < 4; i++) {\n        writer.println(clientName + \" - Log request: \" + i);\n        writer.flush();\n\n        var data = new byte[1024];\n        var read = inputStream.read(data, 0, data.length);\n        if (read == 0) {\n          LOGGER.info(\"Read zero bytes\");\n        } else {\n          LOGGER.info(new String(data, 0, read));\n        }\n\n        artificialDelayOf(100);\n      }\n    }\n  }\n\n  /** A logging client that sends requests to Reactor on UDP socket. */\n  static class UdpLoggingClient implements Runnable {\n    private final String clientName;\n    private final InetSocketAddress remoteAddress;\n\n    /**\n     * Creates a new UDP logging client.\n     *\n     * @param clientName the name of the client to be sent in logging requests.\n     * @param port the port on which client will send logging requests.\n     * @throws UnknownHostException if localhost is unknown\n     */\n    public UdpLoggingClient(String clientName, int port) throws UnknownHostException {\n      this.clientName = clientName;\n      this.remoteAddress = new InetSocketAddress(InetAddress.getLocalHost(), port);\n    }\n\n    @Override\n    public void run() {\n      try (var socket = new DatagramSocket()) {\n        for (var i = 0; i < 4; i++) {\n\n          var message = clientName + \" - Log request: \" + i;\n          var bytes = message.getBytes();\n          var request = new DatagramPacket(bytes, bytes.length, remoteAddress);\n\n          socket.send(request);\n\n          var data = new byte[1024];\n          var reply = new DatagramPacket(data, data.length);\n          socket.receive(reply);\n          if (reply.getLength() == 0) {\n            LOGGER.info(\"Read zero bytes\");\n          } else {\n            LOGGER.info(new String(reply.getData(), 0, reply.getLength()));\n          }\n\n          artificialDelayOf(100);\n        }\n      } catch (IOException e1) {\n        LOGGER.error(\"error sending packets\", e1);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "reactor/src/main/java/com/iluwatar/reactor/app/LoggingHandler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.reactor.app;\n\nimport com.iluwatar.reactor.framework.AbstractNioChannel;\nimport com.iluwatar.reactor.framework.ChannelHandler;\nimport com.iluwatar.reactor.framework.NioDatagramChannel.DatagramPacket;\nimport java.nio.ByteBuffer;\nimport java.nio.channels.SelectionKey;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Logging server application logic. It logs the incoming requests on standard console and returns a\n * canned acknowledgement back to the remote peer.\n */\n@Slf4j\npublic class LoggingHandler implements ChannelHandler {\n\n  private static final byte[] ACK = \"Data logged successfully\".getBytes();\n\n  /** Decodes the received data and logs it on standard console. */\n  @Override\n  public void handleChannelRead(AbstractNioChannel channel, Object readObject, SelectionKey key) {\n    /*\n     * As this handler is attached with both TCP and UDP channels we need to check whether the data\n     * received is a ByteBuffer (from TCP channel) or a DatagramPacket (from UDP channel).\n     */\n    if (readObject instanceof ByteBuffer) {\n      doLogging((ByteBuffer) readObject);\n      sendReply(channel, key);\n    } else if (readObject instanceof DatagramPacket datagram) {\n      doLogging(datagram.getData());\n      sendReply(channel, datagram, key);\n    } else {\n      throw new IllegalStateException(\"Unknown data received\");\n    }\n  }\n\n  private static void sendReply(\n      AbstractNioChannel channel, DatagramPacket incomingPacket, SelectionKey key) {\n    /*\n     * Create a reply acknowledgement datagram packet setting the receiver to the sender of incoming\n     * message.\n     */\n    var replyPacket = new DatagramPacket(ByteBuffer.wrap(ACK));\n    replyPacket.setReceiver(incomingPacket.getSender());\n\n    channel.write(replyPacket, key);\n  }\n\n  private static void sendReply(AbstractNioChannel channel, SelectionKey key) {\n    var buffer = ByteBuffer.wrap(ACK);\n    channel.write(buffer, key);\n  }\n\n  private static void doLogging(ByteBuffer data) {\n    // assuming UTF-8 :(\n    LOGGER.info(new String(data.array(), 0, data.limit()));\n  }\n}\n"
  },
  {
    "path": "reactor/src/main/java/com/iluwatar/reactor/framework/AbstractNioChannel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.reactor.framework;\n\nimport java.io.IOException;\nimport java.nio.channels.SelectableChannel;\nimport java.nio.channels.SelectionKey;\nimport java.nio.channels.Selector;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport lombok.Getter;\n\n/**\n * This represents the <i>Handle</i> of Reactor pattern. These are resources managed by OS which can\n * be submitted to {@link NioReactor}.\n *\n * <p>This class serves has the responsibility of reading the data when a read event occurs and\n * writing the data back when the channel is writable. It leaves the reading and writing of data on\n * the concrete implementation. It provides a block writing mechanism wherein when any {@link\n * ChannelHandler} wants to write data back, it queues the data in pending write queue and clears it\n * in block manner. This provides better throughput.\n */\npublic abstract class AbstractNioChannel {\n\n  private final SelectableChannel channel;\n  @Getter private final ChannelHandler handler;\n  private final Map<SelectableChannel, Queue<Object>> channelToPendingWrites;\n  private NioReactor reactor;\n\n  /**\n   * Creates a new channel.\n   *\n   * @param handler which will handle events occurring on this channel.\n   * @param channel a NIO channel to be wrapped.\n   */\n  public AbstractNioChannel(ChannelHandler handler, SelectableChannel channel) {\n    this.handler = handler;\n    this.channel = channel;\n    this.channelToPendingWrites = new ConcurrentHashMap<>();\n  }\n\n  /** Injects the reactor in this channel. */\n  void setReactor(NioReactor reactor) {\n    this.reactor = reactor;\n  }\n\n  /**\n   * Get channel.\n   *\n   * @return the wrapped NIO channel.\n   */\n  public SelectableChannel getJavaChannel() {\n    return channel;\n  }\n\n  /**\n   * The operation in which the channel is interested, this operation is provided to {@link\n   * Selector}.\n   *\n   * @return interested operation.\n   * @see SelectionKey\n   */\n  public abstract int getInterestedOps();\n\n  /**\n   * Binds the channel on provided port.\n   *\n   * @throws IOException if any I/O error occurs.\n   */\n  public abstract void bind() throws IOException;\n\n  /**\n   * Reads the data using the key and returns the read data. The underlying channel should be\n   * fetched using {@link SelectionKey#channel()}.\n   *\n   * @param key the key on which read event occurred.\n   * @return data read.\n   * @throws IOException if any I/O error occurs.\n   */\n  public abstract Object read(SelectionKey key) throws IOException;\n\n  /*\n   * Called from the context of reactor thread when the key becomes writable. The channel writes the\n   * whole pending block of data at once.\n   */\n  void flush(SelectionKey key) throws IOException {\n    var pendingWrites = channelToPendingWrites.get(key.channel());\n    Object pendingWrite;\n    while ((pendingWrite = pendingWrites.poll()) != null) {\n      // ask the concrete channel to make sense of data and write it to java channel\n      doWrite(pendingWrite, key);\n    }\n    // We don't have anything more to write so channel is interested in reading more data\n    reactor.changeOps(key, SelectionKey.OP_READ);\n  }\n\n  /**\n   * Writes the data to the channel.\n   *\n   * @param pendingWrite the data to be written on channel.\n   * @param key the key which is writable.\n   * @throws IOException if any I/O error occurs.\n   */\n  protected abstract void doWrite(Object pendingWrite, SelectionKey key) throws IOException;\n\n  /**\n   * Queues the data for writing. The data is not guaranteed to be written on underlying channel\n   * when this method returns. It will be written when the channel is flushed.\n   *\n   * <p>This method is used by the {@link ChannelHandler} to send reply back to the client. <br>\n   * Example:\n   *\n   * <pre>\n   * <code>\n   * {@literal @}Override\n   * public void handleChannelRead(AbstractNioChannel channel, Object readObj, SelectionKey key) {\n   *   byte[] data = ((ByteBuffer)readObj).array();\n   *   ByteBuffer buffer = ByteBuffer.wrap(\"Server reply\".getBytes());\n   *   channel.write(buffer, key);\n   * }\n   * </code>\n   * </pre>\n   *\n   * @param data the data to be written on underlying channel.\n   * @param key the key which is writable.\n   */\n  public void write(Object data, SelectionKey key) {\n    var pendingWrites = this.channelToPendingWrites.get(key.channel());\n    if (pendingWrites == null) {\n      synchronized (this.channelToPendingWrites) {\n        pendingWrites =\n            this.channelToPendingWrites.computeIfAbsent(\n                key.channel(), k -> new ConcurrentLinkedQueue<>());\n      }\n    }\n    pendingWrites.add(data);\n    reactor.changeOps(key, SelectionKey.OP_WRITE);\n  }\n}\n"
  },
  {
    "path": "reactor/src/main/java/com/iluwatar/reactor/framework/ChannelHandler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.reactor.framework;\n\nimport java.nio.channels.SelectionKey;\n\n/**\n * Represents the <i>EventHandler</i> of Reactor pattern. It handles the incoming events dispatched\n * to it by the {@link Dispatcher}. This is where the application logic resides.\n *\n * <p>A {@link ChannelHandler} can be associated with one or many {@link AbstractNioChannel}s, and\n * whenever an event occurs on any of the associated channels, the handler is notified of the event.\n */\npublic interface ChannelHandler {\n\n  /**\n   * Called when the {@code channel} receives some data from remote peer.\n   *\n   * @param channel the channel from which the data was received.\n   * @param readObject the data read.\n   * @param key the key on which read event occurred.\n   */\n  void handleChannelRead(AbstractNioChannel channel, Object readObject, SelectionKey key);\n}\n"
  },
  {
    "path": "reactor/src/main/java/com/iluwatar/reactor/framework/Dispatcher.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.reactor.framework;\n\nimport java.nio.channels.SelectionKey;\n\n/**\n * Represents the event dispatching strategy. When {@link NioReactor} senses any event on the\n * registered {@link AbstractNioChannel}s then it de-multiplexes the event type, read or write or\n * connect, and then calls the {@link Dispatcher} to dispatch the read events. This decouples the\n * I/O processing from application specific processing. <br>\n * Dispatcher should call the {@link ChannelHandler} associated with the channel on which event\n * occurred.\n *\n * <p>The application can customize the way in which event is dispatched such as using the reactor\n * thread to dispatch event to channels or use a worker pool to do the non I/O processing.\n *\n * @see SameThreadDispatcher\n * @see ThreadPoolDispatcher\n */\npublic interface Dispatcher {\n  /**\n   * This hook method is called when read event occurs on particular channel. The data read is\n   * provided in <code>readObject</code>. The implementation should dispatch this read event to the\n   * associated {@link ChannelHandler} of <code>channel</code>.\n   *\n   * <p>The type of <code>readObject</code> depends on the channel on which data was received.\n   *\n   * @param channel on which read event occurred\n   * @param readObject object read by channel\n   * @param key on which event occurred\n   */\n  void onChannelReadEvent(AbstractNioChannel channel, Object readObject, SelectionKey key);\n\n  /**\n   * Stops dispatching events and cleans up any acquired resources such as threads.\n   *\n   * @throws InterruptedException if interrupted while stopping dispatcher.\n   */\n  void stop() throws InterruptedException;\n}\n"
  },
  {
    "path": "reactor/src/main/java/com/iluwatar/reactor/framework/NioDatagramChannel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.reactor.framework;\n\nimport java.io.IOException;\nimport java.net.InetAddress;\nimport java.net.InetSocketAddress;\nimport java.net.SocketAddress;\nimport java.nio.ByteBuffer;\nimport java.nio.channels.DatagramChannel;\nimport java.nio.channels.SelectionKey;\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\n\n/** A wrapper over {@link DatagramChannel} which can read and write data on a DatagramChannel. */\n@Slf4j\npublic class NioDatagramChannel extends AbstractNioChannel {\n\n  private final int port;\n\n  /**\n   * Creates a {@link DatagramChannel} which will bind at provided port and use <code>handler</code>\n   * to handle incoming events on this channel.\n   *\n   * <p>Note the constructor does not bind the socket, {@link #bind()} method should be called for\n   * binding the socket.\n   *\n   * @param port the port to be bound to listen for incoming datagram requests.\n   * @param handler the handler to be used for handling incoming requests on this channel.\n   * @throws IOException if any I/O error occurs.\n   */\n  public NioDatagramChannel(int port, ChannelHandler handler) throws IOException {\n    super(handler, DatagramChannel.open());\n    this.port = port;\n  }\n\n  @Override\n  public int getInterestedOps() {\n    /*\n     * there is no need to accept connections in UDP, so the channel shows interest in reading data.\n     */\n    return SelectionKey.OP_READ;\n  }\n\n  /**\n   * Reads and returns a {@link DatagramPacket} from the underlying channel.\n   *\n   * @return the datagram packet read having the sender address.\n   */\n  @Override\n  public DatagramPacket read(SelectionKey key) throws IOException {\n    var buffer = ByteBuffer.allocate(1024);\n    var sender = ((DatagramChannel) key.channel()).receive(buffer);\n\n    /*\n     * It is required to create a DatagramPacket because we need to preserve which socket address\n     * acts as destination for sending reply packets.\n     */\n    buffer.flip();\n    var packet = new DatagramPacket(buffer);\n    packet.setSender(sender);\n\n    return packet;\n  }\n\n  /**\n   * Get datagram channel.\n   *\n   * @return the underlying datagram channel.\n   */\n  @Override\n  public DatagramChannel getJavaChannel() {\n    return (DatagramChannel) super.getJavaChannel();\n  }\n\n  /**\n   * Binds UDP socket on the provided <code>port</code>.\n   *\n   * @throws IOException if any I/O error occurs.\n   */\n  @Override\n  public void bind() throws IOException {\n    getJavaChannel().socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), port));\n    getJavaChannel().configureBlocking(false);\n    LOGGER.info(\"Bound UDP socket at port: {}\", port);\n  }\n\n  /**\n   * Writes the pending {@link DatagramPacket} to the underlying channel sending data to the\n   * intended receiver of the packet.\n   */\n  @Override\n  protected void doWrite(Object pendingWrite, SelectionKey key) throws IOException {\n    var pendingPacket = (DatagramPacket) pendingWrite;\n    getJavaChannel().send(pendingPacket.getData(), pendingPacket.getReceiver());\n  }\n\n  /**\n   * Writes the outgoing {@link DatagramPacket} to the channel. The intended receiver of the\n   * datagram packet must be set in the <code>data</code> using {@link\n   * DatagramPacket#setReceiver(SocketAddress)}.\n   */\n  @Override\n  public void write(Object data, SelectionKey key) {\n    super.write(data, key);\n  }\n\n  /** Container of data used for {@link NioDatagramChannel} to communicate with remote peer. */\n  @Getter\n  public static class DatagramPacket {\n    private final ByteBuffer data;\n    @Setter private SocketAddress sender;\n    @Setter private SocketAddress receiver;\n\n    /**\n     * Creates a container with underlying data.\n     *\n     * @param data the underlying message to be written on channel.\n     */\n    public DatagramPacket(ByteBuffer data) {\n      this.data = data;\n    }\n  }\n}\n"
  },
  {
    "path": "reactor/src/main/java/com/iluwatar/reactor/framework/NioReactor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.reactor.framework;\n\nimport java.io.IOException;\nimport java.nio.channels.SelectionKey;\nimport java.nio.channels.Selector;\nimport java.nio.channels.ServerSocketChannel;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This class acts as Synchronous Event De-multiplexer and Initiation Dispatcher of Reactor pattern.\n * Multiple handles i.e. {@link AbstractNioChannel}s can be registered to the reactor, and it blocks\n * for events from all these handles. Whenever an event occurs on any of the registered handles, it\n * synchronously de-multiplexes the event which can be any of read, write or accept, and dispatches\n * the event to the appropriate {@link ChannelHandler} using the {@link Dispatcher}.\n *\n * <p>Implementation: A NIO reactor runs in its own thread when it is started using {@link #start()}\n * method. {@link NioReactor} uses {@link Selector} for realizing Synchronous Event De-multiplexing.\n *\n * <p>NOTE: This is one of the ways to implement NIO reactor, and it does not take care of all\n * possible edge cases which are required in a real application. This implementation is meant to\n * demonstrate the fundamental concepts that lie behind Reactor pattern.\n */\n@Slf4j\npublic class NioReactor {\n\n  private final Selector selector;\n  private final Dispatcher dispatcher;\n\n  /**\n   * All the work of altering the SelectionKey operations and Selector operations are performed in\n   * the context of main event loop of reactor. So when any channel needs to change its readability\n   * or writability, a new command is added in the command queue and then the event loop picks up\n   * the command and executes it in next iteration.\n   */\n  private final Queue<Runnable> pendingCommands = new ConcurrentLinkedQueue<>();\n\n  private final ExecutorService reactorMain = Executors.newSingleThreadExecutor();\n\n  /**\n   * Creates a reactor which will use provided {@code dispatcher} to dispatch events. The\n   * application can provide various implementations of dispatcher which suits its needs.\n   *\n   * @param dispatcher a non-null dispatcher used to dispatch events on registered channels.\n   * @throws IOException if any I/O error occurs.\n   */\n  public NioReactor(Dispatcher dispatcher) throws IOException {\n    this.dispatcher = dispatcher;\n    this.selector = Selector.open();\n  }\n\n  /** Starts the reactor event loop in a new thread. */\n  public void start() {\n    reactorMain.execute(\n        () -> {\n          try {\n            LOGGER.info(\"Reactor started, waiting for events...\");\n            eventLoop();\n          } catch (IOException e) {\n            LOGGER.error(\"exception in event loop\", e);\n          }\n        });\n  }\n\n  /**\n   * Stops the reactor and related resources such as dispatcher.\n   *\n   * @throws InterruptedException if interrupted while stopping the reactor.\n   * @throws IOException if any I/O error occurs.\n   */\n  public void stop() throws InterruptedException, IOException {\n    reactorMain.shutdown();\n    selector.wakeup();\n    if (!reactorMain.awaitTermination(4, TimeUnit.SECONDS)) {\n      reactorMain.shutdownNow();\n    }\n    selector.close();\n    LOGGER.info(\"Reactor stopped\");\n  }\n\n  /**\n   * Registers a new channel (handle) with this reactor. Reactor will start waiting for events on\n   * this channel and notify of any events. While registering the channel the reactor uses {@link\n   * AbstractNioChannel#getInterestedOps()} to know about the interested operation of this channel.\n   *\n   * @param channel a new channel on which reactor will wait for events. The channel must be bound\n   *     prior to being registered.\n   * @return this\n   * @throws IOException if any I/O error occurs.\n   */\n  public NioReactor registerChannel(AbstractNioChannel channel) throws IOException {\n    var key = channel.getJavaChannel().register(selector, channel.getInterestedOps());\n    key.attach(channel);\n    channel.setReactor(this);\n    return this;\n  }\n\n  private void eventLoop() throws IOException {\n    // honor interrupt request\n    while (!Thread.interrupted()) {\n      // honor any pending commands first\n      processPendingCommands();\n\n      /*\n       * Synchronous event de-multiplexing happens here, this is blocking call which returns when it\n       * is possible to initiate non-blocking operation on any of the registered channels.\n       */\n      selector.select();\n\n      /*\n       * Represents the events that have occurred on registered handles.\n       */\n      var keys = selector.selectedKeys();\n      var iterator = keys.iterator();\n\n      while (iterator.hasNext()) {\n        var key = iterator.next();\n        if (!key.isValid()) {\n          iterator.remove();\n          continue;\n        }\n        processKey(key);\n      }\n      keys.clear();\n    }\n  }\n\n  private void processPendingCommands() {\n    var iterator = pendingCommands.iterator();\n    while (iterator.hasNext()) {\n      var command = iterator.next();\n      command.run();\n      iterator.remove();\n    }\n  }\n\n  /*\n   * Initiation dispatcher logic, it checks the type of event and notifier application specific\n   * event handler to handle the event.\n   */\n  private void processKey(SelectionKey key) throws IOException {\n    if (key.isAcceptable()) {\n      onChannelAcceptable(key);\n    } else if (key.isReadable()) {\n      onChannelReadable(key);\n    } else if (key.isWritable()) {\n      onChannelWritable(key);\n    }\n  }\n\n  private static void onChannelWritable(SelectionKey key) throws IOException {\n    var channel = (AbstractNioChannel) key.attachment();\n    channel.flush(key);\n  }\n\n  private void onChannelReadable(SelectionKey key) {\n    try {\n      // reads the incoming data in context of reactor main loop. Can this be improved?\n      var readObject = ((AbstractNioChannel) key.attachment()).read(key);\n      dispatchReadEvent(key, readObject);\n    } catch (IOException e) {\n      try {\n        key.channel().close();\n      } catch (IOException e1) {\n        LOGGER.error(\"error closing channel\", e1);\n      }\n    }\n  }\n\n  /*\n   * Uses the application provided dispatcher to dispatch events to application handler.\n   */\n  private void dispatchReadEvent(SelectionKey key, Object readObject) {\n    dispatcher.onChannelReadEvent((AbstractNioChannel) key.attachment(), readObject, key);\n  }\n\n  private void onChannelAcceptable(SelectionKey key) throws IOException {\n    var serverSocketChannel = (ServerSocketChannel) key.channel();\n    var socketChannel = serverSocketChannel.accept();\n    socketChannel.configureBlocking(false);\n    var readKey = socketChannel.register(selector, SelectionKey.OP_READ);\n    readKey.attach(key.attachment());\n  }\n\n  /**\n   * Queues the change of operations request of a channel, which will change the interested\n   * operations of the channel sometime in the future.\n   *\n   * <p>This is a non-blocking method and does not guarantee that the operations have changed when\n   * this method returns.\n   *\n   * @param key the key for which operations have to be changed.\n   * @param interestedOps the new interest operations.\n   */\n  public void changeOps(SelectionKey key, int interestedOps) {\n    pendingCommands.add(new ChangeKeyOpsCommand(key, interestedOps));\n    selector.wakeup();\n  }\n\n  /** A command that changes the interested operations of the key provided. */\n  static class ChangeKeyOpsCommand implements Runnable {\n    private final SelectionKey key;\n    private final int interestedOps;\n\n    public ChangeKeyOpsCommand(SelectionKey key, int interestedOps) {\n      this.key = key;\n      this.interestedOps = interestedOps;\n    }\n\n    public void run() {\n      key.interestOps(interestedOps);\n    }\n\n    @Override\n    public String toString() {\n      return \"Change of ops to: \" + interestedOps;\n    }\n  }\n}\n"
  },
  {
    "path": "reactor/src/main/java/com/iluwatar/reactor/framework/NioServerSocketChannel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.reactor.framework;\n\nimport java.io.IOException;\nimport java.net.InetAddress;\nimport java.net.InetSocketAddress;\nimport java.nio.ByteBuffer;\nimport java.nio.channels.SelectionKey;\nimport java.nio.channels.ServerSocketChannel;\nimport java.nio.channels.SocketChannel;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * A wrapper over {@link NioServerSocketChannel} which can read and write data on a {@link\n * SocketChannel}.\n */\n@Slf4j\npublic class NioServerSocketChannel extends AbstractNioChannel {\n\n  private final int port;\n\n  /**\n   * Creates a {@link ServerSocketChannel} which will bind at provided port and use <code>handler\n   * </code> to handle incoming events on this channel.\n   *\n   * <p>Note the constructor does not bind the socket, {@link #bind()} method should be called for\n   * binding the socket.\n   *\n   * @param port the port on which channel will be bound to accept incoming connection requests.\n   * @param handler the handler that will handle incoming requests on this channel.\n   * @throws IOException if any I/O error occurs.\n   */\n  public NioServerSocketChannel(int port, ChannelHandler handler) throws IOException {\n    super(handler, ServerSocketChannel.open());\n    this.port = port;\n  }\n\n  @Override\n  public int getInterestedOps() {\n    // being a server socket channel it is interested in accepting connection from remote peers.\n    return SelectionKey.OP_ACCEPT;\n  }\n\n  /**\n   * Get server socket channel.\n   *\n   * @return the underlying {@link ServerSocketChannel}.\n   */\n  @Override\n  public ServerSocketChannel getJavaChannel() {\n    return (ServerSocketChannel) super.getJavaChannel();\n  }\n\n  /**\n   * Reads and returns {@link ByteBuffer} from the underlying {@link SocketChannel} represented by\n   * the <code>key</code>. Due to the fact that there is a dedicated channel for each client\n   * connection we don't need to store the sender.\n   */\n  @Override\n  public ByteBuffer read(SelectionKey key) throws IOException {\n    var socketChannel = (SocketChannel) key.channel();\n    var buffer = ByteBuffer.allocate(1024);\n    var read = socketChannel.read(buffer);\n    buffer.flip();\n    if (read == -1) {\n      throw new IOException(\"Socket closed\");\n    }\n    return buffer;\n  }\n\n  /**\n   * Binds TCP socket on the provided <code>port</code>.\n   *\n   * @throws IOException if any I/O error occurs.\n   */\n  @Override\n  public void bind() throws IOException {\n    var javaChannel = getJavaChannel();\n    javaChannel.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), port));\n    javaChannel.configureBlocking(false);\n    LOGGER.info(\"Bound TCP socket at port: {}\", port);\n  }\n\n  /**\n   * Writes the pending {@link ByteBuffer} to the underlying channel sending data to the intended\n   * receiver of the packet.\n   */\n  @Override\n  protected void doWrite(Object pendingWrite, SelectionKey key) throws IOException {\n    var pendingBuffer = (ByteBuffer) pendingWrite;\n    ((SocketChannel) key.channel()).write(pendingBuffer);\n  }\n}\n"
  },
  {
    "path": "reactor/src/main/java/com/iluwatar/reactor/framework/SameThreadDispatcher.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.reactor.framework;\n\nimport java.nio.channels.SelectionKey;\n\n/**\n * Dispatches the events in the context of caller thread. This implementation is a good fit for\n * small applications where there are limited clients. Using this implementation limits the\n * scalability because the I/O thread performs the application specific processing.\n *\n * <p>For better performance use {@link ThreadPoolDispatcher}.\n *\n * @see ThreadPoolDispatcher\n */\npublic class SameThreadDispatcher implements Dispatcher {\n\n  /**\n   * Dispatches the read event in the context of caller thread. <br>\n   * Note this is a blocking call. It returns only after the associated handler has handled the read\n   * event.\n   */\n  @Override\n  public void onChannelReadEvent(AbstractNioChannel channel, Object readObject, SelectionKey key) {\n    /*\n     * Calls the associated handler to notify the read event where application specific code\n     * resides.\n     */\n    channel.getHandler().handleChannelRead(channel, readObject, key);\n  }\n\n  /** No resources to free. */\n  @Override\n  public void stop() {\n    // no-op\n  }\n}\n"
  },
  {
    "path": "reactor/src/main/java/com/iluwatar/reactor/framework/ThreadPoolDispatcher.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.reactor.framework;\n\nimport java.nio.channels.SelectionKey;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * An implementation that uses a pool of worker threads to dispatch the events. This provides better\n * scalability as the application specific processing is not performed in the context of I/O\n * (reactor) thread.\n */\npublic class ThreadPoolDispatcher implements Dispatcher {\n\n  private final ExecutorService executorService;\n\n  /**\n   * Creates a pooled dispatcher with tunable pool size.\n   *\n   * @param poolSize number of pooled threads\n   */\n  public ThreadPoolDispatcher(int poolSize) {\n    this.executorService = Executors.newFixedThreadPool(poolSize);\n  }\n\n  /**\n   * Submits the work of dispatching the read event to worker pool, where it gets picked up by\n   * worker threads. <br>\n   * Note that this is a non-blocking call and returns immediately. It is not guaranteed that the\n   * event has been handled by associated handler.\n   */\n  @Override\n  public void onChannelReadEvent(AbstractNioChannel channel, Object readObject, SelectionKey key) {\n    executorService.execute(() -> channel.getHandler().handleChannelRead(channel, readObject, key));\n  }\n\n  /**\n   * Stops the pool of workers.\n   *\n   * @throws InterruptedException if interrupted while stopping pool of workers.\n   */\n  @Override\n  public void stop() throws InterruptedException {\n    executorService.shutdown();\n    if (executorService.awaitTermination(4, TimeUnit.SECONDS)) {\n      executorService.shutdownNow();\n    }\n  }\n}\n"
  },
  {
    "path": "reactor/src/test/java/com/iluwatar/reactor/app/ReactorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.reactor.app;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport com.iluwatar.reactor.framework.SameThreadDispatcher;\nimport com.iluwatar.reactor.framework.ThreadPoolDispatcher;\nimport java.io.IOException;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\n\n/**\n * This class tests the Distributed Logging service by starting a Reactor and then sending it\n * concurrent logging requests using multiple clients.\n */\n@Slf4j\nclass ReactorTest {\n\n  /**\n   * Test the application using pooled thread dispatcher.\n   *\n   * @throws IOException if any I/O error occurs.\n   * @throws InterruptedException if interrupted while stopping the application.\n   */\n  @Test\n  void testAppUsingThreadPoolDispatcher() throws IOException, InterruptedException {\n    LOGGER.info(\"testAppUsingThreadPoolDispatcher start\");\n    var app = new App(new ThreadPoolDispatcher(2));\n    app.start();\n\n    assertNotNull(app);\n\n    var client = new AppClient();\n    client.start();\n\n    assertNotNull(client);\n\n    // allow clients to send requests. Artificial delay.\n    try {\n      Thread.sleep(2000);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"sleep interrupted\", e);\n    }\n\n    client.stop();\n\n    app.stop();\n    LOGGER.info(\"testAppUsingThreadPoolDispatcher stop\");\n  }\n\n  /**\n   * Test the application using same thread dispatcher.\n   *\n   * @throws IOException if any I/O error occurs.\n   * @throws InterruptedException if interrupted while stopping the application.\n   */\n  @Test\n  void testAppUsingSameThreadDispatcher() throws IOException, InterruptedException {\n    LOGGER.info(\"testAppUsingSameThreadDispatcher start\");\n    var app = new App(new SameThreadDispatcher());\n    app.start();\n\n    assertNotNull(app);\n\n    var client = new AppClient();\n    client.start();\n\n    assertNotNull(client);\n\n    // allow clients to send requests. Artificial delay.\n    try {\n      Thread.sleep(2000);\n    } catch (InterruptedException e) {\n      LOGGER.error(\"sleep interrupted\", e);\n    }\n\n    client.stop();\n\n    app.stop();\n    LOGGER.info(\"testAppUsingSameThreadDispatcher stop\");\n  }\n}\n"
  },
  {
    "path": "registry/README.md",
    "content": "---\ntitle: \"Registry Pattern in Java: Implementing a Centralized Control Mechanism for Java Objects\"\nshortTitle: Registry\ndescription: \"Explore the Registry design pattern in Java: Learn how it centralizes object management for improved access and control. Perfect for software developers and architects looking to optimize Java application architecture.\"\ncategory: Creational\nlanguage: en\ntag:\n  - API design\n  - Data access\n  - Decoupling\n  - Dependency management\n  - Enterprise patterns\n  - Instantiation\n---\n\n## Intent of Registry Design Pattern\n\nRegistry Design Pattern centralizes the creation and management of a global set of objects, providing a single point of access and ensuring controlled instantiation.\n\n## Detailed Explanation of Registry Pattern with Real-World Examples\n\nReal-world example\n\n> In a large corporation, managing IT assets such as laptops, desktops, servers, and software licenses can be challenging. To streamline this process, the company uses a centralized IT Asset Management System, which functions as a Registry.\n>\n> * The system provides a single point of access for registering, tracking, and retrieving information about all IT assets.\n> * When a new device or software is procured, it is registered in the system with details such as serial number, purchase date, warranty period, and assigned user.\n> * IT staff can query the system to get details about any asset, check its current status, and update information as needed.\n> * This centralized management promotes efficient utilization and maintenance of assets, ensures compliance with software licenses, and helps in planning for upgrades or replacements.\n>\n> In this analogy, the IT Asset Management System acts as a Registry, managing the lifecycle and providing global access to information about IT assets within the organization.\n\nIn plain words\n\n> Registry is a well-known object that other objects can use to find common objects and services.\n\nwiki.c2.com says\n\n> A registry is a global association from keys to objects, allowing the objects to be reached from anywhere. It involves two methods: one that takes a key and an object and add objects to the registry and one that takes a key and returns the object for the key. It's similar to the MultitonPattern, but doesn't restrict instances to only those in the registry.\n\nFlowchart\n\n![Registry flowchart](./etc/registry-flowchart.png)\n\n## Programmatic Example of Registry Pattern in Java\n\nThe Registry design pattern is a well-known pattern used in software design where objects are stored and provide a global point of access to them. This pattern is particularly useful when you need to manage a global collection of objects, decouple the creation of objects from their usage, ensure a controlled lifecycle for objects, and avoid redundant creation of objects.\n\nFirst, we have the `Customer` record. It represents the objects that will be stored in the registry. Each `Customer` has an `id` and a `name`.\n\n```java\npublic record Customer(String id, String name) {\n\n    @Override\n    public String toString() {\n        return \"Customer{\"\n                + \"id='\" + id + '\\''\n                + \", name='\" + name + '\\''\n                + '}';\n    }\n}\n```\n\nNext, we have the `CustomerRegistry` class. This class is the actual registry where `Customer` objects are stored. It provides methods to add and retrieve customers. The `CustomerRegistry` is a singleton, meaning there is only one instance of it in the application.\n\n```java\npublic final class CustomerRegistry {\n\n    @Getter\n    private static final CustomerRegistry instance = new CustomerRegistry();\n\n    private final Map<String, Customer> customerMap;\n\n    private CustomerRegistry() {\n        customerMap = new ConcurrentHashMap<>();\n    }\n\n    public Customer addCustomer(Customer customer) {\n        return customerMap.put(customer.id(), customer);\n    }\n\n    public Customer getCustomer(String id) {\n        return customerMap.get(id);\n    }\n\n}\n```\n\nFinally, we have the `App` class. This class demonstrates how to use the `CustomerRegistry`. It creates two `Customer` objects, adds them to the `CustomerRegistry`, and then retrieves them.\n\n```java\npublic class App {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n  public static void main(String[] args) {\n    CustomerRegistry customerRegistry = CustomerRegistry.getInstance();\n    var john = new Customer(\"1\", \"John\");\n    customerRegistry.addCustomer(john);\n    var julia = new Customer(\"2\", \"Julia\");\n    customerRegistry.addCustomer(julia);\n\n    LOGGER.info(\"John {}\", customerRegistry.getCustomer(\"1\"));\n    LOGGER.info(\"Julia {}\", customerRegistry.getCustomer(\"2\"));\n  }\n\n}\n```\n\nIn this example, the `CustomerRegistry` provides a global point of access to `Customer` objects. This allows us to manage these objects in a centralized way, promoting reuse and sharing, and facilitating decoupling between components.\n\nRunning the example produces the following output:\n\n```\n09:55:31.109 [main] INFO com.iluwatar.registry.App -- John Customer{id='1', name='John'}\n09:55:31.113 [main] INFO com.iluwatar.registry.App -- Julia Customer{id='2', name='Julia'}\n```\n\n## When to Use the Registry Pattern in Java\n\n* When you need to manage a global collection of objects.\n* When you need to decouple the creation of objects from their usage.\n* When you need to ensure a controlled lifecycle for objects, such as services or resources.\n* When you want to avoid redundant creation of objects.\n\n## Real-World Applications of Registry Pattern in Java\n\n* Managing database connections in an enterprise application.\n* Providing a central place to register and retrieve services or components in a modular application.\n* Creating a central configuration registry that various parts of an application can access.\n\n## Benefits and Trade-offs of Registry Pattern\n\nBenefits:\n\nKey advantages of adopting the Registry pattern in Java\n\n* Centralizes object management, making the application easier to maintain.\n* Promotes reuse and sharing of objects, which can reduce memory footprint and initialization time.\n* Facilitates decoupling between components.\n\nTrade-offs:\n\n* Can become a bottleneck if not implemented efficiently.\n* May introduce a single point of failure if the registry is not designed to be fault-tolerant.\n* Increases complexity in managing the lifecycle of objects.\n\n## Related Patterns\n\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Often used in conjunction with the Registry to ensure there is a single instance of the Registry.\n* [Factory](https://java-design-patterns.com/patterns/factory/): Used to encapsulate the instantiation logic that might be needed when objects are retrieved from the Registry.\n* [Service Locator](https://java-design-patterns.com/patterns/service-locator/): A pattern that is similar in intent and structure, often used interchangeably with the Registry.\n* [Dependency Injection](https://java-design-patterns.com/patterns/dependency-injection/): Provides an alternative method for managing dependencies, which can sometimes replace the need for a Registry.\n* [Multiton](https://java-design-patterns.com/patterns/multiton/): Similar to the Registry in that it manages multiple instances, but does so based on keys, ensuring only one instance per key.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n* [Registry (Martin Fowler)](https://www.martinfowler.com/eaaCatalog/registry.html)\n* [Registry pattern (wiki.c2.com)](https://wiki.c2.com/?RegistryPattern)\n"
  },
  {
    "path": "registry/etc/registry.urm.puml",
    "content": "@startuml\npackage com.iluwatar.registry {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Customer {\n    - id : String\n    - name : String\n    + getId() : String\n    + getName() : String\n    + toString() : String\n  }\n  class CustomerRegistry {\n    + addCustomer(customer : Customer)\n    + getCustomer(id : String)\n  }\n}\nCustomer --> \"-addCustomer\" CustomerRegistry\n@enduml\n"
  },
  {
    "path": "registry/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>registry</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.registry.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "registry/src/main/java/com/iluwatar/registry/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.registry;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * In Registry pattern, objects of a single class are stored and provide a global point of access to\n * them. Note that there is no restriction on the number of objects.\n *\n * <p>The given example {@link CustomerRegistry} represents the registry used to store and access\n * {@link Customer} objects.\n */\npublic class App {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    CustomerRegistry customerRegistry = CustomerRegistry.getInstance();\n    var john = new Customer(\"1\", \"John\");\n    customerRegistry.addCustomer(john);\n\n    var julia = new Customer(\"2\", \"Julia\");\n    customerRegistry.addCustomer(julia);\n\n    LOGGER.info(\"John {}\", customerRegistry.getCustomer(\"1\"));\n    LOGGER.info(\"Julia {}\", customerRegistry.getCustomer(\"2\"));\n  }\n}\n"
  },
  {
    "path": "registry/src/main/java/com/iluwatar/registry/Customer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.registry;\n\n/** Customer entity used in registry pattern example. */\npublic record Customer(String id, String name) {\n\n  @Override\n  public String toString() {\n    return \"Customer{\" + \"id='\" + id + '\\'' + \", name='\" + name + '\\'' + '}';\n  }\n}\n"
  },
  {
    "path": "registry/src/main/java/com/iluwatar/registry/CustomerRegistry.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.registry;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport lombok.Getter;\n\n/** CustomerRegistry class used to store/access {@link Customer} objects. */\npublic final class CustomerRegistry {\n\n  @Getter private static final CustomerRegistry instance = new CustomerRegistry();\n\n  private final Map<String, Customer> customerMap;\n\n  private CustomerRegistry() {\n    customerMap = new ConcurrentHashMap<>();\n  }\n\n  public Customer addCustomer(Customer customer) {\n    return customerMap.put(customer.id(), customer);\n  }\n\n  public Customer getCustomer(String id) {\n    return customerMap.get(id);\n  }\n}\n"
  },
  {
    "path": "registry/src/test/java/com/iluwatar/registry/CustomerRegistryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.registry;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nclass CustomerRegistryTest {\n\n  private static CustomerRegistry customerRegistry;\n\n  @BeforeAll\n  public static void setUp() {\n    customerRegistry = CustomerRegistry.getInstance();\n  }\n\n  @Test\n  void shouldBeAbleToAddAndQueryCustomerObjectFromRegistry() {\n    Customer john = new Customer(\"1\", \"john\");\n    Customer julia = new Customer(\"2\", \"julia\");\n\n    customerRegistry.addCustomer(john);\n    customerRegistry.addCustomer(julia);\n\n    Customer customerWithId1 = customerRegistry.getCustomer(\"1\");\n    assertNotNull(customerWithId1);\n    assertEquals(\"1\", customerWithId1.id());\n    assertEquals(\"john\", customerWithId1.name());\n\n    Customer customerWithId2 = customerRegistry.getCustomer(\"2\");\n    assertNotNull(customerWithId2);\n    assertEquals(\"2\", customerWithId2.id());\n    assertEquals(\"julia\", customerWithId2.name());\n  }\n\n  @Test\n  void shouldReturnNullWhenQueriedCustomerIsNotInRegistry() {\n    Customer customerWithId5 = customerRegistry.getCustomer(\"5\");\n    assertNull(customerWithId5);\n  }\n}\n"
  },
  {
    "path": "repository/README.md",
    "content": "---\ntitle: \"Repository Pattern in Java: Simplifying Data Access with Abstracted Persistence\"\nshortTitle: Repository\ndescription: \"Learn how the Repository design pattern in Java enhances data access and abstraction, simplifying application architecture while boosting maintainability and decoupling. Ideal for Java developers seeking streamlined data management solutions.\"\ncategory: Data access\nlanguage: en\ntag:\n  - Abstraction\n  - Data access\n  - Decoupling\n  - Persistence\n---\n\n## Intent of Repository Design Pattern\n\nThe Repository design pattern acts as a central hub for managing all Java data access logic, abstracting the details of data storage and retrieval from the rest of the application.\n\n## Detailed Explanation of Repository Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a library system where a librarian acts as the repository. Instead of each library patron searching through the entire library for a book (the data), they go to the librarian (the repository) who knows exactly where each book is located, regardless of whether it's on a shelf, in the storeroom, or borrowed by someone else. The librarian abstracts the complexities of book storage, allowing patrons to request books without needing to understand the storage system. This setup simplifies the process for patrons (clients) and centralizes the management of books (data access logic).\n\nIn plain words\n\n> The Repository pattern provides a central place for handling all data access logic, abstracting the complexities of data storage and retrieval from the rest of the application.\n\n[Microsoft documentation](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design) says\n\n> Repositories are classes or components that encapsulate the logic required to access data sources. They centralize common data access functionality, providing better maintainability and decoupling the infrastructure or technology used to access databases from the domain model layer.\n\nSequence diagram\n\n![Repository sequence diagram](./etc/repository-sequence-diagram.png)\n\n## Programmatic Example of Repository Pattern in Java\n\nLet's first look at the person entity that we need to persist.\n\n```java\n\n@ToString\n@EqualsAndHashCode\n@Setter\n@Getter\n@Entity\n@NoArgsConstructor\npublic class Person {\n\n    @Id\n    @GeneratedValue\n    private Long id;\n    private String name;\n    private String surname;\n    private int age;\n\n    public Person(String name, String surname, int age) {\n        this.name = name;\n        this.surname = surname;\n        this.age = age;\n    }\n}\n```\n\nWe are using Spring Data to create the `PersonRepository`, so it becomes really simple.\n\n```java\n@Repository\npublic interface PersonRepository extends CrudRepository<Person, Long>, JpaSpecificationExecutor<Person> {\n    Person findByName(String name);\n}\n```\n\nAdditionally, we define a helper class `PersonSpecifications` for specification queries.\n\n```java\npublic class PersonSpecifications {\n\n    public static class AgeBetweenSpec implements Specification<Person> {\n\n        private final int from;\n        private final int to;\n\n        public AgeBetweenSpec(int from, int to) {\n            this.from = from;\n            this.to = to;\n        }\n\n        @Override\n        public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> query, CriteriaBuilder cb) {\n            return cb.between(root.get(\"age\"), from, to);\n        }\n    }\n\n    public static class NameEqualSpec implements Specification<Person> {\n\n        public String name;\n\n        public NameEqualSpec(String name) {\n            this.name = name;\n        }\n\n        public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> query, CriteriaBuilder cb) {\n            return cb.equal(root.get(\"name\"), this.name);\n        }\n    }\n}\n```\n\nAnd here's the repository example in action.\n\n```java\n  public static void main(String[] args) {\n\n    var context = new ClassPathXmlApplicationContext(\"applicationContext.xml\");\n    var repository = context.getBean(PersonRepository.class);\n\n    var peter = new Person(\"Peter\", \"Sagan\", 17);\n    var nasta = new Person(\"Nasta\", \"Kuzminova\", 25);\n    var john = new Person(\"John\", \"lawrence\", 35);\n    var terry = new Person(\"Terry\", \"Law\", 36);\n\n    // Add new Person records\n    repository.save(peter);\n    repository.save(nasta);\n    repository.save(john);\n    repository.save(terry);\n\n    // Count Person records\n    LOGGER.info(\"Count Person records: {}\", repository.count());\n\n    // Print all records\n    var persons = (List<Person>) repository.findAll();\n    persons.stream().map(Person::toString).forEach(LOGGER::info);\n\n    // Update Person\n    nasta.setName(\"Barbora\");\n    nasta.setSurname(\"Spotakova\");\n    repository.save(nasta);\n\n    repository.findById(2L).ifPresent(p -> LOGGER.info(\"Find by id 2: {}\", p));\n\n    // Remove record from Person\n    repository.deleteById(2L);\n\n    // count records\n    LOGGER.info(\"Count Person records: {}\", repository.count());\n\n    // find by name\n    repository\n            .findOne(new PersonSpecifications.NameEqualSpec(\"John\"))\n            .ifPresent(p -> LOGGER.info(\"Find by John is {}\", p));\n\n    // find by age\n    persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40));\n\n    LOGGER.info(\"Find Person with age between 20,40: \");\n    persons.stream().map(Person::toString).forEach(LOGGER::info);\n\n    repository.deleteAll();\n\n    context.close();\n}\n```\n\nProgram output:\n\n```\nINFO  [2024-05-27 07:00:32,847] com.iluwatar.repository.App: Count Person records: 4\nINFO  [2024-05-27 07:00:32,859] com.iluwatar.repository.App: Person(id=1, name=Peter, surname=Sagan, age=17)\nINFO  [2024-05-27 07:00:32,859] com.iluwatar.repository.App: Person(id=2, name=Nasta, surname=Kuzminova, age=25)\nINFO  [2024-05-27 07:00:32,859] com.iluwatar.repository.App: Person(id=3, name=John, surname=lawrence, age=35)\nINFO  [2024-05-27 07:00:32,859] com.iluwatar.repository.App: Person(id=4, name=Terry, surname=Law, age=36)\nINFO  [2024-05-27 07:00:32,869] com.iluwatar.repository.App: Find by id 2: Person(id=2, name=Barbora, surname=Spotakova, age=25)\nINFO  [2024-05-27 07:00:32,873] com.iluwatar.repository.App: Count Person records: 3\nINFO  [2024-05-27 07:00:32,878] com.iluwatar.repository.App: Find by John is Person(id=3, name=John, surname=lawrence, age=35)\nINFO  [2024-05-27 07:00:32,881] com.iluwatar.repository.App: Find Person with age between 20,40: \nINFO  [2024-05-27 07:00:32,881] com.iluwatar.repository.App: Person(id=3, name=John, surname=lawrence, age=35)\nINFO  [2024-05-27 07:00:32,881] com.iluwatar.repository.App: Person(id=4, name=Terry, surname=Law, age=36)\n```\n\n## When to Use the Repository Pattern in Java\n\n* Apply the Repository pattern when aiming to decouple business logic from data access layers in Java applications, ensuring more flexible and maintainable code.\n* Suitable for scenarios where multiple data sources might be used and the business logic should remain unaware of the data source specifics.\n* Ideal for testing purposes as it allows the use of mock repositories.\n\n## Repository Pattern Java Tutorials\n\n* [Don’t use DAO, use Repository (Thinking in Objects)](http://thinkinginobjects.com/2012/08/26/dont-use-dao-use-repository/)\n* [Advanced Spring Data JPA - Specifications and Querydsl (Spring)](https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/)\n* [Repository Pattern Benefits and Spring Implementation (Stack Overflow)](https://stackoverflow.com/questions/40068965/repository-pattern-benefits-and-spring-implementation)\n* [Design patterns that I often avoid: Repository pattern (InfoWorld)](https://www.infoworld.com/article/3117713/design-patterns-that-i-often-avoid-repository-pattern.html)\n\n## Real-World Applications of Repository Pattern in Java\n\n* Spring Data JPA exemplifies the Repository pattern by providing a robust repository abstraction layer over JPA implementations, tailored for Java.\n* Hibernate: Often used with DAOs that act as repositories for accessing and managing data entities.\n* Java EE applications frequently utilize repository patterns to separate business logic from data access code.\n\n## Benefits and Trade-offs of Repository Pattern\n\nBenefits:\n\n* Improves code maintainability and readability by centralizing data access logic.\n* Enhances testability by allowing mock implementations of repositories.\n* Promotes loose coupling between business logic and data access layers.\n\nTrade-offs:\n\n* Introduces additional layers of abstraction which might add complexity.\n* Potential performance overhead due to the abstraction layer.\n\n## Related Java Design Patterns\n\n* [Data Mapper](https://java-design-patterns.com/patterns/data-mapper/): While Repository handles data access, Data Mapper is responsible for transferring data between objects and a database, maintaining the data integrity.\n* [Unit of Work](https://java-design-patterns.com/patterns/unit-of-work/): Often used alongside Repository to manage transactions and track changes to the data.\n\n## References and Credits\n\n* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3wlDrze)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "repository/etc/repository.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.repository.Person\" project=\"repository\" \n    file=\"/repository/src/main/java/com/iluwatar/repository/Person.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"109\" y=\"67\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"2\" language=\"java\" name=\"com.iluwatar.repository.PersonRepository\" project=\"repository\" \n    file=\"/repository/src/main/java/com/iluwatar/repository/PersonRepository.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"350\" y=\"67\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.repository.PersonSpecifications.AgeBetweenSpec\" project=\"repository\" \n    file=\"/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"412\" y=\"246\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.repository.PersonSpecifications\" project=\"repository\" \n    file=\"/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"627\" y=\"68\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.repository.PersonSpecifications.NameEqualSpec\" project=\"repository\" \n    file=\"/repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"834\" y=\"238\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <nesting id=\"6\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </nesting>  \n  <dependency id=\"7\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </dependency>  \n  <nesting id=\"8\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </nesting>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "repository/etc/repository.urm.puml",
    "content": "@startuml\npackage com.iluwatar.repository {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class AppConfig {\n    - LOGGER : Logger {static}\n    + AppConfig()\n    + dataSource() : DataSource\n    + entityManagerFactory() : LocalContainerEntityManagerFactoryBean\n    - jpaProperties() : Properties {static}\n    + main(args : String[]) {static}\n    + transactionManager() : JpaTransactionManager\n  }\n  class Person {\n    - age : int\n    - id : Long\n    - name : String\n    - surname : String\n    + Person()\n    + Person(name : String, surname : String, age : int)\n    + equals(obj : Object) : boolean\n    + getAge() : int\n    + getId() : Long\n    + getName() : String\n    + getSurname() : String\n    + hashCode() : int\n    + setAge(age : int)\n    + setId(id : Long)\n    + setName(name : String)\n    + setSurname(surname : String)\n    + toString() : String\n  }\n  interface PersonRepository {\n    + findByName(String) : Person {abstract}\n  }\n  class PersonSpecifications {\n    + PersonSpecifications()\n  }\n  class AgeBetweenSpec {\n    - from : int\n    - to : int\n    + AgeBetweenSpec(from : int, to : int)\n    + toPredicate(root : Root<Person>, query : CriteriaQuery<?>, cb : CriteriaBuilder) : Predicate\n  }\n  class NameEqualSpec {\n    + name : String\n    + NameEqualSpec(name : String)\n    + toPredicate(root : Root<Person>, query : CriteriaQuery<?>, cb : CriteriaBuilder) : Predicate\n  }\n}\nNameEqualSpec ..+ PersonSpecifications\nAgeBetweenSpec ..+ PersonSpecifications\n@enduml"
  },
  {
    "path": "repository/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>repository</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.data</groupId>\n      <artifactId>spring-data-jpa</artifactId>\n      <version>3.4.4</version>\n    </dependency>\n    <dependency>\n      <groupId>org.hibernate</groupId>\n      <artifactId>hibernate-core</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>commons-dbcp</groupId>\n      <artifactId>commons-dbcp</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>com.h2database</groupId>\n      <artifactId>h2</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>jakarta.xml.bind</groupId>\n      <artifactId>jakarta.xml.bind-api</artifactId>\n      <version>4.0.2</version>\n    </dependency>\n    <dependency>\n      <groupId>jakarta.annotation</groupId>\n      <artifactId>jakarta.annotation-api</artifactId>\n      <version>2.1.1</version>\n    </dependency>\n    <dependency>\n      <groupId>org.springframework.boot</groupId>\n      <artifactId>spring-boot-starter-test</artifactId>\n        <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.hibernate</groupId>\n      <artifactId>hibernate-core</artifactId>\n      <version>6.4.4.Final</version>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.repository.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "repository/src/main/java/com/iluwatar/repository/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.repository;\n\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\n\n/**\n * Repository pattern mediates between the domain and data mapping layers using a collection-like\n * interface for accessing domain objects. A system with complex domain model often benefits from a\n * layer that isolates domain objects from the details of the database access code and in such\n * systems it can be worthwhile to build another layer of abstraction over the mapping layer where\n * query construction code is concentrated. This becomes more important when there are a large\n * number of domain classes or heavy querying. In these cases particularly, adding this layer helps\n * minimize duplicate query logic.\n *\n * <p>In this example we utilize Spring Data to automatically generate a repository for us from the\n * {@link Person} domain object. Using the {@link PersonRepository} we perform CRUD operations on\n * the entity, moreover, the query by {@link org.springframework.data.jpa.domain.Specification} are\n * also performed. Underneath we have configured in-memory H2 database for which schema is created\n * and dropped on each run.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var context = new ClassPathXmlApplicationContext(\"applicationContext.xml\");\n    var repository = context.getBean(PersonRepository.class);\n\n    var peter = new Person(\"Peter\", \"Sagan\", 17);\n    var nasta = new Person(\"Nasta\", \"Kuzminova\", 25);\n    var john = new Person(\"John\", \"lawrence\", 35);\n    var terry = new Person(\"Terry\", \"Law\", 36);\n\n    // Add new Person records\n    repository.save(peter);\n    repository.save(nasta);\n    repository.save(john);\n    repository.save(terry);\n\n    // Count Person records\n    LOGGER.info(\"Count Person records: {}\", repository.count());\n\n    // Print all records\n    var persons = (List<Person>) repository.findAll();\n    persons.stream().map(Person::toString).forEach(LOGGER::info);\n\n    // Update Person\n    nasta.setName(\"Barbora\");\n    nasta.setSurname(\"Spotakova\");\n    repository.save(nasta);\n\n    repository.findById(2L).ifPresent(p -> LOGGER.info(\"Find by id 2: {}\", p));\n\n    // Remove record from Person\n    repository.deleteById(2L);\n\n    // count records\n    LOGGER.info(\"Count Person records: {}\", repository.count());\n\n    // find by name\n    repository\n        .findOne(new PersonSpecifications.NameEqualSpec(\"John\"))\n        .ifPresent(p -> LOGGER.info(\"Find by John is {}\", p));\n\n    // find by age\n    persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40));\n\n    LOGGER.info(\"Find Person with age between 20,40: \");\n    persons.stream().map(Person::toString).forEach(LOGGER::info);\n\n    repository.deleteAll();\n\n    context.close();\n  }\n}\n"
  },
  {
    "path": "repository/src/main/java/com/iluwatar/repository/AppConfig.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.repository;\n\nimport java.util.List;\nimport java.util.Properties;\nimport javax.sql.DataSource;\nimport lombok.extern.slf4j.Slf4j;\nimport org.apache.commons.dbcp.BasicDataSource;\nimport org.hibernate.jpa.HibernatePersistenceProvider;\nimport org.springframework.boot.SpringBootConfiguration;\nimport org.springframework.context.annotation.AnnotationConfigApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.data.jpa.repository.config.EnableJpaRepositories;\nimport org.springframework.orm.jpa.JpaTransactionManager;\nimport org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;\n\n/**\n * This is the same example as in {@link App} but with annotations based configuration for Spring.\n */\n@EnableJpaRepositories\n@SpringBootConfiguration\n@Slf4j\npublic class AppConfig {\n\n  /**\n   * Creation of H2 db.\n   *\n   * @return A new Instance of DataSource\n   */\n  @Bean(destroyMethod = \"close\")\n  public DataSource dataSource() {\n    var basicDataSource = new BasicDataSource();\n    basicDataSource.setDriverClassName(\"org.h2.Driver\");\n    basicDataSource.setUrl(\"jdbc:h2:mem:databases-person\");\n    basicDataSource.setUsername(\"sa\");\n    basicDataSource.setPassword(\"sa\");\n    return basicDataSource;\n  }\n\n  /** Factory to create a specific instance of Entity Manager. */\n  @Bean\n  public LocalContainerEntityManagerFactoryBean entityManagerFactory() {\n    var entityManager = new LocalContainerEntityManagerFactoryBean();\n    entityManager.setDataSource(dataSource());\n    entityManager.setPackagesToScan(\"com.iluwatar\");\n    entityManager.setPersistenceProvider(new HibernatePersistenceProvider());\n    entityManager.setJpaProperties(jpaProperties());\n    return entityManager;\n  }\n\n  /** Properties for Jpa. */\n  private static Properties jpaProperties() {\n    var properties = new Properties();\n    properties.setProperty(\"hibernate.dialect\", \"org.hibernate.dialect.H2Dialect\");\n    properties.setProperty(\"hibernate.hbm2ddl.auto\", \"create-drop\");\n    return properties;\n  }\n\n  /** Get transaction manager. */\n  @Bean\n  public JpaTransactionManager transactionManager() {\n    var transactionManager = new JpaTransactionManager();\n    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());\n    return transactionManager;\n  }\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var context = new AnnotationConfigApplicationContext(AppConfig.class);\n    var repository = context.getBean(PersonRepository.class);\n\n    var peter = new Person(\"Peter\", \"Sagan\", 17);\n    var nasta = new Person(\"Nasta\", \"Kuzminova\", 25);\n    var john = new Person(\"John\", \"lawrence\", 35);\n    var terry = new Person(\"Terry\", \"Law\", 36);\n\n    // Add new Person records\n    repository.save(peter);\n    repository.save(nasta);\n    repository.save(john);\n    repository.save(terry);\n\n    // Count Person records\n    LOGGER.info(\"Count Person records: {}\", repository.count());\n\n    // Print all records\n    var persons = (List<Person>) repository.findAll();\n    persons.stream().map(Person::toString).forEach(LOGGER::info);\n\n    // Update Person\n    nasta.setName(\"Barbora\");\n    nasta.setSurname(\"Spotakova\");\n    repository.save(nasta);\n\n    repository.findById(2L).ifPresent(p -> LOGGER.info(\"Find by id 2: {}\", p));\n\n    // Remove record from Person\n    repository.deleteById(2L);\n\n    // count records\n    LOGGER.info(\"Count Person records: {}\", repository.count());\n\n    // find by name\n    repository\n        .findOne(new PersonSpecifications.NameEqualSpec(\"John\"))\n        .ifPresent(p -> LOGGER.info(\"Find by John is {}\", p));\n\n    // find by age\n    persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40));\n\n    LOGGER.info(\"Find Person with age between 20,40: \");\n    persons.stream().map(Person::toString).forEach(LOGGER::info);\n\n    context.close();\n  }\n}\n"
  },
  {
    "path": "repository/src/main/java/com/iluwatar/repository/Person.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.repository;\n\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.Id;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\nimport lombok.ToString;\n\n/** Person entity. */\n@ToString\n@EqualsAndHashCode\n@Setter\n@Getter\n@Entity\n@NoArgsConstructor\npublic class Person {\n\n  @Id @GeneratedValue private Long id;\n  private String name;\n  private String surname;\n  private int age;\n\n  /** Constructor. */\n  public Person(String name, String surname, int age) {\n    this.name = name;\n    this.surname = surname;\n    this.age = age;\n  }\n}\n"
  },
  {
    "path": "repository/src/main/java/com/iluwatar/repository/PersonRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.repository;\n\nimport java.util.List;\nimport org.springframework.data.jpa.repository.JpaSpecificationExecutor;\nimport org.springframework.data.repository.CrudRepository;\nimport org.springframework.stereotype.Repository;\n\n/** Person repository. */\n@Repository\npublic interface PersonRepository\n    extends CrudRepository<Person, Long>, JpaSpecificationExecutor<Person> {\n\n  Person findByName(String name);\n\n  List<Person> findAll();\n}\n"
  },
  {
    "path": "repository/src/main/java/com/iluwatar/repository/PersonSpecifications.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.repository;\n\nimport jakarta.persistence.criteria.CriteriaBuilder;\nimport jakarta.persistence.criteria.CriteriaQuery;\nimport jakarta.persistence.criteria.Predicate;\nimport jakarta.persistence.criteria.Root;\nimport org.springframework.data.jpa.domain.Specification;\n\n/** Helper class, includes vary Specification as the abstraction of sql query criteria. */\npublic class PersonSpecifications {\n\n  /** Specifications stating the Between (From - To) Age Specification. */\n  public static class AgeBetweenSpec implements Specification<Person> {\n\n    private final int from;\n\n    private final int to;\n\n    public AgeBetweenSpec(int from, int to) {\n      this.from = from;\n      this.to = to;\n    }\n\n    @Override\n    public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> query, CriteriaBuilder cb) {\n      return cb.between(root.get(\"age\"), from, to);\n    }\n  }\n\n  /** Name specification. */\n  public static class NameEqualSpec implements Specification<Person> {\n\n    public final String name;\n\n    public NameEqualSpec(String name) {\n      this.name = name;\n    }\n\n    /** Get predicate. */\n    public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> query, CriteriaBuilder cb) {\n      return cb.equal(root.get(\"name\"), this.name);\n    }\n  }\n}\n"
  },
  {
    "path": "repository/src/main/resources/META-INF/persistence.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<persistence xmlns=\"http://java.sun.com/xml/ns/persistence\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"1.0\" xsi:schemaLocation=\"http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd\">\n  <persistence-unit name=\"jpaData\" />\n</persistence>\n"
  },
  {
    "path": "repository/src/main/resources/applicationContext.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:aop=\"http://www.springframework.org/schema/aop\" xmlns:context=\"http://www.springframework.org/schema/context\" xmlns:jpa=\"http://www.springframework.org/schema/data/jpa\" xmlns:security=\"http://www.springframework.org/schema/security\" xmlns:tx=\"http://www.springframework.org/schema/tx\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd\">\n  <jpa:repositories base-package=\"com.iluwatar\" />\n  <bean id=\"transactionManager\" class=\"org.springframework.orm.jpa.JpaTransactionManager\">\n    <property name=\"entityManagerFactory\" ref=\"entityManagerFactory\" />\n  </bean>\n  <bean id=\"dataSource\" class=\"org.apache.commons.dbcp.BasicDataSource\" destroy-method=\"close\">\n    <property name=\"driverClassName\" value=\"org.h2.Driver\" />\n    <property name=\"url\" value=\"jdbc:h2:mem:databases-person;DB_CLOSE_DELAY=-1\" />\n    <property name=\"username\" value=\"sa\" />\n    <property name=\"password\" value=\"sa\" />\n  </bean>\n  <bean id=\"entityManagerFactory\" class=\"org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean\">\n    <property name=\"dataSource\" ref=\"dataSource\" />\n    <property name=\"packagesToScan\" value=\"com.iluwatar\" />\n    <property name=\"persistenceProvider\">\n      <bean class=\"org.hibernate.jpa.HibernatePersistenceProvider\" />\n    </property>\n    <property name=\"jpaProperties\">\n      <map>\n        <entry key=\"hibernate.dialect\" value=\"org.hibernate.dialect.H2Dialect\" />\n        <entry key=\"hibernate.hbm2ddl.auto\" value=\"create\" />\n        <entry key=\"hibernate.show_sql\" value=\"false\" />\n      </map>\n    </property>\n  </bean>\n  <context:component-scan base-package=\"com.iluwatar.repository\">\n    <context:include-filter type=\"annotation\" expression=\"org.springframework.stereotype.Repository\" />\n  </context:component-scan>\n</beans>\n"
  },
  {
    "path": "repository/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<configuration>\n  <appender name=\"FILE\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n    <file>repository.log</file>\n    <rollingPolicy class=\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\">\n      <fileNamePattern>repository-%d.log</fileNamePattern>\n      <maxHistory>5</maxHistory>\n    </rollingPolicy>\n    <encoder>\n      <pattern>%-5p [%d{ISO8601,UTC}] %c: %m%n</pattern>\n    </encoder>\n  </appender>\n  <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n    <encoder>\n      <pattern>%-5p [%d{ISO8601,UTC}] %c: %m%n</pattern>\n    </encoder>\n  </appender>\n  <logger name=\"com.iluwatar\" additivity=\"false\">\n    <level value=\"DEBUG\" />\n    <appender-ref ref=\"STDOUT\" />\n  </logger>\n  <root level=\"WARN\">\n    <appender-ref ref=\"FILE\" />\n  </root>\n</configuration>\n"
  },
  {
    "path": "repository/src/test/java/com/iluwatar/repository/AnnotationBasedRepositoryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.repository;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport jakarta.annotation.Resource;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\n/**\n * Test case to test the functions of {@link PersonRepository}, beside the CRUD functions, the query\n * by {@link org.springframework.data.jpa.domain.Specification} are also test.\n */\n@ExtendWith(SpringExtension.class)\n@SpringBootTest(classes = {AppConfig.class})\nclass AnnotationBasedRepositoryTest {\n\n  @Resource private PersonRepository repository;\n\n  private final Person peter = new Person(\"Peter\", \"Sagan\", 17);\n  private final Person nasta = new Person(\"Nasta\", \"Kuzminova\", 25);\n  private final Person john = new Person(\"John\", \"lawrence\", 35);\n  private final Person terry = new Person(\"Terry\", \"Law\", 36);\n\n  private final List<Person> persons = List.of(peter, nasta, john, terry);\n\n  /** Prepare data for test */\n  @BeforeEach\n  void setup() {\n    repository.saveAll(persons);\n  }\n\n  @Test\n  void testFindAll() {\n    var actuals = repository.findAll();\n    assertTrue(actuals.containsAll(persons) && persons.containsAll(actuals));\n  }\n\n  @Test\n  void testSave() {\n    var terry = repository.findByName(\"Terry\");\n    terry.setSurname(\"Lee\");\n    terry.setAge(47);\n    repository.save(terry);\n\n    terry = repository.findByName(\"Terry\");\n    assertEquals(terry.getSurname(), \"Lee\");\n    assertEquals(47, terry.getAge());\n  }\n\n  @Test\n  void testDelete() {\n    var terry = repository.findByName(\"Terry\");\n    repository.delete(terry);\n\n    assertEquals(3, repository.count());\n    assertNull(repository.findByName(\"Terry\"));\n  }\n\n  @Test\n  void testCount() {\n    assertEquals(4, repository.count());\n  }\n\n  @Test\n  void testFindAllByAgeBetweenSpec() {\n    var persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40));\n\n    assertEquals(3, persons.size());\n    assertTrue(persons.stream().allMatch((item) -> item.getAge() > 20 && item.getAge() < 40));\n  }\n\n  @Test\n  void testFindOneByNameEqualSpec() {\n    var actual = repository.findOne(new PersonSpecifications.NameEqualSpec(\"Terry\"));\n    assertTrue(actual.isPresent());\n    assertEquals(terry, actual.get());\n  }\n\n  @AfterEach\n  void cleanup() {\n    repository.deleteAll();\n  }\n}\n"
  },
  {
    "path": "repository/src/test/java/com/iluwatar/repository/AppConfigTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.repository;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport java.sql.SQLException;\nimport javax.sql.DataSource;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.transaction.annotation.Transactional;\n\n/** This case is Just for test the Annotation Based configuration */\n@ExtendWith(SpringExtension.class)\n@SpringBootTest(classes = {AppConfig.class})\nclass AppConfigTest {\n\n  @Autowired DataSource dataSource;\n\n  /** Test for bean instance */\n  @Test\n  void testDataSource() {\n    assertNotNull(dataSource);\n  }\n\n  /** Test for correct query execution */\n  @Test\n  @Transactional\n  void testQuery() throws SQLException {\n    String expected;\n    String result;\n    try (var resultSet = dataSource.getConnection().createStatement().executeQuery(\"SELECT 1\")) {\n      expected = \"1\";\n      result = null;\n      while (resultSet.next()) {\n        result = resultSet.getString(1);\n      }\n    }\n    assertEquals(expected, result);\n  }\n}\n"
  },
  {
    "path": "repository/src/test/java/com/iluwatar/repository/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.repository;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Repository example runs without errors. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "repository/src/test/java/com/iluwatar/repository/RepositoryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.repository;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport jakarta.annotation.Resource;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\n/**\n * Test case to test the functions of {@link PersonRepository}, beside the CRUD functions, the query\n * by {@link org.springframework.data.jpa.domain.Specification} are also test.\n */\n@ExtendWith(SpringExtension.class)\n@SpringBootTest(properties = {\"locations=classpath:applicationContext.xml\"})\nclass RepositoryTest {\n\n  @Resource private PersonRepository repository;\n\n  private final Person peter = new Person(\"Peter\", \"Sagan\", 17);\n  private final Person nasta = new Person(\"Nasta\", \"Kuzminova\", 25);\n  private final Person john = new Person(\"John\", \"lawrence\", 35);\n  private final Person terry = new Person(\"Terry\", \"Law\", 36);\n\n  private final List<Person> persons = List.of(peter, nasta, john, terry);\n\n  /** Prepare data for test */\n  @BeforeEach\n  void setup() {\n    repository.saveAll(persons);\n  }\n\n  @Test\n  void testFindAll() {\n    var actuals = repository.findAll();\n    assertTrue(actuals.containsAll(persons) && persons.containsAll(actuals));\n  }\n\n  @Test\n  void testSave() {\n    var terry = repository.findByName(\"Terry\");\n    terry.setSurname(\"Lee\");\n    terry.setAge(47);\n    repository.save(terry);\n\n    terry = repository.findByName(\"Terry\");\n    assertEquals(terry.getSurname(), \"Lee\");\n    assertEquals(47, terry.getAge());\n  }\n\n  @Test\n  void testDelete() {\n    var terry = repository.findByName(\"Terry\");\n    repository.delete(terry);\n\n    assertEquals(3, repository.count());\n    assertNull(repository.findByName(\"Terry\"));\n  }\n\n  @Test\n  void testCount() {\n    assertEquals(4, repository.count());\n  }\n\n  @Test\n  void testFindAllByAgeBetweenSpec() {\n    var persons = repository.findAll(new PersonSpecifications.AgeBetweenSpec(20, 40));\n\n    assertEquals(3, persons.size());\n    assertTrue(persons.stream().allMatch(item -> item.getAge() > 20 && item.getAge() < 40));\n  }\n\n  @Test\n  void testFindOneByNameEqualSpec() {\n    var actual = repository.findOne(new PersonSpecifications.NameEqualSpec(\"Terry\"));\n    assertTrue(actual.isPresent());\n    assertEquals(terry, actual.get());\n  }\n\n  @AfterEach\n  void cleanup() {\n    repository.deleteAll();\n  }\n}\n"
  },
  {
    "path": "resource-acquisition-is-initialization/README.md",
    "content": "---\ntitle: \"Resource Acquisition Is Initialization in Java: Ensuring Safe Resource Management\"\nshortTitle: Resource Acquisition Is Initialization (RAII)\ndescription: \"Discover how the RAII (Resource Acquisition Is Initialization) pattern can streamline resource management in Java. Learn to implement RAII with practical examples and improve code reliability and maintenance.\"\ncategory: Resource management\nlanguage: en\ntag:\n  - Encapsulation\n  - Memory management\n  - Resource management\n---\n\n## Also known as\n\n* RAII\n* Scope-based Resource Management\n\n## Intent of Resource Acquisition Is Initialization Design Pattern\n\nEnsure efficient Java resource management by tying the resource lifecycle to object lifetime, utilizing the RAII pattern.\n\n## Detailed Explanation of Resource Acquisition Is Initialization Pattern with Real-World Examples\n\nReal-world example\n\n> In a car rental service, each car represents a resource. Using the RAII pattern, when a customer rents a car (acquires the resource), the car is marked as rented. When the customer returns the car (the object goes out of scope), the car is automatically made available for the next customer. This ensures that cars are properly managed and available without manual intervention for checking availability or returns.\n\nIn plain words\n\n> The RAII pattern in Java allows for exception-safe resource management, ensuring robust handling of critical resources.\n\nWikipedia says\n\n> Resource acquisition is initialization (RAII) is a programming idiom used in several object-oriented, statically typed programming languages to describe a particular language behavior. Resource allocation (or acquisition) is done during object creation (specifically initialization), by the constructor, while resource deallocation (release) is done during object destruction (specifically finalization), by the destructor.\n\nSequence diagram\n\n![Resource Acquisition Is Initialization sequence diagram](./etc/raii-sequence-diagram.png)\n\n## Programmatic Example of RAII Pattern in Java\n\nThe RAII pattern is a common idiom used in software design where the acquisition of a resource is done during object creation (initialization), and the release of the resource is done during object destruction. This pattern is particularly useful in dealing with resource leaks and is critical in writing exception-safe code in C++. In Java, RAII is achieved with try-with-resources statement and interfaces `java.io.Closeable` and `AutoCloseable`.\n\n```java\n// This is an example of a resource class that implements the AutoCloseable interface.\n// The resource is acquired in the constructor and released in the close method.\n\n@Slf4j\npublic class SlidingDoor implements AutoCloseable {\n\n  public SlidingDoor() {\n    LOGGER.info(\"Sliding door opens.\"); // Resource acquisition is done here\n  }\n\n  @Override\n  public void close() {\n    LOGGER.info(\"Sliding door closes.\"); // Resource release is done here\n  }\n}\n```\n\nIn the above code, `SlidingDoor` is a resource that implements the `AutoCloseable` interface. The resource (in this case, a door) is \"acquired\" in the constructor (the door is opened), and \"released\" in the `close` method (the door is closed).\n\n```java\n// This is another example of a resource class that implements the Closeable interface.\n// The resource is acquired in the constructor and released in the close method.\n\n@Slf4j\npublic class TreasureChest implements Closeable {\n\n  public TreasureChest() {\n    LOGGER.info(\"Treasure chest opens.\"); // Resource acquisition is done here\n  }\n\n  @Override\n  public void close() {\n    LOGGER.info(\"Treasure chest closes.\"); // Resource release is done here\n  }\n}\n```\n\nSimilarly, `TreasureChest` is another resource that implements the `Closeable` interface. The resource (a treasure chest) is \"acquired\" in the constructor (the chest is opened), and \"released\" in the `close` method (the chest is closed).\n\n```java\n// This is an example of how to use the RAII pattern in Java using the try-with-resources statement.\n\n@Slf4j\npublic class App {\n\n  public static void main(String[] args) {\n\n    try (var ignored = new SlidingDoor()) {\n      LOGGER.info(\"Walking in.\");\n    }\n\n    try (var ignored = new TreasureChest()) {\n      LOGGER.info(\"Looting contents.\");\n    }\n  }\n}\n```\n\nIn the `main` method of the `App` class, we see the RAII pattern in action. The `try-with-resources` statement is used to ensure that each resource is closed at the end of the statement. This is where the `AutoCloseable` or `Closeable` interfaces come into play. When the `try` block is exited (either normally or via an exception), the `close` method of the resource is automatically called, thus ensuring the resource is properly released.\n\nThe console output:\n\n```\n10:07:14.833 [main] INFO com.iluwatar.resource.acquisition.is.initialization.SlidingDoor -- Sliding door opens.\n10:07:14.835 [main] INFO com.iluwatar.resource.acquisition.is.initialization.App -- Walking in.\n10:07:14.835 [main] INFO com.iluwatar.resource.acquisition.is.initialization.SlidingDoor -- Sliding door closes.\n10:07:14.835 [main] INFO com.iluwatar.resource.acquisition.is.initialization.TreasureChest -- Treasure chest opens.\n10:07:14.835 [main] INFO com.iluwatar.resource.acquisition.is.initialization.App -- Looting contents.\n10:07:14.835 [main] INFO com.iluwatar.resource.acquisition.is.initialization.TreasureChest -- Treasure chest closes.\n```\n\n## When to Use the Resource Acquisition Is Initialization Pattern in Java\n\n* Implement RAII in Java applications to manage essential resources such as file handles, network connections, and memory seamlessly.\n* Suitable in environments where deterministic resource management is crucial, such as real-time systems or applications with strict resource constraints.\n\n## Real-World Applications of RAII Pattern in Java\n\n* Java `try-with-resources` statement: Ensures that resources are closed automatically at the end of the statement.\n* Database connections: Using connection pools where the connection is obtained at the beginning of a scope and released at the end.\n* File I/O: Automatically closing files using `try-with-resources`.\n\n## Benefits and Trade-offs of Resource Acquisition Is Initialization Pattern\n\nBenefits:\n\n* Automatic and deterministic resource management.\n* Reduces the likelihood of resource leaks.\n* Enhances code readability and maintainability by clearly defining the scope of resource usage.\n\nTrade-offs:\n\n* May introduce complexity in understanding object lifetimes.\n* Requires careful design to ensure all resources are correctly encapsulated.\n\n## Related Java Design Patterns\n\n* [Object Pool](https://java-design-patterns.com/patterns/object-pool/): Manages a pool of reusable objects to optimize resource allocation and performance, often used for resources that are expensive to create and manage.\n\n## References and Credits\n\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Resource acquisition is initialization](https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization)\n"
  },
  {
    "path": "resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.TreasureChest\" project=\"resource-acquisition-is-initialization\" \n    file=\"/resource-acquisition-is-initialization/src/main/java/com/iluwatar/TreasureChest.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"130\" x=\"229\" y=\"248\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.SlidingDoor\" project=\"resource-acquisition-is-initialization\" \n    file=\"/resource-acquisition-is-initialization/src/main/java/com/iluwatar/SlidingDoor.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"108\" x=\"399\" y=\"248\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "resource-acquisition-is-initialization/etc/resource-acquisition-is-initialization.urm.puml",
    "content": "@startuml\npackage com.iluwatar.resource.acquisition.is.initialization {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class SlidingDoor {\n    - LOGGER : Logger {static}\n    + SlidingDoor()\n    + close()\n  }\n  class TreasureChest {\n    - LOGGER : Logger {static}\n    + TreasureChest()\n    + close()\n  }\n}\n@enduml"
  },
  {
    "path": "resource-acquisition-is-initialization/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>resource-acquisition-is-initialization</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.resource.acquisition.is.initialization.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.resource.acquisition.is.initialization;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Resource Acquisition Is Initialization pattern was developed for exception safe resource\n * management by C++ creator Bjarne Stroustrup.\n *\n * <p>In RAII resource is tied to object lifetime: resource allocation is done during object\n * creation while resource deallocation is done during object destruction.\n *\n * <p>In Java RAII is achieved with try-with-resources statement and interfaces {@link\n * java.io.Closeable} and {@link AutoCloseable}. The try-with-resources statement ensures that each\n * resource is closed at the end of the statement. Any object that implements {@link\n * java.lang.AutoCloseable}, which includes all objects which implement {@link java.io.Closeable},\n * can be used as a resource.\n *\n * <p>In this example, {@link SlidingDoor} implements {@link AutoCloseable} and {@link\n * TreasureChest} implements {@link java.io.Closeable}. Running the example, we can observe that\n * both resources are automatically closed.\n *\n * <p>http://docs.oracle.com/javase/7/docs/technotes/guides/language/try-with-resources.html\n */\n@Slf4j\npublic class App {\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n\n    try (var ignored = new SlidingDoor()) {\n      LOGGER.info(\"Walking in.\");\n    }\n\n    try (var ignored = new TreasureChest()) {\n      LOGGER.info(\"Looting contents.\");\n    }\n  }\n}\n"
  },
  {
    "path": "resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/SlidingDoor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.resource.acquisition.is.initialization;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** SlidingDoor resource. */\n@Slf4j\npublic class SlidingDoor implements AutoCloseable {\n\n  public SlidingDoor() {\n    LOGGER.info(\"Sliding door opens.\");\n  }\n\n  @Override\n  public void close() {\n    LOGGER.info(\"Sliding door closes.\");\n  }\n}\n"
  },
  {
    "path": "resource-acquisition-is-initialization/src/main/java/com/iluwatar/resource/acquisition/is/initialization/TreasureChest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.resource.acquisition.is.initialization;\n\nimport java.io.Closeable;\nimport lombok.extern.slf4j.Slf4j;\n\n/** TreasureChest resource. */\n@Slf4j\npublic class TreasureChest implements Closeable {\n\n  public TreasureChest() {\n    LOGGER.info(\"Treasure chest opens.\");\n  }\n\n  @Override\n  public void close() {\n    LOGGER.info(\"Treasure chest closes.\");\n  }\n}\n"
  },
  {
    "path": "resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.resource.acquisition.is.initialization;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/ClosableTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.resource.acquisition.is.initialization;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/** ClosableTest */\nclass ClosableTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  @Test\n  void testOpenClose() {\n    try (final var ignored = new SlidingDoor();\n        final var ignored1 = new TreasureChest()) {\n      assertTrue(appender.logContains(\"Sliding door opens.\"));\n      assertTrue(appender.logContains(\"Treasure chest opens.\"));\n    }\n    assertTrue(appender.logContains(\"Treasure chest closes.\"));\n    assertTrue(appender.logContains(\"Sliding door closes.\"));\n  }\n\n  /** Logging Appender Implementation */\n  static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender() {\n      ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public boolean logContains(String message) {\n      return log.stream().anyMatch(event -> event.getMessage().equals(message));\n    }\n  }\n}\n"
  },
  {
    "path": "retry/README.md",
    "content": "---\ntitle: \"Retry Pattern in Java: Building Fault-Tolerant Systems with Adaptive Retries\"\nshortTitle: Retry\ndescription: \"Explore the Retry pattern in Java for robust software design. Learn how to implement fault tolerance and improve application reliability through transparent retries of operations involving external communications like network requests.\"\ncategory: Resilience\nlanguage: en\ntag:\n  - Fault tolerance\n  - Performance\n  - Retry\n  - Resilience\n---\n\n## Also known as\n\n* Retry Logic\n* Retry Mechanism\n\n## Intent of Retry Design Pattern\n\nThe Retry pattern in Java transparently retries certain operations that involve communication with external resources, particularly over the network, isolating calling code from the retry implementation details. It is crucial for developing resilient software systems that handle transient failures gracefully.\n\n## Detailed Explanation of Retry Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine you're a delivery driver attempting to deliver a package to a customer's house. You ring the doorbell, but no one answers. Instead of leaving immediately, you wait for a few minutes and try again, repeating this process a few times. This is similar to the Retry pattern in software, where a system retries a failed operation (e.g., making a network request) a certain number of times before finally giving up, in hopes that the issue (e.g., transient network glitch) will be resolved and the operation will succeed. \n\nIn plain words\n\n> Retry pattern transparently retries failed operations over network. \n\n[Microsoft documentation](https://docs.microsoft.com/en-us/azure/architecture/patterns/retry) says\n\n> Enable an application to handle transient failures when it tries to connect to a service or network resource, by transparently retrying a failed operation. This can improve the stability of the application.\n\nFlowchart\n\n![Retry flowchart](./etc/retry-flowchart.png)\n\n## Programmatic Example of Retry Pattern in Java\n\nThe Retry design pattern is a resilience pattern that allows an application to transparently attempt to execute operations multiple times in the expectation that it'll succeed. This pattern is particularly useful when the application is connecting to a network service or a remote resource, where temporary failures are common.\n\nFirst, we have a `BusinessOperation` interface that represents an operation that can be performed and might throw a `BusinessException`.\n\n```java\npublic interface BusinessOperation<T> {\n  T perform() throws BusinessException;\n}\n```\n\nNext, we have a `FindCustomer` class that implements this interface. This class simulates a flaky service that intermittently fails by throwing `BusinessException`s before eventually returning a customer's ID.\n\n```java\npublic final class FindCustomer implements BusinessOperation<String> {\n  @Override\n  public String perform() throws BusinessException {\n    // ...\n  }\n}\n```\n\nThe `Retry` class is where the Retry pattern is implemented. It takes a `BusinessOperation` and a number of attempts, and it will keep trying to perform the operation until it either succeeds or the maximum number of attempts is reached.\n\n```java\npublic final class Retry<T> implements BusinessOperation<T> {\n    \n    private final BusinessOperation<T> op;\n    private final int maxAttempts;\n    private final long delay;\n    private final AtomicInteger attempts;\n    private final Predicate<Exception> test;\n    private final List<Exception> errors;\n\n    @SafeVarargs\n    public Retry(\n            BusinessOperation<T> op,\n            int maxAttempts,\n            long delay,\n            Predicate<Exception>... ignoreTests\n    ) {\n        this.op = op;\n        this.maxAttempts = maxAttempts;\n        this.delay = delay;\n        this.attempts = new AtomicInteger();\n        this.test = Arrays.stream(ignoreTests).reduce(Predicate::or).orElse(e -> false);\n        this.errors = new ArrayList<>();\n    }\n\n    public List<Exception> errors() {\n        return Collections.unmodifiableList(this.errors);\n    }\n\n    public int attempts() {\n        return this.attempts.intValue();\n    }\n\n    @Override\n    public T perform() throws BusinessException {\n        do {\n            try {\n                return this.op.perform();\n            } catch (BusinessException e) {\n                this.errors.add(e);\n\n                if (this.attempts.incrementAndGet() >= this.maxAttempts || !this.test.test(e)) {\n                    throw e;\n                }\n\n                try {\n                    Thread.sleep(this.delay);\n                } catch (InterruptedException f) {\n                    //ignore\n                }\n            }\n        } while (true);\n    }\n}\n```\n\nIn this class, the `perform` method tries to perform the operation. If the operation throws an exception, it checks if the exception is recoverable and if the maximum number of attempts has not been reached. If both conditions are true, it waits for a specified delay and then tries again. If the exception is not recoverable or the maximum number of attempts has been reached, it rethrows the exception.\n\nFinally, here is the `App` class driving the retry pattern example.\n\n```java\npublic final class App {\n    \n  private static final Logger LOG = LoggerFactory.getLogger(App.class);\n  public static final String NOT_FOUND = \"not found\";\n  private static BusinessOperation<String> op;\n\n  public static void main(String[] args) throws Exception {\n    noErrors();\n    errorNoRetry();\n    errorWithRetry();\n    errorWithRetryExponentialBackoff();\n  }\n\n  private static void noErrors() throws Exception {\n    op = new FindCustomer(\"123\");\n    op.perform();\n    LOG.info(\"Sometimes the operation executes with no errors.\");\n  }\n\n  private static void errorNoRetry() throws Exception {\n    op = new FindCustomer(\"123\", new CustomerNotFoundException(NOT_FOUND));\n    try {\n      op.perform();\n    } catch (CustomerNotFoundException e) {\n      LOG.info(\"Yet the operation will throw an error every once in a while.\");\n    }\n  }\n\n  private static void errorWithRetry() throws Exception {\n    final var retry = new Retry<>(\n        new FindCustomer(\"123\", new CustomerNotFoundException(NOT_FOUND)),\n        3,  //3 attempts\n        100, //100 ms delay between attempts\n        e -> CustomerNotFoundException.class.isAssignableFrom(e.getClass())\n    );\n    op = retry;\n    final var customerId = op.perform();\n    LOG.info(String.format(\n        \"However, retrying the operation while ignoring a recoverable error will eventually yield \"\n            + \"the result %s after a number of attempts %s\", customerId, retry.attempts()\n    ));\n  }\n\n  private static void errorWithRetryExponentialBackoff() throws Exception {\n    final var retry = new RetryExponentialBackoff<>(\n        new FindCustomer(\"123\", new CustomerNotFoundException(NOT_FOUND)),\n        6,  //6 attempts\n        30000, //30 s max delay between attempts\n        e -> CustomerNotFoundException.class.isAssignableFrom(e.getClass())\n    );\n    op = retry;\n    final var customerId = op.perform();\n    LOG.info(String.format(\n        \"However, retrying the operation while ignoring a recoverable error will eventually yield \"\n            + \"the result %s after a number of attempts %s\", customerId, retry.attempts()\n    ));\n  }\n}\n```\n\nRunning the code produces the following console output.\n\n```\n10:12:19.573 [main] INFO com.iluwatar.retry.App -- Sometimes the operation executes with no errors.\n10:12:19.575 [main] INFO com.iluwatar.retry.App -- Yet the operation will throw an error every once in a while.\n10:12:19.682 [main] INFO com.iluwatar.retry.App -- However, retrying the operation while ignoring a recoverable error will eventually yield the result 123 after a number of attempts 1\n10:12:22.297 [main] INFO com.iluwatar.retry.App -- However, retrying the operation while ignoring a recoverable error will eventually yield the result 123 after a number of attempts 1\n```\n\nThis way, the Retry pattern allows the application to handle temporary failures gracefully, improving its resilience and reliability.\n\n## When to Use the Retry Pattern in Java\n\nApplying the Retry pattern is particularly effective\n\n* When operations can fail transiently, such as network calls, database connections, or external service integrations.\n* In scenarios where the likelihood of transient failure is high but the cost of retries is low.\n\n## Real-World Applications of Retry Pattern in Java\n\n* In network communication libraries to handle transient failures.\n* Database connection libraries to manage temporary outages or timeouts.\n* APIs interacting with third-party services that may be temporarily unavailable.\n\n## Benefits and Trade-offs of Retry Pattern\n\nBenefits:\n\n* Increases the robustness and fault tolerance of applications.\n* Can significantly reduce the impact of transient failures.\n\nTrade-offs:\n\n* May introduce latency due to retries.\n* Can lead to resource exhaustion if not managed properly.\n* Requires careful configuration of retry parameters to avoid exacerbating the problem.\n\n## Related Java Design Patterns\n\n* [Circuit Breaker](https://java-design-patterns.com/patterns/circuit-breaker/): Used to stop the flow of requests to an external service after a failure threshold is reached, preventing system overload.\n\n## References and Credits\n\n* [Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications](https://amzn.to/4dLvowg)\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n* [Release It!: Design and Deploy Production-Ready Software](https://amzn.to/3UPwmPh)\n* [Retry pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/patterns/retry)\n"
  },
  {
    "path": "retry/etc/retry.urm.puml",
    "content": "@startuml\npackage com.iluwatar.retry {\n  class App {\n    - LOG : Logger {static}\n    - op : BusinessOperation<String> {static}\n    + App()\n    - errorNoRetry() {static}\n    - errorWithRetry() {static}\n    - errorWithRetryExponentialBackoff() {static}\n    + main(args : String[]) {static}\n    - noErrors() {static}\n  }\n  interface BusinessOperation<T> {\n    + perform() : T {abstract}\n  }\n  class FindCustomer {\n    - customerId : String\n    - errors : Deque<BusinessException>\n    + FindCustomer(customerId : String, errors : BusinessException[])\n    + perform() : String\n  }\n  class Retry<T> {\n    - attempts : AtomicInteger\n    - delay : long\n    - errors : List<Exception>\n    - maxAttempts : int\n    - op : BusinessOperation<T>\n    - test : Predicate<Exception>\n    + Retry<T>(op : BusinessOperation<T>, maxAttempts : int, delay : long, ignoreTests : Predicate<Exception>[])\n    + attempts() : int\n    + errors() : List<Exception>\n    + perform() : T\n  }\n  class RetryExponentialBackoff<T> {\n    - RANDOM : Random {static}\n    - attempts : AtomicInteger\n    - errors : List<Exception>\n    - maxAttempts : int\n    - maxDelay : long\n    - op : BusinessOperation<T>\n    - test : Predicate<Exception>\n    + RetryExponentialBackoff<T>(op : BusinessOperation<T>, maxAttempts : int, maxDelay : long, ignoreTests : Predicate<Exception>[])\n    + attempts() : int\n    + errors() : List<Exception>\n    + perform() : T\n  }\n}\nRetryExponentialBackoff -->  \"-op\" BusinessOperation\nRetry -->  \"-op\" BusinessOperation\nApp -->  \"-op\" BusinessOperation\nFindCustomer ..|> BusinessOperation \nRetry ..|> BusinessOperation \nRetryExponentialBackoff ..|> BusinessOperation \n@enduml"
  },
  {
    "path": "retry/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>retry</artifactId>\n  <packaging>jar</packaging>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.hamcrest</groupId>\n      <artifactId>hamcrest-core</artifactId>\n      <version>3.0</version>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.retry.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "retry/src/main/java/com/iluwatar/retry/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.retry;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * The <em>Retry</em> pattern enables applications to handle potentially recoverable failures from\n * the environment if the business requirements and nature of the failures allow it. By retrying\n * failed operations on external dependencies, the application may maintain stability and minimize\n * negative impact on the user experience.\n *\n * <p>In our example, we have the {@link BusinessOperation} interface as an abstraction over all\n * operations that our application performs involving remote systems. The calling code should remain\n * decoupled from implementations.\n *\n * <p>{@link FindCustomer} is a business operation that looks up a customer's record and returns its\n * ID. Imagine its job is performed by looking up the customer in our local database and returning\n * its ID. We can pass {@link CustomerNotFoundException} as one of its {@link\n * FindCustomer#FindCustomer(java.lang.String, com.iluwatar.retry.BusinessException...) constructor\n * parameters} in order to simulate not finding the customer.\n *\n * <p>Imagine that, lately, this operation has experienced intermittent failures due to some weird\n * corruption and/or locking in the data. After retrying a few times the customer is found. The\n * database is still, however, expected to always be available. While a definitive solution is found\n * to the problem, our engineers advise us to retry the operation a set number of times with a set\n * delay between retries, although not too many retries otherwise the end user will be left waiting\n * for a long time, while delays that are too short will not allow the database to recover from the\n * load.\n *\n * <p>To keep the calling code as decoupled as possible from this workaround, we have implemented\n * the retry mechanism as a {@link BusinessOperation} named {@link Retry}.\n *\n * @see <a href=\"https://docs.microsoft.com/en-us/azure/architecture/patterns/retry\">Retry pattern\n *     (Microsoft Azure Docs)</a>\n */\npublic final class App {\n  private static final Logger LOG = LoggerFactory.getLogger(App.class);\n  public static final String NOT_FOUND = \"not found\";\n  private static BusinessOperation<String> op;\n\n  /**\n   * Entry point.\n   *\n   * @param args not used\n   * @throws Exception not expected\n   */\n  public static void main(String[] args) throws Exception {\n    noErrors();\n    errorNoRetry();\n    errorWithRetry();\n    errorWithRetryExponentialBackoff();\n  }\n\n  private static void noErrors() throws Exception {\n    op = new FindCustomer(\"123\");\n    op.perform();\n    LOG.info(\"Sometimes the operation executes with no errors.\");\n  }\n\n  private static void errorNoRetry() throws Exception {\n    op = new FindCustomer(\"123\", new CustomerNotFoundException(NOT_FOUND));\n    try {\n      op.perform();\n    } catch (CustomerNotFoundException e) {\n      LOG.info(\"Yet the operation will throw an error every once in a while.\");\n    }\n  }\n\n  private static void errorWithRetry() throws Exception {\n    final var retry =\n        new Retry<>(\n            new FindCustomer(\"123\", new CustomerNotFoundException(NOT_FOUND)),\n            3, // 3 attempts\n            100, // 100 ms delay between attempts\n            e -> CustomerNotFoundException.class.isAssignableFrom(e.getClass()));\n    op = retry;\n    final var customerId = op.perform();\n    LOG.info(\n        String.format(\n            \"However, retrying the operation while ignoring a recoverable error will eventually yield \"\n                + \"the result %s after a number of attempts %s\",\n            customerId, retry.attempts()));\n  }\n\n  private static void errorWithRetryExponentialBackoff() throws Exception {\n    final var retry =\n        new RetryExponentialBackoff<>(\n            new FindCustomer(\"123\", new CustomerNotFoundException(NOT_FOUND)),\n            6, // 6 attempts\n            30000, // 30 s max delay between attempts\n            e -> CustomerNotFoundException.class.isAssignableFrom(e.getClass()));\n    op = retry;\n    final var customerId = op.perform();\n    LOG.info(\n        String.format(\n            \"However, retrying the operation while ignoring a recoverable error will eventually yield \"\n                + \"the result %s after a number of attempts %s\",\n            customerId, retry.attempts()));\n  }\n}\n"
  },
  {
    "path": "retry/src/main/java/com/iluwatar/retry/BusinessException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.retry;\n\nimport java.io.Serial;\n\n/**\n * The top-most type in our exception hierarchy that signifies that an unexpected error condition\n * occurred. Its use is reserved as a \"catch-all\" for cases where no other subtype captures the\n * specificity of the error condition in question. Calling code is not expected to be able to handle\n * this error and should be reported to the maintainers immediately.\n */\npublic class BusinessException extends Exception {\n  @Serial private static final long serialVersionUID = 6235833142062144336L;\n\n  /**\n   * Ctor.\n   *\n   * @param message the error message\n   */\n  public BusinessException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "retry/src/main/java/com/iluwatar/retry/BusinessOperation.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.retry;\n\n/**\n * Performs some business operation.\n *\n * @param <T> the return type\n */\n@FunctionalInterface\npublic interface BusinessOperation<T> {\n  /**\n   * Performs some business operation, returning a value {@code T} if successful, otherwise throwing\n   * an exception if an error occurs.\n   *\n   * @return the return value\n   * @throws BusinessException if the operation fails. Implementations are allowed to throw more\n   *     specific subtypes depending on the error conditions\n   */\n  T perform() throws BusinessException;\n}\n"
  },
  {
    "path": "retry/src/main/java/com/iluwatar/retry/CustomerNotFoundException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.retry;\n\nimport java.io.Serial;\n\n/**\n * Indicates that the customer was not found.\n *\n * <p>The severity of this error is bounded by its context: was the search for the customer\n * triggered by an input from some end user, or were the search parameters pulled from your\n * database?\n */\npublic final class CustomerNotFoundException extends BusinessException {\n\n  @Serial private static final long serialVersionUID = -6972888602621778664L;\n\n  /**\n   * Ctor.\n   *\n   * @param message the error message\n   */\n  public CustomerNotFoundException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "retry/src/main/java/com/iluwatar/retry/DatabaseNotAvailableException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.retry;\n\nimport java.io.Serial;\n\n/** Catastrophic error indicating that we have lost connection to our database. */\npublic final class DatabaseNotAvailableException extends BusinessException {\n  @Serial private static final long serialVersionUID = -3750769625095997799L;\n\n  /**\n   * Ctor.\n   *\n   * @param message the error message\n   */\n  public DatabaseNotAvailableException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "retry/src/main/java/com/iluwatar/retry/FindCustomer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.retry;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\nimport java.util.List;\n\n/**\n * Finds a customer, returning its ID from our records.\n *\n * <p>This is an imaginary operation that, for some imagined input, returns the ID for a customer.\n * However, this is a \"flaky\" operation that is supposed to fail intermittently, but for the\n * purposes of this example it fails in a programmed way depending on the constructor parameters.\n */\npublic record FindCustomer(String customerId, Deque<BusinessException> errors)\n    implements BusinessOperation<String> {\n  public FindCustomer(String customerId, BusinessException... errors) {\n    this(customerId, new ArrayDeque<>(List.of(errors)));\n  }\n\n  @Override\n  public String perform() throws BusinessException {\n    if (!this.errors.isEmpty()) {\n      throw this.errors.pop();\n    }\n\n    return this.customerId;\n  }\n}\n"
  },
  {
    "path": "retry/src/main/java/com/iluwatar/retry/Retry.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.retry;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.function.Predicate;\n\n/**\n * Decorates {@link BusinessOperation business operation} with \"retry\" capabilities.\n *\n * @param <T> the remote op's return type\n */\npublic final class Retry<T> implements BusinessOperation<T> {\n  private final BusinessOperation<T> op;\n  private final int maxAttempts;\n  private final long delay;\n  private final AtomicInteger attempts;\n  private final Predicate<Exception> test;\n  private final List<Exception> errors;\n\n  /**\n   * Ctor.\n   *\n   * @param op the {@link BusinessOperation} to retry\n   * @param maxAttempts number of times to retry\n   * @param delay delay (in milliseconds) between attempts\n   * @param ignoreTests tests to check whether the remote exception can be ignored. No exceptions\n   *     will be ignored if no tests are given\n   */\n  @SafeVarargs\n  public Retry(\n      BusinessOperation<T> op, int maxAttempts, long delay, Predicate<Exception>... ignoreTests) {\n    this.op = op;\n    this.maxAttempts = maxAttempts;\n    this.delay = delay;\n    this.attempts = new AtomicInteger();\n    this.test = Arrays.stream(ignoreTests).reduce(Predicate::or).orElse(e -> false);\n    this.errors = new ArrayList<>();\n  }\n\n  /**\n   * The errors encountered while retrying, in the encounter order.\n   *\n   * @return the errors encountered while retrying\n   */\n  public List<Exception> errors() {\n    return Collections.unmodifiableList(this.errors);\n  }\n\n  /**\n   * The number of retries performed.\n   *\n   * @return the number of retries performed\n   */\n  public int attempts() {\n    return this.attempts.intValue();\n  }\n\n  @Override\n  public T perform() throws BusinessException {\n    do {\n      try {\n        return this.op.perform();\n      } catch (BusinessException e) {\n        this.errors.add(e);\n\n        if (this.attempts.incrementAndGet() >= this.maxAttempts || !this.test.test(e)) {\n          throw e;\n        }\n\n        try {\n          Thread.sleep(this.delay);\n        } catch (InterruptedException f) {\n          // ignore\n        }\n      }\n    } while (true);\n  }\n}\n"
  },
  {
    "path": "retry/src/main/java/com/iluwatar/retry/RetryExponentialBackoff.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.retry;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Random;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.function.Predicate;\n\n/**\n * Decorates {@link BusinessOperation business operation} with \"retry\" capabilities.\n *\n * @param <T> the remote op's return type\n */\npublic final class RetryExponentialBackoff<T> implements BusinessOperation<T> {\n  private static final Random RANDOM = new Random();\n  private final BusinessOperation<T> op;\n  private final int maxAttempts;\n  private final long maxDelay;\n  private final AtomicInteger attempts;\n  private final Predicate<Exception> test;\n  private final List<Exception> errors;\n\n  /**\n   * Ctor.\n   *\n   * @param op the {@link BusinessOperation} to retry\n   * @param maxAttempts number of times to retry\n   * @param ignoreTests tests to check whether the remote exception can be ignored. No exceptions\n   *     will be ignored if no tests are given\n   */\n  @SafeVarargs\n  public RetryExponentialBackoff(\n      BusinessOperation<T> op,\n      int maxAttempts,\n      long maxDelay,\n      Predicate<Exception>... ignoreTests) {\n    this.op = op;\n    this.maxAttempts = maxAttempts;\n    this.maxDelay = maxDelay;\n    this.attempts = new AtomicInteger();\n    this.test = Arrays.stream(ignoreTests).reduce(Predicate::or).orElse(e -> false);\n    this.errors = new ArrayList<>();\n  }\n\n  /**\n   * The errors encountered while retrying, in the encounter order.\n   *\n   * @return the errors encountered while retrying\n   */\n  public List<Exception> errors() {\n    return Collections.unmodifiableList(this.errors);\n  }\n\n  /**\n   * The number of retries performed.\n   *\n   * @return the number of retries performed\n   */\n  public int attempts() {\n    return this.attempts.intValue();\n  }\n\n  @Override\n  public T perform() throws BusinessException {\n    do {\n      try {\n        return this.op.perform();\n      } catch (BusinessException e) {\n        this.errors.add(e);\n\n        if (this.attempts.incrementAndGet() >= this.maxAttempts || !this.test.test(e)) {\n          throw e;\n        }\n\n        try {\n          var testDelay = (long) Math.pow(2, this.attempts()) * 1000 + RANDOM.nextInt(1000);\n          var delay = Math.min(testDelay, this.maxDelay);\n          Thread.sleep(delay);\n        } catch (InterruptedException f) {\n          // ignore\n        }\n      }\n    } while (true);\n  }\n}\n"
  },
  {
    "path": "retry/src/test/java/com/iluwatar/retry/FindCustomerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.retry;\n\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for {@link FindCustomer}. */\nclass FindCustomerTest {\n  /** Returns the given result with no exceptions. */\n  @Test\n  void noExceptions() throws Exception {\n    assertThat(new FindCustomer(\"123\").perform(), is(\"123\"));\n  }\n\n  /** Throws the given exception. */\n  @Test\n  void oneException() {\n    var findCustomer = new FindCustomer(\"123\", new BusinessException(\"test\"));\n    assertThrows(BusinessException.class, findCustomer::perform);\n  }\n\n  /**\n   * Should first throw the given exceptions, then return the given result.\n   *\n   * @throws Exception not an expected exception\n   */\n  @Test\n  void resultAfterExceptions() throws Exception {\n    final var op =\n        new FindCustomer(\n            \"123\",\n            new CustomerNotFoundException(\"not found\"),\n            new DatabaseNotAvailableException(\"not available\"));\n    try {\n      op.perform();\n    } catch (CustomerNotFoundException e) {\n      // ignore\n    }\n    try {\n      op.perform();\n    } catch (DatabaseNotAvailableException e) {\n      // ignore\n    }\n\n    assertThat(op.perform(), is(\"123\"));\n  }\n}\n"
  },
  {
    "path": "retry/src/test/java/com/iluwatar/retry/RetryExponentialBackoffTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.retry;\n\nimport static org.hamcrest.CoreMatchers.hasItem;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.MatcherAssert.assertThat;\n\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for {@link Retry}. */\nclass RetryExponentialBackoffTest {\n  /** Should contain all errors thrown. */\n  @Test\n  void errors() {\n    final var e = new BusinessException(\"unhandled\");\n    final var retry =\n        new RetryExponentialBackoff<String>(\n            () -> {\n              throw e;\n            },\n            2,\n            0);\n    try {\n      retry.perform();\n    } catch (BusinessException ex) {\n      // ignore\n    }\n\n    assertThat(retry.errors(), hasItem(e));\n  }\n\n  /**\n   * No exceptions will be ignored, hence final number of attempts should be 1 even if we're asking\n   * it to attempt twice.\n   */\n  @Test\n  void attempts() {\n    final var e = new BusinessException(\"unhandled\");\n    final var retry =\n        new RetryExponentialBackoff<String>(\n            () -> {\n              throw e;\n            },\n            2,\n            0);\n    try {\n      retry.perform();\n    } catch (BusinessException ex) {\n      // ignore\n    }\n\n    assertThat(retry.attempts(), is(1));\n  }\n\n  /**\n   * Final number of attempts should be equal to the number of attempts asked because we are asking\n   * it to ignore the exception that will be thrown.\n   */\n  @Test\n  void ignore() {\n    final var e = new CustomerNotFoundException(\"customer not found\");\n    final var retry =\n        new RetryExponentialBackoff<String>(\n            () -> {\n              throw e;\n            },\n            2,\n            0,\n            ex -> CustomerNotFoundException.class.isAssignableFrom(ex.getClass()));\n    try {\n      retry.perform();\n    } catch (BusinessException ex) {\n      // ignore\n    }\n\n    assertThat(retry.attempts(), is(2));\n  }\n}\n"
  },
  {
    "path": "retry/src/test/java/com/iluwatar/retry/RetryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.retry;\n\nimport static org.hamcrest.CoreMatchers.hasItem;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.hamcrest.MatcherAssert.assertThat;\n\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for {@link Retry}. */\nclass RetryTest {\n\n  /** Should contain all errors thrown. */\n  @Test\n  void errors() {\n    final var e = new BusinessException(\"unhandled\");\n    final var retry =\n        new Retry<String>(\n            () -> {\n              throw e;\n            },\n            2,\n            0);\n    try {\n      retry.perform();\n    } catch (BusinessException ex) {\n      // ignore\n    }\n\n    assertThat(retry.errors(), hasItem(e));\n  }\n\n  /**\n   * No exceptions will be ignored, hence final number of attempts should be 1 even if we're asking\n   * it to attempt twice.\n   */\n  @Test\n  void attempts() {\n    final var e = new BusinessException(\"unhandled\");\n    final var retry =\n        new Retry<String>(\n            () -> {\n              throw e;\n            },\n            2,\n            0);\n    try {\n      retry.perform();\n    } catch (BusinessException ex) {\n      // ignore\n    }\n\n    assertThat(retry.attempts(), is(1));\n  }\n\n  /**\n   * Final number of attempts should be equal to the number of attempts asked because we are asking\n   * it to ignore the exception that will be thrown.\n   */\n  @Test\n  void ignore() {\n    final var e = new CustomerNotFoundException(\"customer not found\");\n    final var retry =\n        new Retry<String>(\n            () -> {\n              throw e;\n            },\n            2,\n            0,\n            ex -> CustomerNotFoundException.class.isAssignableFrom(ex.getClass()));\n    try {\n      retry.perform();\n    } catch (BusinessException ex) {\n      // ignore\n    }\n\n    assertThat(retry.attempts(), is(2));\n  }\n}\n"
  },
  {
    "path": "role-object/README.md",
    "content": "---\ntitle: \"Role Object Pattern in Java: Enhancing Flexibility in Object Roles and Behaviors\"\nshortTitle: Role Object\ndescription: \"Explore the Role Object design pattern in Java, which allows objects to dynamically assume various roles, enhancing flexibility and system adaptability. Ideal for developers looking to implement dynamic behavior in applications.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Abstraction\n  - Decoupling\n  - Extensibility\n  - Interface\n  - Object composition\n  - Polymorphism\n  - Runtime\n---\n\n## Intent of Role Object Design Pattern\n\nEfficiently assign dynamic roles to Java objects, enabling them to adapt behaviors and responsibilities on-the-fly, optimizing runtime flexibility.\n\n## Detailed Explanation of Role Object Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a restaurant where staff members can take on different roles based on the needs of the moment. For example, an employee could be a server, a cashier, or a kitchen helper depending on the situation. When the restaurant is busy, a server might also take on the role of a cashier to help process payments quickly. Later, the same employee might assist in the kitchen during a rush. This flexibility allows the restaurant to dynamically allocate responsibilities to meet real-time demands, enhancing efficiency and customer satisfaction. The Role Object pattern in software mimics this by allowing objects to assume different roles and behaviors at runtime, providing similar flexibility and adaptability.\n\nIn plain words\n\n> The Role Object pattern in Java models context-specific views through separate, dynamically managed role objects, enhancing modular design and runtime adaptability.\n\nwiki.c2.com says\n\n> Adapt an object to different client’s needs through transparently attached role objects, each one representing a role the object has to play in that client’s context. The object manages its role set dynamically. By representing roles as individual objects, different contexts are kept separate and system configuration is simplified.\n\nSequence diagram\n\n![Role Object sequence diagram](./etc/role-object-sequence-diagram.png)\n\n## Programmatic Example of Role Object Pattern in Java\n\nThe Role Object design pattern is a pattern that suggests modeling context-specific views of an object as separate role objects. These role objects are dynamically attached to and removed from the core object. The resulting composite object structure, consisting of the core and its role objects, is called a subject. A subject often plays several roles and the same role is likely to be played by different subjects.\n\nIn the provided code, we have a `Customer` object that can play different roles such as `Borrower` and `Investor`. These roles are represented by `BorrowerRole` and `InvestorRole` classes respectively, which extend the `CustomerRole` class.\n\nHere is the `Customer` class:\n\n```java\npublic abstract class Customer {\n\n  public abstract boolean addRole(Role role);\n\n  public abstract boolean hasRole(Role role);\n\n  public abstract boolean remRole(Role role);\n\n  public abstract <T extends Customer> Optional<T> getRole(Role role, Class<T> expectedRole);\n\n  public static Customer newCustomer() {\n    return new CustomerCore();\n  }\n\n  public static Customer newCustomer(Role... role) {\n    var customer = newCustomer();\n    Arrays.stream(role).forEach(customer::addRole);\n    return customer;\n  }\n}\n```\n\nHere is the `BorrowerRole` class:\n\n```java\n@Getter\n@Setter\npublic class BorrowerRole extends CustomerRole {\n\n  private String name;\n\n  public String borrow() {\n    return String.format(\"Borrower %s wants to get some money.\", name);\n  }\n}\n```\n\nIn this class, the `borrow` method represents an operation specific to the `Borrower` role.\n\nSimilarly, the `InvestorRole` class represents the `Investor` role:\n\n```java\n@Getter\n@Setter\npublic class InvestorRole extends CustomerRole {\n\n  private String name;\n\n  private long amountToInvest;\n\n  public String invest() {\n    return String.format(\"Investor %s has invested %d dollars\", name, amountToInvest);\n  }\n}\n```\n\nIn the `InvestorRole` class, the `invest` method represents an operation specific to the `Investor` role.\n\nThe `Customer` object can play either of these roles or both. This is demonstrated in the `main` function:\n\n```java\npublic static void main(String[] args) {\n    var customer = Customer.newCustomer(BORROWER, INVESTOR);\n\n    LOGGER.info(\"New customer created : {}\", customer);\n\n    var hasBorrowerRole = customer.hasRole(BORROWER);\n    LOGGER.info(\"Customer has a borrower role - {}\", hasBorrowerRole);\n    var hasInvestorRole = customer.hasRole(INVESTOR);\n    LOGGER.info(\"Customer has an investor role - {}\", hasInvestorRole);\n\n    customer.getRole(INVESTOR, InvestorRole.class)\n            .ifPresent(inv -> {\n                inv.setAmountToInvest(1000);\n                inv.setName(\"Billy\");\n            });\n    customer.getRole(BORROWER, BorrowerRole.class)\n            .ifPresent(inv -> inv.setName(\"Johny\"));\n\n    customer.getRole(INVESTOR, InvestorRole.class)\n            .map(InvestorRole::invest)\n            .ifPresent(LOGGER::info);\n\n    customer.getRole(BORROWER, BorrowerRole.class)\n            .map(BorrowerRole::borrow)\n            .ifPresent(LOGGER::info);\n}\n```\n\nIn this class, a `Customer` object is created with both `Borrower` and `Investor` roles. The `hasRole` method is used to check if the `Customer` object has a specific role. The `getRole` method is used to get a reference to the role object, which is then used to perform role-specific operations.\n\nRunning the example outputs:\n\n```\n10:22:02.561 [main] INFO com.iluwatar.roleobject.ApplicationRoleObject -- New customer created : Customer{roles=[INVESTOR, BORROWER]}\n10:22:02.564 [main] INFO com.iluwatar.roleobject.ApplicationRoleObject -- Customer has a borrower role - true\n10:22:02.564 [main] INFO com.iluwatar.roleobject.ApplicationRoleObject -- Customer has an investor role - true\n10:22:02.574 [main] INFO com.iluwatar.roleobject.ApplicationRoleObject -- Investor Billy has invested 1000 dollars\n10:22:02.575 [main] INFO com.iluwatar.roleobject.ApplicationRoleObject -- Borrower Johny wants to get some money.\n```\n\n## When to Use the Role Object Pattern in Java\n\n* When an object needs to change its behavior dynamically based on its role.\n* When multiple objects share common behaviors but should exhibit those behaviors differently based on their roles.\n* In scenarios where roles can be added, removed, or changed at runtime.\n\n## Real-World Applications of Role Object Pattern in Java\n\n* User role management in applications where users can have different permissions and responsibilities.\n* Game character roles where characters can take on different roles (e.g., healer, warrior, mage) dynamically.\n* Workflow systems where tasks can be assigned different roles depending on the context.\n\n## Benefits and Trade-offs of Role Object Pattern\n\nBenefits:\n\n* Enhances software flexibility by enabling Java objects to dynamically switch roles, catering to evolving application needs.\n* Enhances code maintainability by decoupling role-specific behaviors from core object logic.\n* Facilitates the addition of new roles without modifying existing code.\n\nTrade-offs:\n\n* Increases complexity due to the need for managing multiple role objects.\n* Potential performance overhead due to the dynamic nature of role assignment and behavior switching.\n\n## Related Java Design Patterns\n\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Similar in dynamically changing an object's behavior, but Role Object focuses on roles that can be combined.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Both can add behaviors to objects, but Role Object allows for dynamic role switching rather than static enhancement.\n* [State](https://java-design-patterns.com/patterns/state/): Manages state transitions similar to role changes, but Role Object deals more with behavioral roles rather than states.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Pattern-Oriented Software Architecture Volume 1: A System of Patterns](https://amzn.to/3xZ1ELU)\n* [Role-Based Access Control](https://amzn.to/3UJzL2l)\n* [Dealing with Roles (Martin Fowler)](https://martinfowler.com/apsupp/roles.pdf)\n* [Role Object (wiki.c2.com)](http://wiki.c2.com/?RoleObject)\n* [The Role Object Pattern (Dirk Bäumer, Dirk Riehle, Wolf Siberski, and Martina Wulf)](https://hillside.net/plop/plop97/Proceedings/riehle.pdf)\n"
  },
  {
    "path": "role-object/etc/role-object.urm.puml",
    "content": "@startuml\npackage com.iluwatar.roleobject {\n  class ApplicationRoleObject {\n    - logger : Logger {static}\n    + ApplicationRoleObject()\n    + main(args : String[]) {static}\n  }\n  class BorrowerRole {\n    - name : String\n    + BorrowerRole()\n    + borrow() : String\n    + getName() : String\n    + setName(name : String)\n  }\n  abstract class Customer {\n    + Customer()\n    + addRole(Role) : boolean {abstract}\n    + getRole(Role, Class<T extends Customer>) : Optional<T extends Customer> {abstract}\n    + hasRole(Role) : boolean {abstract}\n    + newCustomer() : Customer {static}\n    + newCustomer(role : Role[]) : Customer {static}\n    + remRole(Role) : boolean {abstract}\n  }\n  class CustomerCore {\n    - roles : Map<Role, CustomerRole>\n    + CustomerCore()\n    + addRole(role : Role) : boolean\n    + getRole(role : Role, expectedRole : Class<T extends Customer>) : Optional<T extends Customer>\n    + hasRole(role : Role) : boolean\n    + remRole(role : Role) : boolean\n    + toString() : String\n  }\n  abstract class CustomerRole {\n    + CustomerRole()\n  }\n  class InvestorRole {\n    - amountToInvest : long\n    - name : String\n    + InvestorRole()\n    + getAmountToInvest() : long\n    + getName() : String\n    + invest() : String\n    + setAmountToInvest(amountToInvest : long)\n    + setName(name : String)\n  }\n  enum Role {\n    + Borrower {static}\n    + Investor {static}\n    - logger : Logger {static}\n    - typeCst : Class<? extends CustomerRole>\n    + instance() : Optional<T extends CustomerRole>\n    + valueOf(name : String) : Role {static}\n    + values() : Role[] {static}\n  }\n}\nBorrowerRole --|> CustomerRole \nCustomerCore --|> Customer \nCustomerRole --|> CustomerCore \nInvestorRole --|> CustomerRole \n@enduml"
  },
  {
    "path": "role-object/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>role-object</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.roleobject.ApplicationRoleObject</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "role-object/src/main/java/com/iluwatar/roleobject/ApplicationRoleObject.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.roleobject;\n\nimport static com.iluwatar.roleobject.Role.BORROWER;\nimport static com.iluwatar.roleobject.Role.INVESTOR;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Role Object pattern suggests to model context-specific views of an object as separate role\n * objects which are dynamically attached to and removed from the core object. We call the resulting\n * composite object structure, consisting of the core and its role objects, a subject. A subject\n * often plays several roles and the same role is likely to be played by different subjects. As an\n * example consider two different customers playing the role of borrower and investor, respectively.\n * Both roles could as well be played by a single {@link Customer} object. The common superclass for\n * customer-specific roles is provided by {@link CustomerRole}, which also supports the {@link\n * Customer} interface.\n *\n * <p>The {@link CustomerRole} class is abstract and not meant to be instantiated. Concrete\n * subclasses of {@link CustomerRole}, for example {@link BorrowerRole} or {@link InvestorRole},\n * define and implement the interface for specific roles. It is only these subclasses which are\n * instantiated at runtime. The {@link BorrowerRole} class defines the context-specific view of\n * {@link Customer} objects as needed by the loan department. It defines additional operations to\n * manage the customer’s credits and securities. Similarly, the {@link InvestorRole} class adds\n * operations specific to the investment department’s view of customers. A client like the loan\n * application may either work with objects of the {@link CustomerRole} class, using the interface\n * class {@link Customer}, or with objects of concrete {@link CustomerRole} subclasses. Suppose the\n * loan application knows a particular {@link Customer} instance through its {@link Customer}\n * interface. The loan application may want to check whether the {@link Customer} object plays the\n * role of Borrower. To this end it calls {@link Customer#hasRole(Role)} with a suitable role\n * specification. For the purpose of our example, let’s assume we can name roles with enum. If the\n * {@link Customer} object can play the role named “Borrower,” the loan application will ask it to\n * return a reference to the corresponding object. The loan application may now use this reference\n * to call Borrower-specific operations.\n */\n@Slf4j\npublic class ApplicationRoleObject {\n\n  /**\n   * Main entry point.\n   *\n   * @param args program arguments\n   */\n  public static void main(String[] args) {\n    var customer = Customer.newCustomer(BORROWER, INVESTOR);\n\n    LOGGER.info(\"New customer created : {}\", customer);\n\n    var hasBorrowerRole = customer.hasRole(BORROWER);\n    LOGGER.info(\"Customer has a borrower role - {}\", hasBorrowerRole);\n    var hasInvestorRole = customer.hasRole(INVESTOR);\n    LOGGER.info(\"Customer has an investor role - {}\", hasInvestorRole);\n\n    customer\n        .getRole(INVESTOR, InvestorRole.class)\n        .ifPresent(\n            inv -> {\n              inv.setAmountToInvest(1000);\n              inv.setName(\"Billy\");\n            });\n    customer.getRole(BORROWER, BorrowerRole.class).ifPresent(inv -> inv.setName(\"Johny\"));\n\n    customer\n        .getRole(INVESTOR, InvestorRole.class)\n        .map(InvestorRole::invest)\n        .ifPresent(LOGGER::info);\n\n    customer\n        .getRole(BORROWER, BorrowerRole.class)\n        .map(BorrowerRole::borrow)\n        .ifPresent(LOGGER::info);\n  }\n}\n"
  },
  {
    "path": "role-object/src/main/java/com/iluwatar/roleobject/BorrowerRole.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.roleobject;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Borrower role. */\n@Getter\n@Setter\npublic class BorrowerRole extends CustomerRole {\n\n  private String name;\n\n  public String borrow() {\n    return String.format(\"Borrower %s wants to get some money.\", name);\n  }\n}\n"
  },
  {
    "path": "role-object/src/main/java/com/iluwatar/roleobject/Customer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.roleobject;\n\nimport java.util.Arrays;\nimport java.util.Optional;\n\n/** The main abstraction to work with Customer. */\npublic abstract class Customer {\n\n  /**\n   * Add specific role @see {@link Role}.\n   *\n   * @param role to add\n   * @return true if the operation has been successful otherwise false\n   */\n  public abstract boolean addRole(Role role);\n\n  /**\n   * Check specific role @see {@link Role}.\n   *\n   * @param role to check\n   * @return true if the role exists otherwise false\n   */\n  public abstract boolean hasRole(Role role);\n\n  /**\n   * Remove specific role @see {@link Role}.\n   *\n   * @param role to remove\n   * @return true if the operation has been successful otherwise false\n   */\n  public abstract boolean remRole(Role role);\n\n  /**\n   * Get specific instance associated with this role @see {@link Role}.\n   *\n   * @param role to get\n   * @param expectedRole instance class expected to get\n   * @return optional with value if the instance exists and corresponds expected class\n   */\n  public abstract <T extends Customer> Optional<T> getRole(Role role, Class<T> expectedRole);\n\n  public static Customer newCustomer() {\n    return new CustomerCore();\n  }\n\n  /**\n   * Create {@link Customer} with given roles.\n   *\n   * @param role roles\n   * @return Customer\n   */\n  public static Customer newCustomer(Role... role) {\n    var customer = newCustomer();\n    Arrays.stream(role).forEach(customer::addRole);\n    return customer;\n  }\n}\n"
  },
  {
    "path": "role-object/src/main/java/com/iluwatar/roleobject/CustomerCore.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.roleobject;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\n\n/**\n * Core class to store different customer roles.\n *\n * @see CustomerRole Note: not thread safe\n */\npublic class CustomerCore extends Customer {\n\n  private final Map<Role, CustomerRole> roles;\n\n  public CustomerCore() {\n    roles = new HashMap<>();\n  }\n\n  @Override\n  public boolean addRole(Role role) {\n    return role.instance()\n        .map(\n            inst -> {\n              roles.put(role, inst);\n              return true;\n            })\n        .orElse(false);\n  }\n\n  @Override\n  public boolean hasRole(Role role) {\n    return roles.containsKey(role);\n  }\n\n  @Override\n  public boolean remRole(Role role) {\n    return Objects.nonNull(roles.remove(role));\n  }\n\n  @Override\n  public <T extends Customer> Optional<T> getRole(Role role, Class<T> expectedRole) {\n    return Optional.ofNullable(roles.get(role))\n        .filter(expectedRole::isInstance)\n        .map(expectedRole::cast);\n  }\n\n  @Override\n  public String toString() {\n    var roles = Arrays.toString(this.roles.keySet().toArray());\n    return \"Customer{roles=\" + roles + \"}\";\n  }\n}\n"
  },
  {
    "path": "role-object/src/main/java/com/iluwatar/roleobject/CustomerRole.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.roleobject;\n\n/** Key abstraction for segregated roles. */\npublic abstract class CustomerRole extends CustomerCore {}\n"
  },
  {
    "path": "role-object/src/main/java/com/iluwatar/roleobject/InvestorRole.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.roleobject;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Investor role. */\n@Getter\n@Setter\npublic class InvestorRole extends CustomerRole {\n\n  private String name;\n\n  private long amountToInvest;\n\n  public String invest() {\n    return String.format(\"Investor %s has invested %d dollars\", name, amountToInvest);\n  }\n}\n"
  },
  {
    "path": "role-object/src/main/java/com/iluwatar/roleobject/Role.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.roleobject;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Optional;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** Possible roles. */\npublic enum Role {\n  BORROWER(BorrowerRole.class),\n  INVESTOR(InvestorRole.class);\n\n  private final Class<? extends CustomerRole> typeCst;\n\n  Role(Class<? extends CustomerRole> typeCst) {\n    this.typeCst = typeCst;\n  }\n\n  private static final Logger logger = LoggerFactory.getLogger(Role.class);\n\n  /** Get instance. */\n  @SuppressWarnings(\"unchecked\")\n  public <T extends CustomerRole> Optional<T> instance() {\n    var typeCst = this.typeCst;\n    try {\n      return (Optional<T>) Optional.of(typeCst.getDeclaredConstructor().newInstance());\n    } catch (InstantiationException\n        | IllegalAccessException\n        | NoSuchMethodException\n        | InvocationTargetException e) {\n      logger.error(\"error creating an object\", e);\n    }\n    return Optional.empty();\n  }\n}\n"
  },
  {
    "path": "role-object/src/test/java/com/iluwatar/roleobject/ApplicationRoleObjectTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.roleobject;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass ApplicationRoleObjectTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> ApplicationRoleObject.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "role-object/src/test/java/com/iluwatar/roleobject/BorrowerRoleTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.roleobject;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\nclass BorrowerRoleTest {\n\n  @Test\n  void borrowTest() {\n    var borrowerRole = new BorrowerRole();\n    borrowerRole.setName(\"test\");\n    assertEquals(\"Borrower test wants to get some money.\", borrowerRole.borrow());\n  }\n}\n"
  },
  {
    "path": "role-object/src/test/java/com/iluwatar/roleobject/CustomerCoreTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.roleobject;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\nclass CustomerCoreTest {\n\n  @Test\n  void addRole() {\n    var core = new CustomerCore();\n    assertTrue(core.addRole(Role.BORROWER));\n  }\n\n  @Test\n  void hasRole() {\n    var core = new CustomerCore();\n    core.addRole(Role.BORROWER);\n    assertTrue(core.hasRole(Role.BORROWER));\n    assertFalse(core.hasRole(Role.INVESTOR));\n  }\n\n  @Test\n  void remRole() {\n    var core = new CustomerCore();\n    core.addRole(Role.BORROWER);\n\n    var bRole = core.getRole(Role.BORROWER, BorrowerRole.class);\n    assertTrue(bRole.isPresent());\n\n    assertTrue(core.remRole(Role.BORROWER));\n\n    var empt = core.getRole(Role.BORROWER, BorrowerRole.class);\n    assertFalse(empt.isPresent());\n  }\n\n  @Test\n  void getRole() {\n    var core = new CustomerCore();\n    core.addRole(Role.BORROWER);\n\n    var bRole = core.getRole(Role.BORROWER, BorrowerRole.class);\n    assertTrue(bRole.isPresent());\n\n    var nonRole = core.getRole(Role.BORROWER, InvestorRole.class);\n    assertFalse(nonRole.isPresent());\n\n    var invRole = core.getRole(Role.INVESTOR, InvestorRole.class);\n    assertFalse(invRole.isPresent());\n  }\n\n  @Test\n  void toStringTest() {\n    var core = new CustomerCore();\n    core.addRole(Role.BORROWER);\n    assertEquals(\"Customer{roles=[BORROWER]}\", core.toString());\n\n    core = new CustomerCore();\n    core.addRole(Role.INVESTOR);\n    assertEquals(\"Customer{roles=[INVESTOR]}\", core.toString());\n\n    core = new CustomerCore();\n    assertEquals(\"Customer{roles=[]}\", core.toString());\n  }\n}\n"
  },
  {
    "path": "role-object/src/test/java/com/iluwatar/roleobject/InvestorRoleTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.roleobject;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\nclass InvestorRoleTest {\n\n  @Test\n  void investTest() {\n    var investorRole = new InvestorRole();\n    investorRole.setName(\"test\");\n    investorRole.setAmountToInvest(10);\n    assertEquals(\"Investor test has invested 10 dollars\", investorRole.invest());\n  }\n}\n"
  },
  {
    "path": "role-object/src/test/java/com/iluwatar/roleobject/RoleTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.roleobject;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\nclass RoleTest {\n\n  @Test\n  void instanceTest() {\n    var instance = Role.BORROWER.instance();\n    assertTrue(instance.isPresent());\n    assertEquals(instance.get().getClass(), BorrowerRole.class);\n  }\n}\n"
  },
  {
    "path": "saga/README.md",
    "content": "---\ntitle: \"Saga Pattern in Java: Mastering Long-Running Transactions in Distributed Systems\"\nshortTitle: Saga\ndescription: \"Explore the Saga pattern in Java for managing distributed transactions across microservices with resilience and fault tolerance. Learn how the Saga pattern ensures data consistency without locking resources.\"\ncategory: Resilience\nlanguage: en\ntag:\n  - Asynchronous\n  - Decoupling\n  - Fault tolerance\n  - Integration\n  - Microservices\n  - Transactions\n---\n\n## Intent of Saga Design Pattern\n\nTo manage and coordinate distributed transactions across multiple services in a fault-tolerant and reliable manner.\n\n## Detailed Explanation of Saga Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a travel agency coordinating a vacation package for a customer. The package includes booking a flight, reserving a hotel room, and renting a car. Each of these bookings is managed by a different service provider. If the flight booking is successful but the hotel is fully booked, the agency needs to cancel the flight and notify the customer. This ensures that the customer does not end up with only a partial vacation package. In the Saga pattern, this scenario is managed by a series of coordinated transactions, with compensating actions (like canceling the flight) to maintain consistency.\n\nIn plain words\n\n> The Saga pattern in Java coordinates distributed transactions across microservices using a sequence of events and compensating actions to ensure data consistency and fault tolerance.\n\nWikipedia says\n\n> Long-running transactions (also known as the saga interaction pattern) are computer database transactions that avoid locks on non-local resources, use compensation to handle failures, potentially aggregate smaller ACID transactions (also referred to as atomic transactions), and typically use a coordinator to complete or abort the transaction. In contrast to rollback in ACID transactions, compensation restores the original state, or an equivalent, and is business-specific. For example, the compensating action for making a hotel reservation is canceling that reservation.\n\nFlowchart\n\n![Saga flowchart](./etc/saga-flowchart.png)\n\n## Programmatic Example of Saga Pattern in Java\n\nThe Saga design pattern is a sequence of local transactions where each transaction updates data within a single service. It's particularly useful in a microservices architecture where each service has its own database. The Saga pattern ensures data consistency and fault tolerance across services. Here are the key components of the Saga pattern:\n\n1. **Saga**: A Saga is a sequence of local transactions, each of which is called a chapter. The Saga manages the sequence of these transactions, ensuring that each transaction is performed in the correct order and that the Saga is rolled back if a transaction fails.\n\n2. **Chapter**: Each chapter in a Saga represents a local transaction. A chapter has a name, a result (which can be `INIT`, `SUCCESS`, or `ROLLBACK`), and an input value. The `Chapter` class provides methods to get and set these properties.\n\n3. **Service**: A service performs a local transaction. It processes the input value of a chapter and returns a `ChapterResult`. If the transaction fails, it sets the status of the chapter to `ROLLBACK`.\n\n4. **Service Discovery**: This component is responsible for discovering available services and executing the Saga. It processes each chapter in the Saga in order. If a chapter fails, the Saga will be rolled back.\n\n5. **Saga Result**: The result of a Saga can be `PROGRESS`, `FINISHED`, or `ROLLBACKED`. This is determined by the `getResult` method of the `Saga` class.\n\nIn a real-world application, the `Service` class would contain the logic to perform the local transaction and handle failures. The `Saga` class would manage the sequence of local transactions, ensuring that each transaction is performed in the correct order and that the Saga is rolled back if a transaction fails.\n\n**Snippet 1: Creating a Saga**\n\nThe first step in using the Saga pattern is to create a Saga. A Saga is a sequence of chapters, each representing a local transaction. The `Saga` class provides methods to add chapters and to check if a chapter is present.\n\n```java\n// Create a new Saga\nSaga saga = Saga.create();\n```\n\n**Snippet 2: Adding Chapters to the Saga**\n\nEach chapter in a Saga represents a local transaction. We can add chapters to the Saga using the `chapter` method.\n\n```java\n// Add chapters to the Saga\nsaga.chapter(\"init an order\");\nsaga.chapter(\"booking a Fly\");\nsaga.chapter(\"booking a Hotel\");\nsaga.chapter(\"withdrawing Money\");\n```\n\n**Snippet 3: Setting Input Values for Chapters**\n\nEach chapter in a Saga can have an input value. We can set the input value for the last added chapter using the `setInValue` method.\n\n```java\n// Set input values for the chapters\nsaga.chapter(\"init an order\").setInValue(\"good_order\");\n```\n\n**Snippet 4: Executing the Saga**\n\nWe can execute the Saga using a service. The service will process each chapter in the Saga in order. If a chapter fails, the Saga will be rolled back.\n\n```java\n// Execute the Saga\nvar service = sd.findAny();\nvar goodOrderSaga = service.execute(saga);\n```\n\n**Snippet 5: Checking the Result of the Saga**\n\nWe can check the result of the Saga using the `getResult` method. This method returns the result of the Saga, which can be `PROGRESS`, `FINISHED`, or `ROLLBACKED`.\n\n```java\n// Check the result of the Saga\nSagaResult result = goodOrderSaga.getResult();\n```\n\nThe `SagaApplication` class has a `main` method for running the example.\n\n```java\n@Slf4j\npublic class SagaApplication {\n\n  public static void main(String[] args) {\n    var sd = serviceDiscovery();\n    var service = sd.findAny();\n    var goodOrderSaga = service.execute(newSaga(\"good_order\"));\n    var badOrderSaga = service.execute(newSaga(\"bad_order\"));\n    LOGGER.info(\"orders: goodOrder is {}, badOrder is {}\",\n        goodOrderSaga.getResult(), badOrderSaga.getResult());\n  }\n\n  private static Saga newSaga(Object value) {\n    return Saga\n        .create()\n        .chapter(\"init an order\").setInValue(value)\n        .chapter(\"booking a Fly\")\n        .chapter(\"booking a Hotel\")\n        .chapter(\"withdrawing Money\");\n  }\n\n  private static ServiceDiscoveryService serviceDiscovery() {\n    var sd = new ServiceDiscoveryService();\n    return sd\n        .discover(new OrderService(sd))\n        .discover(new FlyBookingService(sd))\n        .discover(new HotelBookingService(sd))\n        .discover(new WithdrawMoneyService(sd));\n  }\n}\n```\n\n1. **Saga**: The `SagaApplication` creates a new Saga using the `Saga.create()` method. It then adds chapters to the Saga using the `chapter` method and sets the input value for each chapter using the `setInValue` method.\n2. **Service**: The `SagaApplication` uses services to execute the chapters in the Saga. Each service represents a local transaction. The `SagaApplication` uses the `ServiceDiscoveryService` to discover available services and execute the Saga.\n3. **Service Discovery**: The `ServiceDiscoveryService` is used to discover available services. The `SagaApplication` uses this to find a service and execute the Saga.\n4. **Saga Execution**: The `SagaApplication` executes the Saga using the `execute` method of a service. It creates two Sagas, one for a good order and one for a bad order, and executes them.\n5. **Saga Result**: The `SagaApplication` checks the result of the Saga using the `getResult` method. It logs the result of the good order Saga and the bad order Saga.\n\nIn summary, the `SagaApplication` creates a Saga, adds chapters to it, sets the input value for each chapter, discovers services, executes the Saga using a service, and checks the result of the Saga.\n\nRunning the example produces the following console output:\n\n```\n11:32:17.779 [main] INFO com.iluwatar.saga.choreography.Service -- The chapter 'init an order' has been started. The data good_order has been stored or calculated successfully\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.Service -- The chapter 'booking a Fly' has been started. The data good_order has been stored or calculated successfully\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.Service -- The chapter 'booking a Hotel' has been started. The data good_order has been stored or calculated successfully\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.Service -- The chapter 'withdrawing Money' has been started. The data good_order has been stored or calculated successfully\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.Service --  the saga has been finished with FINISHED status\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.Service -- The chapter 'init an order' has been started. The data bad_order has been stored or calculated successfully\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.Service -- The chapter 'booking a Fly' has been started. The data bad_order has been stored or calculated successfully\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.Service -- The chapter 'booking a Hotel' has been started. The data bad_order has been stored or calculated successfully\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.Service -- The chapter 'withdrawing Money' has been started. But the exception has been raised.The rollback is about to start\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.Service -- The Rollback for a chapter 'booking a Hotel' has been started. The data bad_order has been rollbacked successfully\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.Service -- The Rollback for a chapter 'booking a Fly' has been started. The data bad_order has been rollbacked successfully\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.Service -- The Rollback for a chapter 'init an order' has been started. The data bad_order has been rollbacked successfully\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.Service --  the saga has been finished with ROLLBACKED status\n11:32:17.782 [main] INFO com.iluwatar.saga.choreography.SagaApplication -- orders: goodOrder is FINISHED, badOrder is ROLLBACKED\n```\n\nThis is a basic example of how to use the Saga design pattern. In a real-world application, the `Saga` class would manage the sequence of local transactions, ensuring that each transaction is performed in the correct order and that the Saga is rolled back if a transaction fails.\n\n## When to Use the Saga Pattern in Java\n\n* When you have a complex transaction that spans multiple microservices.\n* When you need to ensure data consistency across services without using a traditional two-phase commit.\n* When you need to handle long-running transactions in an asynchronous manner.\n\n## Real-World Applications of Saga Pattern in Java\n\n* E-commerce platforms managing orders, inventory, and payment services.\n* Banking systems coordinating between account debits and credits across multiple services.\n* Travel booking systems coordinating flights, hotels, and car rentals.\n\n## Benefits and Trade-offs of Saga Pattern\n\nBenefits:\n\n* Improved fault tolerance and reliability.\n* Scalability due to decoupled services.\n* Flexibility in handling long-running transactions.\n\nTrade-offs:\n\n* Increased complexity in handling compensating transactions.\n* Requires careful design to handle partial failures and rollback scenarios.\n* Potential latency due to asynchronous nature.\n\n## Related Java Design Patterns\n\n* [Event Sourcing](https://java-design-patterns.com/patterns/event-sourcing/): Used to capture state changes as a sequence of events, which can complement the Saga pattern by providing a history of state changes.\n* [Command Query Responsibility Segregation (CQRS)](https://java-design-patterns.com/patterns/cqrs/): Can be used in conjunction with the Saga pattern to separate command and query responsibilities, improving scalability and fault tolerance.\n\n## References and Credits\n\n* [Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems](https://amzn.to/3y6yv1z)\n* [Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions](https://amzn.to/3WcFVui)\n* [Microservices Patterns: With examples in Java](https://amzn.to/3UyWD5O)\n* [Pattern: Saga (microservices.io)](https://microservices.io/patterns/data/saga.html)\n* [Saga distributed transactions pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/reference-architectures/saga/saga)\n"
  },
  {
    "path": "saga/etc/saga.urm.puml",
    "content": "@startuml\npackage com.iluwatar.saga.orchestration {\n  class ChapterResult<K> {\n    - state : State\n    - value : K\n    ~ ChapterResult<K>(value : K, state : State)\n    + failure(val : K) : ChapterResult<K> {static}\n    + getValue() : K\n    + isSuccess() : boolean\n    + success(val : K) : ChapterResult<K> {static}\n  }\n  enum State {\n    + FAILURE {static}\n    + SUCCESS {static}\n    + valueOf(name : String) : State {static}\n    + values() : State[] {static}\n  }\n  class FlyBookingService {\n    + FlyBookingService()\n    + getName() : String\n  }\n  class HotelBookingService {\n    + HotelBookingService()\n    + getName() : String\n    + rollback(value : String) : ChapterResult<String>\n  }\n  interface OrchestrationChapter<K> {\n    + getName() : String {abstract}\n    + process(K) : ChapterResult<K> {abstract}\n    + rollback(K) : ChapterResult<K> {abstract}\n  }\n  class OrderService {\n    + OrderService()\n    + getName() : String\n  }\n  class Saga {\n    - chapters : List<Chapter>\n    - Saga()\n    + chapter(name : String) : Saga\n    + create() : Saga {static}\n    + get(idx : int) : Chapter\n    + isPresent(idx : int) : boolean\n  }\n  class Chapter {\n    ~ name : String\n    + Chapter(name : String)\n    + getName() : String\n  }\n  enum Result {\n    + CRASHED {static}\n    + FINISHED {static}\n    + ROLLBACK {static}\n    + valueOf(name : String) : Result {static}\n    + values() : Result[] {static}\n  }\n  class SagaApplication {\n    - LOGGER : Logger {static}\n    + SagaApplication()\n    + main(args : String[]) {static}\n    - newSaga() : Saga {static}\n    - serviceDiscovery() : ServiceDiscoveryService {static}\n  }\n  class SagaOrchestrator {\n    - LOGGER : Logger {static}\n    - saga : Saga\n    - sd : ServiceDiscoveryService\n    - state : CurrentState\n    + SagaOrchestrator(saga : Saga, sd : ServiceDiscoveryService)\n    + execute(value : K) : Result\n  }\n  -class CurrentState {\n    ~ currentNumber : int\n    ~ isForward : boolean\n    ~ CurrentState()\n    ~ back() : int\n    ~ cleanUp()\n    ~ current() : int\n    ~ directionToBack()\n    ~ forward() : int\n    ~ isForward() : boolean\n  }\n  abstract class Service<K> {\n    # LOGGER : Logger {static}\n    + Service<K>()\n    + getName() : String {abstract}\n    + process(value : K) : ChapterResult<K>\n    + rollback(value : K) : ChapterResult<K>\n  }\n  class ServiceDiscoveryService {\n    - services : Map<String, OrchestrationChapter<?>>\n    + ServiceDiscoveryService()\n    + discover(orchestrationChapterService : OrchestrationChapter<?>) : ServiceDiscoveryService\n    + find(service : String) : Optional<OrchestrationChapter<K>>\n  }\n  class WithdrawMoneyService {\n    + WithdrawMoneyService()\n    + getName() : String\n    + process(value : String) : ChapterResult<String>\n  }\n}\npackage com.iluwatar.saga.choreography {\n  interface ChoreographyChapter {\n    + execute(Saga) : Saga {abstract}\n    + getName() : String {abstract}\n    + process(Saga) : Saga {abstract}\n    + rollback(Saga) : Saga {abstract}\n  }\n  class FlyBookingService {\n    + FlyBookingService(service : ServiceDiscoveryService)\n    + getName() : String\n  }\n  class HotelBookingService {\n    + HotelBookingService(service : ServiceDiscoveryService)\n    + getName() : String\n  }\n  class OrderService {\n    + OrderService(service : ServiceDiscoveryService)\n    + getName() : String\n  }\n  class Saga {\n    - chapters : List<Chapter>\n    - finished : boolean\n    - forward : boolean\n    - pos : int\n    - Saga()\n    ~ back() : int\n    + chapter(name : String) : Saga\n    + create() : Saga {static}\n    ~ forward() : int\n    ~ getCurrent() : Chapter\n    + getCurrentValue() : Object\n    + getResult() : SagaResult\n    ~ isCurrentSuccess() : boolean\n    ~ isForward() : boolean\n    ~ isPresent() : boolean\n    + setCurrentStatus(result : ChapterResult)\n    + setCurrentValue(value : Object)\n    ~ setFinished(finished : boolean)\n    + setInValue(value : Object) : Saga\n    + toString() : String\n  }\n  class Chapter {\n    - inValue : Object\n    - name : String\n    - result : ChapterResult\n    + Chapter(name : String)\n    + getInValue() : Object\n    + getName() : String\n    + isSuccess() : boolean\n    + setInValue(object : Object)\n    + setResult(result : ChapterResult)\n  }\n  enum ChapterResult {\n    + INIT {static}\n    + ROLLBACK {static}\n    + SUCCESS {static}\n    + valueOf(name : String) : ChapterResult {static}\n    + values() : ChapterResult[] {static}\n  }\n  enum SagaResult {\n    + FINISHED {static}\n    + PROGRESS {static}\n    + ROLLBACKED {static}\n    + valueOf(name : String) : SagaResult {static}\n    + values() : SagaResult[] {static}\n  }\n  class SagaApplication {\n    - LOGGER : Logger {static}\n    + SagaApplication()\n    + main(args : String[]) {static}\n    - newSaga(value : Object) : Saga {static}\n    - serviceDiscovery() : ServiceDiscoveryService {static}\n  }\n  abstract class Service {\n    # LOGGER : Logger {static}\n    - sd : ServiceDiscoveryService\n    + Service(service : ServiceDiscoveryService)\n    + execute(saga : Saga) : Saga\n    - isSagaFinished(saga : Saga) : boolean\n    + process(saga : Saga) : Saga\n    + rollback(saga : Saga) : Saga\n    - serviceNotFoundException(chServiceName : String) : Supplier<RuntimeException>\n  }\n  class ServiceDiscoveryService {\n    - services : Map<String, ChoreographyChapter>\n    + ServiceDiscoveryService()\n    + discover(chapterService : ChoreographyChapter) : ServiceDiscoveryService\n    + find(service : String) : Optional<ChoreographyChapter>\n    + findAny() : ChoreographyChapter\n  }\n  class WithdrawMoneyService {\n    + WithdrawMoneyService(service : ServiceDiscoveryService)\n    + getName() : String\n    + process(saga : Saga) : Saga\n  }\n}\nSagaOrchestrator -->  \"-saga\" Saga\nSagaOrchestrator -->  \"-sd\" ServiceDiscoveryService\nSagaOrchestrator -->  \"-state\" CurrentState\nCurrentState ..+ SagaOrchestrator\nChapter ..+ Saga\nSaga -->  \"-chapters\" Chapter\nChapter -->  \"-result\" ChapterResult\nChapterResult ..+ Saga\nChapterResult -->  \"-state\" State\nState ..+ ChapterResult\nResult ..+ Saga\nService -->  \"-sd\" ServiceDiscoveryService\nSagaResult ..+ Saga\nSaga -->  \"-chapters\" Chapter\nChapter ..+ Saga\nFlyBookingService --|> Service \nHotelBookingService --|> Service \nOrderService --|> Service \nService ..|> ChoreographyChapter \nWithdrawMoneyService --|> Service \nFlyBookingService --|> Service \nHotelBookingService --|> Service \nOrderService --|> Service \nService ..|> OrchestrationChapter \nWithdrawMoneyService --|> Service \n@enduml"
  },
  {
    "path": "saga/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>saga</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <id>Choreography</id>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.saga.choreography.SagaApplication</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n          <execution>\n            <id>Orchestration</id>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.saga.orchestration.SagaApplication</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyChapter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.choreography;\n\n/**\n * ChoreographyChapter is an interface representing a contract for an external service. In that\n * case, a service needs to make a decision what to do further hence the server needs to get all\n * context representing {@link Saga}\n */\npublic interface ChoreographyChapter {\n\n  /**\n   * In that case, every method is responsible to make a decision on what to do then.\n   *\n   * @param saga incoming saga\n   * @return saga result\n   */\n  Saga execute(Saga saga);\n\n  /**\n   * get name method.\n   *\n   * @return service name.\n   */\n  String getName();\n\n  /**\n   * The operation executed in general case.\n   *\n   * @param saga incoming saga\n   * @return result {@link Saga}\n   */\n  Saga process(Saga saga);\n\n  /**\n   * The operation executed in rollback case.\n   *\n   * @param saga incoming saga\n   * @return result {@link Saga}\n   */\n  Saga rollback(Saga saga);\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.choreography;\n\n/** Class representing a service to book a fly. */\npublic class FlyBookingService extends Service {\n  public FlyBookingService(ServiceDiscoveryService service) {\n    super(service);\n  }\n\n  @Override\n  public String getName() {\n    return \"booking a Fly\";\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.choreography;\n\n/** Class representing a service to book a hotel. */\npublic class HotelBookingService extends Service {\n  public HotelBookingService(ServiceDiscoveryService service) {\n    super(service);\n  }\n\n  @Override\n  public String getName() {\n    return \"booking a Hotel\";\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.choreography;\n\n/** Class representing a service to init a new order. */\npublic class OrderService extends Service {\n\n  public OrderService(ServiceDiscoveryService service) {\n    super(service);\n  }\n\n  @Override\n  public String getName() {\n    return \"init an order\";\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/choreography/Saga.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.choreography;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/**\n * Saga representation. Saga consists of chapters. Every ChoreographyChapter is executed a certain\n * service.\n */\npublic class Saga {\n\n  private final List<Chapter> chapters;\n  private int pos;\n  private boolean forward;\n  private boolean finished;\n\n  public static Saga create() {\n    return new Saga();\n  }\n\n  /**\n   * get resuzlt of saga.\n   *\n   * @return result of saga @see {@link SagaResult}\n   */\n  public SagaResult getResult() {\n    if (finished) {\n      return forward ? SagaResult.FINISHED : SagaResult.ROLLBACKED;\n    }\n\n    return SagaResult.PROGRESS;\n  }\n\n  /**\n   * add chapter to saga.\n   *\n   * @param name chapter name\n   * @return this\n   */\n  public Saga chapter(String name) {\n    this.chapters.add(new Chapter(name));\n    return this;\n  }\n\n  /**\n   * set value to last chapter.\n   *\n   * @param value invalue\n   * @return this\n   */\n  public Saga setInValue(Object value) {\n    if (chapters.isEmpty()) {\n      return this;\n    }\n    chapters.get(chapters.size() - 1).setInValue(value);\n    return this;\n  }\n\n  /**\n   * get value from current chapter.\n   *\n   * @return value\n   */\n  public Object getCurrentValue() {\n    return chapters.get(pos).getInValue();\n  }\n\n  /**\n   * set value to current chapter.\n   *\n   * @param value to set\n   */\n  public void setCurrentValue(Object value) {\n    chapters.get(pos).setInValue(value);\n  }\n\n  /**\n   * set status for current chapter.\n   *\n   * @param result to set\n   */\n  public void setCurrentStatus(ChapterResult result) {\n    chapters.get(pos).setResult(result);\n  }\n\n  void setFinished(boolean finished) {\n    this.finished = finished;\n  }\n\n  boolean isForward() {\n    return forward;\n  }\n\n  int forward() {\n    return ++pos;\n  }\n\n  int back() {\n    this.forward = false;\n    return --pos;\n  }\n\n  private Saga() {\n    this.chapters = new ArrayList<>();\n    this.pos = 0;\n    this.forward = true;\n    this.finished = false;\n  }\n\n  Chapter getCurrent() {\n    return chapters.get(pos);\n  }\n\n  boolean isPresent() {\n    return pos >= 0 && pos < chapters.size();\n  }\n\n  boolean isCurrentSuccess() {\n    return chapters.get(pos).isSuccess();\n  }\n\n  /**\n   * Class presents a chapter status and incoming parameters(incoming parameter transforms to\n   * outcoming parameter).\n   */\n  public static class Chapter {\n    @Getter private final String name;\n    @Setter private ChapterResult result;\n    @Getter @Setter private Object inValue;\n\n    public Chapter(String name) {\n      this.name = name;\n      this.result = ChapterResult.INIT;\n    }\n\n    /**\n     * the result for chapter is good.\n     *\n     * @return true if is good otherwise bad\n     */\n    public boolean isSuccess() {\n      return result == ChapterResult.SUCCESS;\n    }\n  }\n\n  /** result for chapter. */\n  public enum ChapterResult {\n    INIT,\n    SUCCESS,\n    ROLLBACK\n  }\n\n  /** result for saga. */\n  public enum SagaResult {\n    PROGRESS,\n    FINISHED,\n    ROLLBACKED\n  }\n\n  @Override\n  public String toString() {\n    return \"Saga{\"\n        + \"chapters=\"\n        + Arrays.toString(chapters.toArray())\n        + \", pos=\"\n        + pos\n        + \", forward=\"\n        + forward\n        + '}';\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.choreography;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This pattern is used in distributed services to perform a group of operations atomically. This is\n * an analog of transaction in a database but in terms of microservices architecture this is\n * executed in a distributed environment\n *\n * <p>A saga is a sequence of local transactions in a certain context. If one transaction fails for\n * some reason, the saga executes compensating transactions(rollbacks) to undo the impact of the\n * preceding transactions.\n *\n * <p>In this approach, there are no mediators or orchestrators services. All chapters are handled\n * and moved by services manually.\n *\n * <p>The major difference with choreography saga is an ability to handle crashed services\n * (otherwise in choreography services very hard to prevent a saga if one of them has been crashed)\n *\n * @see com.iluwatar.saga.choreography.Saga\n * @see Service\n */\n@Slf4j\npublic class SagaApplication {\n\n  /** main method. */\n  public static void main(String[] args) {\n    var sd = serviceDiscovery();\n    var service = sd.findAny();\n    var goodOrderSaga = service.execute(newSaga(\"good_order\"));\n    var badOrderSaga = service.execute(newSaga(\"bad_order\"));\n    LOGGER.info(\n        \"orders: goodOrder is {}, badOrder is {}\",\n        goodOrderSaga.getResult(),\n        badOrderSaga.getResult());\n  }\n\n  private static Saga newSaga(Object value) {\n    return Saga.create()\n        .chapter(\"init an order\")\n        .setInValue(value)\n        .chapter(\"booking a Fly\")\n        .chapter(\"booking a Hotel\")\n        .chapter(\"withdrawing Money\");\n  }\n\n  private static ServiceDiscoveryService serviceDiscovery() {\n    var sd = new ServiceDiscoveryService();\n    return sd.discover(new OrderService(sd))\n        .discover(new FlyBookingService(sd))\n        .discover(new HotelBookingService(sd))\n        .discover(new WithdrawMoneyService(sd));\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/choreography/Service.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.choreography;\n\nimport java.util.function.Supplier;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Common abstraction class representing services. implementing a general contract @see {@link\n * ChoreographyChapter}\n */\npublic abstract class Service implements ChoreographyChapter {\n  protected static final Logger LOGGER = LoggerFactory.getLogger(Service.class);\n\n  private final ServiceDiscoveryService sd;\n\n  public Service(ServiceDiscoveryService service) {\n    this.sd = service;\n  }\n\n  @Override\n  public Saga execute(Saga saga) {\n    var nextSaga = saga;\n    Object nextVal;\n    var chapterName = saga.getCurrent().getName();\n    if (chapterName.equals(getName())) {\n      if (saga.isForward()) {\n        nextSaga = process(saga);\n        nextVal = nextSaga.getCurrentValue();\n        if (nextSaga.isCurrentSuccess()) {\n          nextSaga.forward();\n        } else {\n          nextSaga.back();\n        }\n      } else {\n        nextSaga = rollback(saga);\n        nextVal = nextSaga.getCurrentValue();\n        nextSaga.back();\n      }\n\n      if (isSagaFinished(nextSaga)) {\n        return nextSaga;\n      }\n\n      nextSaga.setCurrentValue(nextVal);\n    }\n    var finalNextSaga = nextSaga;\n\n    return sd.find(chapterName)\n        .map(ch -> ch.execute(finalNextSaga))\n        .orElseThrow(serviceNotFoundException(chapterName));\n  }\n\n  private Supplier<RuntimeException> serviceNotFoundException(String chServiceName) {\n    return () ->\n        new RuntimeException(String.format(\"the service %s has not been found\", chServiceName));\n  }\n\n  @Override\n  public Saga process(Saga saga) {\n    var inValue = saga.getCurrentValue();\n    LOGGER.info(\n        \"The chapter '{}' has been started. \"\n            + \"The data {} has been stored or calculated successfully\",\n        getName(),\n        inValue);\n    saga.setCurrentStatus(Saga.ChapterResult.SUCCESS);\n    saga.setCurrentValue(inValue);\n    return saga;\n  }\n\n  @Override\n  public Saga rollback(Saga saga) {\n    var inValue = saga.getCurrentValue();\n    LOGGER.info(\n        \"The Rollback for a chapter '{}' has been started. \"\n            + \"The data {} has been rollbacked successfully\",\n        getName(),\n        inValue);\n\n    saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK);\n    saga.setCurrentValue(inValue);\n    return saga;\n  }\n\n  private boolean isSagaFinished(Saga saga) {\n    if (!saga.isPresent()) {\n      saga.setFinished(true);\n      LOGGER.info(\" the saga has been finished with {} status\", saga.getResult());\n      return true;\n    }\n    return false;\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.choreography;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.NoSuchElementException;\nimport java.util.Optional;\n\n/** The class representing a service discovery pattern. */\npublic class ServiceDiscoveryService {\n  private final Map<String, ChoreographyChapter> services;\n\n  /**\n   * find any service.\n   *\n   * @return any service\n   * @throws NoSuchElementException if no elements further\n   */\n  public ChoreographyChapter findAny() {\n    return services.values().iterator().next();\n  }\n\n  public Optional<ChoreographyChapter> find(String service) {\n    return Optional.ofNullable(services.getOrDefault(service, null));\n  }\n\n  public ServiceDiscoveryService discover(ChoreographyChapter chapterService) {\n    services.put(chapterService.getName(), chapterService);\n    return this;\n  }\n\n  public ServiceDiscoveryService() {\n    this.services = new HashMap<>();\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.choreography;\n\n/** Class representing a service to withdraw a money. */\npublic class WithdrawMoneyService extends Service {\n\n  public WithdrawMoneyService(ServiceDiscoveryService service) {\n    super(service);\n  }\n\n  @Override\n  public String getName() {\n    return \"withdrawing Money\";\n  }\n\n  @Override\n  public Saga process(Saga saga) {\n    var inValue = saga.getCurrentValue();\n\n    if (inValue.equals(\"bad_order\")) {\n      LOGGER.info(\n          \"The chapter '{}' has been started. But the exception has been raised.\"\n              + \"The rollback is about to start\",\n          getName());\n      saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK);\n      return saga;\n    }\n    return super.process(saga);\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\nimport lombok.Getter;\n\n/**\n * Executing result for chapter.\n *\n * @param <K> incoming value\n */\npublic class ChapterResult<K> {\n  @Getter private final K value;\n  private final State state;\n\n  ChapterResult(K value, State state) {\n    this.value = value;\n    this.state = state;\n  }\n\n  public boolean isSuccess() {\n    return state == State.SUCCESS;\n  }\n\n  public static <K> ChapterResult<K> success(K val) {\n    return new ChapterResult<>(val, State.SUCCESS);\n  }\n\n  public static <K> ChapterResult<K> failure(K val) {\n    return new ChapterResult<>(val, State.FAILURE);\n  }\n\n  /** state for chapter. */\n  public enum State {\n    SUCCESS,\n    FAILURE\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\n/** Class representing a service to book a fly. */\npublic class FlyBookingService extends Service<String> {\n  @Override\n  public String getName() {\n    return \"booking a Fly\";\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\n/** Class representing a service to book a hotel. */\npublic class HotelBookingService extends Service<String> {\n  @Override\n  public String getName() {\n    return \"booking a Hotel\";\n  }\n\n  @Override\n  public ChapterResult<String> rollback(String value) {\n    if (value.equals(\"crashed_order\")) {\n      LOGGER.info(\n          \"The Rollback for a chapter '{}' has been started. \"\n              + \"The data {} has been failed.The saga has been crashed.\",\n          getName(),\n          value);\n\n      return ChapterResult.failure(value);\n    }\n\n    LOGGER.info(\n        \"The Rollback for a chapter '{}' has been started. \"\n            + \"The data {} has been rollbacked successfully\",\n        getName(),\n        value);\n\n    return super.rollback(value);\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationChapter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\n/**\n * ChoreographyChapter is an interface representing a contract for an external service.\n *\n * @param <K> is type for passing params\n */\npublic interface OrchestrationChapter<K> {\n\n  /**\n   * method get name.\n   *\n   * @return service name.\n   */\n  String getName();\n\n  /**\n   * The operation executed in general case.\n   *\n   * @param value incoming value\n   * @return result {@link ChapterResult}\n   */\n  ChapterResult<K> process(K value);\n\n  /**\n   * The operation executed in rollback case.\n   *\n   * @param value incoming value\n   * @return result {@link ChapterResult}\n   */\n  ChapterResult<K> rollback(K value);\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\n/** Class representing a service to init a new order. */\npublic class OrderService extends Service<String> {\n  @Override\n  public String getName() {\n    return \"init an order\";\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\n/**\n * Saga representation. Saga consists of chapters. Every ChoreographyChapter is executed by a\n * certain service.\n */\npublic class Saga {\n\n  private final List<Chapter> chapters;\n\n  private Saga() {\n    this.chapters = new ArrayList<>();\n  }\n\n  public Saga chapter(String name) {\n    this.chapters.add(new Chapter(name));\n    return this;\n  }\n\n  public Chapter get(int idx) {\n    return chapters.get(idx);\n  }\n\n  public boolean isPresent(int idx) {\n    return idx >= 0 && idx < chapters.size();\n  }\n\n  public static Saga create() {\n    return new Saga();\n  }\n\n  /** result for saga. */\n  public enum Result {\n    FINISHED,\n    ROLLBACK,\n    CRASHED\n  }\n\n  /** class represents chapter name. */\n  @AllArgsConstructor\n  @Getter\n  public static class Chapter {\n    String name;\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This pattern is used in distributed services to perform a group of operations atomically. This is\n * an analog of transaction in a database but in terms of microservices architecture this is\n * executed in a distributed environment\n *\n * <p>A saga is a sequence of local transactions in a certain context. If one transaction fails for\n * some reason, the saga executes compensating transactions(rollbacks) to undo the impact of the\n * preceding transactions.\n *\n * <p>In this approach, there is an orchestrator @see {@link SagaOrchestrator} that manages all the\n * transactions and directs the participant services to execute local transactions based on events.\n * The major difference with choreography saga is an ability to handle crashed services (otherwise\n * in choreography services very hard to prevent a saga if one of them has been crashed)\n *\n * @see Saga\n * @see SagaOrchestrator\n * @see Service\n */\n@Slf4j\npublic class SagaApplication {\n\n  /** method to show common saga logic. */\n  public static void main(String[] args) {\n    var sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery());\n\n    Saga.Result goodOrder = sagaOrchestrator.execute(\"good_order\");\n    Saga.Result badOrder = sagaOrchestrator.execute(\"bad_order\");\n    Saga.Result crashedOrder = sagaOrchestrator.execute(\"crashed_order\");\n\n    LOGGER.info(\n        \"orders: goodOrder is {}, badOrder is {},crashedOrder is {}\",\n        goodOrder,\n        badOrder,\n        crashedOrder);\n  }\n\n  private static Saga newSaga() {\n    return Saga.create()\n        .chapter(\"init an order\")\n        .chapter(\"booking a Fly\")\n        .chapter(\"booking a Hotel\")\n        .chapter(\"withdrawing Money\");\n  }\n\n  private static ServiceDiscoveryService serviceDiscovery() {\n    return new ServiceDiscoveryService()\n        .discover(new OrderService())\n        .discover(new FlyBookingService())\n        .discover(new HotelBookingService())\n        .discover(new WithdrawMoneyService());\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\nimport static com.iluwatar.saga.orchestration.Saga.Result;\nimport static com.iluwatar.saga.orchestration.Saga.Result.CRASHED;\nimport static com.iluwatar.saga.orchestration.Saga.Result.FINISHED;\nimport static com.iluwatar.saga.orchestration.Saga.Result.ROLLBACK;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The orchestrator that manages all the transactions and directs the participant services to\n * execute local transactions based on events.\n */\n@Slf4j\npublic class SagaOrchestrator {\n  private final Saga saga;\n  private final ServiceDiscoveryService sd;\n  private final CurrentState state;\n\n  /**\n   * Create a new service to orchetrate sagas.\n   *\n   * @param saga saga to process\n   * @param sd service discovery @see {@link ServiceDiscoveryService}\n   */\n  public SagaOrchestrator(Saga saga, ServiceDiscoveryService sd) {\n    this.saga = saga;\n    this.sd = sd;\n    this.state = new CurrentState();\n  }\n\n  /**\n   * pipeline to execute saga process/story.\n   *\n   * @param value incoming value\n   * @param <K> type for incoming value\n   * @return result @see {@link Result}\n   */\n  @SuppressWarnings(\"unchecked\")\n  public <K> Result execute(K value) {\n    state.cleanUp();\n    LOGGER.info(\" The new saga is about to start\");\n    var result = FINISHED;\n    K tempVal = value;\n\n    while (true) {\n      var next = state.current();\n      var ch = saga.get(next);\n      var srvOpt = sd.find(ch.name);\n\n      if (srvOpt.isEmpty()) {\n        state.directionToBack();\n        state.back();\n        continue;\n      }\n\n      var srv = srvOpt.get();\n\n      if (state.isForward()) {\n        var processRes = srv.process(tempVal);\n        if (processRes.isSuccess()) {\n          next = state.forward();\n          tempVal = (K) processRes.getValue();\n        } else {\n          state.directionToBack();\n        }\n      } else {\n        var rlRes = srv.rollback(tempVal);\n        if (rlRes.isSuccess()) {\n          next = state.back();\n          tempVal = (K) rlRes.getValue();\n        } else {\n          result = CRASHED;\n          next = state.back();\n        }\n      }\n\n      if (!saga.isPresent(next)) {\n        return state.isForward() ? FINISHED : result == CRASHED ? CRASHED : ROLLBACK;\n      }\n    }\n  }\n\n  private static class CurrentState {\n    int currentNumber;\n    boolean isForward;\n\n    void cleanUp() {\n      currentNumber = 0;\n      isForward = true;\n    }\n\n    CurrentState() {\n      this.currentNumber = 0;\n      this.isForward = true;\n    }\n\n    boolean isForward() {\n      return isForward;\n    }\n\n    void directionToBack() {\n      isForward = false;\n    }\n\n    int forward() {\n      return ++currentNumber;\n    }\n\n    int back() {\n      return --currentNumber;\n    }\n\n    int current() {\n      return currentNumber;\n    }\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/orchestration/Service.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Common abstraction class representing services. implementing a general contract @see {@link\n * OrchestrationChapter}\n *\n * @param <K> type of incoming param\n */\npublic abstract class Service<K> implements OrchestrationChapter<K> {\n  protected static final Logger LOGGER = LoggerFactory.getLogger(Service.class);\n\n  @Override\n  public abstract String getName();\n\n  @Override\n  public ChapterResult<K> process(K value) {\n    LOGGER.info(\n        \"The chapter '{}' has been started. \"\n            + \"The data {} has been stored or calculated successfully\",\n        getName(),\n        value);\n    return ChapterResult.success(value);\n  }\n\n  @Override\n  public ChapterResult<K> rollback(K value) {\n    LOGGER.info(\n        \"The Rollback for a chapter '{}' has been started. \"\n            + \"The data {} has been rollbacked successfully\",\n        getName(),\n        value);\n    return ChapterResult.success(value);\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Optional;\n\n/** The class representing a service discovery pattern. */\npublic class ServiceDiscoveryService {\n  private final Map<String, OrchestrationChapter<?>> services;\n\n  public Optional<OrchestrationChapter> find(String service) {\n    return Optional.ofNullable(services.getOrDefault(service, null));\n  }\n\n  public ServiceDiscoveryService discover(OrchestrationChapter<?> orchestrationChapterService) {\n    services.put(orchestrationChapterService.getName(), orchestrationChapterService);\n    return this;\n  }\n\n  public ServiceDiscoveryService() {\n    this.services = new HashMap<>();\n  }\n}\n"
  },
  {
    "path": "saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\n/** Class representing a service to withdraw a money. */\npublic class WithdrawMoneyService extends Service<String> {\n  @Override\n  public String getName() {\n    return \"withdrawing Money\";\n  }\n\n  @Override\n  public ChapterResult<String> process(String value) {\n    if (value.equals(\"bad_order\") || value.equals(\"crashed_order\")) {\n      LOGGER.info(\n          \"The chapter '{}' has been started. But the exception has been raised.\"\n              + \"The rollback is about to start\",\n          getName());\n      return ChapterResult.failure(value);\n    }\n    return super.process(value);\n  }\n}\n"
  },
  {
    "path": "saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.choreography;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport com.iluwatar.saga.orchestration.SagaApplication;\nimport org.junit.jupiter.api.Test;\n\n/***\n * empty test\n */\nclass SagaApplicationTest {\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> SagaApplication.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.choreography;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** test to check choreography saga */\nclass SagaChoreographyTest {\n\n  @Test\n  void executeTest() {\n    var sd = serviceDiscovery();\n    var service = sd.findAny();\n    var badOrderSaga = service.execute(newSaga(\"bad_order\"));\n    var goodOrderSaga = service.execute(newSaga(\"good_order\"));\n\n    assertEquals(Saga.SagaResult.ROLLBACKED, badOrderSaga.getResult());\n    assertEquals(Saga.SagaResult.FINISHED, goodOrderSaga.getResult());\n  }\n\n  private static Saga newSaga(Object value) {\n    return Saga.create()\n        .chapter(\"init an order\")\n        .setInValue(value)\n        .chapter(\"booking a Fly\")\n        .chapter(\"booking a Hotel\")\n        .chapter(\"withdrawing Money\");\n  }\n\n  private static ServiceDiscoveryService serviceDiscovery() {\n    var sd = new ServiceDiscoveryService();\n    return sd.discover(new OrderService(sd))\n        .discover(new FlyBookingService(sd))\n        .discover(new HotelBookingService(sd))\n        .discover(new WithdrawMoneyService(sd));\n  }\n}\n"
  },
  {
    "path": "saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test if the application starts without throwing an exception. */\nclass SagaApplicationTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> SagaApplication.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\nimport static com.iluwatar.saga.orchestration.Saga.Result;\nimport static org.junit.jupiter.api.Assertions.assertArrayEquals;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\n\n/** test to test orchestration logic */\nclass SagaOrchestratorInternallyTest {\n\n  private final List<String> records = new ArrayList<>();\n\n  @Test\n  void executeTest() {\n    var sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery());\n    var result = sagaOrchestrator.execute(1);\n    assertEquals(Result.ROLLBACK, result);\n    assertArrayEquals(\n        new String[] {\"+1\", \"+2\", \"+3\", \"+4\", \"-4\", \"-3\", \"-2\", \"-1\"},\n        records.toArray(new String[] {}));\n  }\n\n  private static Saga newSaga() {\n    return Saga.create().chapter(\"1\").chapter(\"2\").chapter(\"3\").chapter(\"4\");\n  }\n\n  private ServiceDiscoveryService serviceDiscovery() {\n    return new ServiceDiscoveryService()\n        .discover(new Service1())\n        .discover(new Service2())\n        .discover(new Service3())\n        .discover(new Service4());\n  }\n\n  class Service1 extends Service<Integer> {\n\n    @Override\n    public String getName() {\n      return \"1\";\n    }\n\n    @Override\n    public ChapterResult<Integer> process(Integer value) {\n      records.add(\"+1\");\n      return ChapterResult.success(value);\n    }\n\n    @Override\n    public ChapterResult<Integer> rollback(Integer value) {\n      records.add(\"-1\");\n      return ChapterResult.success(value);\n    }\n  }\n\n  class Service2 extends Service<Integer> {\n\n    @Override\n    public String getName() {\n      return \"2\";\n    }\n\n    @Override\n    public ChapterResult<Integer> process(Integer value) {\n      records.add(\"+2\");\n      return ChapterResult.success(value);\n    }\n\n    @Override\n    public ChapterResult<Integer> rollback(Integer value) {\n      records.add(\"-2\");\n      return ChapterResult.success(value);\n    }\n  }\n\n  class Service3 extends Service<Integer> {\n\n    @Override\n    public String getName() {\n      return \"3\";\n    }\n\n    @Override\n    public ChapterResult<Integer> process(Integer value) {\n      records.add(\"+3\");\n      return ChapterResult.success(value);\n    }\n\n    @Override\n    public ChapterResult<Integer> rollback(Integer value) {\n      records.add(\"-3\");\n      return ChapterResult.success(value);\n    }\n  }\n\n  class Service4 extends Service<Integer> {\n\n    @Override\n    public String getName() {\n      return \"4\";\n    }\n\n    @Override\n    public ChapterResult<Integer> process(Integer value) {\n      records.add(\"+4\");\n      return ChapterResult.failure(value);\n    }\n\n    @Override\n    public ChapterResult<Integer> rollback(Integer value) {\n      records.add(\"-4\");\n      return ChapterResult.success(value);\n    }\n  }\n}\n"
  },
  {
    "path": "saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.saga.orchestration;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** test to check general logic */\nclass SagaOrchestratorTest {\n\n  @Test\n  void execute() {\n    SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery());\n    Saga.Result badOrder = sagaOrchestrator.execute(\"bad_order\");\n    Saga.Result crashedOrder = sagaOrchestrator.execute(\"crashed_order\");\n\n    assertEquals(Saga.Result.ROLLBACK, badOrder);\n    assertEquals(Saga.Result.CRASHED, crashedOrder);\n  }\n\n  private static Saga newSaga() {\n    return Saga.create()\n        .chapter(\"init an order\")\n        .chapter(\"booking a Fly\")\n        .chapter(\"booking a Hotel\")\n        .chapter(\"withdrawing Money\");\n  }\n\n  private static ServiceDiscoveryService serviceDiscovery() {\n    return new ServiceDiscoveryService()\n        .discover(new OrderService())\n        .discover(new FlyBookingService())\n        .discover(new HotelBookingService())\n        .discover(new WithdrawMoneyService());\n  }\n}\n"
  },
  {
    "path": "separated-interface/README.md",
    "content": "---\ntitle: \"Separated Interface Pattern in Java: Streamlining Java Development with Interface Isolation\"\nshortTitle: Separated Interface\ndescription: \"Explore the Separated Interface design pattern in Java: Enhance software flexibility and maintainability by decoupling interfaces from implementations. Ideal for developers looking to improve code scalability and adaptability.\"\ncategory: Structural\nlanguage: en\ntag:\n  - API design\n  - Decoupling\n  - Interface\n---\n\n## Also known as\n\n* API Segregation\n* Client-Server Interface\n\n## Intent of Separated Interface Design Pattern\n\nThe Separated Interface design pattern defines a client interface in a separate package from its implementation to allow for easier swapping of implementations and better separation of concerns.\n\n## Detailed Explanation of Separated Interface Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a restaurant where the menu (interface) is separate from the kitchen operations (implementation).\n>\n> In this analogy, the menu lists the dishes customers can order, without detailing how they are prepared. Different restaurants (or even different chefs within the same restaurant) can use their own recipes and methods to prepare the dishes listed on the menu. This separation allows the restaurant to update its menu or change its chefs without disrupting the overall dining experience. Similarly, in software, the Separated Interface pattern decouples the interface from its implementation, allowing changes and variations in the implementation without affecting the client code that relies on the interface.\n\nIn plain words\n\n> Defines a client interface separate from its implementation to allow for flexible and interchangeable components.\n\nSequence diagram\n\n![Separated Interface sequence diagram](./etc/separated-interface-sequence-diagram.png)\n\n## Programmatic Example of Separated Interface Pattern in Java\n\nThe Java Separated Interface design pattern is a crucial software architecture strategy that promotes separating the interface definition from its implementation, crucial for enhancing system flexibility and scalability. This allows the client to be completely unaware of the implementation, promoting loose coupling and enhancing flexibility.\n\nIn the given code, the `InvoiceGenerator` class is the client that uses the `TaxCalculator` interface to calculate tax. The `TaxCalculator` interface is implemented by two classes: `ForeignTaxCalculator` and `DomesticTaxCalculator`. These implementations are injected into the `InvoiceGenerator` class at runtime, demonstrating the Separated Interface pattern.\n\nLet's break down the code:\n\nFirst, we have the `TaxCalculator` interface. This interface defines a single method `calculate` that takes an amount and returns the calculated tax.\n\n```java\npublic interface TaxCalculator {\n  double calculate(double amount);\n}\n```\n\nNext, we have two classes `ForeignTaxCalculator` and `DomesticTaxCalculator` that implement the `TaxCalculator` interface. These classes provide the concrete logic for tax calculation.\n\n```java\npublic class ForeignTaxCalculator implements TaxCalculator {\n  public static final double TAX_PERCENTAGE = 60;\n\n  @Override\n  public double calculate(double amount) {\n    return amount * TAX_PERCENTAGE / 100.0;\n  }\n}\n\npublic class DomesticTaxCalculator implements TaxCalculator {\n  public static final double TAX_PERCENTAGE = 20;\n\n  @Override\n  public double calculate(double amount) {\n    return amount * TAX_PERCENTAGE / 100.0;\n  }\n}\n```\n\nThe `InvoiceGenerator` class is the client that uses the `TaxCalculator` interface. It doesn't know about the concrete implementations of the `TaxCalculator` interface. It just knows that it has a `TaxCalculator` that can calculate tax.\n\n```java\npublic class InvoiceGenerator {\n  private final TaxCalculator taxCalculator;\n  private final double amount;\n\n  public InvoiceGenerator(double amount, TaxCalculator taxCalculator) {\n    this.amount = amount;\n    this.taxCalculator = taxCalculator;\n  }\n\n  public double getAmountWithTax() {\n    return amount + taxCalculator.calculate(amount);\n  }\n}\n```\n\nFinally, in the `App` class, we create instances of `InvoiceGenerator` with different `TaxCalculator` implementations. This demonstrates how the Separated Interface pattern allows us to inject different implementations at runtime.\n\n```java\npublic class App {\n  public static final double PRODUCT_COST = 50.0;\n\n  public static void main(String[] args) {\n    var internationalProductInvoice = new InvoiceGenerator(PRODUCT_COST, new ForeignTaxCalculator());\n    LOGGER.info(\"Foreign Tax applied: {}\", \"\" + internationalProductInvoice.getAmountWithTax());\n\n    var domesticProductInvoice = new InvoiceGenerator(PRODUCT_COST, new DomesticTaxCalculator());\n    LOGGER.info(\"Domestic Tax applied: {}\", \"\" + domesticProductInvoice.getAmountWithTax());\n  }\n}\n```\n\nConsole output:\n\n```\n11:38:53.208 [main] INFO com.iluwatar.separatedinterface.App -- Foreign Tax applied: 80.0\n11:38:53.210 [main] INFO com.iluwatar.separatedinterface.App -- Domestic Tax applied: 60.0\n```\n\nIn this way, the Separated Interface pattern allows us to decouple the interface of a component from its implementation, enhancing flexibility and maintainability and making it ideal for dynamic Java application environments.\n\n## When to Use the Separated Interface Pattern in Java\n\n* Use when you want to decouple the interface of a component from its implementation.\n* Particularly effective in large-scale Java systems, where separate teams handle different components, the Separated Interface pattern ensures seamless integration and easier maintenance.\n* Ideal when the implementation might change over time or vary between deployments.\n\n## Separated Interface Pattern Tutorials\n\n* [Separated Interface Design Pattern Explained (Ram N Java)](https://www.youtube.com/watch?v=d3k-hOA7k2Y)\n\n## Real-World Applications of Separated Interface Pattern in Java\n\n* Java's JDBC (Java Database Connectivity) API separates the client interface from the database driver implementations.\n* Remote Method Invocation (RMI) in Java, where the client and server interfaces are defined separately from the implementations.\n\n## Benefits and Trade-offs of Separated Interface Pattern\n\nBenefits:\n\n* Enhances flexibility by allowing multiple implementations to coexist.\n* Facilitates testing by allowing mock implementations.\n* Improves maintainability by isolating changes to specific parts of the code.\n\nTrade-offs:\n\n* Initial setup might be more complex.\n* May lead to increased number of classes and interfaces in the codebase.\n\n## Related Java Design Patterns\n\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): Adapts one interface to another, which can be used alongside Separated Interface to integrate different implementations.\n* [Bridge](https://java-design-patterns.com/patterns/bridge/): Separates an object’s interface from its implementation, similar to Separated Interface but usually applied to larger-scale architectural issues.\n* [Dependency Injection](https://java-design-patterns.com/patterns/dependency-injection/): Often used to inject the implementation of a separated interface, promoting loose coupling.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Pattern-Oriented Software Architecture Volume 1: A System of Patterns](https://amzn.to/3xZ1ELU)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Separated Interface (Martin Fowler)](https://www.martinfowler.com/eaaCatalog/separatedInterface.html)\n"
  },
  {
    "path": "separated-interface/etc/separated-interface.urm.puml",
    "content": "@startuml\npackage com.iluwatar.separatedinterface {\n  class App {\n    - LOGGER : Logger {static}\n    + PRODUCT_COST : double {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n}\npackage com.iluwatar.separatedinterface.taxes {\n  class DomesticTaxCalculator {\n    + TAX_PERCENTAGE : double {static}\n    + DomesticTaxCalculator()\n    + calculate(amount : double) : double\n  }\n  class ForeignTaxCalculator {\n    + TAX_PERCENTAGE : double {static}\n    + ForeignTaxCalculator()\n    + calculate(amount : double) : double\n  }\n}\npackage com.iluwatar.separatedinterface.invoice {\n  class InvoiceGenerator {\n    - amount : double\n    - taxCalculator : TaxCalculator\n    + InvoiceGenerator(amount : double, taxCalculator : TaxCalculator)\n    + getAmountWithTax() : double\n  }\n  interface TaxCalculator {\n    + calculate(double) : double {abstract}\n  }\n}\nInvoiceGenerator -->  \"-taxCalculator\" TaxCalculator\nDomesticTaxCalculator ..|> TaxCalculator \nForeignTaxCalculator ..|> TaxCalculator \n@enduml"
  },
  {
    "path": "separated-interface/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>separated-interface</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-params</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.separatedinterface.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "separated-interface/src/main/java/com/iluwatar/separatedinterface/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.separatedinterface;\n\nimport com.iluwatar.separatedinterface.invoice.InvoiceGenerator;\nimport com.iluwatar.separatedinterface.taxes.DomesticTaxCalculator;\nimport com.iluwatar.separatedinterface.taxes.ForeignTaxCalculator;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Separated Interface pattern encourages to separate the interface definition and\n * implementation in different packages. This allows the client to be completely unaware of the\n * implementation.\n *\n * <p>In this class the {@link InvoiceGenerator} class is injected with different instances of\n * {@link com.iluwatar.separatedinterface.invoice.TaxCalculator} implementations located in separate\n * packages, to receive different responses for both of the implementations.\n */\n@Slf4j\npublic class App {\n\n  public static final double PRODUCT_COST = 50.0;\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    // Create the invoice generator with product cost as 50 and foreign product tax\n    var internationalProductInvoice =\n        new InvoiceGenerator(PRODUCT_COST, new ForeignTaxCalculator());\n    LOGGER.info(\"Foreign Tax applied: {}\", \"\" + internationalProductInvoice.getAmountWithTax());\n\n    // Create the invoice generator with product cost as 50 and domestic product tax\n    var domesticProductInvoice = new InvoiceGenerator(PRODUCT_COST, new DomesticTaxCalculator());\n    LOGGER.info(\"Domestic Tax applied: {}\", \"\" + domesticProductInvoice.getAmountWithTax());\n  }\n}\n"
  },
  {
    "path": "separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/InvoiceGenerator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.separatedinterface.invoice;\n\n/**\n * InvoiceGenerator class generates an invoice, accepting the product cost and calculating the total\n * price payable inclusive tax (calculated by {@link TaxCalculator}).\n */\npublic record InvoiceGenerator(double amount, TaxCalculator taxCalculator) {\n  /**\n   * TaxCalculator description: The TaxCalculator interface to calculate the payable tax. Amount\n   * description: The base product amount without tax.\n   */\n  public double getAmountWithTax() {\n    return amount + taxCalculator.calculate(amount);\n  }\n}\n"
  },
  {
    "path": "separated-interface/src/main/java/com/iluwatar/separatedinterface/invoice/TaxCalculator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.separatedinterface.invoice;\n\n/** TaxCalculator interface to demonstrate The Separated Interface pattern. */\npublic interface TaxCalculator {\n\n  double calculate(double amount);\n}\n"
  },
  {
    "path": "separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.separatedinterface.taxes;\n\nimport com.iluwatar.separatedinterface.invoice.TaxCalculator;\n\n/** TaxCalculator for Domestic goods with 20% tax. */\npublic class DomesticTaxCalculator implements TaxCalculator {\n\n  public static final double TAX_PERCENTAGE = 20;\n\n  @Override\n  public double calculate(double amount) {\n    return amount * TAX_PERCENTAGE / 100.0;\n  }\n}\n"
  },
  {
    "path": "separated-interface/src/main/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.separatedinterface.taxes;\n\nimport com.iluwatar.separatedinterface.invoice.TaxCalculator;\n\n/** TaxCalculator for foreign goods with 60% tax. */\npublic class ForeignTaxCalculator implements TaxCalculator {\n\n  public static final double TAX_PERCENTAGE = 60;\n\n  @Override\n  public double calculate(double amount) {\n    return amount * TAX_PERCENTAGE / 100.0;\n  }\n}\n"
  },
  {
    "path": "separated-interface/src/test/java/com/iluwatar/separatedinterface/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.separatedinterface;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "separated-interface/src/test/java/com/iluwatar/separatedinterface/invoice/InvoiceGeneratorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.separatedinterface.invoice;\n\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass InvoiceGeneratorTest {\n\n  private InvoiceGenerator target;\n\n  @Test\n  void testGenerateTax() {\n    var productCost = 50.0;\n    var tax = 10.0;\n    TaxCalculator taxCalculatorMock = mock(TaxCalculator.class);\n    doReturn(tax).when(taxCalculatorMock).calculate(productCost);\n\n    target = new InvoiceGenerator(productCost, taxCalculatorMock);\n\n    Assertions.assertEquals(target.getAmountWithTax(), productCost + tax);\n    verify(taxCalculatorMock, times(1)).calculate(productCost);\n  }\n}\n"
  },
  {
    "path": "separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/DomesticTaxCalculatorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.separatedinterface.taxes;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass DomesticTaxCalculatorTest {\n\n  private DomesticTaxCalculator target;\n\n  @Test\n  void testTaxCalculation() {\n    target = new DomesticTaxCalculator();\n\n    var tax = target.calculate(100.0);\n    Assertions.assertEquals(tax, 20.0);\n  }\n}\n"
  },
  {
    "path": "separated-interface/src/test/java/com/iluwatar/separatedinterface/taxes/ForeignTaxCalculatorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.separatedinterface.taxes;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nclass ForeignTaxCalculatorTest {\n\n  private ForeignTaxCalculator target;\n\n  @Test\n  void testTaxCalculation() {\n    target = new ForeignTaxCalculator();\n\n    var tax = target.calculate(100.0);\n    Assertions.assertEquals(tax, 60.0);\n  }\n}\n"
  },
  {
    "path": "serialized-entity/README.md",
    "content": "---\ntitle: \"Serialized Entity Pattern in Java: Streamlining Data Persistence and Exchange\"\nshortTitle: Serialized Entity\ndescription: \"Explore the Serialized Entity design pattern in Java for efficient object serialization and storage. Learn how this pattern facilitates easy data transfer and persistence across different systems.\"\ncategories: Data access\nlanguage: en\ntag:\n  - Data access\n  - Data transfer\n  - Persistence\n---\n\n## Also known as\n\n* Object Serialization\n\n## Intent of Serialized Entity Design Pattern\n\nThe Serialized Entity pattern in Java allows for the object serialization to simplify data transfer and storage. It enables easy conversion of Java objects to and from a serialized format, allowing them to be efficiently stored and transferred.\n\n## Detailed Explanation of Serialized Entity Pattern with Real-World Examples\n\nReal-world example\n\n> An example of the Serialized Entity design pattern in the real world can be found in the process of saving and loading game state in video games. When a player decides to save their progress, the current state of the game, including the player's position, inventory, and achievements, is serialized into a file format such as JSON or binary. This file can then be stored on the player's device or on a cloud server. When the player wants to resume their game, the serialized data is deserialized back into the game's objects, allowing the player to continue from where they left off. This mechanism ensures that complex game states can be easily saved and restored, providing a seamless gaming experience.\n\nIn plain words\n\n> The Serialized Entity design pattern enables the conversion of Java objects to and from a serialized format for easy storage and transfer.\n\nWikipedia says\n\n> In computing, serialization is the process of translating a data structure or object state into a format that can be stored (e.g. files in secondary storage devices, data buffers in primary storage devices) or transmitted (e.g. data streams over computer networks) and reconstructed later (possibly in a different computer environment). When the resulting series of bits is reread according to the serialization format, it can be used to create a semantically identical clone of the original object. For many complex objects, such as those that make extensive use of references, this process is not straightforward. Serialization of objects does not include any of their associated methods with which they were previously linked.\n\nFlowchart\n\n![Serialized Entity flowchart](./etc/serialized-entity-flowchart.png)\n\n## Programmatic Example of Serialized Entity Pattern in Java\n\nThe Serialized Entity design pattern is a way to easily persist Java objects to the database. It uses the `Serializable` interface and the DAO (Data Access Object) pattern. The pattern first uses `Serializable` to convert a Java object into a set of bytes, then it uses the DAO pattern to store this set of bytes as a BLOB (Binary Large OBject) in the database.\n\nFirst, we have the `Country` class, which is a simple POJO (Plain Old Java Object) that represents the data that will be serialized and stored in the database. Implementing the Java `Serializable` interface is crucial in the Serialized Entity design pattern, which means that the object can be converted to a byte stream and restored from it.\n\n```java\n@Getter\n@Setter\n@EqualsAndHashCode\n@ToString\n@AllArgsConstructor\npublic class Country implements Serializable {\n\n    private int code;\n    private String name;\n    private String continents;\n    private String language;\n    @Serial\n    private static final long serialVersionUID = 7149851;\n}\n```\n\nNext, we have the `CountryDao` interface, which defines the methods for persisting and retrieving `Country` objects from the database.\n\n```java\npublic interface CountryDao {\n    int insertCountry() throws IOException;\n    int selectCountry() throws IOException, ClassNotFoundException;\n}\n```\n\nThe `CountrySchemaSql` class implements the `CountryDao` interface. It uses a `DataSource` to connect to the database and a `Country` object that it will serialize and store in the database.\n\n```java\n@Slf4j\npublic class CountrySchemaSql implements CountryDao {\n    \n    public static final String CREATE_SCHEMA_SQL = \"CREATE TABLE IF NOT EXISTS WORLD (ID INT PRIMARY KEY, COUNTRY BLOB)\";\n    public static final String DELETE_SCHEMA_SQL = \"DROP TABLE WORLD IF EXISTS\";\n\n    private Country country;\n    private DataSource dataSource;\n\n    public CountrySchemaSql(Country country, DataSource dataSource) {\n        this.country = new Country(\n                country.getCode(),\n                country.getName(),\n                country.getContinents(),\n                country.getLanguage()\n        );\n        this.dataSource = dataSource;\n    }\n\n    @Override\n    public int insertCountry() throws IOException {\n        var sql = \"INSERT INTO WORLD (ID, COUNTRY) VALUES (?, ?)\";\n        try (var connection = dataSource.getConnection();\n             var preparedStatement = connection.prepareStatement(sql);\n             ByteArrayOutputStream baos = new ByteArrayOutputStream();\n             ObjectOutputStream oss = new ObjectOutputStream(baos)) {\n\n            oss.writeObject(country);\n            oss.flush();\n\n            preparedStatement.setInt(1, country.getCode());\n            preparedStatement.setBlob(2, new ByteArrayInputStream(baos.toByteArray()));\n            preparedStatement.execute();\n            return country.getCode();\n        } catch (SQLException e) {\n            LOGGER.info(\"Exception thrown \" + e.getMessage());\n        }\n        return -1;\n    }\n\n    @Override\n    public int selectCountry() throws IOException, ClassNotFoundException {\n        var sql = \"SELECT ID, COUNTRY FROM WORLD WHERE ID = ?\";\n        try (var connection = dataSource.getConnection();\n             var preparedStatement = connection.prepareStatement(sql)) {\n\n            preparedStatement.setInt(1, country.getCode());\n\n            try (ResultSet rs = preparedStatement.executeQuery()) {\n                if (rs.next()) {\n                    Blob countryBlob = rs.getBlob(\"country\");\n                    ByteArrayInputStream baos = new ByteArrayInputStream(countryBlob.getBytes(1, (int) countryBlob.length()));\n                    ObjectInputStream ois = new ObjectInputStream(baos);\n                    country = (Country) ois.readObject();\n                    LOGGER.info(\"Country: \" + country);\n                }\n                return rs.getInt(\"id\");\n            }\n        } catch (SQLException e) {\n            LOGGER.info(\"Exception thrown \" + e.getMessage());\n        }\n        return -1;\n    }\n}\n```\n\nFinally, in the `App` class, we create `Country` objects and `CountrySchemaSql` objects. We then call the `insertCountry` method to serialize the `Country` objects and store them in the database. We also call the `selectCountry` method to retrieve the serialized `Country` objects from the database and deserialize them back into `Country` objects.\n\n```java\npublic static void main(String[] args) throws IOException, ClassNotFoundException {\n    final var dataSource = createDataSource();\n\n    deleteSchema(dataSource);\n    createSchema(dataSource);\n\n    final var China = new Country(86, \"China\", \"Asia\", \"Chinese\");\n    final var UnitedArabEmirates = new Country(971, \"United Arab Emirates\", \"Asia\", \"Arabic\");\n\n    final var serializedChina = new CountrySchemaSql(China, dataSource);\n    final var serializedUnitedArabEmirates = new CountrySchemaSql(UnitedArabEmirates, dataSource);\n\n    serializedChina.insertCountry();\n    serializedUnitedArabEmirates.insertCountry();\n\n    serializedChina.selectCountry();\n    serializedUnitedArabEmirates.selectCountry();\n}\n```\n\nConsole output:\n\n```\n11:55:32.842 [main] INFO com.iluwatar.serializedentity.CountrySchemaSql -- Country: Country(code=86, name=China, continents=Asia, language=Chinese)\n11:55:32.870 [main] INFO com.iluwatar.serializedentity.CountrySchemaSql -- Country: Country(code=971, name=United Arab Emirates, continents=Asia, language=Arabic)\n```\n\nThis is a basic example of the Serialized Entity design pattern. It shows how to serialize Java objects, store them in a database, and then retrieve and deserialize them.\n\n## When to Use the Serialized Entity Pattern in Java\n\n* This pattern is especially useful for applications requiring data persistence across various states in Java environments.\n* Useful in scenarios where objects need to be shared over a network or saved to a file.\n\n## Real-World Applications of Serialized Entity Pattern in Java\n\n* Java's built-in serialization mechanism using `Serializable` interface.\n* Storing session data in web applications.\n* Caching objects to improve performance.\n* Transferring objects in distributed systems using RMI or other RPC mechanisms.\n\n## Benefits and Trade-offs of Serialized Entity Pattern\n\nBenefits:\n\n* Simplifies the process of saving and restoring object state.\n* Facilitates object transfer across different parts of a system.\n* Reduces boilerplate code for manual serialization and deserialization.\n\nTrade-offs:\n\n* Can introduce security risks if not handled properly (e.g., deserialization attacks).\n* Serialized formats may not be easily readable or editable by humans.\n* Changes to the class structure may break compatibility with previously serialized data.\n\n## Related Java Design Patterns\n\n* [Data Transfer Object (DTO)](https://java-design-patterns.com/patterns/data-transfer-object/): Used to encapsulate data and send it over the network. Often serialized for transmission.\n* [Memento](https://java-design-patterns.com/patterns/memento/): Provides a way to capture and restore an object's state, often using serialization.\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): Proxies can serialize requests to interact with remote objects.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Java Concurrency in Practice](https://amzn.to/4aRMruW)\n"
  },
  {
    "path": "serialized-entity/etc/serialize-entity.urm.puml",
    "content": "@startuml\npackage com.iluwatar.serializedentity {\n  class App {\n      - DB_URL : String {static}\n      - LOGGER : Logger {static}\n      + App()\n      - createDataSource() : DataSource {static}\n      - createSchema(dataSource : DataSource) {static}\n      - deleteSchema(dataSource : DataSource) {static}\n      + main(args : String[]) {static}\n  }\n\n  class Country {\n      - code : int\n      - name : String\n      - continents : String\n      - language : String\n      + serialVersionUID : final Long {static}\n      ~Country(int, String, String, String)\n      + getCode() : int\n      + getName() : String\n      + getContinents() : String\n      + getLanguage() : String\n      + setCode(code : int)\n      + setName(name : String)\n      + setContinents(continents : String)\n      + setLanguage(language : String)\n      + equals(that: Object) : boolean\n      + hashCode() : int\n      + toString() : String\n  }\n\n  interface CountryDao {\n    + insertCountry : int {abstract}\n    + selectCountry : int {abstract}\n  }\n\n  class CountrySchemaSql {\n    - CREATE_SCHEMA_SQL : String {static}\n    - DELETE_SCHEMA_SQL : String {static}\n    - LOGGER : Logger {static}\n    - dataSource : DataSource\n    - country : Country\n    ~ CountrySchemaSql(country : Country, dataSource : DataSource)\n    + insertCountry()\n    + selectCountry()\n  }\n  diamond h2db\n}\n\nApp --> \"Initialize Country objects\" Country\nApp --> \"Initialize CountrySchemaSql\" CountrySchemaSql\nCountrySchemaSql --> \"implements\" CountryDao\nCountry --> \"Stored in database\" h2db\nCountrySchemaSql --> \"Perform INSERT and SELECT operation after serialize and deserialize Country object\" h2db\n@enduml"
  },
  {
    "path": "serialized-entity/etc/serialized-entity.urm.puml",
    "content": "@startuml\npackage com.iluwatar.serializedentity {\n  class App {\n    - DB_URL : String {static}\n    - LOGGER : Logger {static}\n    - App()\n    - createDataSource() : DataSource {static}\n    - createSchema(dataSource : DataSource) {static}\n    - deleteSchema(dataSource : DataSource) {static}\n    + main(args : String[]) {static}\n  }\n  class Country {\n    - code : int\n    - continents : String\n    - language : String\n    - name : String\n    + serialVersionUID : long {static}\n    + Country(code : int, name : String, continents : String, language : String)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getCode() : int\n    + getContinents() : String\n    + getLanguage() : String\n    + getName() : String\n    + hashCode() : int\n    + setCode(code : int)\n    + setContinents(continents : String)\n    + setLanguage(language : String)\n    + setName(name : String)\n    + toString() : String\n  }\n  interface CountryDao {\n    + insertCountry() : int {abstract}\n    + selectCountry() : int {abstract}\n  }\n  class CountrySchemaSql {\n    + CREATE_SCHEMA_SQL : String {static}\n    + DELETE_SCHEMA_SQL : String {static}\n    - LOGGER : Logger {static}\n    - country : Country\n    - dataSource : DataSource\n    + CountrySchemaSql(country : Country, dataSource : DataSource)\n    + insertCountry() : int\n    + selectCountry() : int\n  }\n}\nCountrySchemaSql -->  \"-country\" Country\nCountrySchemaSql ..|> CountryDao \n@enduml"
  },
  {
    "path": "serialized-entity/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>serialized-entity</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.h2database</groupId>\n            <artifactId>h2</artifactId>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.serializedentity.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "serialized-entity/src/main/java/com/iluwatar/serializedentity/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.serializedentity;\n\nimport java.io.IOException;\nimport java.sql.SQLException;\nimport javax.sql.DataSource;\nimport lombok.extern.slf4j.Slf4j;\nimport org.h2.jdbcx.JdbcDataSource;\n\n/**\n * Serialized Entity Pattern.\n *\n * <p>Serialized Entity Pattern allow us to easily persist Java objects to the database. It uses\n * Serializable interface and DAO pattern. Serialized Entity Pattern will first use Serializable to\n * convert a Java object into a set of bytes, then it will using DAO pattern to store this set of\n * bytes as BLOB to database.\n *\n * <p>In this example, we first initialize two Java objects (Country) \"China\" and\n * \"UnitedArabEmirates\", then we initialize \"serializedChina\" with \"China\" object and\n * \"serializedUnitedArabEmirates\" with \"UnitedArabEmirates\", then we use method\n * \"serializedChina.insertCountry()\" and \"serializedUnitedArabEmirates.insertCountry()\" to serialize\n * \"China\" and \"UnitedArabEmirates\" and persist them to database. Last, with\n * \"serializedChina.selectCountry()\" and \"serializedUnitedArabEmirates.selectCountry()\" we could\n * read \"China\" and \"UnitedArabEmirates\" from database as sets of bytes, then deserialize them back\n * to Java object (Country).\n */\n@Slf4j\npublic class App {\n\n  private static final String DB_URL = \"jdbc:h2:~/testdb\";\n\n  private App() {}\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args.\n   * @throws IOException if any\n   * @throws ClassNotFoundException if any\n   */\n  public static void main(String[] args) throws IOException, ClassNotFoundException {\n    final var dataSource = createDataSource();\n\n    deleteSchema(dataSource);\n    createSchema(dataSource);\n\n    // Initializing Country Object China\n    final var China = new Country(86, \"China\", \"Asia\", \"Chinese\");\n\n    // Initializing Country Object UnitedArabEmirates\n    final var UnitedArabEmirates = new Country(971, \"United Arab Emirates\", \"Asia\", \"Arabic\");\n\n    // Initializing CountrySchemaSql Object with parameter \"China\" and \"dataSource\"\n    final var serializedChina = new CountrySchemaSql(China, dataSource);\n    // Initializing CountrySchemaSql Object with parameter \"UnitedArabEmirates\" and \"dataSource\"\n    final var serializedUnitedArabEmirates = new CountrySchemaSql(UnitedArabEmirates, dataSource);\n\n    /*\n    By using CountrySchemaSql.insertCountry() method, the private (Country) type variable  within Object\n    CountrySchemaSql will be serialized to a set of bytes and persist to database.\n    For more details of CountrySchemaSql.insertCountry() method please refer to CountrySchemaSql.java file\n    */\n    serializedChina.insertCountry();\n    serializedUnitedArabEmirates.insertCountry();\n\n    /*\n    By using CountrySchemaSql.selectCountry() method, CountrySchemaSql object will read the sets of bytes from database\n    and deserialize it to Country object.\n    For more details of CountrySchemaSql.selectCountry() method please refer to CountrySchemaSql.java file\n    */\n    serializedChina.selectCountry();\n    serializedUnitedArabEmirates.selectCountry();\n  }\n\n  private static void deleteSchema(DataSource dataSource) {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(CountrySchemaSql.DELETE_SCHEMA_SQL);\n    } catch (SQLException e) {\n      LOGGER.info(\"Exception thrown \" + e.getMessage());\n    }\n  }\n\n  private static void createSchema(DataSource dataSource) {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(CountrySchemaSql.CREATE_SCHEMA_SQL);\n    } catch (SQLException e) {\n      LOGGER.info(\"Exception thrown \" + e.getMessage());\n    }\n  }\n\n  private static DataSource createDataSource() {\n    var dataSource = new JdbcDataSource();\n    dataSource.setURL(DB_URL);\n    return dataSource;\n  }\n}\n"
  },
  {
    "path": "serialized-entity/src/main/java/com/iluwatar/serializedentity/Country.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.serializedentity;\n\nimport java.io.Serial;\nimport java.io.Serializable;\nimport lombok.AllArgsConstructor;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\n/** A Country POJO that represents the data that will serialize and store in database. */\n@Getter\n@Setter\n@EqualsAndHashCode\n@ToString\n@AllArgsConstructor\npublic class Country implements Serializable {\n\n  private int code;\n  private String name;\n  private String continents;\n  private String language;\n  @Serial private static final long serialVersionUID = 7149851;\n}\n"
  },
  {
    "path": "serialized-entity/src/main/java/com/iluwatar/serializedentity/CountryDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n/**\n * In an application the Data Access Object (DAO) is a part of Data access layer. It is an object\n * that provides an interface to some type of persistence mechanism. By mapping application calls to\n * the persistence layer, DAO provides some specific data operations without exposing details of the\n * database. This isolation supports the Single responsibility principle. It separates what data\n * accesses the application needs, in terms of domain-specific objects and data types (the public\n * interface of the DAO), from how these needs can be satisfied with a specific DBMS, database\n * schema, etc.\n *\n * <p>Any change in the way data is stored and retrieved will not change the client code as the\n * client will be using interface and need not worry about exact source.\n *\n * @see InMemoryCustomerDao\n * @see DbCustomerDao\n */\npackage com.iluwatar.serializedentity;\n\nimport java.io.IOException;\n\n/** DAO interface for Country transactions. */\npublic interface CountryDao {\n  int insertCountry() throws IOException;\n\n  int selectCountry() throws IOException, ClassNotFoundException;\n}\n"
  },
  {
    "path": "serialized-entity/src/main/java/com/iluwatar/serializedentity/CountrySchemaSql.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.serializedentity;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.ObjectInputStream;\nimport java.io.ObjectOutputStream;\nimport java.sql.Blob;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport javax.sql.DataSource;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Country Schema SQL Class. */\n@Slf4j\npublic class CountrySchemaSql implements CountryDao {\n  public static final String CREATE_SCHEMA_SQL =\n      \"CREATE TABLE IF NOT EXISTS WORLD (ID INT PRIMARY KEY, COUNTRY BLOB)\";\n\n  public static final String DELETE_SCHEMA_SQL = \"DROP TABLE WORLD IF EXISTS\";\n\n  private Country country;\n  private DataSource dataSource;\n\n  /**\n   * Public constructor.\n   *\n   * @param dataSource datasource\n   * @param country country\n   */\n  public CountrySchemaSql(Country country, DataSource dataSource) {\n    this.country =\n        new Country(\n            country.getCode(), country.getName(), country.getContinents(), country.getLanguage());\n    this.dataSource = dataSource;\n  }\n\n  /**\n   * This method will serialize a Country object and store it to database.\n   *\n   * @return int type, if successfully insert a serialized object to database then return country\n   *     code, else return -1.\n   * @throws IOException if any.\n   */\n  @Override\n  public int insertCountry() throws IOException {\n    var sql = \"INSERT INTO WORLD (ID, COUNTRY) VALUES (?, ?)\";\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(sql);\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        ObjectOutputStream oss = new ObjectOutputStream(baos)) {\n\n      oss.writeObject(country);\n      oss.flush();\n\n      preparedStatement.setInt(1, country.getCode());\n      preparedStatement.setBlob(2, new ByteArrayInputStream(baos.toByteArray()));\n      preparedStatement.execute();\n      return country.getCode();\n    } catch (SQLException e) {\n      LOGGER.info(\"Exception thrown \" + e.getMessage());\n    }\n    return -1;\n  }\n\n  /**\n   * This method will select a data item from database and deserialize it.\n   *\n   * @return int type, if successfully select and deserialized object from database then return\n   *     country code, else return -1.\n   * @throws IOException if any.\n   * @throws ClassNotFoundException if any.\n   */\n  @Override\n  public int selectCountry() throws IOException, ClassNotFoundException {\n    var sql = \"SELECT ID, COUNTRY FROM WORLD WHERE ID = ?\";\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(sql)) {\n\n      preparedStatement.setInt(1, country.getCode());\n\n      try (ResultSet rs = preparedStatement.executeQuery()) {\n        if (rs.next()) {\n          Blob countryBlob = rs.getBlob(\"country\");\n          ByteArrayInputStream baos =\n              new ByteArrayInputStream(countryBlob.getBytes(1, (int) countryBlob.length()));\n          ObjectInputStream ois = new ObjectInputStream(baos);\n          country = (Country) ois.readObject();\n          LOGGER.info(\"Country: \" + country);\n        }\n        return rs.getInt(\"id\");\n      }\n    } catch (SQLException e) {\n      LOGGER.info(\"Exception thrown \" + e.getMessage());\n    }\n    return -1;\n  }\n}\n"
  },
  {
    "path": "serialized-entity/src/test/java/com/iluwatar/serializedentity/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.serializedentity;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Serialized Entity example runs without errors. */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case. Solution: Inserted assertion to check\n   * whether the execution of the main method in {@link App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteSerializedEntityWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "serialized-entity/src/test/java/com/iluwatar/serializedentity/CountryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.serializedentity;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.io.*;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Test;\n\n@Slf4j\npublic class CountryTest {\n\n  @Test\n  void testGetMethod() {\n    Country China = new Country(86, \"China\", \"Asia\", \"Chinese\");\n\n    assertEquals(86, China.getCode());\n    assertEquals(\"China\", China.getName());\n    assertEquals(\"Asia\", China.getContinents());\n    assertEquals(\"Chinese\", China.getLanguage());\n  }\n\n  @Test\n  void testSetMethod() {\n    Country country = new Country(86, \"China\", \"Asia\", \"Chinese\");\n\n    country.setCode(971);\n    country.setName(\"UAE\");\n    country.setContinents(\"West-Asia\");\n    country.setLanguage(\"Arabic\");\n\n    assertEquals(971, country.getCode());\n    assertEquals(\"UAE\", country.getName());\n    assertEquals(\"West-Asia\", country.getContinents());\n    assertEquals(\"Arabic\", country.getLanguage());\n  }\n\n  @Test\n  void testSerializable() {\n    // Serializing Country\n    try {\n      Country country = new Country(86, \"China\", \"Asia\", \"Chinese\");\n      ObjectOutputStream objectOutputStream =\n          new ObjectOutputStream(new FileOutputStream(\"output.txt\"));\n      objectOutputStream.writeObject(country);\n      objectOutputStream.close();\n    } catch (IOException e) {\n      LOGGER.error(\"Error occurred: \", e);\n    }\n\n    // De-serialize Country\n    try {\n      ObjectInputStream objectInputStream =\n          new ObjectInputStream(new FileInputStream(\"output.txt\"));\n      Country country = (Country) objectInputStream.readObject();\n      objectInputStream.close();\n      System.out.println(country);\n\n      Country China = new Country(86, \"China\", \"Asia\", \"Chinese\");\n\n      assertEquals(China, country);\n    } catch (Exception e) {\n      LOGGER.error(\"Error occurred: \", e);\n    }\n    try {\n      Files.deleteIfExists(Paths.get(\"output.txt\"));\n    } catch (IOException e) {\n      LOGGER.error(\"Error occurred: \", e);\n    }\n  }\n}\n"
  },
  {
    "path": "serialized-lob/README.md",
    "content": "---\ntitle: \"Serialized LOB Pattern in Java: Managing Large Data Objects with Ease\"\nshortTitle: Serialized LOB\ndescription: \"Explore the Serialized LOB pattern for managing large objects in Java applications. Learn how it simplifies data access and storage of files, multimedia, and large strings efficiently.\"\ncategory: Data access\nlanguage: en\ntag:\n  - Data access\n  - Data processing\n  - Persistence\n---\n\n## Also known as\n\n* Serialized Large Object\n* Serialized BLOB\n* Serialized CLOB\n\n## Intent of Serialized LOB Design Pattern\n\nEfficiently manage and store large data objects, such as multimedia files and extensive text strings, using the Serialized LOB pattern in Java, a strategy for robust database optimization.\n\n## Detailed Explanation of Serialized LOB Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a social media platform optimized for performance, where users can upload and seamlessly share multimedia content, leveraging Java's Serialized LOB pattern for enhanced data handling. Instead of storing these large multimedia files on a separate file server, the platform uses the Serialized LOB design pattern to store the files directly in the database. Each uploaded image or video is serialized into a binary large object (BLOB) and stored within the user's record. This approach ensures that the multimedia files are managed within the same transactional context as other user data, providing consistency and simplifying data access and retrieval.\n\nIn plain words\n\n> The Serialized LOB design pattern manages the storage of large objects, such as files or multimedia, by serializing and storing them directly within a database.\n\nFlowchart\n\n![Serialized LOB flowchart](./etc/serialized-lob-flowchart.png)\n\n## Programmatic Example of Serialized LOB Pattern in Java\n\nThe Serialized Large Object (LOB) design pattern is a way to handle large objects in a database. It involves serializing an object graph into a single large object (a BLOB or CLOB, for Binary Large Object or Character Large Object, respectively) and storing it in the database. When the object graph needs to be retrieved, it is read from the database and deserialized back into the original object graph.\n\nHere's a programmatic example of the Serialized LOB design pattern:\n\n```java\npublic abstract class LobSerializer implements AutoCloseable {\n  // ... omitted for brevity\n  public abstract Object serialize(Forest toSerialize) throws Exception;\n  public abstract Forest deSerialize(Object toDeserialize) throws Exception;\n  // ... omitted for brevity\n}\n```\n\nThe `LobSerializer` class is an abstract class that provides the structure for serializing and deserializing objects. It has two abstract methods: `serialize` and `deSerialize`. These methods are implemented by the subclasses `ClobSerializer` and `BlobSerializer`.\n\n```java\npublic class ClobSerializer extends LobSerializer {\n  // ... omitted for brevity\n  @Override\n  public Object serialize(Forest forest) throws ParserConfigurationException, TransformerException {\n    // ... omitted for brevity\n  }\n\n  @Override\n  public Forest deSerialize(Object toDeserialize)\n      throws ParserConfigurationException, IOException, SAXException {\n    // ... omitted for brevity\n  }\n}\n```\n\nThe `ClobSerializer` class provides an implementation for serializing and deserializing objects into XML strings. The `serialize` method converts a `Forest` object into an XML string, and the `deSerialize` method converts an XML string back into a `Forest` object.\n\n```java\npublic class BlobSerializer extends LobSerializer {\n  // ... omitted for brevity\n  @Override\n  public Object serialize(Forest toSerialize) throws IOException {\n    // ... omitted for brevity\n  }\n\n  @Override\n  public Forest deSerialize(Object toDeserialize) throws IOException, ClassNotFoundException {\n    // ... omitted for brevity\n  }\n}\n```\n\nThe `BlobSerializer` class provides an implementation for serializing and deserializing objects into binary data. The `serialize` method converts a `Forest` object into binary data, and the `deSerialize` method converts binary data back into a `Forest` object.\n\nFinally, here is the `App` class with `main` method that can be used to execute the serialization example.\n\n```java\npublic class App {\n\n  public static final String CLOB = \"CLOB\";\n  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n  public static void main(String[] args) throws SQLException {\n    Forest forest = createForest();\n    LobSerializer serializer = createLobSerializer(args);\n    executeSerializer(forest, serializer);\n  }\n\n  private static LobSerializer createLobSerializer(String[] args) throws SQLException {\n    LobSerializer serializer;\n    if (args.length > 0 && Objects.equals(args[0], CLOB)) {\n      serializer = new ClobSerializer();\n    } else {\n      serializer = new BlobSerializer();\n    }\n    return serializer;\n  }\n\n  private static Forest createForest() {\n    Plant grass = new Plant(\"Grass\", \"Herb\");\n    Plant oak = new Plant(\"Oak\", \"Tree\");\n\n    Animal zebra = new Animal(\"Zebra\", Set.of(grass), Collections.emptySet());\n    Animal buffalo = new Animal(\"Buffalo\", Set.of(grass), Collections.emptySet());\n    Animal lion = new Animal(\"Lion\", Collections.emptySet(), Set.of(zebra, buffalo));\n\n    return new Forest(\"Amazon\", Set.of(lion, buffalo, zebra), Set.of(grass, oak));\n  }\n\n  private static void executeSerializer(Forest forest, LobSerializer lobSerializer) {\n    try (LobSerializer serializer = lobSerializer) {\n\n      Object serialized = serializer.serialize(forest);\n      int id = serializer.persistToDb(1, forest.getName(), serialized);\n\n      Object fromDb = serializer.loadFromDb(id, Forest.class.getSimpleName());\n      Forest forestFromDb = serializer.deSerialize(fromDb);\n\n      LOGGER.info(forestFromDb.toString());\n    } catch (SQLException | IOException | TransformerException | ParserConfigurationException\n             | SAXException\n             | ClassNotFoundException e) {\n      throw new RuntimeException(e);\n    }\n  }\n}\n```\n\nConsole output:\n\n```\n12:01:21.061 [main] INFO com.iluwatar.slob.App -- \nForest Name = Amazon\nAnimals found in the Amazon Forest: \n\n--------------------------\n\nAnimal Name = Lion\n\tAnimals Eaten by Lion: \n\t\t\nAnimal Name = Buffalo\n\n\tPlants Eaten by Buffalo: \n\t\tName = Grass,Type = Herb\n\t\t\nAnimal Name = Zebra\n\n\tPlants Eaten by Zebra: \n\t\tName = Grass,Type = Herb\n\n--------------------------\n\n--------------------------\n\nAnimal Name = Buffalo\n\n\tPlants Eaten by Buffalo: \n\t\tName = Grass,Type = Herb\n--------------------------\n\n--------------------------\n\nAnimal Name = Zebra\n\n\tPlants Eaten by Zebra: \n\t\tName = Grass,Type = Herb\n--------------------------\n\nPlants in the Amazon Forest: \n\n--------------------------\nName = Oak,Type = Tree\n--------------------------\n\n--------------------------\nName = Grass,Type = Herb\n--------------------------\n```\n\n## When to Use the Serialized LOB Pattern in Java\n\n* Use when you need to store large objects in a database and want to optimize data access and storage.\n* Ideal for applications that deal with large binary or character data such as multimedia files, logs, or documents.\n\n## Real-World Applications of Serialized LOB Pattern in Java\n\n* Storing and retrieving images or multimedia files in a database.\n* Managing large text documents or logs in enterprise applications.\n* Handling binary data in applications that require efficient data retrieval and storage.\n\n## Benefits and Trade-offs of Serialized LOB Pattern\n\nBenefits:\n\n* Simplifies the handling of large objects by leveraging Java serialization.\n* Reduces the need for external file storage systems.\n* Ensures consistency by storing LOBs within the same transactional context as other data.\n\nTrade-offs:\n\n* Increases database size due to the storage of serialized data.\n* Potential performance overhead during serialization and deserialization.\n* Requires careful management of serialization format to maintain backward compatibility.\n\n## Related Java Design Patterns\n\n* [DAO (Data Access Object)](https://java-design-patterns.com/patterns/dao/): Often used in conjunction with Serialized LOB to encapsulate data access logic.\n* Active Record: Can use Serialized LOB for managing large data within the same record.\n* [Repository](https://java-design-patterns.com/patterns/repository/): Uses Serialized LOB to handle complex queries and data manipulation involving large objects.\n\n## References and Credits\n\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Java Persistence with Hibernate](https://amzn.to/44tP1ox)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Serialized LOB (Martin Fowler)](https://martinfowler.com/eaaCatalog/serializedLOB.html)\n"
  },
  {
    "path": "serialized-lob/etc/serialized-lob.urm.puml",
    "content": "@startuml\npackage com.iluwatar.slob.lob {\n  class Animal {\n    - animalsEaten : Set<Animal>\n    - name : String\n    - plantsEaten : Set<Plant>\n    + Animal()\n    + Animal(name : String, plantsEaten : Set<Plant>, animalsEaten : Set<Animal>)\n    # canEqual(other : Object) : boolean\n    + createObjectFromXml(node : Node)\n    + equals(o : Object) : boolean\n    + getAnimalsEaten() : Set<Animal>\n    + getName() : String\n    + getPlantsEaten() : Set<Plant>\n    + hashCode() : int\n    # iterateXmlForAnimalAndPlants(childNodes : NodeList, animalsEaten : Set<Animal>, plantsEaten : Set<Plant>) {static}\n    + setAnimalsEaten(animalsEaten : Set<Animal>)\n    + setName(name : String)\n    + setPlantsEaten(plantsEaten : Set<Plant>)\n    + toString() : String\n    + toXmlElement(xmlDoc : Document) : Element\n  }\n  class Forest {\n    - animals : Set<Animal>\n    - name : String\n    - plants : Set<Plant>\n    + Forest()\n    + Forest(name : String, animals : Set<Animal>, plants : Set<Plant>)\n    # canEqual(other : Object) : boolean\n    + createObjectFromXml(document : Document)\n    + equals(o : Object) : boolean\n    + getAnimals() : Set<Animal>\n    + getName() : String\n    + getPlants() : Set<Plant>\n    - getXmlDoc() : Document\n    + hashCode() : int\n    + setAnimals(animals : Set<Animal>)\n    + setName(name : String)\n    + setPlants(plants : Set<Plant>)\n    + toString() : String\n    + toXmlElement() : Element\n  }\n  class Plant {\n    - name : String\n    - type : String\n    + Plant()\n    + Plant(name : String, type : String)\n    # canEqual(other : Object) : boolean\n    + createObjectFromXml(node : Node)\n    + equals(o : Object) : boolean\n    + getName() : String\n    + getType() : String\n    + hashCode() : int\n    + setName(name : String)\n    + setType(type : String)\n    + toString() : String\n    + toXmlElement(xmlDoc : Document) : Element\n  }\n}\npackage com.iluwatar.slob.serializers {\n  class BlobSerializer {\n    + TYPE_OF_DATA_FOR_DB : String {static}\n    + BlobSerializer()\n    + deSerialize(toDeserialize : Object) : Forest\n    + serialize(toSerialize : Forest) : Object\n  }\n  class ClobSerializer {\n    + TYPE_OF_DATA_FOR_DB : String {static}\n    + ClobSerializer()\n    + deSerialize(toDeserialize : Object) : Forest\n    - elementToXmlString(node : Element) : String {static}\n    + serialize(forest : Forest) : Object\n  }\n  abstract class LobSerializer {\n    - databaseService : DatabaseService\n    # LobSerializer(dataTypeDb : String)\n    + close()\n    + deSerialize(Object) : Forest {abstract}\n    + loadFromDb(id : int, columnName : String) : Object\n    + persistToDb(id : int, name : String, object : Object) : int\n    + serialize(Forest) : Object {abstract}\n  }\n}\npackage com.iluwatar.slob.dbservice {\n  class DatabaseService {\n    + BINARY_DATA : String {static}\n    + CREATE_BINARY_SCHEMA_DDL : String {static}\n    + CREATE_TEXT_SCHEMA_DDL : String {static}\n    - DB_URL : String {static}\n    + DELETE_SCHEMA_SQL : String {static}\n    - INSERT : String {static}\n    - LOGGER : Logger {static}\n    - SELECT : String {static}\n    - dataSource : DataSource {static}\n    + dataTypeDb : String\n    + DatabaseService(dataTypeDb : String)\n    - createDataSource() : DataSource {static}\n    + insert(id : int, name : String, data : Object)\n    + select(id : long, columnsName : String) : Object\n    + shutDownService()\n    + startupService()\n  }\n}\npackage com.iluwatar.slob {\n  class App {\n    + CLOB : String {static}\n    - LOGGER : Logger {static}\n    + App()\n    - createForest() : Forest {static}\n    - createLobSerializer(args : String[]) : LobSerializer {static}\n    - executeSerializer(forest : Forest, lobSerializer : LobSerializer) {static}\n    + main(args : String[]) {static}\n  }\n}\nAnimal -->  \"-plantsEaten\" Plant\nLobSerializer -->  \"-databaseService\" DatabaseService\nForest -->  \"-animals\" Animal\nForest -->  \"-plants\" Plant\nAnimal -->  \"-animalsEaten\" Animal\nBlobSerializer --|> LobSerializer \nClobSerializer --|> LobSerializer \n@enduml"
  },
  {
    "path": "serialized-lob/etc/slob.urm.puml",
    "content": "@startuml\npackage com.iluwatar.slob.lob {\n  class Animal {\n    - animalsEaten : Set<Animal>\n    - name : String\n    - plantsEaten : Set<Plant>\n    + Animal()\n    + Animal(name : String, plantsEaten : Set<Plant>, animalsEaten : Set<Animal>)\n    # canEqual(other : Object) : boolean\n    + createObjectFromXml(node : Node)\n    + equals(o : Object) : boolean\n    + getAnimalsEaten() : Set<Animal>\n    + getName() : String\n    + getPlantsEaten() : Set<Plant>\n    + hashCode() : int\n    # iterateXmlForAnimalAndPlants(childNodes : NodeList, animalsEaten : Set<Animal>, plantsEaten : Set<Plant>) {static}\n    + setAnimalsEaten(animalsEaten : Set<Animal>)\n    + setName(name : String)\n    + setPlantsEaten(plantsEaten : Set<Plant>)\n    + toString() : String\n    + toXmlElement(xmlDoc : Document) : Element\n  }\n  class Forest {\n    - animals : Set<Animal>\n    - name : String\n    - plants : Set<Plant>\n    + Forest()\n    + Forest(name : String, animals : Set<Animal>, plants : Set<Plant>)\n    # canEqual(other : Object) : boolean\n    + createObjectFromXml(document : Document)\n    + equals(o : Object) : boolean\n    + getAnimals() : Set<Animal>\n    + getName() : String\n    + getPlants() : Set<Plant>\n    - getXmlDoc() : Document\n    + hashCode() : int\n    + setAnimals(animals : Set<Animal>)\n    + setName(name : String)\n    + setPlants(plants : Set<Plant>)\n    + toString() : String\n    + toXmlElement() : Element\n  }\n  class Plant {\n    - name : String\n    - type : String\n    + Plant()\n    + Plant(name : String, type : String)\n    # canEqual(other : Object) : boolean\n    + createObjectFromXml(node : Node)\n    + equals(o : Object) : boolean\n    + getName() : String\n    + getType() : String\n    + hashCode() : int\n    + setName(name : String)\n    + setType(type : String)\n    + toString() : String\n    + toXmlElement(xmlDoc : Document) : Element\n  }\n}\npackage com.iluwatar.slob.serializers {\n  class BlobSerializer {\n    + TYPE_OF_DATA_FOR_DB : String {static}\n    + BlobSerializer()\n    + deSerialize(toDeserialize : Object) : Forest\n    + serialize(toSerialize : Forest) : Object\n  }\n  class ClobSerializer {\n    + TYPE_OF_DATA_FOR_DB : String {static}\n    + ClobSerializer()\n    + deSerialize(toDeserialize : Object) : Forest\n    - elementToXmlString(node : Element) : String {static}\n    + serialize(forest : Forest) : Object\n  }\n  abstract class LobSerializer {\n    - databaseService : DatabaseService\n    # LobSerializer(dataTypeDb : String)\n    + close()\n    + deSerialize(Object) : Forest {abstract}\n    + loadFromDb(id : int, columnName : String) : Object\n    + persistToDb(id : int, name : String, object : Object) : int\n    + serialize(Forest) : Object {abstract}\n  }\n}\npackage com.iluwatar.slob.dbservice {\n  class DatabaseService {\n    + BINARY_DATA : String {static}\n    + CREATE_BINARY_SCHEMA_DDL : String {static}\n    + CREATE_TEXT_SCHEMA_DDL : String {static}\n    - DB_URL : String {static}\n    + DELETE_SCHEMA_SQL : String {static}\n    - INSERT : String {static}\n    - LOGGER : Logger {static}\n    - SELECT : String {static}\n    - dataSource : DataSource {static}\n    + dataTypeDb : String\n    + DatabaseService(dataTypeDb : String)\n    - createDataSource() : DataSource {static}\n    + insert(id : int, name : String, data : Object)\n    + select(id : long, columnsName : String) : Object\n    + shutDownService()\n    + startupService()\n  }\n}\npackage com.iluwatar.slob {\n  class App {\n    + CLOB : String {static}\n    - LOGGER : Logger {static}\n    + App()\n    - createForest() : Forest {static}\n    - createLobSerializer(args : String[]) : LobSerializer {static}\n    - executeSerializer(forest : Forest, lobSerializer : LobSerializer) {static}\n    + main(args : String[]) {static}\n  }\n}\nAnimal -->  \"-plantsEaten\" Plant\nLobSerializer -->  \"-databaseService\" DatabaseService\nForest -->  \"-animals\" Animal\nForest -->  \"-plants\" Plant\nAnimal -->  \"-animalsEaten\" Animal\nBlobSerializer --|> LobSerializer \nClobSerializer --|> LobSerializer \n@enduml"
  },
  {
    "path": "serialized-lob/etc/slob.urm.uml",
    "content": "@startuml\n\n!theme plain\ntop to bottom direction\nskinparam linetype ortho\n\nclass Animal {\n  - animalsEaten: Set<Animal>\n  - name: String\n  - plantsEaten: Set<Plant>\n   animalsEaten: Set<Animal>\n   name: String\n   plantsEaten: Set<Plant>\n}\nclass App\nclass BlobSerializer\nclass ClobSerializer\nclass DatabaseService\nclass Forest {\n  - animals: Set<Animal>\n  - name: String\n  - plants: Set<Plant>\n   animals: Set<Animal>\n   name: String\n   plants: Set<Plant>\n   xmlDoc: Document\n}\nclass LobSerializer\nclass Plant {\n  - name: String\n  - type: String\n   name: String\n   type: String\n}\n\nAnimal           -[#595959,dashed]->  Plant           : \"«create»\"\nAnimal          \"1\" *-[#595959,plain]-> \"plantsEaten\\n*\" Plant\nApp              -[#595959,dashed]->  Animal          : \"«create»\"\nApp              -[#595959,dashed]->  ClobSerializer  : \"«create»\"\nApp              -[#595959,dashed]->  Forest          : \"«create»\"\nApp              -[#595959,dashed]->  Plant           : \"«create»\"\nBlobSerializer   -[#000082,plain]-^  LobSerializer\nClobSerializer   -[#595959,dashed]->  Forest          : \"«create»\"\nClobSerializer   -[#000082,plain]-^  LobSerializer\nForest          \"1\" *-[#595959,plain]-> \"animals\\n*\" Animal\nForest          \"1\" *-[#595959,plain]-> \"plants\\n*\" Plant\nLobSerializer   \"1\" *-[#595959,plain]-> \"databaseService\\n1\" DatabaseService\nLobSerializer    -[#595959,dashed]->  DatabaseService : \"«create»\"\n@enduml\n"
  },
  {
    "path": "serialized-lob/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <artifactId>serialized-lob</artifactId>\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <artifactId>java-design-patterns</artifactId>\n        <groupId>com.iluwatar</groupId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <build>\n        <plugins>\n            <plugin>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.slob.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n                <groupId>org.apache.maven.plugins</groupId>\n            </plugin>\n        </plugins>\n    </build>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <groupId>org.junit.jupiter</groupId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <artifactId>h2</artifactId>\n            <groupId>com.h2database</groupId>\n        </dependency>\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "serialized-lob/src/main/java/com/iluwatar/slob/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.slob;\n\nimport com.iluwatar.slob.lob.Animal;\nimport com.iluwatar.slob.lob.Forest;\nimport com.iluwatar.slob.lob.Plant;\nimport com.iluwatar.slob.serializers.BlobSerializer;\nimport com.iluwatar.slob.serializers.ClobSerializer;\nimport com.iluwatar.slob.serializers.LobSerializer;\nimport java.io.IOException;\nimport java.sql.SQLException;\nimport java.util.Collections;\nimport java.util.Objects;\nimport java.util.Set;\nimport javax.xml.parsers.ParserConfigurationException;\nimport javax.xml.transform.TransformerException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.xml.sax.SAXException;\n\n/** SLOB Application using {@link LobSerializer} and H2 DB. */\npublic class App {\n\n  public static final String CLOB = \"CLOB\";\n  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n  /**\n   * Main entry point to program.\n   *\n   * <p>In the SLOB pattern, the object graph is serialized into a single large object (a BLOB or\n   * CLOB, for Binary Large Object or Character Large Object, respectively) and stored in the\n   * database. When the object graph needs to be retrieved, it is read from the database and\n   * deserialized back into the original object graph.\n   *\n   * <p>A Forest is created using {@link #createForest()} with Animals and Plants along with their\n   * respective relationships.\n   *\n   * <p>Creates a {@link LobSerializer} using the method {@link #createLobSerializer(String[])}.\n   *\n   * <p>Once created the serializer is passed to the {@link #executeSerializer(Forest,\n   * LobSerializer)} which handles the serialization, deserialization and persisting and loading\n   * from DB.\n   *\n   * @param args if first arg is CLOB then ClobSerializer is used else BlobSerializer is used.\n   */\n  public static void main(String[] args) throws SQLException {\n    Forest forest = createForest();\n    LobSerializer serializer = createLobSerializer(args);\n    executeSerializer(forest, serializer);\n  }\n\n  /**\n   * Creates a {@link LobSerializer} on the basis of input args.\n   *\n   * <p>If input args are not empty and the value equals {@link App#CLOB} then a {@link\n   * ClobSerializer} is created else a {@link BlobSerializer} is created.\n   *\n   * @param args if first arg is {@link App#CLOB} then ClobSerializer is instantiated else\n   *     BlobSerializer is instantiated.\n   */\n  private static LobSerializer createLobSerializer(String[] args) throws SQLException {\n    LobSerializer serializer;\n    if (args.length > 0 && Objects.equals(args[0], CLOB)) {\n      serializer = new ClobSerializer();\n    } else {\n      serializer = new BlobSerializer();\n    }\n    return serializer;\n  }\n\n  /**\n   * Creates a Forest with {@link Animal} and {@link Plant} along with their respective\n   * relationships.\n   *\n   * <p>The method creates a {@link Forest} with 2 Plants Grass and Oak of type Herb and tree\n   * respectively.\n   *\n   * <p>It also creates 3 animals Zebra and Buffalo which eat the plant grass. Lion consumes the\n   * Zebra and the Buffalo.\n   *\n   * <p>With the above animals and plants and their relationships a forest object is created which\n   * represents the Object Graph.\n   *\n   * @return Forest Object\n   */\n  private static Forest createForest() {\n    Plant grass = new Plant(\"Grass\", \"Herb\");\n    Plant oak = new Plant(\"Oak\", \"Tree\");\n\n    Animal zebra = new Animal(\"Zebra\", Set.of(grass), Collections.emptySet());\n    Animal buffalo = new Animal(\"Buffalo\", Set.of(grass), Collections.emptySet());\n    Animal lion = new Animal(\"Lion\", Collections.emptySet(), Set.of(zebra, buffalo));\n\n    return new Forest(\"Amazon\", Set.of(lion, buffalo, zebra), Set.of(grass, oak));\n  }\n\n  /**\n   * Serialize the input object using the input serializer and persist to DB. After this it loads\n   * the same object back from DB and deserializes using the same serializer.\n   *\n   * @param forest Object to Serialize and Persist\n   * @param lobSerializer Serializer to Serialize and Deserialize Object\n   */\n  private static void executeSerializer(Forest forest, LobSerializer lobSerializer) {\n    try (LobSerializer serializer = lobSerializer) {\n\n      Object serialized = serializer.serialize(forest);\n      int id = serializer.persistToDb(1, forest.getName(), serialized);\n\n      Object fromDb = serializer.loadFromDb(id, Forest.class.getSimpleName());\n      Forest forestFromDb = serializer.deSerialize(fromDb);\n\n      LOGGER.info(forestFromDb.toString());\n    } catch (SQLException\n        | IOException\n        | TransformerException\n        | ParserConfigurationException\n        | SAXException\n        | ClassNotFoundException e) {\n      throw new RuntimeException(e);\n    }\n  }\n}\n"
  },
  {
    "path": "serialized-lob/src/main/java/com/iluwatar/slob/dbservice/DatabaseService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.slob.dbservice;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport javax.sql.DataSource;\nimport lombok.extern.slf4j.Slf4j;\nimport org.h2.jdbcx.JdbcDataSource;\n\n/** Service to handle database operations. */\n@Slf4j\npublic class DatabaseService {\n\n  public static final String CREATE_BINARY_SCHEMA_DDL =\n      \"CREATE TABLE IF NOT EXISTS FORESTS (ID NUMBER UNIQUE, NAME VARCHAR(30),FOREST VARBINARY)\";\n  public static final String CREATE_TEXT_SCHEMA_DDL =\n      \"CREATE TABLE IF NOT EXISTS FORESTS (ID NUMBER UNIQUE, NAME VARCHAR(30),FOREST VARCHAR)\";\n  public static final String DELETE_SCHEMA_SQL = \"DROP TABLE FORESTS IF EXISTS\";\n  public static final String BINARY_DATA = \"BINARY\";\n  private static final String DB_URL = \"jdbc:h2:~/test\";\n  private static final String INSERT = \"insert into FORESTS (id,name, forest) values (?,?,?)\";\n  private static final String SELECT = \"select FOREST from FORESTS where id = ?\";\n  private static final DataSource dataSource = createDataSource();\n  public String dataTypeDb;\n\n  /**\n   * Constructor initializes {@link DatabaseService#dataTypeDb}.\n   *\n   * @param dataTypeDb Type of data that is to be stored in DB can be 'TEXT' or 'BINARY'.\n   */\n  public DatabaseService(String dataTypeDb) {\n    this.dataTypeDb = dataTypeDb;\n  }\n\n  /**\n   * Initiates Data source.\n   *\n   * @return created data source\n   */\n  private static DataSource createDataSource() {\n    var dataSource = new JdbcDataSource();\n    dataSource.setURL(DB_URL);\n    return dataSource;\n  }\n\n  /**\n   * Shutdown Sequence executes Query {@link DatabaseService#DELETE_SCHEMA_SQL}.\n   *\n   * @throws SQLException if any issue occurs while executing DROP Query\n   */\n  public void shutDownService() throws SQLException {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(DELETE_SCHEMA_SQL);\n    }\n  }\n\n  /**\n   * Initaites startup sequence and executes the query {@link\n   * DatabaseService#CREATE_BINARY_SCHEMA_DDL} if {@link DatabaseService#dataTypeDb} is binary else\n   * will execute the query {@link DatabaseService#CREATE_TEXT_SCHEMA_DDL}.\n   *\n   * @throws SQLException if there are any issues during DDL execution\n   */\n  public void startupService() throws SQLException {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      if (dataTypeDb.equals(BINARY_DATA)) {\n        statement.execute(CREATE_BINARY_SCHEMA_DDL);\n      } else {\n        statement.execute(CREATE_TEXT_SCHEMA_DDL);\n      }\n    }\n  }\n\n  /**\n   * Executes the insert query {@link DatabaseService#INSERT}.\n   *\n   * @param id with which row is to be inserted\n   * @param name name to be added in the row\n   * @param data object data to be saved in the row\n   * @throws SQLException if there are any issues in executing insert query {@link\n   *     DatabaseService#INSERT}\n   */\n  public void insert(int id, String name, Object data) throws SQLException {\n    try (var connection = dataSource.getConnection();\n        var insert = connection.prepareStatement(INSERT)) {\n      insert.setInt(1, id);\n      insert.setString(2, name);\n      insert.setObject(3, data);\n      insert.execute();\n    }\n  }\n\n  /**\n   * Runs the select query {@link DatabaseService#SELECT} form the result set returns an {@link\n   * java.io.InputStream} if {@link DatabaseService#dataTypeDb} is 'binary' else will return the\n   * object as a {@link String}.\n   *\n   * @param id with which row is to be selected\n   * @param columnsName column in which the object is stored\n   * @return object found from DB\n   * @throws SQLException if there are any issues in executing insert query * {@link\n   *     DatabaseService#SELECT}\n   */\n  public Object select(final long id, String columnsName) throws SQLException {\n    ResultSet resultSet = null;\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(SELECT)) {\n      Object result = null;\n      preparedStatement.setLong(1, id);\n      resultSet = preparedStatement.executeQuery();\n      while (resultSet.next()) {\n        if (dataTypeDb.equals(BINARY_DATA)) {\n          result = resultSet.getBinaryStream(columnsName);\n        } else {\n          result = resultSet.getString(columnsName);\n        }\n      }\n      return result;\n    } finally {\n      if (resultSet != null) {\n        resultSet.close();\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "serialized-lob/src/main/java/com/iluwatar/slob/lob/Animal.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.slob.lob;\n\nimport java.io.Serializable;\nimport java.util.HashSet;\nimport java.util.Set;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.w3c.dom.Document;\nimport org.w3c.dom.Element;\nimport org.w3c.dom.Node;\nimport org.w3c.dom.NodeList;\n\n/** Creates an object Animal with a list of animals and/or plants it consumes. */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class Animal implements Serializable {\n\n  private String name;\n  private Set<Plant> plantsEaten = new HashSet<>();\n  private Set<Animal> animalsEaten = new HashSet<>();\n\n  /**\n   * Iterates over the input nodes recursively and adds new plants to {@link Animal#plantsEaten} or\n   * animals to {@link Animal#animalsEaten} found to input sets respectively.\n   *\n   * @param childNodes contains the XML Node containing the Forest\n   * @param animalsEaten set of Animals eaten\n   * @param plantsEaten set of Plants eaten\n   */\n  protected static void iterateXmlForAnimalAndPlants(\n      NodeList childNodes, Set<Animal> animalsEaten, Set<Plant> plantsEaten) {\n    for (int i = 0; i < childNodes.getLength(); i++) {\n      Node child = childNodes.item(i);\n      if (child.getNodeType() == Node.ELEMENT_NODE) {\n        if (child.getNodeName().equals(Animal.class.getSimpleName())) {\n          Animal animalEaten = new Animal();\n          animalEaten.createObjectFromXml(child);\n          animalsEaten.add(animalEaten);\n        } else if (child.getNodeName().equals(Plant.class.getSimpleName())) {\n          Plant plant = new Plant();\n          plant.createObjectFromXml(child);\n          plantsEaten.add(plant);\n        }\n      }\n    }\n  }\n\n  /**\n   * Provides XML Representation of the Animal.\n   *\n   * @param xmlDoc object to which the XML representation is to be written to\n   * @return XML Element contain the Animal representation\n   */\n  public Element toXmlElement(Document xmlDoc) {\n    Element root = xmlDoc.createElement(Animal.class.getSimpleName());\n    root.setAttribute(\"name\", name);\n    for (Plant plant : plantsEaten) {\n      Element xmlElement = plant.toXmlElement(xmlDoc);\n      if (xmlElement != null) {\n        root.appendChild(xmlElement);\n      }\n    }\n    for (Animal animal : animalsEaten) {\n      Element xmlElement = animal.toXmlElement(xmlDoc);\n      if (xmlElement != null) {\n        root.appendChild(xmlElement);\n      }\n    }\n    xmlDoc.appendChild(root);\n    return (Element) xmlDoc.getFirstChild();\n  }\n\n  /**\n   * Parses the Animal Object from the input XML Node.\n   *\n   * @param node the XML Node from which the Animal Object is to be parsed\n   */\n  public void createObjectFromXml(Node node) {\n    name = node.getAttributes().getNamedItem(\"name\").getNodeValue();\n    NodeList childNodes = node.getChildNodes();\n    iterateXmlForAnimalAndPlants(childNodes, animalsEaten, plantsEaten);\n  }\n\n  @Override\n  public String toString() {\n    StringBuilder sb = new StringBuilder();\n    sb.append(\"\\nAnimal Name = \").append(name);\n    if (!animalsEaten.isEmpty()) {\n      sb.append(\"\\n\\tAnimals Eaten by \").append(name).append(\": \");\n    }\n    for (Animal animal : animalsEaten) {\n      sb.append(\"\\n\\t\\t\").append(animal);\n    }\n    sb.append(\"\\n\");\n    if (!plantsEaten.isEmpty()) {\n      sb.append(\"\\n\\tPlants Eaten by \").append(name).append(\": \");\n    }\n    for (Plant plant : plantsEaten) {\n      sb.append(\"\\n\\t\\t\").append(plant);\n    }\n    return sb.toString();\n  }\n}\n"
  },
  {
    "path": "serialized-lob/src/main/java/com/iluwatar/slob/lob/Forest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.slob.lob;\n\nimport static com.iluwatar.slob.lob.Animal.iterateXmlForAnimalAndPlants;\n\nimport java.io.Serializable;\nimport java.util.HashSet;\nimport java.util.Set;\nimport javax.xml.parsers.DocumentBuilderFactory;\nimport javax.xml.parsers.ParserConfigurationException;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.w3c.dom.Document;\nimport org.w3c.dom.Element;\nimport org.w3c.dom.NodeList;\n\n/**\n * Creates an object Forest which contains animals and plants as its constituents. Animals may eat\n * plants or other animals in the forest.\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class Forest implements Serializable {\n  public static final String HORIZONTAL_DIVIDER = \"\\n--------------------------\\n\";\n  private String name;\n  private Set<Animal> animals = new HashSet<>();\n  private Set<Plant> plants = new HashSet<>();\n\n  /**\n   * Provides the representation of Forest in XML form.\n   *\n   * @return XML Element\n   */\n  public Element toXmlElement() throws ParserConfigurationException {\n    Document xmlDoc = getXmlDoc();\n\n    Element forestXml = xmlDoc.createElement(\"Forest\");\n    forestXml.setAttribute(\"name\", name);\n\n    Element animalsXml = xmlDoc.createElement(\"Animals\");\n    for (Animal animal : animals) {\n      Element animalXml = animal.toXmlElement(xmlDoc);\n      animalsXml.appendChild(animalXml);\n    }\n    forestXml.appendChild(animalsXml);\n\n    Element plantsXml = xmlDoc.createElement(\"Plants\");\n    for (Plant plant : plants) {\n      Element plantXml = plant.toXmlElement(xmlDoc);\n      plantsXml.appendChild(plantXml);\n    }\n    forestXml.appendChild(plantsXml);\n    return forestXml;\n  }\n\n  /**\n   * Returns XMLDoc to use for XML creation.\n   *\n   * @return XML DOC Object\n   * @throws ParserConfigurationException {@inheritDoc}\n   */\n  private Document getXmlDoc() throws ParserConfigurationException {\n    return DocumentBuilderFactory.newDefaultInstance().newDocumentBuilder().newDocument();\n  }\n\n  /**\n   * Parses the Forest Object from the input XML Document.\n   *\n   * @param document the XML document from which the Forest is to be parsed\n   */\n  public void createObjectFromXml(Document document) {\n    name = document.getDocumentElement().getAttribute(\"name\");\n    NodeList nodeList = document.getElementsByTagName(\"*\");\n    iterateXmlForAnimalAndPlants(nodeList, animals, plants);\n  }\n\n  @Override\n  public String toString() {\n    StringBuilder sb = new StringBuilder(\"\\n\");\n    sb.append(\"Forest Name = \").append(name).append(\"\\n\");\n    sb.append(\"Animals found in the \").append(name).append(\" Forest: \\n\");\n    for (Animal animal : animals) {\n      sb.append(HORIZONTAL_DIVIDER);\n      sb.append(animal.toString());\n      sb.append(HORIZONTAL_DIVIDER);\n    }\n    sb.append(\"\\n\");\n    sb.append(\"Plants in the \").append(name).append(\" Forest: \\n\");\n    for (Plant plant : plants) {\n      sb.append(HORIZONTAL_DIVIDER);\n      sb.append(plant.toString());\n      sb.append(HORIZONTAL_DIVIDER);\n    }\n    return sb.toString();\n  }\n}\n"
  },
  {
    "path": "serialized-lob/src/main/java/com/iluwatar/slob/lob/Plant.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.slob.lob;\n\nimport java.io.Serializable;\nimport java.util.StringJoiner;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.w3c.dom.Document;\nimport org.w3c.dom.Element;\nimport org.w3c.dom.NamedNodeMap;\nimport org.w3c.dom.Node;\n\n/** Creates an object Plant which contains its name and type. */\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class Plant implements Serializable {\n\n  private String name;\n  private String type;\n\n  /**\n   * Provides XML Representation of the Plant.\n   *\n   * @param xmlDoc to which the XML representation is to be written to\n   * @return XML Element contain the Animal representation\n   */\n  public Element toXmlElement(Document xmlDoc) {\n    Element root = xmlDoc.createElement(Plant.class.getSimpleName());\n    root.setAttribute(\"name\", name);\n    root.setAttribute(\"type\", type);\n    xmlDoc.appendChild(root);\n    return xmlDoc.getDocumentElement();\n  }\n\n  /**\n   * Parses the Plant Object from the input XML Node.\n   *\n   * @param node the XML Node from which the Animal Object is to be parsed\n   */\n  public void createObjectFromXml(Node node) {\n    NamedNodeMap attributes = node.getAttributes();\n    name = attributes.getNamedItem(\"name\").getNodeValue();\n    type = attributes.getNamedItem(\"type\").getNodeValue();\n  }\n\n  @Override\n  public String toString() {\n    StringJoiner stringJoiner = new StringJoiner(\",\");\n    stringJoiner.add(\"Name = \" + name);\n    stringJoiner.add(\"Type = \" + type);\n    return stringJoiner.toString();\n  }\n}\n"
  },
  {
    "path": "serialized-lob/src/main/java/com/iluwatar/slob/serializers/BlobSerializer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.slob.serializers;\n\nimport com.iluwatar.slob.lob.Forest;\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.ObjectInput;\nimport java.io.ObjectInputStream;\nimport java.io.ObjectOutputStream;\nimport java.sql.SQLException;\n\n/**\n * Creates a Serializer that uses Binary serialization and deserialization of objects graph to and\n * from their Binary Representation.\n */\npublic class BlobSerializer extends LobSerializer {\n\n  public static final String TYPE_OF_DATA_FOR_DB = \"BINARY\";\n\n  public BlobSerializer() throws SQLException {\n    super(TYPE_OF_DATA_FOR_DB);\n  }\n\n  /**\n   * Serializes the input object graph to its Binary Representation using Object Stream.\n   *\n   * @param toSerialize Object which is to be serialized\n   * @return Serialized object\n   * @throws IOException {@inheritDoc}\n   */\n  @Override\n  public Object serialize(Forest toSerialize) throws IOException {\n    ByteArrayOutputStream baos = new ByteArrayOutputStream();\n    ObjectOutputStream oos = new ObjectOutputStream(baos);\n    oos.writeObject(toSerialize);\n    oos.close();\n    return new ByteArrayInputStream(baos.toByteArray());\n  }\n\n  /**\n   * Deserializes the input Byte Array Stream using Object Stream and return its Object Graph\n   * Representation.\n   *\n   * @param toDeserialize Input Object to De-serialize\n   * @return Deserialized Object\n   * @throws ClassNotFoundException {@inheritDoc}\n   * @throws IOException {@inheritDoc}\n   */\n  @Override\n  public Forest deSerialize(Object toDeserialize) throws IOException, ClassNotFoundException {\n    InputStream bis = (InputStream) toDeserialize;\n    Forest forest;\n    try (ObjectInput in = new ObjectInputStream(bis)) {\n      forest = (Forest) in.readObject();\n    }\n    return forest;\n  }\n}\n"
  },
  {
    "path": "serialized-lob/src/main/java/com/iluwatar/slob/serializers/ClobSerializer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.slob.serializers;\n\nimport com.iluwatar.slob.lob.Forest;\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.io.StringWriter;\nimport java.sql.SQLException;\nimport javax.xml.parsers.DocumentBuilder;\nimport javax.xml.parsers.DocumentBuilderFactory;\nimport javax.xml.parsers.ParserConfigurationException;\nimport javax.xml.transform.OutputKeys;\nimport javax.xml.transform.Transformer;\nimport javax.xml.transform.TransformerException;\nimport javax.xml.transform.TransformerFactory;\nimport javax.xml.transform.dom.DOMSource;\nimport javax.xml.transform.stream.StreamResult;\nimport org.w3c.dom.Document;\nimport org.w3c.dom.Element;\nimport org.xml.sax.SAXException;\n\n/**\n * Creates a Serializer that uses Character based serialization and deserialization of objects graph\n * to and from XML Representation.\n */\npublic class ClobSerializer extends LobSerializer {\n\n  public static final String TYPE_OF_DATA_FOR_DB = \"TEXT\";\n\n  public ClobSerializer() throws SQLException {\n    super(TYPE_OF_DATA_FOR_DB);\n  }\n\n  /**\n   * Converts the input node to its XML String Representation.\n   *\n   * @param node XML Node that is to be converted to string\n   * @return String representation of XML parsed from the Node\n   * @throws TransformerException If any issues occur in Transformation from Node to XML\n   */\n  private static String elementToXmlString(Element node) throws TransformerException {\n    StringWriter sw = new StringWriter();\n    Transformer t = TransformerFactory.newDefaultInstance().newTransformer();\n    t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, \"no\");\n    t.setOutputProperty(OutputKeys.INDENT, \"yes\");\n    t.transform(new DOMSource(node), new StreamResult(sw));\n    return sw.toString();\n  }\n\n  /**\n   * Serializes the input object graph to its XML Representation using DOM Elements.\n   *\n   * @param forest Object which is to be serialized\n   * @return Serialized object\n   * @throws ParserConfigurationException If any issues occur in parsing input object\n   * @throws TransformerException If any issues occur in Transformation from Node to XML\n   */\n  @Override\n  public Object serialize(Forest forest) throws ParserConfigurationException, TransformerException {\n    Element xmlElement = forest.toXmlElement();\n    return elementToXmlString(xmlElement);\n  }\n\n  /**\n   * Deserializes the input XML string using DOM Parser and return its Object Graph Representation.\n   *\n   * @param toDeserialize Input Object to De-serialize\n   * @return Deserialized Object\n   * @throws ParserConfigurationException If any issues occur in parsing input object\n   * @throws IOException if any issues occur during reading object\n   * @throws SAXException If any issues occur in Transformation from Node to XML\n   */\n  @Override\n  public Forest deSerialize(Object toDeserialize)\n      throws ParserConfigurationException, IOException, SAXException {\n    DocumentBuilder documentBuilder =\n        DocumentBuilderFactory.newDefaultInstance().newDocumentBuilder();\n    var stream = new ByteArrayInputStream(toDeserialize.toString().getBytes());\n    Document parsed = documentBuilder.parse(stream);\n    Forest forest = new Forest();\n    forest.createObjectFromXml(parsed);\n    return forest;\n  }\n}\n"
  },
  {
    "path": "serialized-lob/src/main/java/com/iluwatar/slob/serializers/LobSerializer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.slob.serializers;\n\nimport com.iluwatar.slob.dbservice.DatabaseService;\nimport com.iluwatar.slob.lob.Forest;\nimport java.io.Closeable;\nimport java.io.IOException;\nimport java.io.Serializable;\nimport java.sql.SQLException;\nimport javax.xml.parsers.ParserConfigurationException;\nimport javax.xml.transform.TransformerException;\nimport org.xml.sax.SAXException;\n\n/**\n * A LobSerializer can be used to create an instance of a serializer which can serialize and\n * deserialize an object and persist and load that object into a DB. from their Binary\n * Representation.\n */\npublic abstract class LobSerializer implements Serializable, Closeable {\n\n  private final transient DatabaseService databaseService;\n\n  /**\n   * Constructor initializes {@link LobSerializer#databaseService}.\n   *\n   * @param dataTypeDb Input provides type of Data to be stored by the Data Base Service\n   * @throws SQLException If any issue occurs during instantiation of DB Service or during startup.\n   */\n  protected LobSerializer(String dataTypeDb) throws SQLException {\n    databaseService = new DatabaseService(dataTypeDb);\n    databaseService.startupService();\n  }\n\n  /**\n   * Provides the specification to Serialize the input object.\n   *\n   * @param toSerialize Input Object to serialize\n   * @return Serialized Object\n   * @throws ParserConfigurationException if any issue occurs during parsing of input object\n   * @throws TransformerException if any issue occurs during Transformation\n   * @throws IOException if any issues occur during reading object\n   */\n  public abstract Object serialize(Forest toSerialize)\n      throws ParserConfigurationException, TransformerException, IOException;\n\n  /**\n   * Saves the object to DB with the provided ID.\n   *\n   * @param id key to be sent to DB service\n   * @param name Object name to store in DB\n   * @param object Object to store in DB\n   * @return ID with which the object is stored in DB\n   * @throws SQLException if any issue occurs while saving to DB\n   */\n  public int persistToDb(int id, String name, Object object) throws SQLException {\n    databaseService.insert(id, name, object);\n    return id;\n  }\n\n  /**\n   * Loads the object from db using the ID and column name.\n   *\n   * @param id to query the DB\n   * @param columnName column from which object is to be extracted\n   * @return Object from DB\n   * @throws SQLException if any issue occurs while loading from DB\n   */\n  public Object loadFromDb(int id, String columnName) throws SQLException {\n    return databaseService.select(id, columnName);\n  }\n\n  /**\n   * Provides the specification to Deserialize the input object.\n   *\n   * @param toDeserialize object to deserialize\n   * @return Deserialized Object\n   * @throws ParserConfigurationException If issue occurs during parsing of input object\n   * @throws IOException if any issues occur during reading object\n   * @throws SAXException if any issues occur during reading object for XML parsing\n   */\n  public abstract Forest deSerialize(Object toDeserialize)\n      throws ParserConfigurationException, IOException, SAXException, ClassNotFoundException;\n\n  @Override\n  public void close() {\n    try {\n      databaseService.shutDownService();\n    } catch (SQLException e) {\n      throw new RuntimeException(e);\n    }\n  }\n}\n"
  },
  {
    "path": "serialized-lob/src/test/java/com/iluwatar/slob/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.slob;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport com.iluwatar.slob.lob.Animal;\nimport com.iluwatar.slob.lob.Forest;\nimport com.iluwatar.slob.lob.Plant;\nimport com.iluwatar.slob.serializers.BlobSerializer;\nimport com.iluwatar.slob.serializers.ClobSerializer;\nimport com.iluwatar.slob.serializers.LobSerializer;\nimport java.io.IOException;\nimport java.sql.SQLException;\nimport java.util.Collections;\nimport java.util.Set;\nimport javax.xml.parsers.ParserConfigurationException;\nimport javax.xml.transform.TransformerException;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\nimport org.xml.sax.SAXException;\n\n/** SLOB Application test */\n@Slf4j\nclass AppTest {\n\n  /**\n   * Creates a Forest with Animals and Plants along with their respective relationships.\n   *\n   * <p>The method creates a forest with 2 Plants Grass and Oak of type Herb and tree respectively.\n   *\n   * <p>It also creates 3 animals Zebra and Buffalo which eat the plant grass. Lion consumes the\n   * Zebra and the Buffalo.\n   *\n   * <p>With the above animals and plants and their relationships a forest object is created which\n   * represents the Object Graph.\n   *\n   * @return Forest Object\n   */\n  private static Forest createForest() {\n    Plant grass = new Plant(\"Grass\", \"Herb\");\n    Plant oak = new Plant(\"Oak\", \"Tree\");\n\n    Animal zebra = new Animal(\"Zebra\", Set.of(grass), Collections.emptySet());\n    Animal buffalo = new Animal(\"Buffalo\", Set.of(grass), Collections.emptySet());\n    Animal lion = new Animal(\"Lion\", Collections.emptySet(), Set.of(zebra, buffalo));\n\n    return new Forest(\"Amazon\", Set.of(lion, buffalo, zebra), Set.of(grass, oak));\n  }\n\n  /**\n   * Tests the {@link App} without passing any argument in the args to test the {@link\n   * ClobSerializer}.\n   */\n  @Test\n  void shouldExecuteWithoutExceptionClob() {\n    assertDoesNotThrow(() -> App.main(new String[] {\"CLOB\"}));\n  }\n\n  /**\n   * Tests the {@link App} without passing any argument in the args to test the {@link\n   * BlobSerializer}.\n   */\n  @Test\n  void shouldExecuteWithoutExceptionBlob() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n\n  /**\n   * Tests the serialization of the input object using the {@link ClobSerializer} and persists the\n   * serialized object to DB, then load the object back from DB and deserializes it using the\n   * provided {@link ClobSerializer}.\n   *\n   * <p>After loading the object back from DB the test matches the hash of the input object with the\n   * hash of the object that was loaded from DB and deserialized.\n   */\n  @Test\n  void clobSerializerTest() {\n    Forest forest = createForest();\n    try (LobSerializer serializer = new ClobSerializer()) {\n\n      Object serialized = serializer.serialize(forest);\n      int id = serializer.persistToDb(1, forest.getName(), serialized);\n\n      Object fromDb = serializer.loadFromDb(id, Forest.class.getSimpleName());\n      Forest forestFromDb = serializer.deSerialize(fromDb);\n\n      Assertions.assertEquals(\n          forest.hashCode(),\n          forestFromDb.hashCode(),\n          \"Hashes of objects after Serializing and Deserializing are the same\");\n    } catch (SQLException\n        | IOException\n        | TransformerException\n        | ParserConfigurationException\n        | SAXException\n        | ClassNotFoundException e) {\n      throw new RuntimeException(e);\n    }\n  }\n\n  /**\n   * Tests the serialization of the input object using the {@link BlobSerializer} and persists the\n   * serialized object to DB, then loads the object back from DB and deserializes it using the\n   * {@link BlobSerializer}.\n   *\n   * <p>After loading the object back from DB the test matches the hash of the input object with the\n   * hash of the object that was loaded from DB and deserialized.\n   */\n  @Test\n  void blobSerializerTest() {\n    Forest forest = createForest();\n    try (LobSerializer serializer = new BlobSerializer()) {\n\n      Object serialized = serializer.serialize(forest);\n      int id = serializer.persistToDb(1, forest.getName(), serialized);\n\n      Object fromDb = serializer.loadFromDb(id, Forest.class.getSimpleName());\n      Forest forestFromDb = serializer.deSerialize(fromDb);\n\n      Assertions.assertEquals(\n          forest.hashCode(),\n          forestFromDb.hashCode(),\n          \"Hashes of objects after Serializing and Deserializing are the same\");\n    } catch (SQLException\n        | IOException\n        | TransformerException\n        | ParserConfigurationException\n        | SAXException\n        | ClassNotFoundException e) {\n      throw new RuntimeException(e);\n    }\n  }\n}\n"
  },
  {
    "path": "servant/README.md",
    "content": "---\ntitle: \"Servant Pattern in Java: Facilitating Rich Interactions with Servant Helpers\"\nshortTitle: Servant\ndescription: \"Explore the Servant design pattern in Java, an essential technique for decoupling operations from object classes. Learn how this pattern facilitates reusable and efficient code management through our detailed examples and explanations.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Decoupling\n  - Interface\n  - Messaging\n  - Object composition\n  - Resource management\n---\n\n## Also known as\n\n* Helper\n\n## Intent of Servant Design Pattern\n\nThe Servant pattern is used to perform specific operations for a group of objects without changing the classes of the elements on which it operates.\n\n## Detailed Explanation of Servant Pattern with Real-World Examples\n\nReal-world example\n\n> In a restaurant, a waiter (Servant) serves multiple tables (objects) by taking orders, delivering food, and handling payments. The waiter provides these common services without altering the fundamental nature of the tables or customers, allowing the restaurant to efficiently manage customer service while keeping the roles of the tables and customers unchanged.\n\nIn plain words\n\n> The Java Servant pattern effectively centralizes common functionality for multiple classes, enabling decoupled and reusable operations in software development without altering the original classes, promoting efficient Java design practices.\n\nWikipedia says\n\n> In software engineering, the servant pattern defines an object used to offer some functionality to a group of classes without defining that functionality in each of them. A Servant is a class whose instance (or even just class) provides methods that take care of a desired service, while objects for which (or with whom) the servant does something, are taken as parameters.\n\nSequence diagram\n\n![Servant sequence diagram](./etc/servant-sequence-diagram.png)\n\n## Programmatic Example of Servant Pattern in Java\n\nThe Servant design pattern is a behavioral design pattern that defines a class that provides some sort of service to a group of classes. This pattern is particularly useful when these classes lack some common functionality that can't be added to the superclass. The Servant class brings this common functionality to a group of classes.\n\nIn the provided code, we have a `Servant` class that provides services to the `Royalty` class. The `Servant` class has methods like `feed()`, `giveWine()`, and `giveCompliments()` which are services provided to the `Royalty` class.\n\nHere is the `Servant` class:\n\n```java\npublic class Servant {\n\n    public String name;\n\n    public Servant(String name) {\n        this.name = name;\n    }\n\n    public void feed(Royalty r) {\n        r.getFed();\n    }\n\n    public void giveWine(Royalty r) {\n        r.getDrink();\n    }\n\n    public void giveCompliments(Royalty r) {\n        r.receiveCompliments();\n    }\n\n    public boolean checkIfYouWillBeHanged(List<Royalty> tableGuests) {\n        return tableGuests.stream().allMatch(Royalty::getMood);\n    }\n}\n```\n\nThe `Royalty` class is an interface that is implemented by the classes that use the services of the `Servant`. Here is a simplified version of the `Royalty` interface:\n\n```java\npublic interface Royalty {\n    void getFed();\n\n    void getDrink();\n\n    void receiveCompliments();\n\n    void changeMood();\n\n    boolean getMood();\n}\n```\n\nThe `App` class uses the `Servant` to provide services to the `Royalty` objects. Here is a simplified version of the `App` class:\n\n```java\npublic class App {\n\n    private static final Servant jenkins = new Servant(\"Jenkins\");\n    private static final Servant travis = new Servant(\"Travis\");\n\n    public static void main(String[] args) {\n        scenario(jenkins, 1);\n        scenario(travis, 0);\n    }\n\n    public static void scenario(Servant servant, int compliment) {\n        var k = new King();\n        var q = new Queen();\n\n        var guests = List.of(k, q);\n\n        servant.feed(k);\n        servant.feed(q);\n        servant.giveWine(k);\n        servant.giveWine(q);\n        servant.giveCompliments(guests.get(compliment));\n\n        guests.forEach(Royalty::changeMood);\n\n        if (servant.checkIfYouWillBeHanged(guests)) {\n            LOGGER.info(\"{} will live another day\", servant.name);\n        } else {\n            LOGGER.info(\"Poor {}. His days are numbered\", servant.name);\n        }\n    }\n}\n```\n\nRunning the application produces:\n\n```\n09:10:38.795 [main] INFO com.iluwatar.servant.App -- Jenkins will live another day\n09:10:38.797 [main] INFO com.iluwatar.servant.App -- Poor Travis. His days are numbered\n```\n\nIn this example, the `Servant` class provides services to the `Royalty` objects. The `Servant` class doesn't know about the specific implementation of the `Royalty` objects, it only knows that it can provide certain services to them. This is a good example of the Servant design pattern.\n\n## When to Use the Servant Pattern in Java\n\n* Use the Servant pattern when you need to provide a common functionality to a group of classes without polluding their class definitions, perfect for enhancing Java application architecture.\n* Suitable when the operations performed on the objects are not the primary responsibility of the objects themselves.\n\n## Real-World Applications of Servant Pattern in Java\n\n* In GUI applications to handle operations like rendering or hit-testing which are common across different UI components.\n* In games where various entities (like players, enemies, or items) need common behavior such as movement or collision detection.\n* Logging or auditing functionalities that are required across multiple business objects.\n\n## Benefits and Trade-offs of Servant Pattern\n\nBenefits:\n\n* Promotes code reuse and separation of concerns by decoupling the operations from the objects they operate on.\n* Reduces code duplication by centralizing the shared functionality.\n\nTrade-offs:\n\n* Can lead to an increase in the number of classes, potentially making the system harder to understand.\n* May introduce tight coupling between the Servant and the classes it serves if not designed carefully.\n\n## Related Java Design Patterns\n\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): The Servant pattern is similar to the Adapter pattern in that both provide a way to work with classes without modifying them, but the Servant pattern focuses on providing additional behavior to multiple classes rather than adapting one interface to another.\n* [Facade](https://java-design-patterns.com/patterns/facade/): Both patterns provide a simplified interface to a set of functionalities, but the Servant pattern is typically used for adding functionalities to a group of classes, while the Facade pattern hides the complexities of a subsystem.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. The Servant pattern can be used in conjunction with the Strategy pattern to define operations that apply to multiple classes.\n* View Helper: The View Helper pattern is related as it also centralizes common functionality, but it focuses on separating presentation logic from business logic in web applications.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n* [Pattern-Oriented Software Architecture Volume 1: A System of Patterns](https://amzn.to/3xZ1ELU)\n"
  },
  {
    "path": "servant/etc/servant-pattern.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<class-diagram version=\"1.1.7\" icons=\"true\" automaticImage=\"JPEG\" always-add-relationships=\"false\" \r\n  generalizations=\"true\" realizations=\"true\" associations=\"true\" dependencies=\"true\" nesting-relationships=\"true\">  \r\n  <class id=\"1\" language=\"java\" name=\"App\" project=\"servant\" file=\"/servant/src/App.java\" binary=\"false\" \r\n    corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"228\" y=\"149\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <class id=\"2\" language=\"java\" name=\"King\" project=\"servant\" file=\"/servant/src/King.java\" binary=\"false\" \r\n    corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"522\" y=\"673\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <class id=\"3\" language=\"java\" name=\"Queen\" project=\"servant\" file=\"/servant/src/Queen.java\" binary=\"false\" \r\n    corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"729\" y=\"691\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <interface id=\"4\" language=\"java\" name=\"Royalty\" project=\"servant\" file=\"/servant/src/Royalty.java\" binary=\"false\" \r\n    corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"579\" y=\"378\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </interface>  \r\n  <class id=\"5\" language=\"java\" name=\"Servant\" project=\"servant\" file=\"/servant/src/Servant.java\" binary=\"false\" \r\n    corner=\"BOTTOM_RIGHT\">    \r\n    <position height=\"-1\" width=\"-1\" x=\"577\" y=\"151\"/>    \r\n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \r\n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \r\n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    </display>  \r\n  </class>  \r\n  <realization id=\"6\">    \r\n    <end type=\"SOURCE\" refId=\"2\"/>    \r\n    <end type=\"TARGET\" refId=\"4\"/>  \r\n  </realization>  \r\n  <dependency id=\"7\">    \r\n    <end type=\"SOURCE\" refId=\"5\"/>    \r\n    <end type=\"TARGET\" refId=\"4\"/>  \r\n  </dependency>  \r\n  <realization id=\"8\">    \r\n    <end type=\"SOURCE\" refId=\"3\"/>    \r\n    <end type=\"TARGET\" refId=\"4\"/>  \r\n  </realization>  \r\n  <dependency id=\"9\">    \r\n    <end type=\"SOURCE\" refId=\"1\"/>    \r\n    <end type=\"TARGET\" refId=\"4\"/>  \r\n  </dependency>  \r\n  <association id=\"10\">    \r\n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \r\n      <attribute id=\"11\" name=\"jenkins\"/>      \r\n      <multiplicity id=\"12\" minimum=\"0\" maximum=\"1\"/>    \r\n    </end>    \r\n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \r\n    <display labels=\"false\" multiplicity=\"false\"/>  \r\n  </association>  \r\n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \r\n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \r\n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \r\n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \r\n  </classifier-display>  \r\n  <association-display labels=\"true\" multiplicity=\"true\"/>\r\n</class-diagram>"
  },
  {
    "path": "servant/etc/servant.urm.puml",
    "content": "@startuml\npackage com.iluwatar.servant {\n  class App {\n    - LOGGER : Logger {static}\n    - jenkins : Servant {static}\n    - travis : Servant {static}\n    + App()\n    + main(args : String[]) {static}\n    + scenario(servant : Servant, compliment : int) {static}\n  }\n  class King {\n    - complimentReceived : boolean\n    - isDrunk : boolean\n    - isHappy : boolean\n    - isHungry : boolean\n    + King()\n    + changeMood()\n    + getDrink()\n    + getFed()\n    + getMood() : boolean\n    + receiveCompliments()\n  }\n  class Queen {\n    - complimentReceived : boolean\n    - isDrunk : boolean\n    - isFlirty : boolean\n    - isHappy : boolean\n    - isHungry : boolean\n    + Queen()\n    + changeMood()\n    + getDrink()\n    + getFed()\n    + getMood() : boolean\n    + receiveCompliments()\n    + setFlirtiness(f : boolean)\n  }\n  ~interface Royalty {\n    + changeMood() {abstract}\n    + getDrink() {abstract}\n    + getFed() {abstract}\n    + getMood() : boolean {abstract}\n    + receiveCompliments() {abstract}\n  }\n  class Servant {\n    + name : String\n    + Servant(name : String)\n    + checkIfYouWillBeHanged(tableGuests : List<Royalty>) : boolean\n    + feed(r : Royalty)\n    + giveCompliments(r : Royalty)\n    + giveWine(r : Royalty)\n  }\n}\nApp -->  \"-jenkins\" Servant\nKing ..|> Royalty \nQueen ..|> Royalty \n@enduml"
  },
  {
    "path": "servant/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <groupId>servant</groupId>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>servant</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.servant.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "servant/src/etc/servant.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<uml:Model xmlns:uml=\"http://www.eclipse.org/uml2/4.0.0/UML\" xmlns:xmi=\"http://www.omg.org/XMI\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmi:version=\"2.0\" xmi:id=\"_BWy4cHlgEeSYU-Ff_V1D0Q\" name=\"java-design-patterns\">\n  <eAnnotations xmi:id=\"_BWy4cXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n    <details xmi:id=\"_BWy4cnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_oCfYEHleEeSYU-Ff_V1D0Q\" />\n  </eAnnotations>\n  <packageImport xmi:id=\"_BWy4c3lgEeSYU-Ff_V1D0Q\">\n    <eAnnotations xmi:id=\"_BWy4dHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n      <details xmi:id=\"_BWy4dXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGRXleEeSMFa_mT0wMkw\" />\n    </eAnnotations>\n    <importedPackage href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#/\" />\n  </packageImport>\n  <packageImport xmi:id=\"_BWy4dnlgEeSYU-Ff_V1D0Q\">\n    <eAnnotations xmi:id=\"_BWy4d3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n      <details xmi:id=\"_BWy4eHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGRnleEeSMFa_mT0wMkw\" />\n    </eAnnotations>\n    <importedPackage href=\"pathmap://GENMYMODEL_LIBRARIES/GenMyModelPrimitiveTypes.library.uml#/\" />\n  </packageImport>\n  <packagedElement xsi:type=\"uml:Package\" xmi:id=\"_BWy4eXlgEeSYU-Ff_V1D0Q\" name=\"com\">\n    <eAnnotations xmi:id=\"_BWy4enlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n      <details xmi:id=\"_BWy4e3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGR3leEeSMFa_mT0wMkw\" />\n    </eAnnotations>\n    <packagedElement xsi:type=\"uml:Package\" xmi:id=\"_BWy4fHlgEeSYU-Ff_V1D0Q\" name=\"iluwatar\">\n      <eAnnotations xmi:id=\"_BWy4fXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n        <details xmi:id=\"_BWy4fnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGSHleEeSMFa_mT0wMkw\" />\n      </eAnnotations>\n      <packagedElement xsi:type=\"uml:Class\" xmi:id=\"_BWy4f3lgEeSYU-Ff_V1D0Q\" name=\"App\">\n        <eAnnotations xmi:id=\"_BWy4gHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWy4gXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGSXleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n        <ownedComment xmi:id=\"_BWy4gnlgEeSYU-Ff_V1D0Q\" body=\"Servant offers some functionality to a group of classes without defining that functionality in each of them. A Servant is a class whose instance provides methods that take care of a desired service,while objects for which the servant does something, are taken as parameters.\">\n          <eAnnotations xmi:id=\"_BWy4g3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy4hHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGSnleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n        </ownedComment>\n        <ownedOperation xmi:id=\"_BWy4hXlgEeSYU-Ff_V1D0Q\" name=\"main\" visibility=\"public\" isStatic=\"true\">\n          <eAnnotations xmi:id=\"_BWy4hnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy4h3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGS3leEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy4iHlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy4iXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4inlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGTHleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n          <ownedParameter xmi:id=\"_BWy4i3lgEeSYU-Ff_V1D0Q\" name=\"args\">\n            <eAnnotations xmi:id=\"_BWy4jHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4jXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGTXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//String\" />\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWy4jnlgEeSYU-Ff_V1D0Q\">\n              <eAnnotations xmi:id=\"_BWy4j3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWy4kHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGTnleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWy4kXlgEeSYU-Ff_V1D0Q\" value=\"*\">\n              <eAnnotations xmi:id=\"_BWy4knlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWy4k3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGT3leEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWy4lHlgEeSYU-Ff_V1D0Q\" name=\"scenario\" visibility=\"public\" isStatic=\"true\">\n          <eAnnotations xmi:id=\"_BWy4lXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy4lnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGUHleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy4l3lgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy4mHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4mXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGUXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n          <ownedParameter xmi:id=\"_BWy4mnlgEeSYU-Ff_V1D0Q\" name=\"servant\" type=\"_BWzfp3lgEeSYU-Ff_V1D0Q\">\n            <eAnnotations xmi:id=\"_BWy4m3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4nHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGUnleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWy4nXlgEeSYU-Ff_V1D0Q\">\n              <eAnnotations xmi:id=\"_BWy4nnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWy4n3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGU3leEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWy4oHlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWy4oXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWy4onlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGVHleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n          <ownedParameter xmi:id=\"_BWy4o3lgEeSYU-Ff_V1D0Q\" name=\"compliment\">\n            <eAnnotations xmi:id=\"_BWy4pHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4pXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGVXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//Integer\" />\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWy4pnlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWy4p3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWy4qHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGVnleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWy4qXlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWy4qnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWy4q3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGV3leEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n        </ownedOperation>\n      </packagedElement>\n      <packagedElement xsi:type=\"uml:Class\" xmi:id=\"_BWy4rHlgEeSYU-Ff_V1D0Q\" clientDependency=\"_BWy4wXlgEeSYU-Ff_V1D0Q\" name=\"King\">\n        <eAnnotations xmi:id=\"_BWy4rXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWy4rnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGWHleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n        <ownedAttribute xmi:id=\"_BWy4r3lgEeSYU-Ff_V1D0Q\" name=\"isHappy\" visibility=\"private\">\n          <eAnnotations xmi:id=\"_BWy4sHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy4sXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGWXleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//Boolean\" />\n          <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWy4snlgEeSYU-Ff_V1D0Q\" value=\"1\">\n            <eAnnotations xmi:id=\"_BWy4s3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4tHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGWnleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </lowerValue>\n          <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWy4tXlgEeSYU-Ff_V1D0Q\" value=\"1\">\n            <eAnnotations xmi:id=\"_BWy4tnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4t3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGW3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </upperValue>\n        </ownedAttribute>\n        <ownedAttribute xmi:id=\"_BWy4uHlgEeSYU-Ff_V1D0Q\" name=\"complimentReceived\" visibility=\"private\">\n          <eAnnotations xmi:id=\"_BWy4uXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy4unlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGXHleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//Boolean\" />\n          <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWy4u3lgEeSYU-Ff_V1D0Q\" value=\"1\">\n            <eAnnotations xmi:id=\"_BWy4vHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4vXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGXXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </lowerValue>\n          <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWy4vnlgEeSYU-Ff_V1D0Q\" value=\"1\">\n            <eAnnotations xmi:id=\"_BWy4v3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4wHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGXnleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </upperValue>\n        </ownedAttribute>\n        <interfaceRealization xmi:id=\"_BWy4wXlgEeSYU-Ff_V1D0Q\" client=\"_BWy4rHlgEeSYU-Ff_V1D0Q\" supplier=\"_BWzfgHlgEeSYU-Ff_V1D0Q\" contract=\"_BWzfgHlgEeSYU-Ff_V1D0Q\">\n          <eAnnotations xmi:id=\"_BWy4wnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy4w3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGX3leEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n        </interfaceRealization>\n        <ownedOperation xmi:id=\"_BWy4xHlgEeSYU-Ff_V1D0Q\" name=\"getFed\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWy4xXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy4xnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGYHleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy4x3lgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy4yHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4yXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGYXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWy4ynlgEeSYU-Ff_V1D0Q\" name=\"getDrink\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWy4y3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy4zHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGYnleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy4zXlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy4znlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4z3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGY3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWy40HlgEeSYU-Ff_V1D0Q\" name=\"receiveCompliments\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWy40XlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy40nlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGZHleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy403lgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy41HlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy41XlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGZXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWy41nlgEeSYU-Ff_V1D0Q\" name=\"changeMood\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWy413lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy42HlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGZnleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy42XlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy42nlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy423lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGZ3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWy43HlgEeSYU-Ff_V1D0Q\" name=\"getMood\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWy43XlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy43nlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGaHleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy433lgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy44HlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy44XlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGaXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//Boolean\" />\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWy44nlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWy443lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWy45HlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGanleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWy45XlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWy45nlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWy453lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGa3leEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n        </ownedOperation>\n      </packagedElement>\n      <packagedElement xsi:type=\"uml:Class\" xmi:id=\"_BWy46HlgEeSYU-Ff_V1D0Q\" clientDependency=\"_BWy4_XlgEeSYU-Ff_V1D0Q\" name=\"Queen\">\n        <eAnnotations xmi:id=\"_BWy46XlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWy46nlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGbHleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n        <ownedAttribute xmi:id=\"_BWy463lgEeSYU-Ff_V1D0Q\" name=\"isHappy\" visibility=\"private\">\n          <eAnnotations xmi:id=\"_BWy47HlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy47XlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGbXleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//Boolean\" />\n          <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWy47nlgEeSYU-Ff_V1D0Q\" value=\"1\">\n            <eAnnotations xmi:id=\"_BWy473lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy48HlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGbnleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </lowerValue>\n          <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWy48XlgEeSYU-Ff_V1D0Q\" value=\"1\">\n            <eAnnotations xmi:id=\"_BWy48nlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy483lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGb3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </upperValue>\n        </ownedAttribute>\n        <ownedAttribute xmi:id=\"_BWy49HlgEeSYU-Ff_V1D0Q\" name=\"complimentReceived\" visibility=\"private\">\n          <eAnnotations xmi:id=\"_BWy49XlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy49nlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGcHleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//Boolean\" />\n          <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWy493lgEeSYU-Ff_V1D0Q\" value=\"1\">\n            <eAnnotations xmi:id=\"_BWy4-HlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4-XlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGcXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </lowerValue>\n          <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWy4-nlgEeSYU-Ff_V1D0Q\" value=\"1\">\n            <eAnnotations xmi:id=\"_BWy4-3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy4_HlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGcnleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </upperValue>\n        </ownedAttribute>\n        <interfaceRealization xmi:id=\"_BWy4_XlgEeSYU-Ff_V1D0Q\" client=\"_BWy46HlgEeSYU-Ff_V1D0Q\" supplier=\"_BWzfgHlgEeSYU-Ff_V1D0Q\" contract=\"_BWzfgHlgEeSYU-Ff_V1D0Q\">\n          <eAnnotations xmi:id=\"_BWy4_nlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy4_3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGc3leEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n        </interfaceRealization>\n        <ownedOperation xmi:id=\"_BWy5AHlgEeSYU-Ff_V1D0Q\" name=\"getFed\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWy5AXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy5AnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGdHleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy5A3lgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy5BHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy5BXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGdXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWy5BnlgEeSYU-Ff_V1D0Q\" name=\"getDrink\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWy5B3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy5CHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGdnleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy5CXlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy5CnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy5C3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGd3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWy5DHlgEeSYU-Ff_V1D0Q\" name=\"receiveCompliments\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWy5DXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy5DnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGeHleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy5D3lgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy5EHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy5EXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGeXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWy5EnlgEeSYU-Ff_V1D0Q\" name=\"changeMood\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWy5E3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy5FHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGenleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy5FXlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy5FnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy5F3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGe3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWy5GHlgEeSYU-Ff_V1D0Q\" name=\"getMood\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWy5GXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy5GnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGfHleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy5G3lgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy5HHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy5HXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGfXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//Boolean\" />\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWy5HnlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWy5H3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWy5IHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGfnleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWy5IXlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWy5InlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWy5I3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGf3leEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWy5JHlgEeSYU-Ff_V1D0Q\" name=\"setFlirtiness\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWy5JXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWy5JnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGgHleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWy5J3lgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWy5KHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy5KXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGgXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n          <ownedParameter xmi:id=\"_BWy5KnlgEeSYU-Ff_V1D0Q\" name=\"f\">\n            <eAnnotations xmi:id=\"_BWy5K3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWy5LHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGgnleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//Boolean\" />\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWy5LXlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWy5LnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWy5L3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGg3leEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWy5MHlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWy5MXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWy5MnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGhHleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n        </ownedOperation>\n      </packagedElement>\n      <packagedElement xsi:type=\"uml:Interface\" xmi:id=\"_BWzfgHlgEeSYU-Ff_V1D0Q\" clientDependency=\"_BWzgMHlgEeSYU-Ff_V1D0Q\" name=\"Royalty\" visibility=\"package\">\n        <eAnnotations xmi:id=\"_BWzfgXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWzfgnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGhXleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n        <ownedOperation xmi:id=\"_BWzfg3lgEeSYU-Ff_V1D0Q\" name=\"getFed\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWzfhHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWzfhXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGhnleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWzfhnlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWzfh3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzfiHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGh3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWzfiXlgEeSYU-Ff_V1D0Q\" name=\"getDrink\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWzfinlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWzfi3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGiHleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWzfjHlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWzfjXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzfjnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGiXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWzfj3lgEeSYU-Ff_V1D0Q\" name=\"changeMood\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWzfkHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWzfkXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGinleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWzfknlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWzfk3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzflHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGi3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWzflXlgEeSYU-Ff_V1D0Q\" name=\"receiveCompliments\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWzflnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWzfl3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGjHleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWzfmHlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWzfmXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzfmnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGjXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWzfm3lgEeSYU-Ff_V1D0Q\" name=\"getMood\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWzfnHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWzfnXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGjnleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWzfnnlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWzfn3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzfoHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGj3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//Boolean\" />\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWzfoXlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWzfonlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzfo3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGkHleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWzfpHlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWzfpXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzfpnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGkXleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n        </ownedOperation>\n      </packagedElement>\n      <packagedElement xsi:type=\"uml:Class\" xmi:id=\"_BWzfp3lgEeSYU-Ff_V1D0Q\" name=\"Servant\">\n        <eAnnotations xmi:id=\"_BWzfqHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWzfqXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGknleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n        <ownedAttribute xmi:id=\"_BWzfqnlgEeSYU-Ff_V1D0Q\" name=\"name\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWzfq3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWzfrHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGk3leEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//String\" />\n          <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWzfrXlgEeSYU-Ff_V1D0Q\">\n            <eAnnotations xmi:id=\"_BWzfrnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzfr3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGlHleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </lowerValue>\n          <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWzfsHlgEeSYU-Ff_V1D0Q\" value=\"1\">\n            <eAnnotations xmi:id=\"_BWzfsXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzfsnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGlXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </upperValue>\n        </ownedAttribute>\n        <ownedOperation xmi:id=\"_BWzfs3lgEeSYU-Ff_V1D0Q\" name=\"Servant\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWzftHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWzftXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGlnleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWzftnlgEeSYU-Ff_V1D0Q\" name=\"name\">\n            <eAnnotations xmi:id=\"_BWzft3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzfuHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGl3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//String\" />\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWzfuXlgEeSYU-Ff_V1D0Q\">\n              <eAnnotations xmi:id=\"_BWzfunlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzfu3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGmHleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWzfvHlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWzfvXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzfvnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGmXleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWzfv3lgEeSYU-Ff_V1D0Q\" name=\"feed\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWzfwHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWzfwXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGmnleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWzfwnlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWzfw3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzfxHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGm3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n          <ownedParameter xmi:id=\"_BWzfxXlgEeSYU-Ff_V1D0Q\" name=\"r\" type=\"_BWzfgHlgEeSYU-Ff_V1D0Q\">\n            <eAnnotations xmi:id=\"_BWzfxnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzfx3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGnHleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWzfyHlgEeSYU-Ff_V1D0Q\">\n              <eAnnotations xmi:id=\"_BWzfyXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzfynlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGnXleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWzfy3lgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWzfzHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzfzXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGnnleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWzfznlgEeSYU-Ff_V1D0Q\" name=\"giveWine\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWzfz3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWzf0HlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGn3leEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWzf0XlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWzf0nlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzf03lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGoHleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n          <ownedParameter xmi:id=\"_BWzf1HlgEeSYU-Ff_V1D0Q\" name=\"r\" type=\"_BWzfgHlgEeSYU-Ff_V1D0Q\">\n            <eAnnotations xmi:id=\"_BWzf1XlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzf1nlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQGoXleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWzf13lgEeSYU-Ff_V1D0Q\">\n              <eAnnotations xmi:id=\"_BWzf2HlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzf2XlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtUHleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWzf2nlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWzf23lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzf3HlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtUXleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWzf3XlgEeSYU-Ff_V1D0Q\" name=\"GiveCompliments\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWzf3nlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWzf33lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtUnleEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWzf4HlgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWzf4XlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzf4nlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtU3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n          </ownedParameter>\n          <ownedParameter xmi:id=\"_BWzf43lgEeSYU-Ff_V1D0Q\" name=\"r\" type=\"_BWzfgHlgEeSYU-Ff_V1D0Q\">\n            <eAnnotations xmi:id=\"_BWzf5HlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzf5XlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtVHleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWzf5nlgEeSYU-Ff_V1D0Q\">\n              <eAnnotations xmi:id=\"_BWzf53lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzf6HlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtVXleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWzf6XlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWzf6nlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzf63lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtVnleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n        </ownedOperation>\n        <ownedOperation xmi:id=\"_BWzf7HlgEeSYU-Ff_V1D0Q\" name=\"checkIfYouWillBeHanged\" visibility=\"public\">\n          <eAnnotations xmi:id=\"_BWzf7XlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n            <details xmi:id=\"_BWzf7nlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtV3leEeSMFa_mT0wMkw\" />\n          </eAnnotations>\n          <ownedParameter xmi:id=\"_BWzf73lgEeSYU-Ff_V1D0Q\" direction=\"return\">\n            <eAnnotations xmi:id=\"_BWzf8HlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzf8XlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtWHleEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <type xsi:type=\"uml:PrimitiveType\" href=\"pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//Boolean\" />\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWzf8nlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWzf83lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzf9HlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtWXleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWzf9XlgEeSYU-Ff_V1D0Q\" value=\"1\">\n              <eAnnotations xmi:id=\"_BWzf9nlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzf93lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtWnleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n          <ownedParameter xmi:id=\"_BWzf-HlgEeSYU-Ff_V1D0Q\" name=\"tableGuests\" type=\"_BWzfgHlgEeSYU-Ff_V1D0Q\" isUnique=\"false\">\n            <eAnnotations xmi:id=\"_BWzf-XlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n              <details xmi:id=\"_BWzf-nlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtW3leEeSMFa_mT0wMkw\" />\n            </eAnnotations>\n            <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWzf-3lgEeSYU-Ff_V1D0Q\">\n              <eAnnotations xmi:id=\"_BWzf_HlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzf_XlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtXHleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </lowerValue>\n            <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWzf_nlgEeSYU-Ff_V1D0Q\" value=\"*\">\n              <eAnnotations xmi:id=\"_BWzf_3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n                <details xmi:id=\"_BWzgAHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtXXleEeSMFa_mT0wMkw\" />\n              </eAnnotations>\n            </upperValue>\n          </ownedParameter>\n        </ownedOperation>\n      </packagedElement>\n    </packagedElement>\n  </packagedElement>\n  <packagedElement xsi:type=\"uml:Package\" xmi:id=\"_BWzgAXlgEeSYU-Ff_V1D0Q\" name=\"genmymodelreverse\">\n    <eAnnotations xmi:id=\"_BWzgAnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n      <details xmi:id=\"_BWzgA3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtXnleEeSMFa_mT0wMkw\" />\n    </eAnnotations>\n  </packagedElement>\n  <packagedElement xsi:type=\"uml:Association\" xmi:id=\"_BWzgBHlgEeSYU-Ff_V1D0Q\" name=\"jenkins_App_Servant_1\" memberEnd=\"_BWzgEHlgEeSYU-Ff_V1D0Q _BWzgB3lgEeSYU-Ff_V1D0Q\" navigableOwnedEnd=\"_BWzgEHlgEeSYU-Ff_V1D0Q\">\n    <eAnnotations xmi:id=\"_BWzgBXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n      <details xmi:id=\"_BWzgBnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtX3leEeSMFa_mT0wMkw\" />\n    </eAnnotations>\n    <ownedEnd xmi:id=\"_BWzgB3lgEeSYU-Ff_V1D0Q\" name=\"app\" type=\"_BWy4f3lgEeSYU-Ff_V1D0Q\" association=\"_BWzgBHlgEeSYU-Ff_V1D0Q\">\n      <eAnnotations xmi:id=\"_BWzgCHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n        <details xmi:id=\"_BWzgCXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtYHleEeSMFa_mT0wMkw\" />\n      </eAnnotations>\n      <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWzgCnlgEeSYU-Ff_V1D0Q\">\n        <eAnnotations xmi:id=\"_BWzgC3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWzgDHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtYXleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n      </lowerValue>\n      <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWzgDXlgEeSYU-Ff_V1D0Q\" value=\"1\">\n        <eAnnotations xmi:id=\"_BWzgDnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWzgD3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtYnleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n      </upperValue>\n    </ownedEnd>\n    <ownedEnd xmi:id=\"_BWzgEHlgEeSYU-Ff_V1D0Q\" name=\"\" visibility=\"package\" isStatic=\"true\" type=\"_BWzfp3lgEeSYU-Ff_V1D0Q\" association=\"_BWzgBHlgEeSYU-Ff_V1D0Q\">\n      <eAnnotations xmi:id=\"_BWzgEXlgEeSYU-Ff_V1D0Q\" source=\"association\" />\n      <eAnnotations xmi:id=\"_BWzgEnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n        <details xmi:id=\"_BWzgE3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtY3leEeSMFa_mT0wMkw\" />\n      </eAnnotations>\n      <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWzgFHlgEeSYU-Ff_V1D0Q\" value=\"1\">\n        <eAnnotations xmi:id=\"_BWzgFXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWzgFnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtZXleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n      </lowerValue>\n      <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWzgF3lgEeSYU-Ff_V1D0Q\" value=\"*\">\n        <eAnnotations xmi:id=\"_BWzgGHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWzgGXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtZnleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n      </upperValue>\n    </ownedEnd>\n  </packagedElement>\n  <packagedElement xsi:type=\"uml:Association\" xmi:id=\"_BWzgGnlgEeSYU-Ff_V1D0Q\" name=\"travis_App_Servant_0\" memberEnd=\"_BWzgJnlgEeSYU-Ff_V1D0Q _BWzgHXlgEeSYU-Ff_V1D0Q\" navigableOwnedEnd=\"_BWzgJnlgEeSYU-Ff_V1D0Q\">\n    <eAnnotations xmi:id=\"_BWzgG3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n      <details xmi:id=\"_BWzgHHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtZ3leEeSMFa_mT0wMkw\" />\n    </eAnnotations>\n    <ownedEnd xmi:id=\"_BWzgHXlgEeSYU-Ff_V1D0Q\" name=\"app\" type=\"_BWy4f3lgEeSYU-Ff_V1D0Q\" association=\"_BWzgGnlgEeSYU-Ff_V1D0Q\">\n      <eAnnotations xmi:id=\"_BWzgHnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n        <details xmi:id=\"_BWzgH3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtaHleEeSMFa_mT0wMkw\" />\n      </eAnnotations>\n      <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWzgIHlgEeSYU-Ff_V1D0Q\">\n        <eAnnotations xmi:id=\"_BWzgIXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWzgInlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtaXleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n      </lowerValue>\n      <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWzgI3lgEeSYU-Ff_V1D0Q\" value=\"1\">\n        <eAnnotations xmi:id=\"_BWzgJHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWzgJXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtanleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n      </upperValue>\n    </ownedEnd>\n    <ownedEnd xmi:id=\"_BWzgJnlgEeSYU-Ff_V1D0Q\" name=\"\" visibility=\"package\" isStatic=\"true\" type=\"_BWzfp3lgEeSYU-Ff_V1D0Q\" association=\"_BWzgGnlgEeSYU-Ff_V1D0Q\">\n      <eAnnotations xmi:id=\"_BWzgJ3lgEeSYU-Ff_V1D0Q\" source=\"association\" />\n      <eAnnotations xmi:id=\"_BWzgKHlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n        <details xmi:id=\"_BWzgKXlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQta3leEeSMFa_mT0wMkw\" />\n      </eAnnotations>\n      <lowerValue xsi:type=\"uml:LiteralInteger\" xmi:id=\"_BWzgKnlgEeSYU-Ff_V1D0Q\">\n        <eAnnotations xmi:id=\"_BWzgK3lgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWzgLHlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtbXleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n      </lowerValue>\n      <upperValue xsi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_BWzgLXlgEeSYU-Ff_V1D0Q\" value=\"*\">\n        <eAnnotations xmi:id=\"_BWzgLnlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n          <details xmi:id=\"_BWzgL3lgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pIQtbnleEeSMFa_mT0wMkw\" />\n        </eAnnotations>\n      </upperValue>\n    </ownedEnd>\n  </packagedElement>\n  <packagedElement xsi:type=\"uml:Usage\" xmi:id=\"_BWzgMHlgEeSYU-Ff_V1D0Q\" client=\"_BWzfgHlgEeSYU-Ff_V1D0Q\" supplier=\"_BWzfp3lgEeSYU-Ff_V1D0Q\">\n    <eAnnotations xmi:id=\"_BWzgMXlgEeSYU-Ff_V1D0Q\" source=\"genmymodel\">\n      <details xmi:id=\"_BWzgMnlgEeSYU-Ff_V1D0Q\" key=\"uuid\" value=\"_pRiR4FuNEDKdUvsjWYqjEA\" />\n    </eAnnotations>\n  </packagedElement>\n</uml:Model>\n"
  },
  {
    "path": "servant/src/main/java/com/iluwatar/servant/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servant;\n\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Servant offers some functionality to a group of classes without defining that functionality in\n * each of them. A Servant is a class whose instance provides methods that take care of a desired\n * service, while objects for which the servant does something, are taken as parameters.\n *\n * <p>In this example {@link Servant} is serving {@link King} and {@link Queen}.\n */\n@Slf4j\npublic class App {\n\n  private static final Servant jenkins = new Servant(\"Jenkins\");\n  private static final Servant travis = new Servant(\"Travis\");\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n    scenario(jenkins, 1);\n    scenario(travis, 0);\n  }\n\n  /** Can add a List with enum Actions for variable scenarios. */\n  public static void scenario(Servant servant, int compliment) {\n    var k = new King();\n    var q = new Queen();\n\n    var guests = List.of(k, q);\n\n    // feed\n    servant.feed(k);\n    servant.feed(q);\n    // serve drinks\n    servant.giveWine(k);\n    servant.giveWine(q);\n    // compliment\n    servant.giveCompliments(guests.get(compliment));\n\n    // outcome of the night\n    guests.forEach(Royalty::changeMood);\n\n    // check your luck\n    if (servant.checkIfYouWillBeHanged(guests)) {\n      LOGGER.info(\"{} will live another day\", servant.name);\n    } else {\n      LOGGER.info(\"Poor {}. His days are numbered\", servant.name);\n    }\n  }\n}\n"
  },
  {
    "path": "servant/src/main/java/com/iluwatar/servant/King.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servant;\n\n/** King. */\npublic class King implements Royalty {\n\n  private boolean isDrunk;\n  private boolean isHungry = true;\n  private boolean isHappy;\n  private boolean complimentReceived;\n\n  @Override\n  public void getFed() {\n    isHungry = false;\n  }\n\n  @Override\n  public void getDrink() {\n    isDrunk = true;\n  }\n\n  public void receiveCompliments() {\n    complimentReceived = true;\n  }\n\n  @Override\n  public void changeMood() {\n    if (!isHungry && isDrunk) {\n      isHappy = true;\n    }\n    if (complimentReceived) {\n      isHappy = false;\n    }\n  }\n\n  @Override\n  public boolean getMood() {\n    return isHappy;\n  }\n}\n"
  },
  {
    "path": "servant/src/main/java/com/iluwatar/servant/Queen.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servant;\n\n/** Queen. */\npublic class Queen implements Royalty {\n\n  private boolean isDrunk = true;\n  private boolean isHungry;\n  private boolean isHappy;\n  private boolean isFlirty = true;\n  private boolean complimentReceived;\n\n  @Override\n  public void getFed() {\n    isHungry = false;\n  }\n\n  @Override\n  public void getDrink() {\n    isDrunk = true;\n  }\n\n  public void receiveCompliments() {\n    complimentReceived = true;\n  }\n\n  @Override\n  public void changeMood() {\n    if (complimentReceived && isFlirty && isDrunk && !isHungry) {\n      isHappy = true;\n    }\n  }\n\n  @Override\n  public boolean getMood() {\n    return isHappy;\n  }\n\n  public void setFlirtiness(boolean f) {\n    this.isFlirty = f;\n  }\n}\n"
  },
  {
    "path": "servant/src/main/java/com/iluwatar/servant/Royalty.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servant;\n\n/** Royalty. */\ninterface Royalty {\n\n  void getFed();\n\n  void getDrink();\n\n  void changeMood();\n\n  void receiveCompliments();\n\n  boolean getMood();\n}\n"
  },
  {
    "path": "servant/src/main/java/com/iluwatar/servant/Servant.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servant;\n\nimport java.util.List;\n\n/** Servant. */\npublic class Servant {\n\n  public String name;\n\n  /** Constructor. */\n  public Servant(String name) {\n    this.name = name;\n  }\n\n  public void feed(Royalty r) {\n    r.getFed();\n  }\n\n  public void giveWine(Royalty r) {\n    r.getDrink();\n  }\n\n  public void giveCompliments(Royalty r) {\n    r.receiveCompliments();\n  }\n\n  /** Check if we will be hanged. */\n  public boolean checkIfYouWillBeHanged(List<Royalty> tableGuests) {\n    return tableGuests.stream().allMatch(Royalty::getMood);\n  }\n}\n"
  },
  {
    "path": "servant/src/test/java/com/iluwatar/servant/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servant;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "servant/src/test/java/com/iluwatar/servant/KingTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servant;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** KingTest */\nclass KingTest {\n\n  @Test\n  void testHungrySoberUncomplimentedKing() {\n    final var king = new King();\n    king.changeMood();\n    assertFalse(king.getMood());\n  }\n\n  @Test\n  void testFedSoberUncomplimentedKing() {\n    final var king = new King();\n    king.getFed();\n    king.changeMood();\n    assertFalse(king.getMood());\n  }\n\n  @Test\n  void testHungryDrunkUncomplimentedKing() {\n    final var king = new King();\n    king.getDrink();\n    king.changeMood();\n    assertFalse(king.getMood());\n  }\n\n  @Test\n  void testHungrySoberComplimentedKing() {\n    final var king = new King();\n    king.receiveCompliments();\n    king.changeMood();\n    assertFalse(king.getMood());\n  }\n\n  @Test\n  void testFedDrunkUncomplimentedKing() {\n    final var king = new King();\n    king.getFed();\n    king.getDrink();\n    king.changeMood();\n    assertTrue(king.getMood());\n  }\n\n  @Test\n  void testFedSoberComplimentedKing() {\n    final var king = new King();\n    king.getFed();\n    king.receiveCompliments();\n    king.changeMood();\n    assertFalse(king.getMood());\n  }\n\n  @Test\n  void testFedDrunkComplimentedKing() {\n    final var king = new King();\n    king.getFed();\n    king.getDrink();\n    king.receiveCompliments();\n    king.changeMood();\n    assertFalse(king.getMood());\n  }\n\n  @Test\n  void testHungryDrunkComplimentedKing() {\n    final King king = new King();\n    king.getDrink();\n    king.receiveCompliments();\n    king.changeMood();\n    assertFalse(king.getMood());\n  }\n}\n"
  },
  {
    "path": "servant/src/test/java/com/iluwatar/servant/QueenTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servant;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** QueenTest */\nclass QueenTest {\n\n  @Test\n  void testNotFlirtyUncomplemented() {\n    final var queen = new Queen();\n    queen.setFlirtiness(false);\n    queen.changeMood();\n    assertFalse(queen.getMood());\n  }\n\n  @Test\n  void testNotFlirtyComplemented() {\n    final var queen = new Queen();\n    queen.setFlirtiness(false);\n    queen.receiveCompliments();\n    queen.changeMood();\n    assertFalse(queen.getMood());\n  }\n\n  @Test\n  void testFlirtyUncomplemented() {\n    final var queen = new Queen();\n    queen.changeMood();\n    assertFalse(queen.getMood());\n  }\n\n  @Test\n  void testFlirtyComplemented() {\n    final var queen = new Queen();\n    queen.receiveCompliments();\n    queen.changeMood();\n    assertTrue(queen.getMood());\n  }\n}\n"
  },
  {
    "path": "servant/src/test/java/com/iluwatar/servant/ServantTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servant;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\nimport static org.mockito.Mockito.when;\n\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\n\n/** ServantTest */\nclass ServantTest {\n\n  @Test\n  void testFeed() {\n    final var royalty = mock(Royalty.class);\n    final var servant = new Servant(\"test\");\n    servant.feed(royalty);\n    verify(royalty).getFed();\n    verifyNoMoreInteractions(royalty);\n  }\n\n  @Test\n  void testGiveWine() {\n    final var royalty = mock(Royalty.class);\n    final var servant = new Servant(\"test\");\n    servant.giveWine(royalty);\n    verify(royalty).getDrink();\n    verifyNoMoreInteractions(royalty);\n  }\n\n  @Test\n  void testGiveCompliments() {\n    final var royalty = mock(Royalty.class);\n    final var servant = new Servant(\"test\");\n    servant.giveCompliments(royalty);\n    verify(royalty).receiveCompliments();\n    verifyNoMoreInteractions(royalty);\n  }\n\n  @Test\n  void testCheckIfYouWillBeHanged() {\n    final var goodMoodRoyalty = mock(Royalty.class);\n    when(goodMoodRoyalty.getMood()).thenReturn(true);\n\n    final var badMoodRoyalty = mock(Royalty.class);\n    when(badMoodRoyalty.getMood()).thenReturn(true);\n\n    final var goodCompany = List.of(goodMoodRoyalty, goodMoodRoyalty, goodMoodRoyalty);\n\n    final var badCompany = List.of(goodMoodRoyalty, goodMoodRoyalty, badMoodRoyalty);\n\n    assertTrue(new Servant(\"test\").checkIfYouWillBeHanged(goodCompany));\n    assertTrue(new Servant(\"test\").checkIfYouWillBeHanged(badCompany));\n  }\n}\n"
  },
  {
    "path": "server-session/README.md",
    "content": "---\ntitle: \"Server Session Pattern in Java: Managing User Sessions with Enhanced Security\"\nshortTitle: Server Session\ndescription: \"Explore the Server Session Pattern for Java applications. Learn how this design pattern helps manage user sessions securely and maintain state across multiple client requests with detailed examples and uses.\"\ncategory: Resource management\nlanguage: en\ntag:\n  - Client-server\n  - Cookies\n  - Session management \n  - State tracking\n  - Web development\n---\n\n## Also known as\n\n* Server-Side Session Management\n\n## Intent of Server Session Design Pattern\n\nEffectively manage user session data on the server-side with Java's Server Session pattern to maintain consistent state across multiple client interactions, enhancing both security and user experience.\n\n## Detailed Explanation of Server Session Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a hotel where each guest is given a unique room key card upon check-in. Similar to how a hotel key card stores a guest's personal preferences (such as preferred room temperature, wake-up call times, and minibar choices), the Server Session pattern in Java securely stores user preferences server-side, ensuring a personalized and secure user experience. Whenever the guest interacts with hotel services, such as ordering room service or accessing the gym, the system retrieves their preferences using the information on the key card. The hotel’s central server maintains these preferences, ensuring consistent and personalized service throughout the guest's stay. Similarly, the Server Session design pattern manages user data on the server, providing a seamless experience across multiple interactions within a web application. \n\nIn plain words\n\n> The Server Session design pattern manages and stores user session data on the server to maintain state across multiple client requests in web applications.\n\nWikipedia says\n\n> A session token is a unique identifier that is generated and sent from a server to a client to identify the current interaction session. The client usually stores and sends the token as an HTTP cookie and/or sends it as a parameter in GET or POST queries. The reason to use session tokens is that the client only has to handle the identifier—all session data is stored on the server (usually in a database, to which the client does not have direct access) linked to that identifier.\n\nSequence diagram\n\n![Server Session sequence diagram](./etc/server-session-sequence-diagram.png)\n\n## Programmatic Example of Server Session Pattern in Java\n\nThe Server Session design pattern is a behavioral design pattern that assigns the responsibility of storing session data on the server side. This pattern is particularly useful in the context of stateless protocols like HTTP where all requests are isolated events independent of previous requests.\n\nIn this pattern, when a user logs in, a session identifier is created and stored for future requests in a list. When a user logs out, the session identifier is deleted from the list along with the appropriate user session data.\n\nLet's take a look at a programmatic example of the Server Session design pattern.\n\nThe `main` application starts a server and assigns handlers to manage login and logout requests. It also starts a background task to check for expired sessions.\n\n```java\npublic class App {\n\n  private static Map<String, Integer> sessions = new HashMap<>();\n  private static Map<String, Instant> sessionCreationTimes = new HashMap<>();\n  private static final long SESSION_EXPIRATION_TIME = 10000;\n\n  public static void main(String[] args) throws IOException {\n    HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);\n\n    server.createContext(\"/login\", new LoginHandler(sessions, sessionCreationTimes));\n    server.createContext(\"/logout\", new LogoutHandler(sessions, sessionCreationTimes));\n\n    server.start();\n\n    sessionExpirationTask();\n  }\n\n  private static void sessionExpirationTask() {\n    new Thread(() -> {\n      while (true) {\n        try {\n          Thread.sleep(SESSION_EXPIRATION_TIME);\n          Instant currentTime = Instant.now();\n          synchronized (sessions) {\n            synchronized (sessionCreationTimes) {\n              Iterator<Map.Entry<String, Instant>> iterator =\n                  sessionCreationTimes.entrySet().iterator();\n              while (iterator.hasNext()) {\n                Map.Entry<String, Instant> entry = iterator.next();\n                if (entry.getValue().plusMillis(SESSION_EXPIRATION_TIME).isBefore(currentTime)) {\n                  sessions.remove(entry.getKey());\n                  iterator.remove();\n                }\n              }\n            }\n          }\n        } catch (InterruptedException e) {\n          Thread.currentThread().interrupt();\n        }\n      }\n    }).start();\n  }\n}\n```\n\nThe `LoginHandler` is responsible for handling login requests. When a user logs in, a session identifier is created and stored for future requests in a list.\n\n```java\npublic class LoginHandler {\n\n  private Map<String, Integer> sessions;\n  private Map<String, Instant> sessionCreationTimes;\n\n  public LoginHandler(Map<String, Integer> sessions, Map<String, Instant> sessionCreationTimes) {\n    this.sessions = sessions;\n    this.sessionCreationTimes = sessionCreationTimes;\n  }\n\n  public void handle(HttpExchange exchange) {\n    // Implementation of the handle method\n  }\n}\n```\n\nThe `LogoutHandler` is responsible for handling logout requests. When a user logs out, the session identifier is deleted from the list along with the appropriate user session data.\n\n```java\npublic class LogoutHandler {\n\n  private Map<String, Integer> sessions;\n  private Map<String, Instant> sessionCreationTimes;\n\n  public LogoutHandler(Map<String, Integer> sessions, Map<String, Instant> sessionCreationTimes) {\n    this.sessions = sessions;\n    this.sessionCreationTimes = sessionCreationTimes;\n  }\n\n  public void handle(HttpExchange exchange) {\n    // Implementation of the handle method\n  }\n}\n```\n\nConsole output for starting the `App` class's `main` method:\n\n```\n12:09:50.998 [Thread-1] INFO com.iluwatar.sessionserver.App -- Session expiration checker started...\n12:09:50.998 [main] INFO com.iluwatar.sessionserver.App -- Server started. Listening on port 8080...\n```\n\nThis is a basic example of the Server Session design pattern. The actual implementation of the `handle` methods in the `LoginHandler` and `LogoutHandler` classes would depend on the specific requirements of your application.\n\n## When to Use the Server Session Pattern in Java\n\n* Use when building web applications that require maintaining user state information across multiple requests.\n* Suitable for applications needing to track user interactions, preferences, or authentication state.\n* Ideal for scenarios where client-side storage is insecure or insufficient.\n\n## Real-World Applications of Server Session Pattern in Java\n\n* Java EE applications using HttpSession for session management.\n* Spring Framework's `@SessionAttributes` for handling user session data.\n* Apache Tomcat's session management mechanism.\n\n## Benefits and Trade-offs of Server Session Pattern\n\nBenefits:\n\n* Simplifies client-side logic by offloading state management to the server.\n* Enhances security by storing sensitive information server-side.\n* Supports complex state management scenarios like multistep forms or shopping carts.\n\nTrade-offs:\n\n* Increases server memory usage due to storage of session data.\n* Requires session management logic to handle session timeouts and data persistence.\n* Potential scalability issues with high user concurrency.\n\n## Related Java Design Patterns\n\n* [State](https://java-design-patterns.com/patterns/state/): Manages state-specific behavior, which can be utilized within session management to handle different user states.\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): Can be used to add a layer of control over session data access.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Often used to create a single instance of a session manager.\n\n## References and Credits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap)\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "server-session/etc/server-session.urm.puml",
    "content": "@startuml\npackage com.iluwatar.sessionserver {\n  class App {\n    - LOGGER : Logger {static}\n    - SESSION_EXPIRATION_TIME : long {static}\n    - sessionCreationTimes : Map<String, Instant> {static}\n    - sessions : Map<String, Integer> {static}\n    + App()\n    + main(args : String[]) {static}\n    - sessionExpirationTask() {static}\n  }\n  class LoginHandler {\n    - LOGGER : Logger {static}\n    - sessionCreationTimes : Map<String, Instant>\n    - sessions : Map<String, Integer>\n    + LoginHandler(sessions : Map<String, Integer>, sessionCreationTimes : Map<String, Instant>)\n    + handle(exchange : HttpExchange)\n  }\n  class LogoutHandler {\n    - LOGGER : Logger {static}\n    - sessionCreationTimes : Map<String, Instant>\n    - sessions : Map<String, Integer>\n    + LogoutHandler(sessions : Map<String, Integer>, sessionCreationTimes : Map<String, Instant>)\n    + handle(exchange : HttpExchange)\n  }\n}\n@enduml"
  },
  {
    "path": "server-session/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>server-session</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n</project>"
  },
  {
    "path": "server-session/src/main/java/com/iluwatar/sessionserver/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sessionserver;\n\nimport com.sun.net.httpserver.HttpServer;\nimport java.io.IOException;\nimport java.net.InetSocketAddress;\nimport java.time.Instant;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The server session pattern is a behavioral design pattern concerned with assigning the\n * responsibility of storing session data on the server side. Within the context of stateless\n * protocols like HTTP all requests are isolated events independent of previous requests. In order\n * to create sessions during user-access for a particular web application various methods can be\n * used, such as cookies. Cookies are a small piece of data that can be sent between client and\n * server on every request and response so that the server can \"remember\" the previous requests. In\n * general cookies can either store the session data or the cookie can store a session identifier\n * and be used to access appropriate data from a persistent storage. In the latter case the session\n * data is stored on the server-side and appropriate data is identified by the cookie sent from a\n * client's request. This project demonstrates the latter case. In the following example the ({@link\n * App}) class starts a server and assigns ({@link LoginHandler}) class to handle login request.\n * When a user logs in a session identifier is created and stored for future requests in a list.\n * When a user logs out the session identifier is deleted from the list along with the appropriate\n * user session data, which is handle by the ({@link LogoutHandler}) class.\n */\n@Slf4j\npublic class App {\n\n  // Map to store session data (simulated using a HashMap)\n  private static Map<String, Integer> sessions = new HashMap<>();\n  private static Map<String, Instant> sessionCreationTimes = new HashMap<>();\n  private static final long SESSION_EXPIRATION_TIME = 10000;\n\n  /**\n   * Main entry point.\n   *\n   * @param args arguments\n   * @throws IOException ex\n   */\n  public static void main(String[] args) throws IOException {\n    // Create HTTP server listening on port 8000\n    HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);\n\n    // Set up session management endpoints\n    server.createContext(\"/login\", new LoginHandler(sessions, sessionCreationTimes));\n    server.createContext(\"/logout\", new LogoutHandler(sessions, sessionCreationTimes));\n\n    // Start the server\n    server.start();\n\n    // Start background task to check for expired sessions\n    sessionExpirationTask();\n\n    LOGGER.info(\"Server started. Listening on port 8080...\");\n  }\n\n  private static void sessionExpirationTask() {\n    new Thread(\n            () -> {\n              while (true) {\n                try {\n                  LOGGER.info(\"Session expiration checker started...\");\n                  Thread.sleep(SESSION_EXPIRATION_TIME); // Sleep for expiration time\n                  Instant currentTime = Instant.now();\n                  synchronized (sessions) {\n                    synchronized (sessionCreationTimes) {\n                      Iterator<Map.Entry<String, Instant>> iterator =\n                          sessionCreationTimes.entrySet().iterator();\n                      while (iterator.hasNext()) {\n                        Map.Entry<String, Instant> entry = iterator.next();\n                        if (entry\n                            .getValue()\n                            .plusMillis(SESSION_EXPIRATION_TIME)\n                            .isBefore(currentTime)) {\n                          sessions.remove(entry.getKey());\n                          iterator.remove();\n                        }\n                      }\n                    }\n                  }\n                  LOGGER.info(\"Session expiration checker finished!\");\n                } catch (InterruptedException e) {\n                  LOGGER.error(\"An error occurred: \", e);\n                  Thread.currentThread().interrupt();\n                }\n              }\n            })\n        .start();\n  }\n}\n"
  },
  {
    "path": "server-session/src/main/java/com/iluwatar/sessionserver/LoginHandler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sessionserver;\n\nimport com.sun.net.httpserver.HttpExchange;\nimport com.sun.net.httpserver.HttpHandler;\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.time.Instant;\nimport java.util.Map;\nimport java.util.UUID;\nimport lombok.extern.slf4j.Slf4j;\n\n/** LoginHandler. */\n@Slf4j\npublic class LoginHandler implements HttpHandler {\n\n  private Map<String, Integer> sessions;\n  private Map<String, Instant> sessionCreationTimes;\n\n  public LoginHandler(Map<String, Integer> sessions, Map<String, Instant> sessionCreationTimes) {\n    this.sessions = sessions;\n    this.sessionCreationTimes = sessionCreationTimes;\n  }\n\n  @Override\n  public void handle(HttpExchange exchange) {\n    // Generate session ID\n    String sessionId = UUID.randomUUID().toString();\n\n    // Store session data (simulated)\n    int newUser = sessions.size() + 1;\n    sessions.put(sessionId, newUser);\n    sessionCreationTimes.put(sessionId, Instant.now());\n    LOGGER.info(\"User \" + newUser + \" created at time \" + sessionCreationTimes.get(sessionId));\n\n    // Set session ID as cookie\n    exchange.getResponseHeaders().add(\"Set-Cookie\", \"sessionID=\" + sessionId);\n\n    // Send response\n    String response = \"Login successful!\\n\" + \"Session ID: \" + sessionId;\n    try {\n      exchange.sendResponseHeaders(200, response.length());\n    } catch (IOException e) {\n      LOGGER.error(\"An error occurred: \", e);\n    }\n    try (OutputStream os = exchange.getResponseBody()) {\n      os.write(response.getBytes());\n    } catch (IOException e) {\n      LOGGER.error(\"An error occurred: \", e);\n    }\n  }\n}\n"
  },
  {
    "path": "server-session/src/main/java/com/iluwatar/sessionserver/LogoutHandler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sessionserver;\n\nimport com.sun.net.httpserver.HttpExchange;\nimport com.sun.net.httpserver.HttpHandler;\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.time.Instant;\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\n\n/** LogoutHandler. */\n@Slf4j\npublic class LogoutHandler implements HttpHandler {\n\n  private Map<String, Integer> sessions;\n  private Map<String, Instant> sessionCreationTimes;\n\n  public LogoutHandler(Map<String, Integer> sessions, Map<String, Instant> sessionCreationTimes) {\n    this.sessions = sessions;\n    this.sessionCreationTimes = sessionCreationTimes;\n  }\n\n  @Override\n  public void handle(HttpExchange exchange) {\n    // Get session ID from cookie\n    String sessionId = exchange.getRequestHeaders().getFirst(\"Cookie\").replace(\"sessionID=\", \"\");\n    String currentSessionId = sessions.get(sessionId) == null ? null : sessionId;\n\n    // Send response\n\n    String response = \"\";\n    if (currentSessionId == null) {\n      response += \"Session has already expired!\";\n    } else {\n      response = \"Logout successful!\\n\" + \"Session ID: \" + currentSessionId;\n    }\n\n    // Remove session\n    if (currentSessionId != null) {\n      LOGGER.info(\"User \" + sessions.get(currentSessionId) + \" deleted!\");\n    } else {\n      LOGGER.info(\"User already deleted!\");\n    }\n    sessions.remove(sessionId);\n    sessionCreationTimes.remove(sessionId);\n\n    try {\n      exchange.sendResponseHeaders(200, response.length());\n    } catch (IOException e) {\n      LOGGER.error(\"An error has occurred: \", e);\n    }\n\n    try (OutputStream os = exchange.getResponseBody()) {\n      os.write(response.getBytes());\n    } catch (IOException e) {\n      LOGGER.error(\"An error has occurred: \", e);\n    }\n  }\n}\n"
  },
  {
    "path": "server-session/src/test/java/com/iluwatar/sessionserver/LoginHandlerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sessionserver;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\nimport com.sun.net.httpserver.Headers;\nimport com.sun.net.httpserver.HttpExchange;\nimport java.io.ByteArrayOutputStream;\nimport java.time.Instant;\nimport java.util.HashMap;\nimport java.util.Map;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\n\n/** LoginHandlerTest. */\npublic class LoginHandlerTest {\n\n  private LoginHandler loginHandler;\n  // private Headers headers;\n  private Map<String, Integer> sessions;\n  private Map<String, Instant> sessionCreationTimes;\n\n  @Mock private HttpExchange exchange;\n\n  /** Setup tests. */\n  @BeforeEach\n  public void setUp() {\n    MockitoAnnotations.initMocks(this);\n    sessions = new HashMap<>();\n    sessionCreationTimes = new HashMap<>();\n    loginHandler = new LoginHandler(sessions, sessionCreationTimes);\n  }\n\n  @Test\n  public void testHandle() {\n\n    // assemble\n    ByteArrayOutputStream outputStream =\n        new ByteArrayOutputStream(); // Exchange object is mocked so OutputStream must be manually\n    // created\n    when(exchange.getResponseHeaders())\n        .thenReturn(\n            new Headers()); // Exchange object is mocked so Header object must be manually created\n    when(exchange.getResponseBody()).thenReturn(outputStream);\n\n    // act\n    loginHandler.handle(exchange);\n\n    // assert\n    String[] response = outputStream.toString().split(\"Session ID: \");\n    assertEquals(sessions.entrySet().toArray()[0].toString().split(\"=1\")[0], response[1]);\n  }\n}\n"
  },
  {
    "path": "server-session/src/test/java/com/iluwatar/sessionserver/LogoutHandlerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sessionserver;\n\nimport static org.mockito.Mockito.when;\n\nimport com.sun.net.httpserver.Headers;\nimport com.sun.net.httpserver.HttpExchange;\nimport java.io.ByteArrayOutputStream;\nimport java.time.Instant;\nimport java.util.HashMap;\nimport java.util.Map;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\n\n/** LogoutHandlerTest. */\npublic class LogoutHandlerTest {\n\n  private LogoutHandler logoutHandler;\n  private Headers headers;\n  private Map<String, Integer> sessions;\n  private Map<String, Instant> sessionCreationTimes;\n\n  @Mock private HttpExchange exchange;\n\n  /** Setup tests. */\n  @BeforeEach\n  public void setUp() {\n    MockitoAnnotations.initMocks(this);\n    sessions = new HashMap<>();\n    sessionCreationTimes = new HashMap<>();\n    logoutHandler = new LogoutHandler(sessions, sessionCreationTimes);\n    headers = new Headers();\n    headers.add(\n        \"Cookie\",\n        \"sessionID=1234\"); // Exchange object methods return Header Object but Exchange is mocked so\n    // Headers must be manually created\n  }\n\n  @Test\n  public void testHandler_SessionNotExpired() {\n\n    // assemble\n    sessions.put(\"1234\", 1); // Fake login details since LoginHandler isn't called\n    sessionCreationTimes.put(\n        \"1234\", Instant.now()); // Fake login details since LoginHandler isn't called\n    when(exchange.getRequestHeaders()).thenReturn(headers);\n    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();\n    when(exchange.getResponseBody()).thenReturn(outputStream);\n\n    // act\n    logoutHandler.handle(exchange);\n\n    // assert\n    String[] response = outputStream.toString().split(\"Session ID: \");\n    Assertions.assertEquals(\"1234\", response[1]);\n    Assertions.assertFalse(sessions.containsKey(response[1]));\n    Assertions.assertFalse(sessionCreationTimes.containsKey(response[1]));\n  }\n\n  @Test\n  public void testHandler_SessionExpired() {\n\n    // assemble\n    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();\n    when(exchange.getRequestHeaders()).thenReturn(headers);\n    when(exchange.getResponseBody()).thenReturn(outputStream);\n\n    // act\n    logoutHandler.handle(exchange);\n\n    // assert\n    String[] response = outputStream.toString().split(\"Session ID: \");\n    Assertions.assertEquals(\"Session has already expired!\", response[0]);\n  }\n}\n"
  },
  {
    "path": "service-layer/README.md",
    "content": "---\ntitle: \"Service Layer Pattern in Java: Enhancing Application Architecture with Robust Service Layers\"\nshortTitle: Service Layer\ndescription: \"Explore the Service Layer pattern for Java applications, a key design solution for separating business logic from presentation logic. Learn its uses, benefits, and implementation with real-world examples and class diagrams to optimize your architectural strategies.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - API design\n  - Business\n  - Decoupling\n  - Enterprise patterns\n  - Layered architecture\n---\n\n## Also known as\n\n* Application Facade\n\n## Intent of Service Layer Design Pattern\n\nThe Service Layer pattern is crucial for Java developers focusing on building robust application architectures that separate business processes from user interface concerns.\n\nThe pattern encapsulate business logic in a distinct layer to promote separation of concerns and to provide a well-defined API for the presentation layer.\n\n## Detailed Explanation of Service Layer Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a complex restaurant system where orders are managed through a centralized 'service layer' to ensure efficient operation and clear communication between the front and back of the house. Each section specializes in a part of the meal, but the waitstaff don't interact directly with the kitchen staff. Instead, all orders go through a head chef who coordinates the workflow. The head chef acts like the service layer, handling the business logic (order coordination) and providing a unified interface for the waitstaff (presentation layer) to interact with the kitchen (data access layer).\n\nIn plain words\n\n> A pattern that encapsulates business logic into a distinct layer to promote separation of concerns and provide a clear API for the presentation layer.\n\nWikipedia says\n\n> Service layer is an architectural pattern, applied within the service-orientation design paradigm, which aims to organize the services, within a service inventory, into a set of logical layers. Services that are categorized into a particular layer share functionality. This helps to reduce the conceptual overhead related to managing the service inventory, as the services belonging to the same layer address a smaller set of activities.\n\nArchitecture diagram\n\n![Service Layer Architecture Diagram](./etc/service-layer-architecture-diagram.png)\n\n## Programmatic Example of Service Layer Pattern in Java\n\nOur Java implementation uses the Service Layer pattern to streamline interactions between data access objects (DAOs) and the business logic, ensuring a clean separation of concerns.\n\nThe example application demonstrates interactions between a client `App` and a service `MagicService` that allows interaction between wizards, spellbooks and spells. The service is implemented with 3-layer architecture\n(entity, dao, service).\n\nFor this explanation we are looking at one vertical slice of the system. Let's start from the entity layer and look at `Wizard` class. Other entities not shown here are `Spellbook` and `Spell`.\n\n```java\n\n@Entity\n@Table(name = \"WIZARD\")\n@Getter\n@Setter\npublic class Wizard extends BaseEntity {\n\n    @Id\n    @GeneratedValue\n    @Column(name = \"WIZARD_ID\")\n    private Long id;\n\n    private String name;\n\n    @ManyToMany(cascade = CascadeType.ALL)\n    private Set<Spellbook> spellbooks;\n\n    public Wizard() {\n        spellbooks = new HashSet<>();\n    }\n\n    public Wizard(String name) {\n        this();\n        this.name = name;\n    }\n\n    public void addSpellbook(Spellbook spellbook) {\n        spellbook.getWizards().add(this);\n        spellbooks.add(spellbook);\n    }\n\n    @Override\n    public String toString() {\n        return name;\n    }\n}\n```\n\nAbove the entity layer we have DAOs. For `Wizard` the DAO layer looks as follows.\n\n```java\npublic interface WizardDao extends Dao<Wizard> {\n\n    Wizard findByName(String name);\n}\n```\n\n```java\npublic class WizardDaoImpl extends DaoBaseImpl<Wizard> implements WizardDao {\n\n    @Override\n    public Wizard findByName(String name) {\n        Transaction tx = null;\n        Wizard result;\n        try (var session = getSessionFactory().openSession()) {\n            tx = session.beginTransaction();\n            var criteria = session.createCriteria(persistentClass);\n            criteria.add(Restrictions.eq(\"name\", name));\n            result = (Wizard) criteria.uniqueResult();\n            tx.commit();\n        } catch (Exception e) {\n            if (tx != null) {\n                tx.rollback();\n            }\n            throw e;\n        }\n        return result;\n    }\n}\n```\n\nNext we can look at the Service Layer, which in our case consists of a single `MagicService`.\n\n```java\npublic interface MagicService {\n\n    List<Wizard> findAllWizards();\n\n    List<Spellbook> findAllSpellbooks();\n\n    List<Spell> findAllSpells();\n\n    List<Wizard> findWizardsWithSpellbook(String name);\n\n    List<Wizard> findWizardsWithSpell(String name);\n}\n\npublic class MagicServiceImpl implements MagicService {\n\n    private final WizardDao wizardDao;\n    private final SpellbookDao spellbookDao;\n    private final SpellDao spellDao;\n\n    public MagicServiceImpl(WizardDao wizardDao, SpellbookDao spellbookDao, SpellDao spellDao) {\n        this.wizardDao = wizardDao;\n        this.spellbookDao = spellbookDao;\n        this.spellDao = spellDao;\n    }\n\n    @Override\n    public List<Wizard> findAllWizards() {\n        return wizardDao.findAll();\n    }\n\n    @Override\n    public List<Spellbook> findAllSpellbooks() {\n        return spellbookDao.findAll();\n    }\n\n    @Override\n    public List<Spell> findAllSpells() {\n        return spellDao.findAll();\n    }\n\n    @Override\n    public List<Wizard> findWizardsWithSpellbook(String name) {\n        var spellbook = spellbookDao.findByName(name);\n        return new ArrayList<>(spellbook.getWizards());\n    }\n\n    @Override\n    public List<Wizard> findWizardsWithSpell(String name) {\n        var spell = spellDao.findByName(name);\n        var spellbook = spell.getSpellbook();\n        return new ArrayList<>(spellbook.getWizards());\n    }\n}\n```\n\nAnd finally, we can show how the client `App` interacts with `MagicService` in the Service Layer.\n\n```java\n@Slf4j\npublic class App {\n    \n    public static final String BOOK_OF_IDORES = \"Book of Idores\";\n\n    public static void main(String[] args) {\n        // populate the in-memory database\n        initData();\n        // query the data using the service\n        queryData();\n    }\n\n    public static void initData() {\n        // spells\n        var spell1 = new Spell(\"Ice dart\");\n        var spell2 = new Spell(\"Invisibility\");\n        var spell3 = new Spell(\"Stun bolt\");\n        var spell4 = new Spell(\"Confusion\");\n        var spell5 = new Spell(\"Darkness\");\n        var spell6 = new Spell(\"Fireball\");\n        var spell7 = new Spell(\"Enchant weapon\");\n        var spell8 = new Spell(\"Rock armour\");\n        var spell9 = new Spell(\"Light\");\n        var spell10 = new Spell(\"Bee swarm\");\n        var spell11 = new Spell(\"Haste\");\n        var spell12 = new Spell(\"Levitation\");\n        var spell13 = new Spell(\"Magic lock\");\n        var spell14 = new Spell(\"Summon hell bat\");\n        var spell15 = new Spell(\"Water walking\");\n        var spell16 = new Spell(\"Magic storm\");\n        var spell17 = new Spell(\"Entangle\");\n        var spellDao = new SpellDaoImpl();\n        spellDao.persist(spell1);\n        spellDao.persist(spell2);\n        spellDao.persist(spell3);\n        spellDao.persist(spell4);\n        spellDao.persist(spell5);\n        spellDao.persist(spell6);\n        spellDao.persist(spell7);\n        spellDao.persist(spell8);\n        spellDao.persist(spell9);\n        spellDao.persist(spell10);\n        spellDao.persist(spell11);\n        spellDao.persist(spell12);\n        spellDao.persist(spell13);\n        spellDao.persist(spell14);\n        spellDao.persist(spell15);\n        spellDao.persist(spell16);\n        spellDao.persist(spell17);\n\n        // spellbooks\n        var spellbookDao = new SpellbookDaoImpl();\n        var spellbook1 = new Spellbook(\"Book of Orgymon\");\n        spellbookDao.persist(spellbook1);\n        spellbook1.addSpell(spell1);\n        spellbook1.addSpell(spell2);\n        spellbook1.addSpell(spell3);\n        spellbook1.addSpell(spell4);\n        spellbookDao.merge(spellbook1);\n        var spellbook2 = new Spellbook(\"Book of Aras\");\n        spellbookDao.persist(spellbook2);\n        spellbook2.addSpell(spell5);\n        spellbook2.addSpell(spell6);\n        spellbookDao.merge(spellbook2);\n        var spellbook3 = new Spellbook(\"Book of Kritior\");\n        spellbookDao.persist(spellbook3);\n        spellbook3.addSpell(spell7);\n        spellbook3.addSpell(spell8);\n        spellbook3.addSpell(spell9);\n        spellbookDao.merge(spellbook3);\n        var spellbook4 = new Spellbook(\"Book of Tamaex\");\n        spellbookDao.persist(spellbook4);\n        spellbook4.addSpell(spell10);\n        spellbook4.addSpell(spell11);\n        spellbook4.addSpell(spell12);\n        spellbookDao.merge(spellbook4);\n        var spellbook5 = new Spellbook(BOOK_OF_IDORES);\n        spellbookDao.persist(spellbook5);\n        spellbook5.addSpell(spell13);\n        spellbookDao.merge(spellbook5);\n        var spellbook6 = new Spellbook(\"Book of Opaen\");\n        spellbookDao.persist(spellbook6);\n        spellbook6.addSpell(spell14);\n        spellbook6.addSpell(spell15);\n        spellbookDao.merge(spellbook6);\n        var spellbook7 = new Spellbook(\"Book of Kihione\");\n        spellbookDao.persist(spellbook7);\n        spellbook7.addSpell(spell16);\n        spellbook7.addSpell(spell17);\n        spellbookDao.merge(spellbook7);\n\n        // wizards\n        var wizardDao = new WizardDaoImpl();\n        var wizard1 = new Wizard(\"Aderlard Boud\");\n        wizardDao.persist(wizard1);\n        wizard1.addSpellbook(spellbookDao.findByName(\"Book of Orgymon\"));\n        wizard1.addSpellbook(spellbookDao.findByName(\"Book of Aras\"));\n        wizardDao.merge(wizard1);\n        var wizard2 = new Wizard(\"Anaxis Bajraktari\");\n        wizardDao.persist(wizard2);\n        wizard2.addSpellbook(spellbookDao.findByName(\"Book of Kritior\"));\n        wizard2.addSpellbook(spellbookDao.findByName(\"Book of Tamaex\"));\n        wizardDao.merge(wizard2);\n        var wizard3 = new Wizard(\"Xuban Munoa\");\n        wizardDao.persist(wizard3);\n        wizard3.addSpellbook(spellbookDao.findByName(BOOK_OF_IDORES));\n        wizard3.addSpellbook(spellbookDao.findByName(\"Book of Opaen\"));\n        wizardDao.merge(wizard3);\n        var wizard4 = new Wizard(\"Blasius Dehooge\");\n        wizardDao.persist(wizard4);\n        wizard4.addSpellbook(spellbookDao.findByName(\"Book of Kihione\"));\n        wizardDao.merge(wizard4);\n    }\n\n    public static void queryData() {\n        var wizardDao = new WizardDaoImpl();\n        var spellbookDao = new SpellbookDaoImpl();\n        var spellDao = new SpellDaoImpl();\n        var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);\n        LOGGER.info(\"Enumerating all wizards\");\n        service.findAllWizards().stream().map(Wizard::getName).forEach(LOGGER::info);\n        LOGGER.info(\"Enumerating all spellbooks\");\n        service.findAllSpellbooks().stream().map(Spellbook::getName).forEach(LOGGER::info);\n        LOGGER.info(\"Enumerating all spells\");\n        service.findAllSpells().stream().map(Spell::getName).forEach(LOGGER::info);\n        LOGGER.info(\"Find wizards with spellbook 'Book of Idores'\");\n        var wizardsWithSpellbook = service.findWizardsWithSpellbook(BOOK_OF_IDORES);\n        wizardsWithSpellbook.forEach(w -> LOGGER.info(\"{} has 'Book of Idores'\", w.getName()));\n        LOGGER.info(\"Find wizards with spell 'Fireball'\");\n        var wizardsWithSpell = service.findWizardsWithSpell(\"Fireball\");\n        wizardsWithSpell.forEach(w -> LOGGER.info(\"{} has 'Fireball'\", w.getName()));\n    }\n}\n```\n\nThe program output:\n\n```\nINFO  [2024-05-27 09:16:40,668] com.iluwatar.servicelayer.app.App: Enumerating all wizards\nINFO  [2024-05-27 09:16:40,671] com.iluwatar.servicelayer.app.App: Aderlard Boud\nINFO  [2024-05-27 09:16:40,671] com.iluwatar.servicelayer.app.App: Anaxis Bajraktari\nINFO  [2024-05-27 09:16:40,671] com.iluwatar.servicelayer.app.App: Xuban Munoa\nINFO  [2024-05-27 09:16:40,671] com.iluwatar.servicelayer.app.App: Blasius Dehooge\nINFO  [2024-05-27 09:16:40,671] com.iluwatar.servicelayer.app.App: Enumerating all spellbooks\nINFO  [2024-05-27 09:16:40,675] com.iluwatar.servicelayer.app.App: Book of Orgymon\nINFO  [2024-05-27 09:16:40,675] com.iluwatar.servicelayer.app.App: Book of Aras\nINFO  [2024-05-27 09:16:40,675] com.iluwatar.servicelayer.app.App: Book of Kritior\nINFO  [2024-05-27 09:16:40,675] com.iluwatar.servicelayer.app.App: Book of Tamaex\nINFO  [2024-05-27 09:16:40,675] com.iluwatar.servicelayer.app.App: Book of Idores\nINFO  [2024-05-27 09:16:40,675] com.iluwatar.servicelayer.app.App: Book of Opaen\nINFO  [2024-05-27 09:16:40,675] com.iluwatar.servicelayer.app.App: Book of Kihione\nINFO  [2024-05-27 09:16:40,675] com.iluwatar.servicelayer.app.App: Enumerating all spells\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Ice dart\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Invisibility\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Stun bolt\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Confusion\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Darkness\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Fireball\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Enchant weapon\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Rock armour\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Light\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Bee swarm\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Haste\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Levitation\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Magic lock\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Summon hell bat\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Water walking\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Magic storm\nINFO  [2024-05-27 09:16:40,679] com.iluwatar.servicelayer.app.App: Entangle\nINFO  [2024-05-27 09:16:40,680] com.iluwatar.servicelayer.app.App: Find wizards with spellbook 'Book of Idores'\nINFO  [2024-05-27 09:16:40,680] com.iluwatar.servicelayer.app.App: Xuban Munoa has 'Book of Idores'\nINFO  [2024-05-27 09:16:40,681] com.iluwatar.servicelayer.app.App: Find wizards with spell 'Fireball'\nINFO  [2024-05-27 09:16:40,683] com.iluwatar.servicelayer.app.App: Aderlard Boud has 'Fireball'\n```\n\n## When to Use the Service Layer Pattern in Java\n\n* Use when you need to separate business logic from presentation logic.\n* Ideal for applications with complex business rules and workflows.\n* Suitable for projects requiring a clear API for the presentation layer.\n\n## Real-World Applications of Service Layer Pattern in Java\n\n* Java EE applications where Enterprise JavaBeans (EJB) are used to implement the service layer.\n* Spring Framework applications using the @Service annotation to denote service layer classes.\n* Web applications that need to separate business logic from controller logic.\n\n## Benefits and Trade-offs of Service Layer Pattern\n\nBenefits:\n\nImplementing a Service Layer in Java\n\n* Promotes code reuse by encapsulating business logic in one place.\n* Enhances testability by isolating business logic.\n* Improves maintainability and flexibility of enterprise applications.\n\nTrade-offs:\n\n* May introduce additional complexity by adding another layer to the application.\n* Can result in performance overhead due to the extra layer of abstraction.\n\n## Related Java Design Patterns\n\n* [Facade](https://java-design-patterns.com/patterns/facade/): Simplifies interactions with complex subsystems by providing a unified interface.\n* [DAO (Data Access Object)](https://java-design-patterns.com/patterns/dao/): Often used together with the Service Layer to handle data persistence.\n* [MVC (Model-View-Controller)](https://java-design-patterns.com/patterns/model-view-controller/): The Service Layer can be used to encapsulate business logic in the model component.\n\n## References and Credits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Spring in Action](https://amzn.to/4asnpSG)\n* [Service Layer (Martin Fowler)](http://martinfowler.com/eaaCatalog/serviceLayer.html)\n"
  },
  {
    "path": "service-layer/etc/service-layer.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.common.BaseEntity\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/common/BaseEntity.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"131\" x=\"327\" y=\"-200\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.spell.SpellDaoImpl\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/spell/SpellDaoImpl.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"171\" x=\"553\" y=\"53\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.magic.MagicServiceImpl\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/magic/MagicServiceImpl.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"178\" width=\"339\" x=\"1174\" y=\"53\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.spellbook.SpellbookDaoImpl\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/spellbook/SpellbookDaoImpl.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"199\" x=\"764\" y=\"53\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.spellbook.Spellbook\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/spellbook/Spellbook.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"322\" width=\"203\" x=\"257\" y=\"379\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"6\" language=\"java\" name=\"com.iluwatar.spellbook.SpellbookDao\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/spellbook/SpellbookDao.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"199\" x=\"935\" y=\"379\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.common.DaoBaseImpl\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/common/DaoBaseImpl.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"213\" width=\"182\" x=\"968\" y=\"-200\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"8\" language=\"java\" name=\"com.iluwatar.wizard.WizardDao\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/wizard/WizardDao.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"183\" x=\"1516\" y=\"379\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"9\" language=\"java\" name=\"com.iluwatar.spell.SpellDao\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/spell/SpellDao.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"171\" x=\"724\" y=\"379\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"10\" language=\"java\" name=\"com.iluwatar.wizard.WizardDaoImpl\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/wizard/WizardDaoImpl.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"183\" x=\"1553\" y=\"53\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"11\" language=\"java\" name=\"com.iluwatar.common.Dao\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/common/Dao.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"160\" width=\"131\" x=\"1003\" y=\"53\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"12\" language=\"java\" name=\"com.iluwatar.spell.Spell\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/spell/Spell.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"268\" width=\"192\" x=\"25\" y=\"53\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"13\" language=\"java\" name=\"com.iluwatar.magic.MagicService\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/magic/MagicService.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"160\" width=\"302\" x=\"1174\" y=\"379\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"14\" language=\"java\" name=\"com.iluwatar.wizard.Wizard\" project=\"service-layer\" \n    file=\"/service-layer/src/main/java/com/iluwatar/wizard/Wizard.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"286\" width=\"235\" x=\"257\" y=\"53\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <generalization id=\"15\">    \n    <bendpoint x=\"522\" y=\"53\"/>    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <association id=\"16\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"17\" name=\"wizardDao\"/>      \n      <multiplicity id=\"18\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"8\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"19\">    \n    <end type=\"SOURCE\" refId=\"6\"/>    \n    <end type=\"TARGET\" refId=\"11\"/>  \n  </generalization>  \n  <generalization id=\"20\">    \n    <end type=\"SOURCE\" refId=\"10\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <generalization id=\"21\">    \n    <end type=\"SOURCE\" refId=\"14\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <realization id=\"22\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </realization>  \n  <generalization id=\"23\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"11\"/>  \n  </generalization>  \n  <association id=\"24\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"25\" name=\"spellbookDao\"/>      \n      <multiplicity id=\"26\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"6\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"27\">    \n    <end type=\"SOURCE\" refId=\"9\"/>    \n    <end type=\"TARGET\" refId=\"11\"/>  \n  </generalization>  \n  <generalization id=\"28\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <association id=\"29\">    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"30\" name=\"spells\"/>      \n      <multiplicity id=\"31\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"12\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"32\">    \n    <end type=\"SOURCE\" refId=\"12\" navigable=\"false\">      \n      <attribute id=\"33\" name=\"spellbook\"/>      \n      <multiplicity id=\"34\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"35\">    \n    <end type=\"SOURCE\" refId=\"12\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </generalization>  \n  <association id=\"36\">    \n    <end type=\"SOURCE\" refId=\"14\" navigable=\"false\">      \n      <attribute id=\"37\" name=\"spellbooks\"/>      \n      <multiplicity id=\"38\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"39\">    \n    <end type=\"SOURCE\" refId=\"10\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </realization>  \n  <association id=\"40\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"41\" name=\"spellDao\"/>      \n      <multiplicity id=\"42\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"9\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"43\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <realization id=\"44\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"9\"/>  \n  </realization>  \n  <association id=\"45\">    \n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"46\" name=\"wizards\"/>      \n      <multiplicity id=\"47\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"14\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"48\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"13\"/>  \n  </realization>  \n  <realization id=\"49\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"11\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "service-layer/etc/service-layer.urm.puml",
    "content": "@startuml\npackage com.iluwatar.servicelayer.hibernate {\n  class HibernateUtil {\n    - LOGGER : Logger {static}\n    - sessionFactory : SessionFactory {static}\n    - HibernateUtil()\n    + dropSession() {static}\n    + getSessionFactory() : SessionFactory {static}\n  }\n}\npackage com.iluwatar.servicelayer.common {\n  abstract class BaseEntity {\n    + BaseEntity()\n    + getId() : Long {abstract}\n    + getName() : String {abstract}\n    + setId(Long) {abstract}\n    + setName(String) {abstract}\n  }\n  interface Dao<E extends BaseEntity> {\n    + delete(E extends BaseEntity) {abstract}\n    + find(Long) : E extends BaseEntity {abstract}\n    + findAll() : List<E extends BaseEntity> {abstract}\n    + merge(E extends BaseEntity) : E extends BaseEntity {abstract}\n    + persist(E extends BaseEntity) {abstract}\n  }\n  abstract class DaoBaseImpl<E extends BaseEntity> {\n    # persistentClass : Class<E extends BaseEntity>\n    + DaoBaseImpl<E extends BaseEntity>()\n    + delete(entity : E extends BaseEntity)\n    + find(id : Long) : E extends BaseEntity\n    + findAll() : List<E extends BaseEntity>\n    # getSessionFactory() : SessionFactory\n    + merge(entity : E extends BaseEntity) : E extends BaseEntity\n    + persist(entity : E extends BaseEntity)\n  }\n}\npackage com.iluwatar.servicelayer.magic {\n  interface MagicService {\n    + findAllSpellbooks() : List<Spellbook> {abstract}\n    + findAllSpells() : List<Spell> {abstract}\n    + findAllWizards() : List<Wizard> {abstract}\n    + findWizardsWithSpell(String) : List<Wizard> {abstract}\n    + findWizardsWithSpellbook(String) : List<Wizard> {abstract}\n  }\n  class MagicServiceImpl {\n    - spellDao : SpellDao\n    - spellbookDao : SpellbookDao\n    - wizardDao : WizardDao\n    + MagicServiceImpl(wizardDao : WizardDao, spellbookDao : SpellbookDao, spellDao : SpellDao)\n    + findAllSpellbooks() : List<Spellbook>\n    + findAllSpells() : List<Spell>\n    + findAllWizards() : List<Wizard>\n    + findWizardsWithSpell(name : String) : List<Wizard>\n    + findWizardsWithSpellbook(name : String) : List<Wizard>\n  }\n}\npackage com.iluwatar.servicelayer.wizard {\n  class Wizard {\n    - id : Long\n    - name : String\n    - spellbooks : Set<Spellbook>\n    + Wizard()\n    + Wizard(name : String)\n    + addSpellbook(spellbook : Spellbook)\n    + getId() : Long\n    + getName() : String\n    + getSpellbooks() : Set<Spellbook>\n    + setId(id : Long)\n    + setName(name : String)\n    + setSpellbooks(spellbooks : Set<Spellbook>)\n    + toString() : String\n  }\n  interface WizardDao {\n    + findByName(String) : Wizard {abstract}\n  }\n  class WizardDaoImpl {\n    + WizardDaoImpl()\n    + findByName(name : String) : Wizard\n  }\n}\npackage com.iluwatar.servicelayer.spellbook {\n  class Spellbook {\n    - id : Long\n    - name : String\n    - spells : Set<Spell>\n    - wizards : Set<Wizard>\n    + Spellbook()\n    + Spellbook(name : String)\n    + addSpell(spell : Spell)\n    + getId() : Long\n    + getName() : String\n    + getSpells() : Set<Spell>\n    + getWizards() : Set<Wizard>\n    + setId(id : Long)\n    + setName(name : String)\n    + setSpells(spells : Set<Spell>)\n    + setWizards(wizards : Set<Wizard>)\n    + toString() : String\n  }\n  interface SpellbookDao {\n    + findByName(String) : Spellbook {abstract}\n  }\n  class SpellbookDaoImpl {\n    + SpellbookDaoImpl()\n    + findByName(name : String) : Spellbook\n  }\n}\npackage com.iluwatar.servicelayer.spell {\n  class Spell {\n    - id : Long\n    - name : String\n    - spellbook : Spellbook\n    + Spell()\n    + Spell(name : String)\n    + getId() : Long\n    + getName() : String\n    + getSpellbook() : Spellbook\n    + setId(id : Long)\n    + setName(name : String)\n    + setSpellbook(spellbook : Spellbook)\n    + toString() : String\n  }\n  interface SpellDao {\n    + findByName(String) : Spell {abstract}\n  }\n  class SpellDaoImpl {\n    + SpellDaoImpl()\n    + findByName(name : String) : Spell\n  }\n}\npackage com.iluwatar.servicelayer.app {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + initData() {static}\n    + main(args : String[]) {static}\n    + queryData() {static}\n  }\n}\nMagicServiceImpl -->  \"-wizardDao\" WizardDao\nMagicServiceImpl -->  \"-spellbookDao\" SpellbookDao\nMagicServiceImpl -->  \"-spellDao\" SpellDao\nSpellbook -->  \"-spells\" Spell\nSpellbook -->  \"-wizards\" Wizard\nDaoBaseImpl ..|> Dao \nMagicServiceImpl ..|> MagicService \nSpell --|> BaseEntity \nSpellDao --|> Dao \nSpellDaoImpl ..|> SpellDao \nSpellDaoImpl --|> DaoBaseImpl \nSpellbook --|> BaseEntity \nSpellbookDao --|> Dao \nSpellbookDaoImpl ..|> SpellbookDao \nSpellbookDaoImpl --|> DaoBaseImpl \nWizard --|> BaseEntity \nWizardDao --|> Dao \nWizardDaoImpl ..|> WizardDao \nWizardDaoImpl --|> DaoBaseImpl \n@enduml"
  },
  {
    "path": "service-layer/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>service-layer</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.hibernate</groupId>\n      <artifactId>hibernate-core</artifactId>\n      <version>6.6.11.Final</version>\n    </dependency>\n    <dependency>\n      <groupId>com.h2database</groupId>\n      <artifactId>h2</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.glassfish.jaxb</groupId>\n      <artifactId>jaxb-runtime</artifactId>\n      <version>4.0.5</version>\n    </dependency>\n    <dependency>\n      <groupId>javax.xml.bind</groupId>\n      <artifactId>jaxb-api</artifactId>\n      <version>2.4.0-b180830.0359</version>\n    </dependency>\n    <dependency>\n      <groupId>jakarta.persistence</groupId>\n      <artifactId>jakarta.persistence-api</artifactId>\n      <version>3.2.0</version>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.servicelayer.app.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/app/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.app;\n\nimport com.iluwatar.servicelayer.magic.MagicService;\nimport com.iluwatar.servicelayer.magic.MagicServiceImpl;\nimport com.iluwatar.servicelayer.spell.Spell;\nimport com.iluwatar.servicelayer.spell.SpellDaoImpl;\nimport com.iluwatar.servicelayer.spellbook.Spellbook;\nimport com.iluwatar.servicelayer.spellbook.SpellbookDaoImpl;\nimport com.iluwatar.servicelayer.wizard.Wizard;\nimport com.iluwatar.servicelayer.wizard.WizardDaoImpl;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Service layer defines an application's boundary with a layer of services that establishes a set\n * of available operations and coordinates the application's response in each operation.\n *\n * <p>Enterprise applications typically require different kinds of interfaces to the data they store\n * and the logic they implement: data loaders, user interfaces, integration gateways, and others.\n * Despite their different purposes, these interfaces often need common interactions with the\n * application to access and manipulate its data and invoke its business logic. The interactions may\n * be complex, involving transactions across multiple resources and the coordination of several\n * responses to an action. Encoding the logic of the interactions separately in each interface\n * causes a lot of duplication.\n *\n * <p>The example application demonstrates interactions between a client ({@link App}) and a service\n * ({@link MagicService}). The service is implemented with 3-layer architecture (entity, dao,\n * service). For persistence the example uses in-memory H2 database which is populated on each\n * application startup.\n */\n@Slf4j\npublic class App {\n  public static final String BOOK_OF_IDORES = \"Book of Idores\";\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    // populate the in-memory database\n    initData();\n    // query the data using the service\n    queryData();\n  }\n\n  /** Initialize data. */\n  public static void initData() {\n    // spells\n    var spell1 = new Spell(\"Ice dart\");\n    var spell2 = new Spell(\"Invisibility\");\n    var spell3 = new Spell(\"Stun bolt\");\n    var spell4 = new Spell(\"Confusion\");\n    var spell5 = new Spell(\"Darkness\");\n    var spell6 = new Spell(\"Fireball\");\n    var spell7 = new Spell(\"Enchant weapon\");\n    var spell8 = new Spell(\"Rock armour\");\n    var spell9 = new Spell(\"Light\");\n    var spell10 = new Spell(\"Bee swarm\");\n    var spell11 = new Spell(\"Haste\");\n    var spell12 = new Spell(\"Levitation\");\n    var spell13 = new Spell(\"Magic lock\");\n    var spell14 = new Spell(\"Summon hell bat\");\n    var spell15 = new Spell(\"Water walking\");\n    var spell16 = new Spell(\"Magic storm\");\n    var spell17 = new Spell(\"Entangle\");\n    var spellDao = new SpellDaoImpl();\n    spellDao.persist(spell1);\n    spellDao.persist(spell2);\n    spellDao.persist(spell3);\n    spellDao.persist(spell4);\n    spellDao.persist(spell5);\n    spellDao.persist(spell6);\n    spellDao.persist(spell7);\n    spellDao.persist(spell8);\n    spellDao.persist(spell9);\n    spellDao.persist(spell10);\n    spellDao.persist(spell11);\n    spellDao.persist(spell12);\n    spellDao.persist(spell13);\n    spellDao.persist(spell14);\n    spellDao.persist(spell15);\n    spellDao.persist(spell16);\n    spellDao.persist(spell17);\n\n    // spellbooks\n    var spellbookDao = new SpellbookDaoImpl();\n    var spellbook1 = new Spellbook(\"Book of Orgymon\");\n    spellbookDao.persist(spellbook1);\n    spellbook1.addSpell(spell1);\n    spellbook1.addSpell(spell2);\n    spellbook1.addSpell(spell3);\n    spellbook1.addSpell(spell4);\n    spellbookDao.merge(spellbook1);\n    var spellbook2 = new Spellbook(\"Book of Aras\");\n    spellbookDao.persist(spellbook2);\n    spellbook2.addSpell(spell5);\n    spellbook2.addSpell(spell6);\n    spellbookDao.merge(spellbook2);\n    var spellbook3 = new Spellbook(\"Book of Kritior\");\n    spellbookDao.persist(spellbook3);\n    spellbook3.addSpell(spell7);\n    spellbook3.addSpell(spell8);\n    spellbook3.addSpell(spell9);\n    spellbookDao.merge(spellbook3);\n    var spellbook4 = new Spellbook(\"Book of Tamaex\");\n    spellbookDao.persist(spellbook4);\n    spellbook4.addSpell(spell10);\n    spellbook4.addSpell(spell11);\n    spellbook4.addSpell(spell12);\n    spellbookDao.merge(spellbook4);\n    var spellbook5 = new Spellbook(BOOK_OF_IDORES);\n    spellbookDao.persist(spellbook5);\n    spellbook5.addSpell(spell13);\n    spellbookDao.merge(spellbook5);\n    var spellbook6 = new Spellbook(\"Book of Opaen\");\n    spellbookDao.persist(spellbook6);\n    spellbook6.addSpell(spell14);\n    spellbook6.addSpell(spell15);\n    spellbookDao.merge(spellbook6);\n    var spellbook7 = new Spellbook(\"Book of Kihione\");\n    spellbookDao.persist(spellbook7);\n    spellbook7.addSpell(spell16);\n    spellbook7.addSpell(spell17);\n    spellbookDao.merge(spellbook7);\n\n    // wizards\n    var wizardDao = new WizardDaoImpl();\n    var wizard1 = new Wizard(\"Aderlard Boud\");\n    wizardDao.persist(wizard1);\n    wizard1.addSpellbook(spellbookDao.findByName(\"Book of Orgymon\"));\n    wizard1.addSpellbook(spellbookDao.findByName(\"Book of Aras\"));\n    wizardDao.merge(wizard1);\n    var wizard2 = new Wizard(\"Anaxis Bajraktari\");\n    wizardDao.persist(wizard2);\n    wizard2.addSpellbook(spellbookDao.findByName(\"Book of Kritior\"));\n    wizard2.addSpellbook(spellbookDao.findByName(\"Book of Tamaex\"));\n    wizardDao.merge(wizard2);\n    var wizard3 = new Wizard(\"Xuban Munoa\");\n    wizardDao.persist(wizard3);\n    wizard3.addSpellbook(spellbookDao.findByName(BOOK_OF_IDORES));\n    wizard3.addSpellbook(spellbookDao.findByName(\"Book of Opaen\"));\n    wizardDao.merge(wizard3);\n    var wizard4 = new Wizard(\"Blasius Dehooge\");\n    wizardDao.persist(wizard4);\n    wizard4.addSpellbook(spellbookDao.findByName(\"Book of Kihione\"));\n    wizardDao.merge(wizard4);\n  }\n\n  /** Query the data. */\n  public static void queryData() {\n    var wizardDao = new WizardDaoImpl();\n    var spellbookDao = new SpellbookDaoImpl();\n    var spellDao = new SpellDaoImpl();\n    var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);\n    LOGGER.info(\"Enumerating all wizards\");\n    service.findAllWizards().stream().map(Wizard::getName).forEach(LOGGER::info);\n    LOGGER.info(\"Enumerating all spellbooks\");\n    service.findAllSpellbooks().stream().map(Spellbook::getName).forEach(LOGGER::info);\n    LOGGER.info(\"Enumerating all spells\");\n    service.findAllSpells().stream().map(Spell::getName).forEach(LOGGER::info);\n    LOGGER.info(\"Find wizards with spellbook 'Book of Idores'\");\n    var wizardsWithSpellbook = service.findWizardsWithSpellbook(BOOK_OF_IDORES);\n    wizardsWithSpellbook.forEach(w -> LOGGER.info(\"{} has 'Book of Idores'\", w.getName()));\n    LOGGER.info(\"Find wizards with spell 'Fireball'\");\n    var wizardsWithSpell = service.findWizardsWithSpell(\"Fireball\");\n    wizardsWithSpell.forEach(w -> LOGGER.info(\"{} has 'Fireball'\", w.getName()));\n  }\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/common/BaseEntity.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.common;\n\nimport jakarta.persistence.MappedSuperclass;\n\n/** Base class for entities. */\n@MappedSuperclass\npublic abstract class BaseEntity {\n\n  /**\n   * Indicates the unique id of this entity.\n   *\n   * @return The id of the entity, or 'null' when not persisted\n   */\n  public abstract Long getId();\n\n  /**\n   * Set the id of this entity.\n   *\n   * @param id The new id\n   */\n  public abstract void setId(Long id);\n\n  /**\n   * Get the name of this entity.\n   *\n   * @return The name of the entity\n   */\n  public abstract String getName();\n\n  /**\n   * Set the name of this entity.\n   *\n   * @param name The new name\n   */\n  public abstract void setName(final String name);\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/common/Dao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.common;\n\nimport java.util.List;\n\n/**\n * Dao interface.\n *\n * @param <E> Type of Entity\n */\npublic interface Dao<E extends BaseEntity> {\n\n  E find(Long id);\n\n  void persist(E entity);\n\n  E merge(E entity);\n\n  void delete(E entity);\n\n  List<E> findAll();\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/common/DaoBaseImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.common;\n\nimport com.iluwatar.servicelayer.hibernate.HibernateUtil;\nimport jakarta.persistence.criteria.CriteriaBuilder;\nimport jakarta.persistence.criteria.CriteriaQuery;\nimport jakarta.persistence.criteria.Root;\nimport java.lang.reflect.ParameterizedType;\nimport java.util.List;\nimport org.hibernate.SessionFactory;\nimport org.hibernate.Transaction;\nimport org.hibernate.query.Query;\n\n/**\n * Base class for Dao implementations.\n *\n * @param <E> Type of Entity\n */\npublic abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {\n\n  @SuppressWarnings(\"unchecked\")\n  protected Class<E> persistentClass =\n      (Class<E>)\n          ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];\n\n  /*\n   * Making this getSessionFactory() instead of getSession() so that it is the responsibility\n   * of the caller to open as well as close the session (prevents potential resource leak).\n   */\n  protected SessionFactory getSessionFactory() {\n    return HibernateUtil.getSessionFactory();\n  }\n\n  @Override\n  public E find(Long id) {\n    Transaction tx = null;\n    E result;\n    try (var session = getSessionFactory().openSession()) {\n      tx = session.beginTransaction();\n      CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();\n      CriteriaQuery<E> builderQuery = criteriaBuilder.createQuery(persistentClass);\n      Root<E> root = builderQuery.from(persistentClass);\n      builderQuery.select(root).where(criteriaBuilder.equal(root.get(\"id\"), id));\n      Query<E> query = session.createQuery(builderQuery);\n      result = query.uniqueResult();\n      tx.commit();\n    } catch (Exception e) {\n      if (tx != null) {\n        tx.rollback();\n      }\n      throw e;\n    }\n    return result;\n  }\n\n  @Override\n  public void persist(E entity) {\n    Transaction tx = null;\n    try (var session = getSessionFactory().openSession()) {\n      tx = session.beginTransaction();\n      session.persist(entity);\n      tx.commit();\n    } catch (Exception e) {\n      if (tx != null) {\n        tx.rollback();\n      }\n      throw e;\n    }\n  }\n\n  @Override\n  public E merge(E entity) {\n    Transaction tx = null;\n    E result;\n    try (var session = getSessionFactory().openSession()) {\n      tx = session.beginTransaction();\n      result = (E) session.merge(entity);\n      tx.commit();\n    } catch (Exception e) {\n      if (tx != null) {\n        tx.rollback();\n      }\n      throw e;\n    }\n    return result;\n  }\n\n  @Override\n  public void delete(E entity) {\n    Transaction tx = null;\n    try (var session = getSessionFactory().openSession()) {\n      tx = session.beginTransaction();\n      session.delete(entity);\n      tx.commit();\n    } catch (Exception e) {\n      if (tx != null) {\n        tx.rollback();\n      }\n      throw e;\n    }\n  }\n\n  @Override\n  public List<E> findAll() {\n    Transaction tx = null;\n    List<E> result;\n    try (var session = getSessionFactory().openSession()) {\n      tx = session.beginTransaction();\n      CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();\n      CriteriaQuery<E> builderQuery = criteriaBuilder.createQuery(persistentClass);\n      Root<E> root = builderQuery.from(persistentClass);\n      builderQuery.select(root);\n      Query<E> query = session.createQuery(builderQuery);\n      result = query.getResultList();\n    } catch (Exception e) {\n      if (tx != null) {\n        tx.rollback();\n      }\n      throw e;\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.hibernate;\n\nimport com.iluwatar.servicelayer.spell.Spell;\nimport com.iluwatar.servicelayer.spellbook.Spellbook;\nimport com.iluwatar.servicelayer.wizard.Wizard;\nimport lombok.extern.slf4j.Slf4j;\nimport org.hibernate.SessionFactory;\nimport org.hibernate.cfg.Configuration;\n\n/** Produces the Hibernate {@link SessionFactory}. */\n@Slf4j\npublic final class HibernateUtil {\n\n  /** The cached session factory. */\n  private static volatile SessionFactory sessionFactory;\n\n  private HibernateUtil() {}\n\n  /**\n   * Create the current session factory instance, create a new one when there is none yet.\n   *\n   * @return The session factory\n   */\n  public static synchronized SessionFactory getSessionFactory() {\n    if (sessionFactory == null) {\n      try {\n        sessionFactory =\n            new Configuration()\n                .addAnnotatedClass(Wizard.class)\n                .addAnnotatedClass(Spellbook.class)\n                .addAnnotatedClass(Spell.class)\n                .setProperty(\"hibernate.dialect\", \"org.hibernate.dialect.H2Dialect\")\n                .setProperty(\"hibernate.connection.url\", \"jdbc:h2:mem:test;DB_CLOSE_DELAY=-1\")\n                .setProperty(\"hibernate.current_session_context_class\", \"thread\")\n                .setProperty(\"hibernate.show_sql\", \"false\")\n                .setProperty(\"hibernate.hbm2ddl.auto\", \"create-drop\")\n                .buildSessionFactory();\n      } catch (Throwable ex) {\n        LOGGER.error(\"Initial SessionFactory creation failed.\", ex);\n        throw new ExceptionInInitializerError(ex);\n      }\n    }\n    return sessionFactory;\n  }\n\n  /**\n   * Drop the current connection, resulting in a create-drop clean database next time. This is\n   * mainly used for JUnit testing since one test should not influence the other\n   */\n  public static void dropSession() {\n    getSessionFactory().close();\n    sessionFactory = null;\n  }\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.magic;\n\nimport com.iluwatar.servicelayer.spell.Spell;\nimport com.iluwatar.servicelayer.spellbook.Spellbook;\nimport com.iluwatar.servicelayer.wizard.Wizard;\nimport java.util.List;\n\n/** Service interface. */\npublic interface MagicService {\n\n  List<Wizard> findAllWizards();\n\n  List<Spellbook> findAllSpellbooks();\n\n  List<Spell> findAllSpells();\n\n  List<Wizard> findWizardsWithSpellbook(String name);\n\n  List<Wizard> findWizardsWithSpell(String name);\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/magic/MagicServiceImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.magic;\n\nimport com.iluwatar.servicelayer.spell.Spell;\nimport com.iluwatar.servicelayer.spell.SpellDao;\nimport com.iluwatar.servicelayer.spellbook.Spellbook;\nimport com.iluwatar.servicelayer.spellbook.SpellbookDao;\nimport com.iluwatar.servicelayer.wizard.Wizard;\nimport com.iluwatar.servicelayer.wizard.WizardDao;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** Service implementation. */\npublic class MagicServiceImpl implements MagicService {\n\n  private final WizardDao wizardDao;\n  private final SpellbookDao spellbookDao;\n  private final SpellDao spellDao;\n\n  /** Constructor. */\n  public MagicServiceImpl(WizardDao wizardDao, SpellbookDao spellbookDao, SpellDao spellDao) {\n    this.wizardDao = wizardDao;\n    this.spellbookDao = spellbookDao;\n    this.spellDao = spellDao;\n  }\n\n  @Override\n  public List<Wizard> findAllWizards() {\n    return wizardDao.findAll();\n  }\n\n  @Override\n  public List<Spellbook> findAllSpellbooks() {\n    return spellbookDao.findAll();\n  }\n\n  @Override\n  public List<Spell> findAllSpells() {\n    return spellDao.findAll();\n  }\n\n  @Override\n  public List<Wizard> findWizardsWithSpellbook(String name) {\n    var spellbook = spellbookDao.findByName(name);\n    return new ArrayList<>(spellbook.getWizards());\n  }\n\n  @Override\n  public List<Wizard> findWizardsWithSpell(String name) {\n    var spell = spellDao.findByName(name);\n    var spellbook = spell.getSpellbook();\n    return new ArrayList<>(spellbook.getWizards());\n  }\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/spell/Spell.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.spell;\n\nimport com.iluwatar.servicelayer.common.BaseEntity;\nimport com.iluwatar.servicelayer.spellbook.Spellbook;\nimport jakarta.persistence.Column;\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.Id;\nimport jakarta.persistence.Inheritance;\nimport jakarta.persistence.InheritanceType;\nimport jakarta.persistence.JoinColumn;\nimport jakarta.persistence.ManyToOne;\nimport jakarta.persistence.Table;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Spell entity. */\n@Entity\n@Table(name = \"SPELL\")\n@Getter\n@Setter\n@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)\npublic class Spell extends BaseEntity {\n\n  private String name;\n\n  @Id\n  @GeneratedValue\n  @Column(name = \"SPELL_ID\")\n  private Long id;\n\n  @ManyToOne\n  @JoinColumn(name = \"SPELLBOOK_ID_FK\", referencedColumnName = \"SPELLBOOK_ID\")\n  private Spellbook spellbook;\n\n  public Spell() {}\n\n  public Spell(String name) {\n    this();\n    this.name = name;\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.spell;\n\nimport com.iluwatar.servicelayer.common.Dao;\n\n/** SpellDao interface. */\npublic interface SpellDao extends Dao<Spell> {\n\n  Spell findByName(String name);\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.spell;\n\nimport com.iluwatar.servicelayer.common.DaoBaseImpl;\nimport jakarta.persistence.criteria.CriteriaBuilder;\nimport jakarta.persistence.criteria.CriteriaQuery;\nimport jakarta.persistence.criteria.Root;\nimport org.hibernate.Transaction;\nimport org.hibernate.query.Query;\n\n/** SpellDao implementation. */\npublic class SpellDaoImpl extends DaoBaseImpl<Spell> implements SpellDao {\n\n  @Override\n  public Spell findByName(String name) {\n    Transaction tx = null;\n    Spell result;\n    try (var session = getSessionFactory().openSession()) {\n      tx = session.beginTransaction();\n      CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();\n      CriteriaQuery<Spell> builderQuery = criteriaBuilder.createQuery(Spell.class);\n      Root<Spell> root = builderQuery.from(Spell.class);\n      builderQuery.select(root).where(criteriaBuilder.equal(root.get(\"name\"), name));\n      Query<Spell> query = session.createQuery(builderQuery);\n      result = query.uniqueResult();\n      tx.commit();\n    } catch (Exception e) {\n      if (tx != null) {\n        tx.rollback();\n      }\n      throw e;\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/Spellbook.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.spellbook;\n\nimport com.iluwatar.servicelayer.common.BaseEntity;\nimport com.iluwatar.servicelayer.spell.Spell;\nimport com.iluwatar.servicelayer.wizard.Wizard;\nimport jakarta.persistence.CascadeType;\nimport jakarta.persistence.Column;\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.FetchType;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.Id;\nimport jakarta.persistence.Inheritance;\nimport jakarta.persistence.InheritanceType;\nimport jakarta.persistence.ManyToMany;\nimport jakarta.persistence.OneToMany;\nimport jakarta.persistence.Table;\nimport java.util.HashSet;\nimport java.util.Set;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Spellbook entity. */\n@Entity\n@Table(name = \"SPELLBOOK\")\n@Getter\n@Setter\n@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)\npublic class Spellbook extends BaseEntity {\n\n  @Id\n  @GeneratedValue\n  @Column(name = \"SPELLBOOK_ID\")\n  private Long id;\n\n  private String name;\n\n  @ManyToMany(mappedBy = \"spellbooks\", fetch = FetchType.EAGER)\n  private Set<Wizard> wizards;\n\n  @OneToMany(mappedBy = \"spellbook\", orphanRemoval = true, cascade = CascadeType.ALL)\n  private Set<Spell> spells;\n\n  public Spellbook() {\n    spells = new HashSet<>();\n    wizards = new HashSet<>();\n  }\n\n  public Spellbook(String name) {\n    this();\n    this.name = name;\n  }\n\n  public void addSpell(Spell spell) {\n    spell.setSpellbook(this);\n    spells.add(spell);\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.spellbook;\n\nimport com.iluwatar.servicelayer.common.Dao;\n\n/** SpellbookDao interface. */\npublic interface SpellbookDao extends Dao<Spellbook> {\n\n  Spellbook findByName(String name);\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.spellbook;\n\nimport com.iluwatar.servicelayer.common.DaoBaseImpl;\nimport jakarta.persistence.criteria.CriteriaBuilder;\nimport jakarta.persistence.criteria.CriteriaQuery;\nimport jakarta.persistence.criteria.Root;\nimport org.hibernate.Transaction;\nimport org.hibernate.query.Query;\n\n/** SpellbookDao implementation. */\npublic class SpellbookDaoImpl extends DaoBaseImpl<Spellbook> implements SpellbookDao {\n\n  @Override\n  public Spellbook findByName(String name) {\n    Transaction tx = null;\n    Spellbook result;\n    try (var session = getSessionFactory().openSession()) {\n      tx = session.beginTransaction();\n      CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();\n      CriteriaQuery<Spellbook> builderQuery = criteriaBuilder.createQuery(Spellbook.class);\n      Root<Spellbook> root = builderQuery.from(Spellbook.class);\n      builderQuery.select(root).where(criteriaBuilder.equal(root.get(\"name\"), name));\n      Query<Spellbook> query = session.createQuery(builderQuery);\n      result = query.uniqueResult();\n      tx.commit();\n    } catch (Exception e) {\n      if (tx != null) {\n        tx.rollback();\n      }\n      throw e;\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/wizard/Wizard.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.wizard;\n\nimport com.iluwatar.servicelayer.common.BaseEntity;\nimport com.iluwatar.servicelayer.spellbook.Spellbook;\nimport jakarta.persistence.CascadeType;\nimport jakarta.persistence.Column;\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.Id;\nimport jakarta.persistence.Inheritance;\nimport jakarta.persistence.InheritanceType;\nimport jakarta.persistence.ManyToMany;\nimport jakarta.persistence.Table;\nimport java.util.HashSet;\nimport java.util.Set;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Wizard entity. */\n@Entity\n@Table(name = \"WIZARD\")\n@Getter\n@Setter\n@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)\npublic class Wizard extends BaseEntity {\n\n  @Id\n  @GeneratedValue\n  @Column(name = \"WIZARD_ID\")\n  private Long id;\n\n  private String name;\n\n  @ManyToMany(cascade = CascadeType.ALL)\n  private Set<Spellbook> spellbooks;\n\n  public Wizard() {\n    spellbooks = new HashSet<>();\n  }\n\n  public Wizard(String name) {\n    this();\n    this.name = name;\n  }\n\n  public void addSpellbook(Spellbook spellbook) {\n    spellbook.getWizards().add(this);\n    spellbooks.add(spellbook);\n  }\n\n  @Override\n  public String toString() {\n    return name;\n  }\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.wizard;\n\nimport com.iluwatar.servicelayer.common.Dao;\n\n/** WizardDao interface. */\npublic interface WizardDao extends Dao<Wizard> {\n\n  Wizard findByName(String name);\n}\n"
  },
  {
    "path": "service-layer/src/main/java/com/iluwatar/servicelayer/wizard/WizardDaoImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.wizard;\n\nimport com.iluwatar.servicelayer.common.DaoBaseImpl;\nimport jakarta.persistence.criteria.CriteriaBuilder;\nimport jakarta.persistence.criteria.CriteriaQuery;\nimport jakarta.persistence.criteria.Root;\nimport org.hibernate.Transaction;\nimport org.hibernate.query.Query;\n\n/** WizardDao implementation. */\npublic class WizardDaoImpl extends DaoBaseImpl<Wizard> implements WizardDao {\n\n  @Override\n  public Wizard findByName(String name) {\n    Transaction tx = null;\n    Wizard result;\n    try (var session = getSessionFactory().openSession()) {\n      tx = session.beginTransaction();\n      CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();\n      CriteriaQuery<Wizard> builderQuery = criteriaBuilder.createQuery(Wizard.class);\n      Root<Wizard> root = builderQuery.from(Wizard.class);\n      builderQuery.select(root).where(criteriaBuilder.equal(root.get(\"name\"), name));\n      Query<Wizard> query = session.createQuery(builderQuery);\n      result = query.uniqueResult();\n      tx.commit();\n    } catch (Exception e) {\n      if (tx != null) {\n        tx.rollback();\n      }\n      throw e;\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "service-layer/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    The MIT License\n    Copyright © 2014-2021 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<configuration>\n  <appender name=\"FILE\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n    <file>service-layer.log</file>\n    <rollingPolicy class=\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\">\n      <fileNamePattern>service-layer-%d.log</fileNamePattern>\n      <maxHistory>5</maxHistory>\n    </rollingPolicy>\n    <encoder>\n      <pattern>%-5p [%d{ISO8601,UTC}] %c: %m%n</pattern>\n    </encoder>\n  </appender>\n  <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n    <encoder>\n      <pattern>%-5p [%d{ISO8601,UTC}] %c: %m%n</pattern>\n    </encoder>\n  </appender>\n  <logger name=\"com.iluwatar\" additivity=\"false\">\n    <level value=\"DEBUG\" />\n    <appender-ref ref=\"FILE\" />\n    <appender-ref ref=\"STDOUT\" />\n  </logger>\n  <logger name=\"org.hibernate\" additivity=\"false\">\n    <level value=\"ERROR\" />\n    <appender-ref ref=\"STDOUT\" />\n  </logger>\n  <root level=\"WARN\">\n    <appender-ref ref=\"STDOUT\" />\n  </root>\n</configuration>\n"
  },
  {
    "path": "service-layer/src/test/java/com/iluwatar/servicelayer/app/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.app;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport com.iluwatar.servicelayer.hibernate.HibernateUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n\n  @AfterEach\n  void tearDown() {\n    HibernateUtil.dropSession();\n  }\n}\n"
  },
  {
    "path": "service-layer/src/test/java/com/iluwatar/servicelayer/common/BaseDaoTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.common;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nimport com.iluwatar.servicelayer.hibernate.HibernateUtil;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.function.Function;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/**\n * Test for Base Data Access Objects\n *\n * @param <E> Type of Base Entity\n * @param <D> Type of Dao Base Implementation\n */\npublic abstract class BaseDaoTest<E extends BaseEntity, D extends DaoBaseImpl<E>> {\n\n  /** The number of entities stored before each test */\n  private static final int INITIAL_COUNT = 5;\n\n  /** The unique id generator, shared between all entities */\n  private static final AtomicInteger ID_GENERATOR = new AtomicInteger();\n\n  /** Factory, used to create new entity instances with the given name */\n  private final Function<String, E> factory;\n\n  /** The tested data access object */\n  private final D dao;\n\n  /**\n   * Create a new test using the given factory and dao\n   *\n   * @param factory The factory, used to create new entity instances with the given name\n   * @param dao The tested data access object\n   */\n  public BaseDaoTest(final Function<String, E> factory, final D dao) {\n    this.factory = factory;\n    this.dao = dao;\n  }\n\n  @BeforeEach\n  void setUp() {\n    for (int i = 0; i < INITIAL_COUNT; i++) {\n      final var className = dao.persistentClass.getSimpleName();\n      final var entityName = String.format(\"%s%d\", className, ID_GENERATOR.incrementAndGet());\n      this.dao.persist(this.factory.apply(entityName));\n    }\n  }\n\n  @AfterEach\n  void tearDown() {\n    HibernateUtil.dropSession();\n  }\n\n  protected final D getDao() {\n    return this.dao;\n  }\n\n  @Test\n  void testFind() {\n    final var all = this.dao.findAll();\n    for (final var entity : all) {\n      final var byId = this.dao.find(entity.getId());\n      assertNotNull(byId);\n      assertEquals(byId.getId(), byId.getId());\n    }\n  }\n\n  @Test\n  void testDelete() {\n    final var originalEntities = this.dao.findAll();\n    this.dao.delete(originalEntities.get(1));\n    this.dao.delete(originalEntities.get(2));\n\n    final var entitiesLeft = this.dao.findAll();\n    assertNotNull(entitiesLeft);\n    assertEquals(INITIAL_COUNT - 2, entitiesLeft.size());\n  }\n\n  @Test\n  void testFindAll() {\n    final var all = this.dao.findAll();\n    assertNotNull(all);\n    assertEquals(INITIAL_COUNT, all.size());\n  }\n\n  @Test\n  void testSetId() {\n    final var entity = this.factory.apply(\"name\");\n    assertNull(entity.getId());\n\n    final var expectedId = 1L;\n    entity.setId(expectedId);\n    assertEquals(expectedId, entity.getId());\n  }\n\n  @Test\n  void testSetName() {\n    final var entity = this.factory.apply(\"name\");\n    assertEquals(\"name\", entity.getName());\n    assertEquals(\"name\", entity.toString());\n\n    final var expectedName = \"new name\";\n    entity.setName(expectedName);\n    assertEquals(expectedName, entity.getName());\n    assertEquals(expectedName, entity.toString());\n  }\n}\n"
  },
  {
    "path": "service-layer/src/test/java/com/iluwatar/servicelayer/magic/MagicServiceImplTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.magic;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoInteractions;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.servicelayer.spell.Spell;\nimport com.iluwatar.servicelayer.spell.SpellDao;\nimport com.iluwatar.servicelayer.spellbook.Spellbook;\nimport com.iluwatar.servicelayer.spellbook.SpellbookDao;\nimport com.iluwatar.servicelayer.wizard.Wizard;\nimport com.iluwatar.servicelayer.wizard.WizardDao;\nimport java.util.Set;\nimport org.junit.jupiter.api.Test;\n\n/** MagicServiceImplTest */\nclass MagicServiceImplTest {\n\n  @Test\n  void testFindAllWizards() {\n    final var wizardDao = mock(WizardDao.class);\n    final var spellbookDao = mock(SpellbookDao.class);\n    final var spellDao = mock(SpellDao.class);\n\n    final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);\n    verifyNoInteractions(wizardDao, spellbookDao, spellDao);\n\n    service.findAllWizards();\n    verify(wizardDao).findAll();\n    verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao);\n  }\n\n  @Test\n  void testFindAllSpellbooks() {\n    final var wizardDao = mock(WizardDao.class);\n    final var spellbookDao = mock(SpellbookDao.class);\n    final var spellDao = mock(SpellDao.class);\n\n    final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);\n    verifyNoInteractions(wizardDao, spellbookDao, spellDao);\n\n    service.findAllSpellbooks();\n    verify(spellbookDao).findAll();\n    verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao);\n  }\n\n  @Test\n  void testFindAllSpells() {\n    final var wizardDao = mock(WizardDao.class);\n    final var spellbookDao = mock(SpellbookDao.class);\n    final var spellDao = mock(SpellDao.class);\n\n    final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);\n    verifyNoInteractions(wizardDao, spellbookDao, spellDao);\n\n    service.findAllSpells();\n    verify(spellDao).findAll();\n    verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao);\n  }\n\n  @Test\n  void testFindWizardsWithSpellbook() {\n    final var bookname = \"bookname\";\n    final var spellbook = mock(Spellbook.class);\n    final var wizards = Set.of(mock(Wizard.class), mock(Wizard.class), mock(Wizard.class));\n    when(spellbook.getWizards()).thenReturn(wizards);\n\n    final var spellbookDao = mock(SpellbookDao.class);\n    when(spellbookDao.findByName(bookname)).thenReturn(spellbook);\n\n    final var wizardDao = mock(WizardDao.class);\n    final var spellDao = mock(SpellDao.class);\n\n    final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);\n    verifyNoInteractions(wizardDao, spellbookDao, spellDao, spellbook);\n\n    final var result = service.findWizardsWithSpellbook(bookname);\n    verify(spellbookDao).findByName(bookname);\n    verify(spellbook).getWizards();\n\n    assertNotNull(result);\n    assertEquals(3, result.size());\n\n    verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao);\n  }\n\n  @Test\n  void testFindWizardsWithSpell() {\n    final var wizards = Set.of(mock(Wizard.class), mock(Wizard.class), mock(Wizard.class));\n    final var spellbook = mock(Spellbook.class);\n    when(spellbook.getWizards()).thenReturn(wizards);\n\n    final var spellbookDao = mock(SpellbookDao.class);\n    final var wizardDao = mock(WizardDao.class);\n\n    final var spell = mock(Spell.class);\n    when(spell.getSpellbook()).thenReturn(spellbook);\n\n    final var spellName = \"spellname\";\n    final var spellDao = mock(SpellDao.class);\n    when(spellDao.findByName(spellName)).thenReturn(spell);\n\n    final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);\n    verifyNoInteractions(wizardDao, spellbookDao, spellDao, spellbook);\n\n    final var result = service.findWizardsWithSpell(spellName);\n    verify(spellDao).findByName(spellName);\n    verify(spellbook).getWizards();\n\n    assertNotNull(result);\n    assertEquals(3, result.size());\n\n    verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao);\n  }\n}\n"
  },
  {
    "path": "service-layer/src/test/java/com/iluwatar/servicelayer/spell/SpellDaoImplTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.spell;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport com.iluwatar.servicelayer.common.BaseDaoTest;\nimport org.junit.jupiter.api.Test;\n\n/** SpellDaoImplTest */\nclass SpellDaoImplTest extends BaseDaoTest<Spell, SpellDaoImpl> {\n\n  public SpellDaoImplTest() {\n    super(Spell::new, new SpellDaoImpl());\n  }\n\n  @Test\n  void testFindByName() {\n    final var dao = getDao();\n    final var allSpells = dao.findAll();\n    for (final var spell : allSpells) {\n      final var spellByName = dao.findByName(spell.getName());\n      assertNotNull(spellByName);\n      assertEquals(spell.getId(), spellByName.getId());\n      assertEquals(spell.getName(), spellByName.getName());\n    }\n  }\n}\n"
  },
  {
    "path": "service-layer/src/test/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImplTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.spellbook;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport com.iluwatar.servicelayer.common.BaseDaoTest;\nimport org.junit.jupiter.api.Test;\n\n/** SpellbookDaoImplTest */\nclass SpellbookDaoImplTest extends BaseDaoTest<Spellbook, SpellbookDaoImpl> {\n\n  public SpellbookDaoImplTest() {\n    super(Spellbook::new, new SpellbookDaoImpl());\n  }\n\n  @Test\n  void testFindByName() {\n    final var dao = getDao();\n    final var allBooks = dao.findAll();\n    for (final var book : allBooks) {\n      final var spellByName = dao.findByName(book.getName());\n      assertNotNull(spellByName);\n      assertEquals(book.getId(), spellByName.getId());\n      assertEquals(book.getName(), spellByName.getName());\n    }\n  }\n}\n"
  },
  {
    "path": "service-layer/src/test/java/com/iluwatar/servicelayer/wizard/WizardDaoImplTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelayer.wizard;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport com.iluwatar.servicelayer.common.BaseDaoTest;\nimport org.junit.jupiter.api.Test;\n\n/** WizardDaoImplTest */\nclass WizardDaoImplTest extends BaseDaoTest<Wizard, WizardDaoImpl> {\n\n  public WizardDaoImplTest() {\n    super(Wizard::new, new WizardDaoImpl());\n  }\n\n  @Test\n  void testFindByName() {\n    final var dao = getDao();\n    final var allWizards = dao.findAll();\n    for (final var spell : allWizards) {\n      final var byName = dao.findByName(spell.getName());\n      assertNotNull(byName);\n      assertEquals(spell.getId(), byName.getId());\n      assertEquals(spell.getName(), byName.getName());\n    }\n  }\n}\n"
  },
  {
    "path": "service-locator/README.md",
    "content": "---\ntitle: \"Service Locator Pattern in Java: Simplifying Service Access in Complex Systems\"\nshortTitle: Service Locator\ndescription: \"Master the Service Locator pattern in Java with our comprehensive guide. Learn how it simplifies dependency management in large-scale applications, promoting cleaner code and reusability.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Decoupling\n  - Dependency management\n  - Enterprise patterns\n  - Instantiation\n---\n\n## Also known as\n\n* Service Registry\n\n## Intent of Service Locator Design Pattern\n\nThe Java Service Locator pattern provides a method to decouple Java clients and services by using a central service registry.\n\n## Detailed Explanation of Service Locator Pattern with Real-World Examples\n\nReal-world example\n\n> In a large hotel, the concierge desk acts as a Service Locator. When guests need a service, such as booking a restaurant reservation, finding transportation, or arranging a city tour, they do not directly seek out each service themselves. Instead, they go to the concierge desk, which locates and arranges the required services. This way, the guests are decoupled from the service providers and can rely on a central point to handle their requests, ensuring convenience and efficiency.\n\nIn plain words\n\n> The Service Locator pattern centralizes the logic for locating services, thereby decoupling clients from the concrete implementations of these services.\n\nWikipedia says\n\n> The service locator pattern is a design pattern used in software development to encapsulate the processes involved in obtaining a service with a strong abstraction layer. This pattern uses a central registry known as the \"service locator\", which on request returns the information necessary to perform a certain task. Proponents of the pattern say the approach simplifies component-based applications where all dependencies are cleanly listed at the beginning of the whole application design, consequently making traditional dependency injection a more complex way of connecting objects. Critics of the pattern argue that it is an antipattern which obscures dependencies and makes software harder to test.\n\nSequence diagram\n\n![Service Locator sequence diagram](./etc/service-locator-sequence-diagram.png)\n\n## Programmatic Example of Service Locator Pattern in Java\n\nThe Service Locator design pattern is used to abstract the processes involved in obtaining a service. It uses a central registry, the \"service locator\", which returns the necessary information to perform a task upon request. This Java design pattern is particularly useful in enterprise Java applications where services need centralized management.\n\nIn this example, we have a `Service` interface and a `ServiceLocator` class. The `Service` interface defines the methods that all services must implement. The `ServiceLocator` class is responsible for retrieving and caching these services.\n\n```java\npublic interface Service {\n    String getName();\n\n    int getId();\n\n    void execute();\n}\n```\n\nThe `Service` interface defines three methods: `getName()`, `getId()`, and `execute()`. Any class that implements this interface must provide an implementation for these methods.\n\n```java\npublic class App {\n\n    public static final String JNDI_SERVICE_A = \"jndi/serviceA\";\n    public static final String JNDI_SERVICE_B = \"jndi/serviceB\";\n\n    public static void main(String[] args) {\n        // Get the service from the ServiceLocator\n        var service = ServiceLocator.getService(JNDI_SERVICE_A);\n        // Execute the service\n        service.execute();\n        // Get another service from the ServiceLocator\n        service = ServiceLocator.getService(JNDI_SERVICE_B);\n        // Execute the service\n        service.execute();\n        // Get the service from the ServiceLocator again\n        service = ServiceLocator.getService(JNDI_SERVICE_A);\n        // Execute the service\n        service.execute();\n        // Get the service from the ServiceLocator again\n        service = ServiceLocator.getService(JNDI_SERVICE_A);\n        // Execute the service\n        service.execute();\n    }\n}\n```\n\nIn the `App` class, we use the `ServiceLocator` to get services by their names and then execute them. The `ServiceLocator` handles the details of looking up and caching the services. This way, the `App` class is decoupled from the concrete implementations of the services.\n\nHere is the output from running the example:\n\n```\n15:39:51.417 [main] INFO com.iluwatar.servicelocator.InitContext -- Looking up service A and creating new service for A\n15:39:51.419 [main] INFO com.iluwatar.servicelocator.ServiceImpl -- Service jndi/serviceA is now executing with id 56\n15:39:51.420 [main] INFO com.iluwatar.servicelocator.InitContext -- Looking up service B and creating new service for B\n15:39:51.420 [main] INFO com.iluwatar.servicelocator.ServiceImpl -- Service jndi/serviceB is now executing with id 196\n15:39:51.420 [main] INFO com.iluwatar.servicelocator.ServiceCache -- (cache call) Fetched service jndi/serviceA(56) from cache... !\n15:39:51.420 [main] INFO com.iluwatar.servicelocator.ServiceImpl -- Service jndi/serviceA is now executing with id 56\n15:39:51.420 [main] INFO com.iluwatar.servicelocator.ServiceCache -- (cache call) Fetched service jndi/serviceA(56) from cache... !\n15:39:51.420 [main] INFO com.iluwatar.servicelocator.ServiceImpl -- Service jndi/serviceA is now executing with id 56\n```\n\n## When to Use the Service Locator Pattern in Java\n\n* Use when you want to decouple service creation from client classes to reduce dependencies and improve code maintainability.\n* Applicable in large-scale enterprise applications where multiple services are used and dependencies need to be managed centrally.\n* Suitable when service instances need to be reused or shared among multiple clients.\n\n## Real-World Applications of Service Locator Pattern in Java\n\n* Enterprise Java applications often use Service Locator to manage business services.\n* Spring Framework uses a similar concept with its BeanFactory and ApplicationContext for dependency injection.\n* EJB (Enterprise JavaBeans) uses the Service Locator pattern to find and access EJB components.\n\n## Benefits and Trade-offs of Service Locator Pattern\n\nBenefits:\n\n* Decouples client and service classes, reducing code dependencies.\n* Centralizes service management, making it easier to configure and manage services.\n* Promotes reuse of service instances, which can improve performance and resource utilization.\n\nTrade-offs:\n\n* Can introduce a single point of failure if the Service Locator itself fails.\n* May add complexity to the codebase, especially in terms of configuration and maintenance.\n* Potential performance overhead due to the lookup mechanism.\n\n## Related Java Design Patterns\n\n* [Factory](https://java-design-patterns.com/patterns/factory/): Both patterns deal with object creation but Service Locator focuses on locating services while Factory focuses on creating them.\n* [Dependency Injection](https://java-design-patterns.com/patterns/dependency-injection/): An alternative to Service Locator that injects dependencies directly into clients rather than having clients request them from a locator.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Service Locator often uses Singleton pattern to ensure a single instance of the locator.\n\n## References and Credits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap)\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Pattern-Oriented Software Architecture Volume 3: Patterns for Resource Management](https://amzn.to/4bnBcKZ)\n"
  },
  {
    "path": "service-locator/etc/service-locator.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.servicelocator.InitContext\" project=\"service-locator\" \n    file=\"/service-locator/src/main/java/com/iluwatar/servicelocator/InitContext.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"158\" x=\"188\" y=\"284\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.servicelocator.ServiceImpl\" project=\"service-locator\" \n    file=\"/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"178\" width=\"158\" x=\"188\" y=\"430\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.servicelocator.ServiceLocator\" project=\"service-locator\" \n    file=\"/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceLocator.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"106\" width=\"174\" x=\"386\" y=\"284\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.servicelocator.ServiceCache\" project=\"service-locator\" \n    file=\"/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceCache.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"174\" x=\"386\" y=\"430\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"5\" language=\"java\" name=\"com.iluwatar.servicelocator.Service\" project=\"service-locator\" \n    file=\"/service-locator/src/main/java/com/iluwatar/servicelocator/Service.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"158\" x=\"287\" y=\"648\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <association id=\"6\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"7\" name=\"serviceCache\"/>      \n      <multiplicity id=\"8\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"5\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <realization id=\"9\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </realization>  \n  <association id=\"10\">    \n    <end type=\"SOURCE\" refId=\"3\" navigable=\"false\">      \n      <attribute id=\"11\" name=\"serviceCache\"/>      \n      <multiplicity id=\"12\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "service-locator/etc/service-locator.urm.puml",
    "content": "@startuml\npackage com.iluwatar.servicelocator {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class InitContext {\n    - LOGGER : Logger {static}\n    + InitContext()\n    + lookup(serviceName : String) : Object\n  }\n  interface Service {\n    + execute() {abstract}\n    + getId() : int {abstract}\n    + getName() : String {abstract}\n  }\n  class ServiceCache {\n    - LOGGER : Logger {static}\n    - serviceCache : Map<String, Service>\n    + ServiceCache()\n    + addService(newService : Service)\n    + getService(serviceName : String) : Service\n  }\n  class ServiceImpl {\n    - LOGGER : Logger {static}\n    - id : int\n    - serviceName : String\n    + ServiceImpl(serviceName : String)\n    + execute()\n    + getId() : int\n    + getName() : String\n  }\n  class ServiceLocator {\n    - serviceCache : ServiceCache {static}\n    - ServiceLocator()\n    + getService(serviceJndiName : String) : Service {static}\n  }\n}\nServiceLocator -->  \"-serviceCache\" ServiceCache\nServiceImpl ..|> Service \n@enduml"
  },
  {
    "path": "service-locator/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>service-locator</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.servicelocator.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "service-locator/src/main/java/com/iluwatar/servicelocator/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelocator;\n\n/**\n * The Service Locator pattern is a design pattern used in software development to encapsulate the\n * processes involved in obtaining a service with a strong abstraction layer. This pattern uses a\n * central registry known as the \"service locator\", which on request returns the information\n * necessary to perform a certain task.\n *\n * <p>In this example we use the Service locator pattern to lookup JNDI-services and cache them for\n * subsequent requests. <br>\n */\npublic class App {\n\n  public static final String JNDI_SERVICE_A = \"jndi/serviceA\";\n  public static final String JNDI_SERVICE_B = \"jndi/serviceB\";\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var service = ServiceLocator.getService(JNDI_SERVICE_A);\n    service.execute();\n    service = ServiceLocator.getService(JNDI_SERVICE_B);\n    service.execute();\n    service = ServiceLocator.getService(JNDI_SERVICE_A);\n    service.execute();\n    service = ServiceLocator.getService(JNDI_SERVICE_A);\n    service.execute();\n  }\n}\n"
  },
  {
    "path": "service-locator/src/main/java/com/iluwatar/servicelocator/InitContext.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelocator;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * For JNDI lookup of services from the web.xml. Will match name of the service name that is being\n * requested and return a newly created service object with the name\n */\n@Slf4j\npublic class InitContext {\n\n  /**\n   * Perform the lookup based on the service name. The returned object will need to be cast into a\n   * {@link Service}\n   *\n   * @param serviceName a string\n   * @return an {@link Object}\n   */\n  public Object lookup(String serviceName) {\n    if (serviceName.equals(\"jndi/serviceA\")) {\n      LOGGER.info(\"Looking up service A and creating new service for A\");\n      return new ServiceImpl(\"jndi/serviceA\");\n    } else if (serviceName.equals(\"jndi/serviceB\")) {\n      LOGGER.info(\"Looking up service B and creating new service for B\");\n      return new ServiceImpl(\"jndi/serviceB\");\n    } else {\n      return null;\n    }\n  }\n}\n"
  },
  {
    "path": "service-locator/src/main/java/com/iluwatar/servicelocator/Service.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelocator;\n\n/**\n * This is going to be the parent service interface which we will use to create our services. All\n * services will have a\n *\n * <ul>\n *   <li>service name\n *   <li>unique id\n *   <li>execution work flow\n * </ul>\n */\npublic interface Service {\n\n  /*\n   * The human-readable name of the service\n   */\n  String getName();\n\n  /*\n   * Unique ID of the particular service\n   */\n  int getId();\n\n  /*\n   * The workflow method that defines what this service does\n   */\n  void execute();\n}\n"
  },
  {
    "path": "service-locator/src/main/java/com/iluwatar/servicelocator/ServiceCache.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelocator;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The service cache implementation which will cache services that are being created. On first hit,\n * the cache will be empty and thus any service that is being requested, will be created fresh and\n * then placed into the cache map. On next hit, if same service name will be requested, it will be\n * returned from the cache\n */\n@Slf4j\npublic class ServiceCache {\n\n  private final Map<String, Service> serviceCache;\n\n  public ServiceCache() {\n    serviceCache = new HashMap<>();\n  }\n\n  /**\n   * Get the service from the cache. null if no service is found matching the name\n   *\n   * @param serviceName a string\n   * @return {@link Service}\n   */\n  public Service getService(String serviceName) {\n    if (serviceCache.containsKey(serviceName)) {\n      var cachedService = serviceCache.get(serviceName);\n      var name = cachedService.getName();\n      var id = cachedService.getId();\n      LOGGER.info(\"(cache call) Fetched service {}({}) from cache... !\", name, id);\n      return cachedService;\n    }\n    return null;\n  }\n\n  /**\n   * Adds the service into the cache map.\n   *\n   * @param newService a {@link Service}\n   */\n  public void addService(Service newService) {\n    serviceCache.put(newService.getName(), newService);\n  }\n}\n"
  },
  {
    "path": "service-locator/src/main/java/com/iluwatar/servicelocator/ServiceImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelocator;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This is a single service implementation of a sample service. This is the actual service that will\n * process the request. The reference for this service is to be looked upon in the JNDI server that\n * can be set in the web.xml deployment descriptor\n */\n@Slf4j\npublic class ServiceImpl implements Service {\n\n  private final String serviceName;\n  private final int id;\n\n  /** Constructor. */\n  public ServiceImpl(String serviceName) {\n    // set the service name\n    this.serviceName = serviceName;\n\n    // Generate a random id to this service object\n    this.id = (int) Math.floor(Math.random() * 1000) + 1;\n  }\n\n  @Override\n  public String getName() {\n    return serviceName;\n  }\n\n  @Override\n  public int getId() {\n    return id;\n  }\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"Service {} is now executing with id {}\", getName(), getId());\n  }\n}\n"
  },
  {
    "path": "service-locator/src/main/java/com/iluwatar/servicelocator/ServiceLocator.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelocator;\n\n/**\n * The service locator module. Will fetch service from cache, otherwise creates a fresh service and\n * update cache\n */\npublic final class ServiceLocator {\n\n  private static final ServiceCache serviceCache = new ServiceCache();\n\n  private ServiceLocator() {}\n\n  /**\n   * Fetch the service with the name param from the cache first, if no service is found, lookup the\n   * service from the {@link InitContext} and then add the newly created service into the cache map\n   * for future requests.\n   *\n   * @param serviceJndiName a string\n   * @return {@link Service}\n   */\n  public static Service getService(String serviceJndiName) {\n    var serviceObj = serviceCache.getService(serviceJndiName);\n    if (serviceObj == null) {\n      /*\n       * If we are unable to retrieve anything from cache, then lookup the service and add it in the\n       * cache map\n       */\n      var ctx = new InitContext();\n      serviceObj = (Service) ctx.lookup(serviceJndiName);\n      if (serviceObj != null) { // Only cache a service if it actually exists\n        serviceCache.addService(serviceObj);\n      }\n    }\n    return serviceObj;\n  }\n}\n"
  },
  {
    "path": "service-locator/src/test/java/com/iluwatar/servicelocator/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelocator;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicelocator;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertSame;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.List;\nimport org.junit.jupiter.api.Test;\n\n/** ServiceLocatorTest */\nclass ServiceLocatorTest {\n\n  /** Verify if we just receive 'null' when requesting a non-existing service */\n  @Test\n  void testGetNonExistentService() {\n    assertNull(ServiceLocator.getService(\"fantastic/unicorn/service\"));\n    assertNull(ServiceLocator.getService(\"another/fantastic/unicorn/service\"));\n  }\n\n  /** Verify if we get the same cached instance when requesting the same service twice */\n  @Test\n  void testServiceCache() {\n    final var serviceNames = List.of(\"jndi/serviceA\", \"jndi/serviceB\");\n\n    for (final var serviceName : serviceNames) {\n      final var service = ServiceLocator.getService(serviceName);\n      assertNotNull(service);\n      assertEquals(serviceName, service.getName());\n      assertTrue(service.getId() > 0); // The id is generated randomly, but the minimum value is '1'\n      assertSame(service, ServiceLocator.getService(serviceName));\n    }\n  }\n}\n"
  },
  {
    "path": "service-stub/README.md",
    "content": "---\ntitle: \"Service Stub Pattern in Java: Simplifying Testing with Stub Implementations\"\nshortTitle: Service Stub\ndescription: \"Explore the Service Stub design pattern in Java using a Sentiment Analysis example. Learn how stub implementations provide dummy services to facilitate testing and development.\"\ncategory: Testing\nlanguage: en\ntag:\n    - API design\n    - Decoupling\n    - Integration\n    - Microservices\n    - Testing\n---\n\n## Also known as\n\n* Service Mock\n* Test Double\n\n## Intent of Service Stub Pattern\n\nProvide a lightweight, simplified implementation of a remote or external service to facilitate testing in isolation.\n\n## Detailed Explanation of Service Stub Pattern with Real-World Example\n\nReal-world example\n\n> A real-world analogy for the Service Stub pattern could be a flight simulator used to train pilots. Instead of learning to fly directly using a real airplane—which would be costly, dangerous, and often impractical—pilots initially practice within a simulator. This simulator provides predefined, realistic scenarios and reactions, enabling pilots to train safely, repeatedly, and predictably without the complexities and risks associated with actual flight operations. Similarly, a Service Stub provides controlled, predictable responses for external services during testing, simplifying and accelerating software development and testing processes.\n\nIn plain words\n\n> Use a fake service to return predictable results without relying on external systems.\n\nWikipedia says\n\n> A test stub is a dummy component used during testing to isolate behavior.\n\nSequence diagram\n\n![Service Stub sequence diagram](./etc/service-stub-sequence-diagram.png)\n\n## Programmatic Example of Service Stub Pattern in Java\n\nWe demonstrate the Service Stub pattern using a simple sentiment analysis example. To illustrate this clearly, we define a common interface `SentimentAnalysisServer` and create two separate implementations:\n\n**RealSentimentAnalysisServer**: Represents a slow, realistic sentiment analysis service, returning random sentiment results to simulate external complexity and latency.\n\n**StubSentimentAnalysisServer**: Provides fast, deterministic results based on simple keyword matching, suitable for isolated testing without external dependencies.\n\n### Step-by-step Example Implementation\n\nFirst, define a common interface that both implementations will use:\n\n```java\npublic interface SentimentAnalysisServer {\n    String analyzeSentiment(String text);\n}\n```\n\nNext, we create a realistic implementation that simulates a slow, external service. It introduces a delay of 5 seconds and returns random sentiment results (`Positive`, `Negative`, or `Neutral`). For flexibility and easier testing, it allows injecting a custom sentiment supplier:\n\n```java\npublic class RealSentimentAnalysisServer implements SentimentAnalysisServer {\n    \n    private final Supplier<Integer> sentimentSupplier;\n\n    public RealSentimentAnalysisServer(Supplier<Integer> sentimentSupplier) {\n        this.sentimentSupplier = sentimentSupplier;\n    }\n\n    public RealSentimentAnalysisServer() {\n        this(() -> new Random().nextInt(3));\n    }\n\n    @Override\n    public String analyzeSentiment(String text) {\n        int sentiment = sentimentSupplier.get();\n        try {\n            Thread.sleep(5000);\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n        }\n        return sentiment == 0 ? \"Positive\" : sentiment == 1 ? \"Negative\" : \"Neutral\";\n    }\n}\n```\n\nThen, we provide a simplified stub implementation designed specifically for testing purposes. It returns immediate and predictable results based on simple keyword detection. This enables tests to run quickly and consistently without relying on external factors:\n\n```java\npublic class StubSentimentAnalysisServer implements SentimentAnalysisServer {\n\n  @Override\n  public String analyzeSentiment(String text) {\n    if (text.toLowerCase().contains(\"good\")) {\n      return \"Positive\";\n    }\n    else if (text.toLowerCase().contains(\"bad\")) {\n      return \"Negative\";\n    }\n    else {\n      return \"Neutral\";\n    }\n  }\n}\n```\n\nFinally, here's the main application logic illustrating how to use both implementations in practice. Notice the significant performance difference between the real and stub implementations:\n\n```java\n@Slf4j\n  public static void main(String[] args) {\n  LOGGER.info(\"Setting up the real sentiment analysis server.\");\n  RealSentimentAnalysisServer realSentimentAnalysisServer = new RealSentimentAnalysisServer();\n  String text = \"This movie is soso\";\n  LOGGER.info(\"Analyzing input: {}\", text);\n  String sentiment = realSentimentAnalysisServer.analyzeSentiment(text);\n  LOGGER.info(\"The sentiment is: {}\", sentiment);\n\n    LOGGER.info(\"Setting up the stub sentiment analysis server.\");\n    StubSentimentAnalysisServer stubSentimentAnalysisServer = new StubSentimentAnalysisServer();\n    text = \"This movie is so bad\";\n    LOGGER.info(\"Analyzing input: {}\", text);\n    sentiment = stubSentimentAnalysisServer.analyzeSentiment(text);\n    LOGGER.info(\"The sentiment is: {}\", sentiment);\n  }\n```\n\nIn summary, implementing a Service Stub involves creating a simplified substitute (`StubSentimentAnalysisServer`) for an actual external service (`RealSentimentAnalysisServer`). This approach allows your tests to run quickly and consistently by isolating them from external complexity and unpredictability.\n\n## When to Use the Service Stub Pattern in Java\n\n* When testing systems with external or third-party service dependencies.\n* In integration tests to isolate the service being tested from network or external dependencies.\n* During development when the actual services are unavailable or unreliable.\n* To speed up tests by avoiding calls to slower external systems.\n\n## Real-World Applications of Service Stub Pattern in Java\n\n* WireMock: Widely used in Java testing to stub HTTP-based external services.\n* Mockito: Allows creating lightweight stubs for dependencies in unit testing.\n* Spring Cloud Contract: Provides contracts and stub servers for services in microservices architectures.\n\n## Benefits and Trade-offs of Service Stub Pattern\n\nBenefits:\n\n* Simplifies testing by eliminating dependencies on external systems.\n* Speeds up testing processes by removing latency from external network calls.\n* Allows consistent, repeatable, and predictable testing scenarios.\n* Enables parallel test execution, improving overall development productivity.\n\nTrade-offs:\n\n* Stubs need to be regularly updated to reflect changes in the actual external services.\n* May introduce false confidence if stubs do not accurately represent external system behavior.\n* Can lead to additional overhead and maintenance of stub configurations.\n\n## Related Java Design Patterns\n\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): Service Stub may sometimes implement Adapter interfaces to mimic external dependencies in a test environment.\n* Mock Object: Similar to Service Stub, but Mock Objects usually verify interactions explicitly, while Service Stubs primarily provide predefined responses without verification.\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): Both Service Stub and Proxy introduce intermediate objects to control access or communication with actual components, though Proxy typically manages access control and communication, while Service Stub specifically aims to isolate for testing.\n\n## References and Credits\n\n* [Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation](https://amzn.to/4bjhTSK)\n* [Growing Object-Oriented Software, Guided by Tests](https://amzn.to/4dGfIuk)\n* [Mocks Aren't Stubs (Martin Fowler)](https://martinfowler.com/articles/mocksArentStubs.html)\n* [xUnit Test Patterns: Refactoring Test Code](https://amzn.to/4dHGDpm)\n"
  },
  {
    "path": "service-stub/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>service-stub</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n</project>"
  },
  {
    "path": "service-stub/src/main/java/com/iluwatar/servicestub/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicestub;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * A Service Stub is a dummy implementation of an external service used during development or\n * testing. The purpose is to provide a lightweight \"stub\" when the real service may not always be\n * available (or too slow to use during testing).\n *\n * <p>This implementation simulates a simple sentiment analysis program, where a text is analyzed to\n * deduce whether it is a positive, negative or neutral sentiment. The stub returns a response based\n * on whether the analyzed text contains the words \"good\" or \"bad\", not accounting for stopwords or\n * the underlying semantic of the text.\n *\n * <p>The \"real\" sentiment analysis class simulates the processing time for the request by pausing\n * the execution of the thread for 5 seconds. In the stub sentiment analysis class the response is\n * immediate. In addition, the stub returns a deterministic output with regard to the input. This is\n * extra useful for testing purposes.\n */\n@Slf4j\npublic class App {\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    LOGGER.info(\"Setting up the real sentiment analysis server.\");\n    RealSentimentAnalysisServer realSentimentAnalysisServer = new RealSentimentAnalysisServer();\n    String text = \"This movie is soso\";\n    LOGGER.info(\"Analyzing input: {}\", text);\n    String sentiment = realSentimentAnalysisServer.analyzeSentiment(text);\n    LOGGER.info(\"The sentiment is: {}\", sentiment);\n\n    LOGGER.info(\"Setting up the stub sentiment analysis server.\");\n    StubSentimentAnalysisServer stubSentimentAnalysisServer = new StubSentimentAnalysisServer();\n    text = \"This movie is so bad\";\n    LOGGER.info(\"Analyzing input: {}\", text);\n    sentiment = stubSentimentAnalysisServer.analyzeSentiment(text);\n    LOGGER.info(\"The sentiment is: {}\", sentiment);\n  }\n}\n"
  },
  {
    "path": "service-stub/src/main/java/com/iluwatar/servicestub/RealSentimentAnalysisServer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicestub;\n\nimport java.util.Random;\nimport java.util.function.Supplier;\n\n/**\n * Real implementation of SentimentAnalysisServer. Simulates random sentiment classification with\n * processing delay.\n */\npublic class RealSentimentAnalysisServer implements SentimentAnalysisServer {\n  /**\n   * A real sentiment analysis implementation would analyze the input string using, e.g., NLP and\n   * determine whether the sentiment is positive, negative or neutral. Here we simply choose a\n   * random number to simulate this. The \"model\" may take some time to process the input and we\n   * simulate this by delaying the execution 5 seconds. Analyzes the sentiment of the given input\n   * string and returns the classification result (Positive, Negative, or Neutral).\n   */\n  private final Supplier<Integer> sentimentSupplier;\n\n  // Constructor\n  public RealSentimentAnalysisServer(Supplier<Integer> sentimentSupplier) {\n    this.sentimentSupplier = sentimentSupplier;\n  }\n\n  @SuppressWarnings(\"java:S2245\") // Safe use: Randomness is for simulation/testing only\n  public RealSentimentAnalysisServer() {\n    this(() -> new Random().nextInt(3));\n  }\n\n  @Override\n  public String analyzeSentiment(String text) {\n    int sentiment = sentimentSupplier.get();\n    try {\n      Thread.sleep(5000);\n    } catch (InterruptedException e) {\n      Thread.currentThread().interrupt();\n    }\n\n    return switch (sentiment) {\n      case 0 -> \"Positive\";\n      case 1 -> \"Negative\";\n      default -> \"Neutral\";\n    };\n  }\n}\n"
  },
  {
    "path": "service-stub/src/main/java/com/iluwatar/servicestub/SentimentAnalysisServer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicestub;\n\n/** Sentiment analysis server interface to be implemented by sentiment analysis services. */\npublic interface SentimentAnalysisServer {\n  /**\n   * Analyzes the sentiment of the input text and returns the result.\n   *\n   * @param text the input text to analyze\n   * @return sentiment classification result\n   */\n  String analyzeSentiment(String text);\n}\n"
  },
  {
    "path": "service-stub/src/main/java/com/iluwatar/servicestub/StubSentimentAnalysisServer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicestub;\n\n/**\n * Stub implementation of SentimentAnalysisServer. Returns deterministic sentiment based on input\n * keywords.\n */\npublic class StubSentimentAnalysisServer implements SentimentAnalysisServer {\n\n  /**\n   * Fake sentiment analyzer, always returns \"Positive\" if input string contains the word \"good\",\n   * \"Negative\" if the string contains \"bad\" and \"Neutral\" otherwise.\n   *\n   * @param text the input string to analyze\n   * @return sentiment classification result (Positive, Negative, or Neutral)\n   */\n  @Override\n  public String analyzeSentiment(String text) {\n    if (text.toLowerCase().contains(\"good\")) {\n      return \"Positive\";\n    } else if (text.toLowerCase().contains(\"bad\")) {\n      return \"Negative\";\n    } else {\n      return \"Neutral\";\n    }\n  }\n}\n"
  },
  {
    "path": "service-stub/src/test/java/com/iluwatar/servicestub/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicestub;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "service-stub/src/test/java/com/iluwatar/servicestub/RealSentimentAnalysisServerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicestub;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass RealSentimentAnalysisServerTest {\n\n  @Test\n  void testPositiveSentiment() {\n    RealSentimentAnalysisServer server = new RealSentimentAnalysisServer(() -> 0);\n    assertEquals(\"Positive\", server.analyzeSentiment(\"Test\"));\n  }\n\n  @Test\n  void testNegativeSentiment() {\n    RealSentimentAnalysisServer server = new RealSentimentAnalysisServer(() -> 1);\n    assertEquals(\"Negative\", server.analyzeSentiment(\"Test\"));\n  }\n\n  @Test\n  void testNeutralSentiment() {\n    RealSentimentAnalysisServer server = new RealSentimentAnalysisServer(() -> 2);\n    assertEquals(\"Neutral\", server.analyzeSentiment(\"Test\"));\n  }\n}\n"
  },
  {
    "path": "service-stub/src/test/java/com/iluwatar/servicestub/StubSentimentAnalysisServerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicestub;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass StubSentimentAnalysisServerTest {\n\n  private final StubSentimentAnalysisServer stub = new StubSentimentAnalysisServer();\n\n  @Test\n  void testPositiveSentiment() {\n    String result = stub.analyzeSentiment(\"This is a good product\");\n    assertEquals(\"Positive\", result);\n  }\n\n  @Test\n  void testNegativeSentiment() {\n    String result = stub.analyzeSentiment(\"This is a bad product\");\n    assertEquals(\"Negative\", result);\n  }\n\n  @Test\n  void testNeutralSentiment() {\n    String result = stub.analyzeSentiment(\"This product is average\");\n    assertEquals(\"Neutral\", result);\n  }\n}\n"
  },
  {
    "path": "service-to-worker/README.md",
    "content": "---\ntitle: \"Service to Worker Pattern in Java: Enhancing UI and Business Logic Integration\"\nshortTitle: Service to Worker\ndescription: \"Discover the Service to Worker design pattern in Java: an essential strategy for separating control flow and view management to enhance web application maintainability and scalability.\"\ncategory: Architectural\nlanguage: en\ntag:\n  - Business\n  - Decoupling\n  - Layered architecture\n  - Presentation\n  - Web development\n---\n\n## Intent of Service to Worker Design Pattern\n\nThe Service to Worker design pattern in Java combines the Dispatcher View and Service Locator patterns to facilitate the separation of processing, control flow, and view management in web applications.\n\n## Detailed Explanation of Service to Worker Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a large restaurant chain with a central kitchen and multiple waitstaff. When a customer places an order, the waitstaff (Controller) takes the order and hands it over to the kitchen (Service). The kitchen then processes the order, prepares the dish, and hands it back to the waitstaff. The waitstaff finally delivers the dish to the customer (View). This scenario mirrors Java web applications using the Service to Worker pattern, where backend logic (like the kitchen) is separated from frontend interactions (like the waitstaff), improving focus and efficiency in design pattern implementation.\n\nIn plain words\n\n> Separates the processing logic from the view in web applications to improve maintainability and scalability.\n\nSequence diagram\n\n![Service to Worker sequence diagram](./etc/service-to-worker-sequence-diagram.png)\n\n## Programmatic Example of Service to Worker Pattern in Java\n\nThe Service to Worker design pattern separates the processing logic from the view in web applications to improve maintainability and scalability. It combines the Dispatcher View and Service Locator patterns to facilitate the separation of processing, control flow, and view management in web applications.\n\nIn our example, we have a `GiantController` class, which acts as the controller in the Service to Worker pattern. It takes commands and updates the view. The `Dispatcher` class is responsible for performing actions and updating the view.\n\nHere is the `GiantController` class:\n\n```java\npublic class GiantController {\n\n  public Dispatcher dispatcher;\n\n  public GiantController(Dispatcher dispatcher) {\n    this.dispatcher = dispatcher;\n  }\n\n  public void setCommand(Command s, int index) {\n    dispatcher.performAction(s, index);\n  }\n\n  public void updateView(GiantModel giantModel) {\n    dispatcher.updateView(giantModel);\n  }\n}\n```\n\nIn the `GiantController` class, we have a `setCommand` method that takes a `Command` and an index. This method is used to control the dispatcher. The `updateView` method is used to update the view with the provided `GiantModel`.\n\nThe `App` class is the entry point of our application:\n\n```java\npublic class App {\n\n  public static void main(String[] args) {\n    var giant1 = new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    var giant2 = new GiantModel(\"giant2\", Health.DEAD, Fatigue.SLEEPING, Nourishment.STARVING);\n    var action1 = new Action(giant1);\n    var action2 = new Action(giant2);\n    var view = new GiantView();\n    var dispatcher = new Dispatcher(view);\n    dispatcher.addAction(action1);\n    dispatcher.addAction(action2);\n    var controller = new GiantController(dispatcher);\n\n    controller.updateView(giant1);\n    controller.updateView(giant2);\n\n    controller.setCommand(new Command(Fatigue.SLEEPING, Health.HEALTHY, Nourishment.STARVING), 0);\n    controller.setCommand(new Command(Fatigue.ALERT, Health.HEALTHY, Nourishment.HUNGRY), 1);\n\n    controller.updateView(giant1);\n    controller.updateView(giant2);\n  }\n}\n```\n\nIn the `main` method, we create two `GiantModel` instances, `giant1` and `giant2`, and two `Action` instances, `action1` and `action2`. We then create a `GiantView` instance and a `Dispatcher` instance. We add `action1` and `action2` to the `Dispatcher` and create a `GiantController` with the `Dispatcher`. We then update the view with `giant1` and `giant2`, set some commands, and update the view again.\n\nConsole output:\n\n```\n12:23:10.895 [main] INFO com.iluwatar.servicetoworker.GiantView -- Giant giant1, The giant looks healthy, alert and saturated.\n12:23:10.897 [main] INFO com.iluwatar.servicetoworker.GiantView -- Giant giant2, The giant looks dead, sleeping and starving.\n12:23:10.897 [main] INFO com.iluwatar.servicetoworker.GiantView -- Giant giant1, The giant looks healthy, sleeping and starving.\n12:23:10.897 [main] INFO com.iluwatar.servicetoworker.GiantView -- Giant giant2, The giant looks healthy, alert and hungry.\n```\n\nThis is a simple example of how the Service to Worker pattern can be implemented in a Java application.\n\n## When to Use the Service to Worker Pattern in Java\n\n* Use when you need to separate the controller logic from the view to improve code maintainability and enable team members to work on different parts of the application independently.\n* Suitable for Java web applications that utilize MVC architecture.\n* Appropriate for scenarios requiring complex request processing before displaying a view.\n\n## Real-World Applications of Service to Worker Pattern in Java\n\n* Java-based web frameworks like Struts and Spring MVC.\n* Enterprise web applications requiring a clean separation between presentation logic and business logic.\n\n## Benefits and Trade-offs of Service to Worker Pattern\n\nBenefits:\n\n* Enhances code maintainability by separating concerns.\n* Facilitates team collaboration by decoupling the controller and view components.\n* Simplifies the addition of new views and modifications to existing ones.\n\nTrade-offs:\n\n* Increases the complexity of the application structure.\n* May introduce additional overhead due to the layered architecture.\n\n## Related Java Design Patterns\n\n* [Model-View-Controller (MVC)](https://java-design-patterns.com/patterns/model-view-controller/): Service to Worker is a specialized form of MVC, focusing on separating request handling and view management.\n* [Front Controller](https://java-design-patterns.com/patterns/front-controller/): Often used in conjunction with Service to Worker to centralize request handling and routing.\n\n## References and Credits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap)\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "service-to-worker/etc/service-to-worker.puml",
    "content": "@startuml\npackage com.iluwatar.servicetoworker {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  enum Health {\n    + DEAD {static}\n    + HEALTHY {static}\n    + WOUNDED {static}\n    - title : String\n    + toString() : String\n  }\n  enum Nourishment {\n    + HUNGRY {static}\n    + SATURATED {static}\n    + STARVING {static}\n    - title : String\n    + toString() : String\n  }\n  enum Fatigue {\n    + ALERT {static}\n    + SLEEPING {static}\n    + TIRED {static}\n    - title : String\n    + toString() : String\n  }\n\n  class GiantController {\n    - dispatcher : Dispatcher\n    + GiantController(dispatcher : Dispatcher)\n    + setCommand(s : Command, index : int)\n    + updateView(giantModel : GiantModel)\n  }\n\n  class GiantModel {\n    - fatigue : Fatigue\n    - health : Health\n    - nourishment : Nourishment\n    # GiantModel(health : Health, fatigue : Fatigue, nourishment : Nourishment)\n    + getFatigue() : Fatigue\n    + getHealth() : Health\n    + getNourishment() : Nourishment\n    + setFatigue(fatigue : Fatigue)\n    + setHealth(health : Health)\n    + setNourishment(nourishment : Nourishment)\n    + toString() : String\n  }\n  class GiantView {\n    - LOGGER : Logger {static}\n    + GiantView()\n    + displayGiant(giant : GiantModel)\n  }\n\n  class Action{\n    - giant : GiantModel\n    + Action(giant: GiantModel)\n    + updateModel(command: Command)\n    + setHealth(health : Health)\n    + setFatigue(fatigue : Fatigue)\n    + setNourishment(nourishment : Nourishment)\n  }\n\n  class Dispatcher{\n    - giantView : GiantView\n    - actions : ArrayList<Action>\n    + Dispatcher(giantView : GiantView)\n    + addAction(action: Action)\n    + performAction(s: Command, actionIndex: int)\n    + updateView(giant : GiantModel)\n  }\n}\nGiantModel --> Nourishment\nGiantModel --> Fatigue\nGiantModel --> Health\n\nGiantView ..>  GiantModel\nDispatcher o-up- Action\nGiantController -up-> Dispatcher\n\nGiantController .up.> GiantModel\nAction --> GiantModel\nDispatcher -up-> GiantView\nDispatcher .left.> GiantModel\n\n@enduml"
  },
  {
    "path": "service-to-worker/etc/service-to-worker.urm.puml",
    "content": "@startuml\npackage com.iluwatar.servicetoworker {\n  class Action {\n    + giant : GiantModel\n    + Action(giant : GiantModel)\n    + setFatigue(fatigue : Fatigue)\n    + setHealth(health : Health)\n    + setNourishment(nourishment : Nourishment)\n    + updateModel(command : Command)\n  }\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Command {\n    - fatigue : Fatigue\n    - health : Health\n    - nourishment : Nourishment\n    + Command(fatigue : Fatigue, health : Health, nourishment : Nourishment)\n    + getFatigue() : Fatigue\n    + getHealth() : Health\n    + getNourishment() : Nourishment\n  }\n  class Dispatcher {\n    - actions : List<Action>\n    - giantView : GiantView\n    + Dispatcher(giantView : GiantView)\n    ~ addAction(action : Action)\n    + getGiantView() : GiantView\n    + performAction(s : Command, actionIndex : int)\n    + updateView(giantModel : GiantModel)\n  }\n  class GiantController {\n    + dispatcher : Dispatcher\n    + GiantController(dispatcher : Dispatcher)\n    + setCommand(s : Command, index : int)\n    + updateView(giantModel : GiantModel)\n  }\n  class GiantModel {\n    - model : GiantModel\n    - name : String\n    ~ GiantModel(name : String, health : Health, fatigue : Fatigue, nourishment : Nourishment)\n    ~ getFatigue() : Fatigue\n    ~ getHealth() : Health\n    + getName() : String\n    ~ getNourishment() : Nourishment\n    ~ setFatigue(fatigue : Fatigue)\n    ~ setHealth(health : Health)\n    ~ setNourishment(nourishment : Nourishment)\n    + toString() : String\n  }\n  class GiantView {\n    - LOGGER : Logger {static}\n    + GiantView()\n    + displayGiant(giant : GiantModel)\n  }\n}\npackage com.iluwatar.model.view.controller {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  enum Fatigue {\n    + ALERT {static}\n    + SLEEPING {static}\n    + TIRED {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Fatigue {static}\n    + values() : Fatigue[] {static}\n  }\n  class GiantController {\n    - giant : GiantModel\n    - view : GiantView\n    + GiantController(giant : GiantModel, view : GiantView)\n    + getFatigue() : Fatigue\n    + getHealth() : Health\n    + getNourishment() : Nourishment\n    + setFatigue(fatigue : Fatigue)\n    + setHealth(health : Health)\n    + setNourishment(nourishment : Nourishment)\n    + updateView()\n  }\n  class GiantModel {\n    - fatigue : Fatigue\n    - health : Health\n    - nourishment : Nourishment\n    + GiantModel(health : Health, fatigue : Fatigue, nourishment : Nourishment)\n    + getFatigue() : Fatigue\n    + getHealth() : Health\n    + getNourishment() : Nourishment\n    + setFatigue(fatigue : Fatigue)\n    + setHealth(health : Health)\n    + setNourishment(nourishment : Nourishment)\n    + toString() : String\n  }\n  class GiantView {\n    - LOGGER : Logger {static}\n    + GiantView()\n    + displayGiant(giant : GiantModel)\n  }\n  enum Health {\n    + DEAD {static}\n    + HEALTHY {static}\n    + WOUNDED {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Health {static}\n    + values() : Health[] {static}\n  }\n  enum Nourishment {\n    + HUNGRY {static}\n    + SATURATED {static}\n    + STARVING {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Nourishment {static}\n    + values() : Nourishment[] {static}\n  }\n}\nCommand -->  \"-nourishment\" Nourishment\nGiantModel -->  \"-nourishment\" Nourishment\nGiantController -->  \"-giant\" GiantModel\nGiantController -->  \"-dispatcher\" Dispatcher\nGiantModel -->  \"-fatigue\" Fatigue\nDispatcher -->  \"-actions\" Action\nGiantModel -->  \"-health\" Health\nGiantModel -->  \"-model\" GiantModel\nCommand -->  \"-fatigue\" Fatigue\nCommand -->  \"-health\" Health\nGiantController -->  \"-view\" GiantView\nAction -->  \"-giant\" GiantModel\nDispatcher -->  \"-giantView\" GiantView\n@enduml"
  },
  {
    "path": "service-to-worker/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n\n  <artifactId>service-to-worker</artifactId>\n\n  <dependencies>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>com.iluwatar</groupId>\n      <artifactId>model-view-controller</artifactId>\n      <version>1.26.0-SNAPSHOT</version>\n      <scope>compile</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.servicetoworker.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>"
  },
  {
    "path": "service-to-worker/src/main/java/com/iluwatar/servicetoworker/Action.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\nimport com.iluwatar.model.view.controller.Fatigue;\nimport com.iluwatar.model.view.controller.Health;\nimport com.iluwatar.model.view.controller.Nourishment;\n\n/**\n * The type Action (Worker), which can process user input and perform a specific update on the\n * model.\n */\npublic class Action {\n\n  public GiantModel giant;\n\n  /**\n   * Instantiates a new Action.\n   *\n   * @param giant the giant\n   */\n  public Action(GiantModel giant) {\n    this.giant = giant;\n  }\n\n  /**\n   * Update model based on command.\n   *\n   * @param command the command\n   */\n  public void updateModel(Command command) {\n    setFatigue(command.fatigue());\n    setHealth(command.health());\n    setNourishment(command.nourishment());\n  }\n\n  /**\n   * Sets health.\n   *\n   * @param health the health\n   */\n  public void setHealth(Health health) {\n    giant.setHealth(health);\n  }\n\n  /**\n   * Sets fatigue.\n   *\n   * @param fatigue the fatigue\n   */\n  public void setFatigue(Fatigue fatigue) {\n    giant.setFatigue(fatigue);\n  }\n\n  /**\n   * Sets nourishment.\n   *\n   * @param nourishment the nourishment\n   */\n  public void setNourishment(Nourishment nourishment) {\n    giant.setNourishment(nourishment);\n  }\n}\n"
  },
  {
    "path": "service-to-worker/src/main/java/com/iluwatar/servicetoworker/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\nimport com.iluwatar.model.view.controller.Fatigue;\nimport com.iluwatar.model.view.controller.Health;\nimport com.iluwatar.model.view.controller.Nourishment;\n\n/**\n * The front controller intercepts all requests and performs common functions using decorators. The\n * front controller passes request information to the dispatcher, which uses the request and an\n * internal model to chooses and execute appropriate actions. The actions process user input,\n * translating it into appropriate updates to the model. The model applies business rules and stores\n * the data persistently. Based on the user input and results of the actions, the dispatcher chooses\n * a view. The view transforms the updated model data into a form suitable for the user.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    // create model, view and controller\n    var giant1 = new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    var giant2 = new GiantModel(\"giant2\", Health.DEAD, Fatigue.SLEEPING, Nourishment.STARVING);\n    var action1 = new Action(giant1);\n    var action2 = new Action(giant2);\n    var view = new GiantView();\n    var dispatcher = new Dispatcher(view);\n    dispatcher.addAction(action1);\n    dispatcher.addAction(action2);\n    var controller = new GiantController(dispatcher);\n\n    // initial display\n    controller.updateView(giant1);\n    controller.updateView(giant2);\n\n    // controller receives some interactions that affect the giant\n    controller.setCommand(new Command(Fatigue.SLEEPING, Health.HEALTHY, Nourishment.STARVING), 0);\n    controller.setCommand(new Command(Fatigue.ALERT, Health.HEALTHY, Nourishment.HUNGRY), 1);\n\n    // redisplay\n    controller.updateView(giant1);\n    controller.updateView(giant2);\n    // controller receives some interactions that affect the giant\n  }\n}\n"
  },
  {
    "path": "service-to-worker/src/main/java/com/iluwatar/servicetoworker/Command.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\nimport com.iluwatar.model.view.controller.Fatigue;\nimport com.iluwatar.model.view.controller.Health;\nimport com.iluwatar.model.view.controller.Nourishment;\n\n/**\n * The type Command. Instantiates a new Command.\n *\n * @param fatigue the fatigue\n * @param health the health\n * @param nourishment the nourishment\n */\npublic record Command(Fatigue fatigue, Health health, Nourishment nourishment) {}\n"
  },
  {
    "path": "service-to-worker/src/main/java/com/iluwatar/servicetoworker/Dispatcher.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.Getter;\n\n/**\n * The type Dispatcher, which encapsulates worker and view selection based on request information\n * and/or an internal navigation model.\n */\npublic class Dispatcher {\n\n  @Getter private final GiantView giantView;\n  private final List<Action> actions;\n\n  /**\n   * Instantiates a new Dispatcher.\n   *\n   * @param giantView the giant view\n   */\n  public Dispatcher(GiantView giantView) {\n    this.giantView = giantView;\n    this.actions = new ArrayList<>();\n  }\n\n  /**\n   * Add an action.\n   *\n   * @param action the action\n   */\n  void addAction(Action action) {\n    actions.add(action);\n  }\n\n  /**\n   * Perform an action.\n   *\n   * @param s the s\n   * @param actionIndex the action index\n   */\n  public void performAction(Command s, int actionIndex) {\n    actions.get(actionIndex).updateModel(s);\n  }\n\n  /**\n   * Update view.\n   *\n   * @param giantModel the giant model\n   */\n  public void updateView(GiantModel giantModel) {\n    giantView.displayGiant(giantModel);\n  }\n}\n"
  },
  {
    "path": "service-to-worker/src/main/java/com/iluwatar/servicetoworker/GiantController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\n/**\n * GiantController can update the giant data and redraw it using the view. Singleton object that\n * intercepts all requests and performs common functions.\n */\npublic class GiantController {\n\n  public Dispatcher dispatcher;\n\n  /**\n   * Instantiates a new Giant controller.\n   *\n   * @param dispatcher the dispatcher\n   */\n  public GiantController(Dispatcher dispatcher) {\n    this.dispatcher = dispatcher;\n  }\n\n  /**\n   * Sets command to control the dispatcher.\n   *\n   * @param s the s\n   * @param index the index\n   */\n  public void setCommand(Command s, int index) {\n    dispatcher.performAction(s, index);\n  }\n\n  /**\n   * Update view. This is a simple implementation, in fact, View can be implemented in a concrete\n   * way\n   *\n   * @param giantModel the giant model\n   */\n  public void updateView(GiantModel giantModel) {\n    dispatcher.updateView(giantModel);\n  }\n}\n"
  },
  {
    "path": "service-to-worker/src/main/java/com/iluwatar/servicetoworker/GiantModel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\nimport com.iluwatar.model.view.controller.Fatigue;\nimport com.iluwatar.model.view.controller.Health;\nimport com.iluwatar.model.view.controller.Nourishment;\nimport lombok.Getter;\n\n/** GiantModel contains the giant data. */\npublic class GiantModel {\n\n  private final com.iluwatar.model.view.controller.GiantModel model;\n  @Getter private final String name;\n\n  /**\n   * Instantiates a new Giant model.\n   *\n   * @param name the name\n   * @param health the health\n   * @param fatigue the fatigue\n   * @param nourishment the nourishment\n   */\n  GiantModel(String name, Health health, Fatigue fatigue, Nourishment nourishment) {\n    this.name = name;\n    this.model = new com.iluwatar.model.view.controller.GiantModel(health, fatigue, nourishment);\n  }\n\n  /**\n   * Gets health.\n   *\n   * @return the health\n   */\n  Health getHealth() {\n    return model.getHealth();\n  }\n\n  /**\n   * Sets health.\n   *\n   * @param health the health\n   */\n  void setHealth(Health health) {\n    model.setHealth(health);\n  }\n\n  /**\n   * Gets fatigue.\n   *\n   * @return the fatigue\n   */\n  Fatigue getFatigue() {\n    return model.getFatigue();\n  }\n\n  void setFatigue(Fatigue fatigue) {\n    model.setFatigue(fatigue);\n  }\n\n  /**\n   * Gets nourishment.\n   *\n   * @return the nourishment\n   */\n  Nourishment getNourishment() {\n    return model.getNourishment();\n  }\n\n  /**\n   * Sets nourishment.\n   *\n   * @param nourishment the nourishment\n   */\n  void setNourishment(Nourishment nourishment) {\n    model.setNourishment(nourishment);\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\n        \"Giant %s, The giant looks %s, %s and %s.\",\n        name, model.getHealth(), model.getFatigue(), model.getNourishment());\n  }\n}\n"
  },
  {
    "path": "service-to-worker/src/main/java/com/iluwatar/servicetoworker/GiantView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** GiantView displays the giant. */\n@Slf4j\npublic class GiantView {\n\n  /**\n   * Display the GiantModel simply.\n   *\n   * @param giant the giant\n   */\n  public void displayGiant(GiantModel giant) {\n    LOGGER.info(giant.toString());\n  }\n}\n"
  },
  {
    "path": "service-to-worker/src/test/java/com/iluwatar/servicetoworker/ActionTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.model.view.controller.Fatigue;\nimport com.iluwatar.model.view.controller.Health;\nimport com.iluwatar.model.view.controller.Nourishment;\nimport org.junit.jupiter.api.Test;\n\n/** The type Action test. */\nclass ActionTest {\n\n  /** Verify if the health value is set properly though the constructor and setter */\n  @Test\n  void testSetHealth() {\n    final var model =\n        new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    Action action = new Action(model);\n    assertEquals(Health.HEALTHY, model.getHealth());\n    var messageFormat = \"Giant giant1, The giant looks %s, alert and saturated.\";\n    for (final var health : Health.values()) {\n      action.setHealth(health);\n      assertEquals(health, model.getHealth());\n      assertEquals(String.format(messageFormat, health), model.toString());\n    }\n  }\n\n  /** Verify if the fatigue level is set properly though the constructor and setter */\n  @Test\n  void testSetFatigue() {\n    final var model =\n        new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    Action action = new Action(model);\n    assertEquals(Fatigue.ALERT, model.getFatigue());\n    var messageFormat = \"Giant giant1, The giant looks healthy, %s and saturated.\";\n    for (final var fatigue : Fatigue.values()) {\n      action.setFatigue(fatigue);\n      assertEquals(fatigue, model.getFatigue());\n      assertEquals(String.format(messageFormat, fatigue), model.toString());\n    }\n  }\n\n  /** Verify if the nourishment level is set properly though the constructor and setter */\n  @Test\n  void testSetNourishment() {\n    final var model =\n        new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    Action action = new Action(model);\n    assertEquals(Nourishment.SATURATED, model.getNourishment());\n    var messageFormat = \"Giant giant1, The giant looks healthy, alert and %s.\";\n    for (final var nourishment : Nourishment.values()) {\n      action.setNourishment(nourishment);\n      assertEquals(nourishment, model.getNourishment());\n      assertEquals(String.format(messageFormat, nourishment), model.toString());\n    }\n  }\n\n  /** Test update model. */\n  @Test\n  void testUpdateModel() {\n    final var model =\n        new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    Action action = new Action(model);\n    assertEquals(Nourishment.SATURATED, model.getNourishment());\n    for (final var nourishment : Nourishment.values()) {\n      for (final var fatigue : Fatigue.values()) {\n        for (final var health : Health.values()) {\n          Command cmd = new Command(fatigue, health, nourishment);\n          action.updateModel(cmd);\n          assertEquals(nourishment, model.getNourishment());\n          assertEquals(fatigue, model.getFatigue());\n          assertEquals(health, model.getHealth());\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "service-to-worker/src/test/java/com/iluwatar/servicetoworker/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "service-to-worker/src/test/java/com/iluwatar/servicetoworker/DispatcherTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.model.view.controller.Fatigue;\nimport com.iluwatar.model.view.controller.Health;\nimport com.iluwatar.model.view.controller.Nourishment;\nimport org.junit.jupiter.api.Test;\n\n/** The type Dispatcher test. */\nclass DispatcherTest {\n\n  /** Test perform action. */\n  @Test\n  void testPerformAction() {\n    final var model =\n        new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    Action action = new Action(model);\n    GiantView giantView = new GiantView();\n    Dispatcher dispatcher = new Dispatcher(giantView);\n    assertEquals(Nourishment.SATURATED, model.getNourishment());\n    dispatcher.addAction(action);\n    for (final var nourishment : Nourishment.values()) {\n      for (final var fatigue : Fatigue.values()) {\n        for (final var health : Health.values()) {\n          Command cmd = new Command(fatigue, health, nourishment);\n          dispatcher.performAction(cmd, 0);\n          assertEquals(nourishment, model.getNourishment());\n          assertEquals(fatigue, model.getFatigue());\n          assertEquals(health, model.getHealth());\n        }\n      }\n    }\n  }\n\n  @Test\n  void testUpdateView() {\n    final var model =\n        new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    GiantView giantView = new GiantView();\n    Dispatcher dispatcher = new Dispatcher(giantView);\n    assertDoesNotThrow(() -> dispatcher.updateView(model));\n  }\n}\n"
  },
  {
    "path": "service-to-worker/src/test/java/com/iluwatar/servicetoworker/GiantControllerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.model.view.controller.Fatigue;\nimport com.iluwatar.model.view.controller.Health;\nimport com.iluwatar.model.view.controller.Nourishment;\nimport org.junit.jupiter.api.Test;\n\n/** The type Giant controller test. */\nclass GiantControllerTest {\n\n  /** Test set command. */\n  @Test\n  void testSetCommand() {\n    final var model =\n        new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    Action action = new Action(model);\n    GiantView giantView = new GiantView();\n    Dispatcher dispatcher = new Dispatcher(giantView);\n    assertEquals(Nourishment.SATURATED, model.getNourishment());\n    dispatcher.addAction(action);\n    GiantController controller = new GiantController(dispatcher);\n    controller.setCommand(new Command(Fatigue.ALERT, Health.HEALTHY, Nourishment.HUNGRY), 0);\n    assertEquals(Fatigue.ALERT, model.getFatigue());\n    assertEquals(Health.HEALTHY, model.getHealth());\n    assertEquals(Nourishment.HUNGRY, model.getNourishment());\n  }\n\n  /** Test update view. */\n  @Test\n  void testUpdateView() {\n    final var model =\n        new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    GiantView giantView = new GiantView();\n    Dispatcher dispatcher = new Dispatcher(giantView);\n    GiantController giantController = new GiantController(dispatcher);\n    assertDoesNotThrow(() -> giantController.updateView(model));\n  }\n}\n"
  },
  {
    "path": "service-to-worker/src/test/java/com/iluwatar/servicetoworker/GiantModelTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.model.view.controller.Fatigue;\nimport com.iluwatar.model.view.controller.Health;\nimport com.iluwatar.model.view.controller.Nourishment;\nimport org.junit.jupiter.api.Test;\n\n/** The type Giant model test. */\nclass GiantModelTest {\n\n  /** Verify if the health value is set properly though the constructor and setter */\n  @Test\n  void testSetHealth() {\n    final var model =\n        new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    assertEquals(Health.HEALTHY, model.getHealth());\n    var messageFormat = \"Giant giant1, The giant looks %s, alert and saturated.\";\n    for (final var health : Health.values()) {\n      model.setHealth(health);\n      assertEquals(health, model.getHealth());\n      assertEquals(String.format(messageFormat, health), model.toString());\n    }\n  }\n\n  /** Verify if the fatigue level is set properly though the constructor and setter */\n  @Test\n  void testSetFatigue() {\n    final var model =\n        new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    assertEquals(Fatigue.ALERT, model.getFatigue());\n    var messageFormat = \"Giant giant1, The giant looks healthy, %s and saturated.\";\n    for (final var fatigue : Fatigue.values()) {\n      model.setFatigue(fatigue);\n      assertEquals(fatigue, model.getFatigue());\n      assertEquals(String.format(messageFormat, fatigue), model.toString());\n    }\n  }\n\n  /** Verify if the nourishment level is set properly though the constructor and setter */\n  @Test\n  void testSetNourishment() {\n    final var model =\n        new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    assertEquals(Nourishment.SATURATED, model.getNourishment());\n    var messageFormat = \"Giant giant1, The giant looks healthy, alert and %s.\";\n    for (final var nourishment : Nourishment.values()) {\n      model.setNourishment(nourishment);\n      assertEquals(nourishment, model.getNourishment());\n      assertEquals(String.format(messageFormat, nourishment), model.toString());\n    }\n  }\n}\n"
  },
  {
    "path": "service-to-worker/src/test/java/com/iluwatar/servicetoworker/GiantViewTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.servicetoworker;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport com.iluwatar.model.view.controller.Fatigue;\nimport com.iluwatar.model.view.controller.Health;\nimport com.iluwatar.model.view.controller.Nourishment;\nimport org.junit.jupiter.api.Test;\n\n/** The type Giant view test. */\nclass GiantViewTest {\n\n  /** Test display giant. */\n  @Test\n  void testDispalyGiant() {\n    GiantModel giantModel =\n        new GiantModel(\"giant1\", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);\n    GiantView giantView = new GiantView();\n    assertDoesNotThrow(() -> giantView.displayGiant(giantModel));\n  }\n}\n"
  },
  {
    "path": "session-facade/README.md",
    "content": "---\ntitle: \"Session Facade Pattern in Java: Simplifying Complex System Interfaces\"\nshortTitle: Session Facade\ndescription: \"Learn how to implement the Session Facade Design Pattern in Java to create a unified interface for complex subsystems. Simplify your code and enhance maintainability with practical examples and use cases.\"\ncategory: Structural\nlanguage: en\ntag:\n    - API design\n    - Abstraction\n    - Architecture\n    - Business\n    - Decoupling\n    - Enterprise patterns\n    - Facade\n    - Layered architecture\n    - Session management\n---\n\n## Also known as\n\n* Remote Facade\n\n## Intent of Session Facade Design Pattern\n\nProvide a simplified interface to a complex subsystem, reducing complexity and coupling between client and business logic in enterprise Java applications.\n\n## Detailed Explanation of Session Facade Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy for the Session Facade pattern is a hotel concierge service. Guests (clients) don't directly interact with various departments like housekeeping, kitchen, transport services, or maintenance. Instead, they interact with the concierge (the facade), who simplifies these interactions. When a guest requests services like room cleaning, dinner reservations, or taxi bookings, the concierge handles communication with multiple hotel departments behind the scenes, providing a simplified and unified interface to the guest, reducing complexity and enhancing guest satisfaction.\n\nIn plain words\n\n> Session Facade provides a simplified interface to complex business logic in Java applications, reducing client complexity and minimizing network overhead by encapsulating interactions within a single session component.\n\nSequence diagram\n\n![Session Facade sequence diagram](./etc/session-facade-sequence-diagram.png)\n\n## Programmatic Example of Session Facade Pattern in Java\n\nThe Session Facade pattern is a structural design pattern that provides a simplified interface to complex subsystems, making the system easier for clients to interact with. It is especially useful when a client needs access to multiple underlying services without needing to understand their internal complexities.\n\nIn the context of an e-commerce website, consider a scenario where users browse products, manage their shopping carts, place orders, and process payments. Rather than directly interacting with each subsystem individually (such as the cart, order, and payment systems), a client can communicate through a single unified Session Facade interface.\n\n### Example Scenario:\n\nIn this example, the `ShoppingFacade` class simplifies client interactions with three services: the `CartService`, `OrderService`, and `PaymentService`. The client uses the facade to perform high-level operations like adding products to the cart, placing an order, and choosing a payment method, without needing to know the underlying details.\n\nHere's a simplified Java program demonstrating this pattern:\n\n```java\npublic class App {\n    public static void main(String[] args) {\n        ShoppingFacade shoppingFacade = new ShoppingFacade();\n        shoppingFacade.addToCart(1);\n        shoppingFacade.order();\n        shoppingFacade.selectPaymentMethod(\"cash\");\n    }\n}\n```\n\nThe `ShoppingFacade` serves as a centralized point of interaction for various shopping-related operations, thereby reducing direct coupling between client code and individual subsystem services:\n\n```java\npublic class ShoppingFacade {\n\n    private final CartService cartService;\n    private final OrderService orderService;\n    private final PaymentService paymentService;\n\n    public ShoppingFacade() {\n        Map<Integer, Product> productCatalog = new HashMap<>();\n        productCatalog.put(1, new Product(1, \"Wireless Mouse\", 25.99, \"Ergonomic wireless mouse with USB receiver.\"));\n        productCatalog.put(2, new Product(2, \"Gaming Keyboard\", 79.99, \"RGB mechanical gaming keyboard with programmable keys.\"));\n        Map<Integer, Product> cart = new HashMap<>();\n        cartService = new CartService(cart, productCatalog);\n        orderService = new OrderService(cart);\n        paymentService = new PaymentService();\n    }\n\n    public Map<Integer, Product> getCart() {\n        return this.cartService.getCart();\n    }\n\n    public void addToCart(int productId) {\n        this.cartService.addToCart(productId);\n    }\n\n\n    public void removeFromCart(int productId) {\n        this.cartService.removeFromCart(productId);\n    }\n\n    public void order() {\n        this.orderService.order();\n    }\n\n    public Boolean isPaymentRequired() {\n        double total = this.orderService.getTotal();\n        if (total==0.0) {\n            LOGGER.info(\"No payment required\");\n            return false;\n        }\n        return true;\n    }\n\n    public void processPayment(String method) {\n        Boolean isPaymentRequired = isPaymentRequired();\n        if (Boolean.TRUE.equals(isPaymentRequired)) {\n            paymentService.selectPaymentMethod(method);\n        }\n    }\n}\n```\n\n### Console Output\n\nWhen running the provided example (App.main()), the output might look similar to:\n\n```\n19:43:17.883 [main] INFO com.iluwatar.sessionfacade.CartService -- ID: 1\nName: Wireless Mouse\nPrice: $25.99\nDescription: Ergonomic wireless mouse with USB receiver. successfully added to the cart\n19:43:17.910 [main] INFO com.iluwatar.sessionfacade.OrderService -- Client has chosen to order [ID: 1\n```\n\nThis simplified example demonstrates the essence of the Session Facade pattern. Your actual implementation may vary based on the specific needs of your application.\n\n## When to Use the Session Facade Pattern in Java\n\n* When dealing with complex enterprise applications containing multiple business objects.\n* To provide simplified API calls to clients, hiding the underlying complexity.\n* When seeking improved performance and reduced network calls between clients and servers.\n\n## Real-World Applications of Server Session Pattern in Java\n\n* Java EE applications utilizing Enterprise JavaBeans (EJB) as session facades to encapsulate business logic.\n* Spring-based applications using services as session facades to simplify interactions between controllers and repositories.\n\n## Benefits and Trade-offs of Server Session Pattern\n\nBenefits:\n\n* Reduces complexity by providing a simpler interface to a subsystem.\n* Improves performance by minimizing network traffic and reducing remote calls.\n* Enhances modularity and maintainability by clearly separating business logic and client interactions.\n\nTrade-offs:\n\n* Can introduce additional layers that might increase initial complexity.\n* Risk of creating overly broad facades that violate single responsibility principles.\n\n## Related Java Design Patterns\n\n* [Data Transfer Object (DTO)](https://java-design-patterns.com/patterns/data-transfer-object/): Often used together, Session Facade simplifies data transfer by utilizing DTOs to encapsulate data passed between client and server.\n* [Facade](https://java-design-patterns.com/patterns/facade/): Session Facade is a specialized version of the Facade pattern, applied specifically in enterprise systems to manage business logic and remote interactions.\n\n## References and Credits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Real World Java EE Patterns-Rethinking Best Practices](https://amzn.to/3EvkzS8)\n* [Remote Facade (Martin Fowler)](https://martinfowler.com/eaaCatalog/remoteFacade.html)\n"
  },
  {
    "path": "session-facade/etc/session-facade.urm.puml",
    "content": "@startuml\npackage com.iluwatar.sessionfacade {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class CartService {\n    - LOGGER : Logger {static}\n    - cart : List<Product>\n    - productCatalog : List<Product>\n    + CartService(cart : List<Product>, productCatalog : List<Product>)\n    + addToCart(productId : int)\n    + removeFromCart(productId : int)\n  }\n  class OrderService {\n    - LOGGER : Logger {static}\n    - cart : List<Product>\n    + OrderService(cart : List<Product>)\n    + order()\n  }\n  class PaymentService {\n    + LOGGER : Logger {static}\n    + PaymentService()\n    + cashPayment()\n    + creditCardPayment()\n    + selectPaymentMethod(method : String)\n  }\n  class ProductCatalogService {\n    - products : List<Product>\n    + ProductCatalogService(products : List<Product>)\n  }\n  class ShoppingFacade {\n    ~ cart : List<Product>\n    ~ cartService : CartService\n    ~ orderService : OrderService\n    ~ paymentService : PaymentService\n    ~ productCatalog : List<Product>\n    + ShoppingFacade()\n    + addToCart(productId : int)\n    + order()\n    + removeFromCart(productId : int)\n    + selectPaymentMethod(method : String)\n  }\n}\nShoppingFacade -->  \"-cartService\" CartService\nShoppingFacade -->  \"-paymentService\" PaymentService\nShoppingFacade -->  \"-orderService\" OrderService\n@enduml"
  },
  {
    "path": "session-facade/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>session-facade</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-params</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.sessionfacade.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>"
  },
  {
    "path": "session-facade/src/main/java/com/iluwatar/sessionfacade/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.sessionfacade;\n\n/**\n * The main entry point of the application that demonstrates the usage of the ShoppingFacade to\n * manage the shopping process using the Session Facade pattern. This class serves as a client that\n * interacts with the simplified interface provided by the ShoppingFacade, which encapsulates\n * complex interactions with the underlying business services. The ShoppingFacade acts as a session\n * bean that coordinates the communication between multiple services, hiding their complexity and\n * providing a single, unified API.\n */\npublic class App {\n  /**\n   * The entry point of the application. This method demonstrates how the ShoppingFacade, acting as\n   * a Session Facade, is used to: - Add items to the shopping cart - Process a payment - Place the\n   * order The session facade manages the communication between the individual services and\n   * simplifies the interactions for the client.\n   *\n   * @param args the input arguments\n   */\n  public static void main(String[] args) {\n    ShoppingFacade shoppingFacade = new ShoppingFacade();\n\n    // Adding items to the shopping cart\n    shoppingFacade.addToCart(1);\n    shoppingFacade.addToCart(2);\n\n    // Processing the payment with the chosen method\n    shoppingFacade.processPayment(\"cash\");\n\n    // Finalizing the order\n    shoppingFacade.order();\n  }\n}\n"
  },
  {
    "path": "session-facade/src/main/java/com/iluwatar/sessionfacade/CartService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.sessionfacade;\n\nimport java.util.Map;\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The type Cart service. Represents the cart entity, has add to cart and remove from cart methods\n */\n@Slf4j\npublic class CartService {\n  /** -- GETTER -- Gets cart. */\n  @Getter private final Map<Integer, Product> cart;\n\n  private final Map<Integer, Product> productCatalog;\n\n  /**\n   * Instantiates a new Cart service.\n   *\n   * @param cart the cart\n   * @param productCatalog the product catalog\n   */\n  public CartService(Map<Integer, Product> cart, Map<Integer, Product> productCatalog) {\n    this.cart = cart;\n    this.productCatalog = productCatalog;\n  }\n\n  /**\n   * Add to cart.\n   *\n   * @param productId the product id\n   */\n  public void addToCart(int productId) {\n    Product product = productCatalog.get(productId);\n    if (product != null) {\n      cart.put(productId, product);\n      LOGGER.info(\"{} successfully added to the cart\", product);\n    } else {\n      LOGGER.info(\"No product is found in catalog with id {}\", productId);\n    }\n  }\n\n  /**\n   * Remove from cart.\n   *\n   * @param productId the product id\n   */\n  public void removeFromCart(int productId) {\n    Product product = cart.remove(productId); // Remove product from cart\n    if (product != null) {\n      LOGGER.info(\"{} successfully removed from the cart\", product);\n    } else {\n      LOGGER.info(\"No product is found in cart with id {}\", productId);\n    }\n  }\n}\n"
  },
  {
    "path": "session-facade/src/main/java/com/iluwatar/sessionfacade/OrderService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.sessionfacade;\n\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The OrderService class is responsible for finalizing a customer's order. It includes a method to\n * calculate the total cost of the order, which follows the information expert principle from GRASP\n * by assigning the responsibility of total calculation to this service. Additionally, it provides a\n * method to complete the order, which empties the client's shopping cart once the order is\n * finalized.\n */\n@Slf4j\npublic class OrderService {\n  private final Map<Integer, Product> cart;\n\n  /**\n   * Instantiates a new Order service.\n   *\n   * @param cart the cart\n   */\n  public OrderService(Map<Integer, Product> cart) {\n    this.cart = cart;\n  }\n\n  /** Order. */\n  public void order() {\n    Double total = getTotal();\n    if (!this.cart.isEmpty()) {\n      LOGGER.info(\n          \"Client has chosen to order {} with total {}\", cart, String.format(\"%.2f\", total));\n      this.completeOrder();\n    } else {\n      LOGGER.info(\"Client's shopping cart is empty\");\n    }\n  }\n\n  /**\n   * Gets total.\n   *\n   * @return the total\n   */\n  public double getTotal() {\n    final double[] total = {0.0};\n    this.cart.forEach((key, product) -> total[0] += product.price());\n    return total[0];\n  }\n\n  /** Complete order. */\n  public void completeOrder() {\n    this.cart.clear();\n  }\n}\n"
  },
  {
    "path": "session-facade/src/main/java/com/iluwatar/sessionfacade/PaymentService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.sessionfacade;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * The PaymentService class is responsible for handling the selection and processing of different\n * payment methods. It provides functionality to select a payment method (cash or credit card) and\n * process the corresponding payment option. The class uses logging to inform the client of the\n * selected payment method. It includes methods to: - Select the payment method based on the\n * client's choice. - Process cash payments through the `cashPayment()` method. - Process credit\n * card payments through the `creditCardPayment()` method.\n */\npublic class PaymentService {\n  /** The constant LOGGER. */\n  public static Logger LOGGER = LoggerFactory.getLogger(PaymentService.class);\n\n  /**\n   * Select payment method.\n   *\n   * @param method the method\n   */\n  public void selectPaymentMethod(String method) {\n    if (method.equals(\"cash\")) {\n      cashPayment();\n    } else if (method.equals(\"credit\")) {\n      creditCardPayment();\n    } else {\n      LOGGER.info(\"Unspecified payment method type\");\n    }\n  }\n\n  /** Cash payment. */\n  public void cashPayment() {\n    LOGGER.info(\"Client have chosen cash payment option\");\n  }\n\n  /** Credit card payment. */\n  public void creditCardPayment() {\n    LOGGER.info(\"Client have chosen credit card payment option\");\n  }\n}\n"
  },
  {
    "path": "session-facade/src/main/java/com/iluwatar/sessionfacade/Product.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.sessionfacade;\n\n/** The type Product. */\npublic record Product(int id, String name, double price, String description) {\n  @Override\n  public String toString() {\n    return \"ID: \" + id + \"\\nName: \" + name + \"\\nPrice: $\" + price + \"\\nDescription: \" + description;\n  }\n}\n"
  },
  {
    "path": "session-facade/src/main/java/com/iluwatar/sessionfacade/ProductCatalogService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.sessionfacade;\n\nimport java.util.Map;\n\n/**\n * The type ProductCatalogService. This class manages a catalog of products. It holds a map of\n * products, where each product is identified by a unique ID. The class provides functionality to\n * access and manage the products in the catalog.\n */\npublic class ProductCatalogService {\n\n  private final Map<Integer, Product> products;\n\n  /**\n   * Instantiates a new ProductCatalogService.\n   *\n   * @param products the map of products to be used by this service\n   */\n  public ProductCatalogService(Map<Integer, Product> products) {\n    this.products = products;\n  }\n\n  // Additional methods to interact with products can be added here, for example:\n\n  /**\n   * Retrieves a product by its ID.\n   *\n   * @param id the product ID\n   * @return the product corresponding to the ID\n   */\n  public Product getProductById(int id) {\n    return products.get(id);\n  }\n}\n"
  },
  {
    "path": "session-facade/src/main/java/com/iluwatar/sessionfacade/ShoppingFacade.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.sessionfacade;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The ShoppingFacade class provides a simplified interface for clients to interact with the\n * shopping system. It acts as a facade to handle operations related to a shopping cart, order\n * processing, and payment. Responsibilities: - Add products to the shopping cart. - Remove products\n * from the shopping cart. - Retrieve the current shopping cart. - Finalize an order by calling the\n * order service. - Check if a payment is required based on the order total. - Process payment using\n * different payment methods (e.g., cash, credit card). The ShoppingFacade class delegates\n * operations to the following services: - CartService: Manages the cart and product catalog. -\n * OrderService: Handles the order finalization process and calculation of the total. -\n * PaymentService: Handles the payment processing based on the selected payment method.\n */\n@Slf4j\npublic class ShoppingFacade {\n  private final CartService cartService;\n  private final OrderService orderService;\n  private final PaymentService paymentService;\n\n  /** Instantiates a new Shopping facade. */\n  public ShoppingFacade() {\n    Map<Integer, Product> productCatalog = new HashMap<>();\n    productCatalog.put(\n        1, new Product(1, \"Wireless Mouse\", 25.99, \"Ergonomic wireless mouse with USB receiver.\"));\n    productCatalog.put(\n        2,\n        new Product(\n            2, \"Gaming Keyboard\", 79.99, \"RGB mechanical gaming keyboard with programmable keys.\"));\n    Map<Integer, Product> cart = new HashMap<>();\n    cartService = new CartService(cart, productCatalog);\n    orderService = new OrderService(cart);\n    paymentService = new PaymentService();\n  }\n\n  /**\n   * Gets cart.\n   *\n   * @return the cart\n   */\n  public Map<Integer, Product> getCart() {\n    return this.cartService.getCart();\n  }\n\n  /**\n   * Add to cart.\n   *\n   * @param productId the product id\n   */\n  public void addToCart(int productId) {\n    this.cartService.addToCart(productId);\n  }\n\n  /**\n   * Remove from cart.\n   *\n   * @param productId the product id\n   */\n  public void removeFromCart(int productId) {\n    this.cartService.removeFromCart(productId);\n  }\n\n  /** Order. */\n  public void order() {\n    this.orderService.order();\n  }\n\n  /**\n   * Is payment required boolean.\n   *\n   * @return the boolean\n   */\n  public Boolean isPaymentRequired() {\n    double total = this.orderService.getTotal();\n    if (total == 0.0) {\n      LOGGER.info(\"No payment required\");\n      return false;\n    }\n    return true;\n  }\n\n  /**\n   * Process payment.\n   *\n   * @param method the method\n   */\n  public void processPayment(String method) {\n    Boolean isPaymentRequired = isPaymentRequired();\n    if (Boolean.TRUE.equals(isPaymentRequired)) {\n      paymentService.selectPaymentMethod(method);\n    }\n  }\n}\n"
  },
  {
    "path": "session-facade/src/test/java/com/iluwatar/sessionfacade/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sessionfacade;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\n/** The type App test. */\nclass AppTest {\n\n  /** Should execute application without exception. */\n  @org.junit.jupiter.api.Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "session-facade/src/test/java/com/iluwatar/sessionfacade/CartServiceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sessionfacade;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.MockitoAnnotations;\n\n/** The type Cart service test. */\n@Slf4j\nclass CartServiceTest {\n\n  private CartService cartService;\n  private Map<Integer, Product> cart;\n\n  /** Sets up. */\n  @BeforeEach\n  void setUp() {\n    MockitoAnnotations.openMocks(this);\n    cart = new HashMap<>();\n    Map<Integer, Product> productCatalog = new HashMap<>();\n    productCatalog.put(1, new Product(1, \"Product A\", 2.0, \"any description\"));\n    productCatalog.put(2, new Product(2, \"Product B\", 300.0, \"a watch\"));\n    cartService = new CartService(cart, productCatalog);\n  }\n\n  /** Test add to cart. */\n  @Test\n  void testAddToCart() {\n    cartService.addToCart(1);\n    assertEquals(1, cart.size());\n    assertEquals(\"Product A\", cart.get(1).name());\n  }\n\n  /** Test remove from cart. */\n  @Test\n  void testRemoveFromCart() {\n    cartService.addToCart(1);\n    assertEquals(1, cart.size());\n    cartService.removeFromCart(1);\n    assertTrue(cart.isEmpty());\n  }\n\n  /** Test add to cart with invalid product id. */\n  @Test\n  void testAddToCartWithInvalidProductId() {\n    cartService.addToCart(999);\n    assertTrue(cart.isEmpty());\n  }\n\n  /** Test remove from cart with invalid product id. */\n  @Test\n  void testRemoveFromCartWithInvalidProductId() {\n    cartService.removeFromCart(999);\n    assertTrue(cart.isEmpty());\n  }\n}\n"
  },
  {
    "path": "session-facade/src/test/java/com/iluwatar/sessionfacade/PaymentServiceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sessionfacade;\n\nimport static org.mockito.Mockito.*;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.CsvSource;\nimport org.slf4j.Logger;\n\n/** The type Payment service test. */\nclass PaymentServiceTest {\n  private PaymentService paymentService;\n  private Logger mockLogger;\n\n  /** Sets up. */\n  @BeforeEach\n  void setUp() {\n    paymentService = new PaymentService();\n    mockLogger = mock(Logger.class);\n    paymentService.LOGGER = mockLogger;\n  }\n\n  @ParameterizedTest\n  @CsvSource({\n    \"cash, Client have chosen cash payment option\",\n    \"credit, Client have chosen credit card payment option\",\n    \"cheque, Unspecified payment method type\"\n  })\n  void testSelectPaymentMethod(String method, String expectedLogMessage) {\n    paymentService.selectPaymentMethod(method);\n    verify(mockLogger).info(expectedLogMessage);\n  }\n}\n"
  },
  {
    "path": "session-facade/src/test/java/com/iluwatar/sessionfacade/ProductTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sessionfacade;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\n/** The type Product test. */\npublic class ProductTest {\n  /** Test product creation. */\n  @Test\n  public void testProductCreation() {\n    int id = 1;\n    String name = \"Product A\";\n    double price = 200.0;\n    String description = \"a description\";\n    Product product = new Product(id, name, price, description);\n    assertEquals(id, product.id());\n    assertEquals(name, product.name());\n    assertEquals(price, product.price());\n    assertEquals(description, product.description());\n  }\n\n  /** Test equals and hash code. */\n  @Test\n  public void testEqualsAndHashCode() {\n    Product product1 = new Product(1, \"Product A\", 99.99, \"a description\");\n    Product product2 = new Product(1, \"Product A\", 99.99, \"a description\");\n    Product product3 = new Product(2, \"Product B\", 199.99, \"a description\");\n\n    assertEquals(product1, product2);\n    assertNotEquals(product1, product3);\n    assertEquals(product1.hashCode(), product2.hashCode());\n    assertNotEquals(product1.hashCode(), product3.hashCode());\n  }\n\n  /** Test to string. */\n  @Test\n  public void testToString() {\n    Product product = new Product(1, \"Product A\", 99.99, \"a description\");\n    String toStringResult = product.toString();\n    assertTrue(toStringResult.contains(\"Product A\"));\n    assertTrue(toStringResult.contains(\"99.99\"));\n  }\n}\n"
  },
  {
    "path": "session-facade/src/test/java/com/iluwatar/sessionfacade/ShoppingFacadeTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sessionfacade;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.Map;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for ShoppingFacade. */\nclass ShoppingFacadeTest {\n\n  private ShoppingFacade shoppingFacade;\n\n  @BeforeEach\n  void setUp() {\n    shoppingFacade = new ShoppingFacade();\n  }\n\n  @Test\n  void testAddToCart() {\n    shoppingFacade.addToCart(1);\n    shoppingFacade.addToCart(2);\n    Map<Integer, Product> cart = shoppingFacade.getCart();\n    assertEquals(2, cart.size(), \"Cart should contain two items.\");\n    assertEquals(\n        \"Wireless Mouse\", cart.get(1).name(), \"First item in the cart should be 'Wireless Mouse'.\");\n    assertEquals(\n        \"Gaming Keyboard\",\n        cart.get(2).name(),\n        \"Second item in the cart should be 'Gaming Keyboard'.\");\n  }\n\n  @Test\n  void testRemoveFromCart() {\n    shoppingFacade.addToCart(1);\n    shoppingFacade.addToCart(2);\n    shoppingFacade.removeFromCart(1);\n    Map<Integer, Product> cart = shoppingFacade.getCart();\n    assertEquals(1, cart.size(), \"Cart should contain one item after removal.\");\n    assertEquals(\n        \"Gaming Keyboard\", cart.get(2).name(), \"Remaining item should be 'Gaming Keyboard'.\");\n  }\n\n  @Test\n  void testOrder() {\n    shoppingFacade.addToCart(1);\n    shoppingFacade.addToCart(2);\n    shoppingFacade.processPayment(\"cash\");\n    shoppingFacade.order();\n    assertTrue(shoppingFacade.getCart().isEmpty(), \"Cart should be empty after placing the order.\");\n  }\n}\n"
  },
  {
    "path": "sharding/README.md",
    "content": "---\ntitle: \"Sharding Pattern in Java: Mastering Horizontal Partitioning to Boost Application Throughput\"\nshortTitle: Sharding\ndescription: \"Explore how Sharding, or horizontal partitioning, enhances database scalability and performance. This guide covers the Sharding pattern's intent, implementation, and benefits for Java developers.\"\ncategory: Data access\nlanguage: en\ntag:\n  - Data access\n  - Optimization\n  - Scalability\n---\n\n## Also known as\n\n* Data Partitioning\n* Horizontal Partitioning\n\n## Intent of Sharding Design Pattern\n\nSharding, a pivotal Java design pattern, significantly boosts database scalability and performance through horizontal partitioning.\n\n## Detailed Explanation of Sharding Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a large e-commerce website with millions of users and transactions. To handle the immense amount of data and ensure the system remains responsive, the user data is sharded across multiple database servers. For instance, users with IDs ending in 0-4 might be stored on one server, and those ending in 5-9 on another. This distribution allows the system to handle a higher load by parallelizing read and write operations across multiple servers.\n\nIn plain words\n\n> Separates the processing logic from the view in web applications to improve maintainability and scalability.\n\nWikipedia says\n\n> Horizontal partitioning is a database design principle whereby rows of a database table are held separately, rather than being split into columns (which is what normalization and vertical partitioning do, to differing extents). Each partition forms part of a shard, which may in turn be located on a separate database server or physical location.\n>\n> There are numerous advantages to the horizontal partitioning approach. Since the tables are divided and distributed into multiple servers, the total number of rows in each table in each database is reduced. This reduces index size, which generally improves search performance. A database shard can be placed on separate hardware, and multiple shards can be placed on multiple machines. This enables a distribution of the database over a large number of machines, greatly improving performance. In addition, if the database shard is based on some real-world segmentation of the data (e.g., European customers v. American customers) then it may be possible to infer the appropriate shard membership easily and automatically, and query only the relevant shard.\n\nFlowchart\n\n![Sharding flowchart](./etc/sharding-flowchart.png)\n\n## Programmatic Example of Sharding Pattern in Java\n\nSharding is a type of database partitioning that separates very large databases into smaller, faster, more easily managed parts called data shards. The word shard means a small part of a whole. In software architecture, it refers to a horizontal partition in a database or search engine. Each individual partition is referred to as a shard or database shard.\n\nIn the given code, we have a `ShardManager` class that manages the shards. It has two subclasses `HashShardManager` and `RangeShardManager` that implement different sharding strategies. The `Shard` class represents a shard that stores data. The `Data` class represents the data to be stored in the shards.\n\nThe `ShardManager` is an abstract class that provides the basic structure for managing shards. It has a `storeData` method that stores data in a shard and an `allocateShard` method that determines which shard to store the data in. The `allocateShard` method is abstract and must be implemented by subclasses.\n\n```java\npublic abstract class ShardManager {\n  protected Map<Integer, Shard> shardMap = new HashMap<>();\n\n  public abstract int storeData(Data data);\n\n  protected abstract int allocateShard(Data data);\n}\n```\n\nThe `HashShardManager` is a subclass of `ShardManager` that implements a hash-based sharding strategy. In the `allocateShard` method, it calculates a hash of the data key and uses it to determine the shard to store the data in.\n\n```java\npublic class HashShardManager extends ShardManager {\n\n  @Override\n  protected int allocateShard(Data data) {\n    var shardCount = shardMap.size();\n    var hash = data.getKey() % shardCount;\n    return hash == 0 ? hash + shardCount : hash;\n  }\n}\n```\n\nThe `RangeShardManager` is another subclass of `ShardManager` that implements a range-based sharding strategy. In the `allocateShard` method, it uses the data type to determine the shard to store the data in.\n\n```java\npublic class RangeShardManager extends ShardManager {\n\n  @Override\n  protected int allocateShard(Data data) {\n    var type = data.getType();\n    return switch (type) {\n      case TYPE_1 -> 1;\n      case TYPE_2 -> 2;\n      case TYPE_3 -> 3;\n    };\n  }\n}\n```\n\nThe `Shard` class represents a shard. It has a `storeData` method that stores data in the shard and a `getDataById` method that retrieves data from the shard by its id.\n\n```java\npublic class Shard {\n\n  @Getter\n  private final int id;\n\n  private final Map<Integer, Data> dataStore;\n\n  public Shard(final int id) {\n    this.id = id;\n    this.dataStore = new HashMap<>();\n  }\n\n  public void storeData(Data data) {\n    dataStore.put(data.getKey(), data);\n  }\n\n  public Data getDataById(final int id) {\n    return dataStore.get(id);\n  }\n}\n```\n\nThe `Data` class represents the data to be stored in the shards. It has a key, a value, and a type.\n\n```java\n@Getter\n@Setter\npublic class Data {\n\n  private int key;\n\n  private String value;\n\n  private DataType type;\n\n  public Data(final int key, final String value, final DataType type) {\n    this.key = key;\n    this.value = value;\n    this.type = type;\n  }\n\n  enum DataType {\n    TYPE_1, TYPE_2, TYPE_3\n  }\n}\n```\n\nThis is the `main` function of the example demonstrating three different sharding strategies: lookup, range, and hash. Each strategy determines which shard to store the data in a different way. The lookup strategy uses a lookup table, the range strategy uses the data type, and the hash strategy uses a hash of the data key.\n\n```java\npublic static void main(String[] args) {\n\n    var data1 = new Data(1, \"data1\", Data.DataType.TYPE_1);\n    var data2 = new Data(2, \"data2\", Data.DataType.TYPE_2);\n    var data3 = new Data(3, \"data3\", Data.DataType.TYPE_3);\n    var data4 = new Data(4, \"data4\", Data.DataType.TYPE_1);\n\n    var shard1 = new Shard(1);\n    var shard2 = new Shard(2);\n    var shard3 = new Shard(3);\n\n    var manager = new LookupShardManager();\n    manager.addNewShard(shard1);\n    manager.addNewShard(shard2);\n    manager.addNewShard(shard3);\n    manager.storeData(data1);\n    manager.storeData(data2);\n    manager.storeData(data3);\n    manager.storeData(data4);\n\n    shard1.clearData();\n    shard2.clearData();\n    shard3.clearData();\n\n    var rangeShardManager = new RangeShardManager();\n    rangeShardManager.addNewShard(shard1);\n    rangeShardManager.addNewShard(shard2);\n    rangeShardManager.addNewShard(shard3);\n    rangeShardManager.storeData(data1);\n    rangeShardManager.storeData(data2);\n    rangeShardManager.storeData(data3);\n    rangeShardManager.storeData(data4);\n\n    shard1.clearData();\n    shard2.clearData();\n    shard3.clearData();\n\n    var hashShardManager = new HashShardManager();\n    hashShardManager.addNewShard(shard1);\n    hashShardManager.addNewShard(shard2);\n    hashShardManager.addNewShard(shard3);\n    hashShardManager.storeData(data1);\n    hashShardManager.storeData(data2);\n    hashShardManager.storeData(data3);\n    hashShardManager.storeData(data4);\n\n    shard1.clearData();\n    shard2.clearData();\n    shard3.clearData();\n}\n```\n\nFinally, here is the program output:\n\n```\n18:32:26.503 [main] INFO com.iluwatar.sharding.LookupShardManager -- Data {key=1, value='data1', type=TYPE_1} is stored in Shard 2\n18:32:26.505 [main] INFO com.iluwatar.sharding.LookupShardManager -- Data {key=2, value='data2', type=TYPE_2} is stored in Shard 2\n18:32:26.505 [main] INFO com.iluwatar.sharding.LookupShardManager -- Data {key=3, value='data3', type=TYPE_3} is stored in Shard 1\n18:32:26.505 [main] INFO com.iluwatar.sharding.LookupShardManager -- Data {key=4, value='data4', type=TYPE_1} is stored in Shard 1\n18:32:26.506 [main] INFO com.iluwatar.sharding.RangeShardManager -- Data {key=1, value='data1', type=TYPE_1} is stored in Shard 1\n18:32:26.506 [main] INFO com.iluwatar.sharding.RangeShardManager -- Data {key=2, value='data2', type=TYPE_2} is stored in Shard 2\n18:32:26.506 [main] INFO com.iluwatar.sharding.RangeShardManager -- Data {key=3, value='data3', type=TYPE_3} is stored in Shard 3\n18:32:26.506 [main] INFO com.iluwatar.sharding.RangeShardManager -- Data {key=4, value='data4', type=TYPE_1} is stored in Shard 1\n18:32:26.506 [main] INFO com.iluwatar.sharding.HashShardManager -- Data {key=1, value='data1', type=TYPE_1} is stored in Shard 1\n18:32:26.506 [main] INFO com.iluwatar.sharding.HashShardManager -- Data {key=2, value='data2', type=TYPE_2} is stored in Shard 2\n18:32:26.506 [main] INFO com.iluwatar.sharding.HashShardManager -- Data {key=3, value='data3', type=TYPE_3} is stored in Shard 3\n18:32:26.506 [main] INFO com.iluwatar.sharding.HashShardManager -- Data {key=4, value='data4', type=TYPE_1} is stored in Shard 1\n```\n\n## When to Use the Sharding Pattern in Java\n\n* Use when dealing with large datasets that exceed the capacity of a single database.\n* Ideal for Java applications requiring robust scalability, sharding improves performance by distributing database loads effectively.\n* Useful for applications requiring high availability and fault tolerance.\n* Effective in environments where read and write operations can be parallelized across shards.\n\n## Real-World Applications of Sharding Pattern in Java\n\n* Distributed databases such as Apache Cassandra, MongoDB, and Amazon DynamoDB.\n* Large-scale web applications like social networks, e-commerce platforms, and SaaS products.\n\n## Benefits and Trade-offs of Sharding Pattern\n\nBenefits:\n\n* Enhances performance by distributing load.\n* Improves scalability by allowing horizontal scaling.\n* Increases availability and fault tolerance by isolating failures to individual shards.\n\nTrade-offs:\n\n* Complexity in managing and maintaining multiple shards.\n* Potential challenges in rebalancing shards as data grows.\n* Increased latency for cross-shard queries.\n\n## Related Java Design Patterns\n\n* [Caching](https://java-design-patterns.com/patterns/caching/): Can be used in conjunction with sharding to further improve performance.\n* [Data Mapper](https://java-design-patterns.com/patterns/data-mapper/): Helps in abstracting and encapsulating the details of database interactions, which can be complex in a sharded environment.\n* [Repository](https://java-design-patterns.com/patterns/repository/): Provides a way to manage data access logic centrally, which is useful when dealing with multiple shards.\n* [Service Locator](https://java-design-patterns.com/patterns/service-locator/): Can be used to find and interact with different shards in a distributed system.\n\n## References and Credits\n\n* [Building Scalable Web Sites: Building, Scaling, and Optimizing the Next Generation of Web Applications](https://amzn.to/4bqpejJ)\n* [Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems](https://amzn.to/3y6yv1z)\n* [NoSQL Distilled: A Brief Guide to the Emerging World of Polyglot Persistence](https://amzn.to/3UWvdpw)\n* [Sharding pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/patterns/sharding)\n"
  },
  {
    "path": "sharding/etc/sharding.urm.puml",
    "content": "@startuml\npackage com.iluwatar.sharding {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Data {\n    - key : int\n    - type : DataType\n    - value : String\n    + Data(key : int, value : String, type : DataType)\n    + getKey() : int\n    + getType() : DataType\n    + getValue() : String\n    + setKey(key : int)\n    + setType(type : DataType)\n    + setValue(value : String)\n    + toString() : String\n  }\n  ~enum DataType {\n    + type1 {static}\n    + type2 {static}\n    + type3 {static}\n    + valueOf(name : String) : DataType {static}\n    + values() : DataType[] {static}\n  }\n  class HashShardManager {\n    - LOGGER : Logger {static}\n    + HashShardManager()\n    # allocateShard(data : Data) : int\n    + storeData(data : Data) : int\n  }\n  class LookupShardManager {\n    - LOGGER : Logger {static}\n    - lookupMap : Map<Integer, Integer>\n    + LookupShardManager()\n    # allocateShard(data : Data) : int\n    + storeData(data : Data) : int\n  }\n  class RangeShardManager {\n    - LOGGER : Logger {static}\n    + RangeShardManager()\n    # allocateShard(data : Data) : int\n    + storeData(data : Data) : int\n  }\n  class Shard {\n    - dataStore : Map<Integer, Data>\n    - id : int\n    + Shard(id : int)\n    + clearData()\n    + getDataById(id : int) : Data\n    + getId() : int\n    + storeData(data : Data)\n  }\n  abstract class ShardManager {\n    - LOGGER : Logger {static}\n    # shardMap : Map<Integer, Shard>\n    + ShardManager()\n    + addNewShard(shard : Shard) : boolean\n    # allocateShard(Data) : int {abstract}\n    + getShardById(shardId : int) : Shard\n    + removeShardById(shardId : int) : boolean\n    + storeData(Data) : int {abstract}\n  }\n}\nDataType ..+ Data\nData -->  \"-type\" DataType\nHashShardManager --|> ShardManager \nLookupShardManager --|> ShardManager \nRangeShardManager --|> ShardManager \n@enduml"
  },
  {
    "path": "sharding/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>sharding</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.sharding.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "sharding/src/main/java/com/iluwatar/sharding/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\n/**\n * Sharding pattern means dividing a data store into a set of horizontal partitions or shards. This\n * pattern can improve scalability when storing and accessing large volumes of data.\n */\npublic class App {\n\n  /**\n   * Program main entry point.\n   *\n   * @param args program runtime arguments\n   */\n  public static void main(String[] args) {\n\n    var data1 = new Data(1, \"data1\", Data.DataType.TYPE_1);\n    var data2 = new Data(2, \"data2\", Data.DataType.TYPE_2);\n    var data3 = new Data(3, \"data3\", Data.DataType.TYPE_3);\n    var data4 = new Data(4, \"data4\", Data.DataType.TYPE_1);\n\n    var shard1 = new Shard(1);\n    var shard2 = new Shard(2);\n    var shard3 = new Shard(3);\n\n    var manager = new LookupShardManager();\n    manager.addNewShard(shard1);\n    manager.addNewShard(shard2);\n    manager.addNewShard(shard3);\n    manager.storeData(data1);\n    manager.storeData(data2);\n    manager.storeData(data3);\n    manager.storeData(data4);\n\n    shard1.clearData();\n    shard2.clearData();\n    shard3.clearData();\n\n    var rangeShardManager = new RangeShardManager();\n    rangeShardManager.addNewShard(shard1);\n    rangeShardManager.addNewShard(shard2);\n    rangeShardManager.addNewShard(shard3);\n    rangeShardManager.storeData(data1);\n    rangeShardManager.storeData(data2);\n    rangeShardManager.storeData(data3);\n    rangeShardManager.storeData(data4);\n\n    shard1.clearData();\n    shard2.clearData();\n    shard3.clearData();\n\n    var hashShardManager = new HashShardManager();\n    hashShardManager.addNewShard(shard1);\n    hashShardManager.addNewShard(shard2);\n    hashShardManager.addNewShard(shard3);\n    hashShardManager.storeData(data1);\n    hashShardManager.storeData(data2);\n    hashShardManager.storeData(data3);\n    hashShardManager.storeData(data4);\n\n    shard1.clearData();\n    shard2.clearData();\n    shard3.clearData();\n  }\n}\n"
  },
  {
    "path": "sharding/src/main/java/com/iluwatar/sharding/Data.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Basic data structure for each tuple stored in data shards. */\n@Getter\n@Setter\npublic class Data {\n\n  private int key;\n\n  private String value;\n\n  private DataType type;\n\n  /**\n   * Constructor of Data class.\n   *\n   * @param key data key\n   * @param value data value\n   * @param type data type\n   */\n  public Data(final int key, final String value, final DataType type) {\n    this.key = key;\n    this.value = value;\n    this.type = type;\n  }\n\n  enum DataType {\n    TYPE_1,\n    TYPE_2,\n    TYPE_3\n  }\n\n  @Override\n  public String toString() {\n    return \"Data {\" + \"key=\" + key + \", value='\" + value + '\\'' + \", type=\" + type + '}';\n  }\n}\n"
  },
  {
    "path": "sharding/src/main/java/com/iluwatar/sharding/HashShardManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * ShardManager with hash strategy. The purpose of this strategy is to reduce the chance of\n * hot-spots in the data. It aims to distribute the data across the shards in a way that achieves a\n * balance between the size of each shard and the average load that each shard will encounter.\n */\n@Slf4j\npublic class HashShardManager extends ShardManager {\n\n  @Override\n  public int storeData(Data data) {\n    var shardId = allocateShard(data);\n    var shard = shardMap.get(shardId);\n    shard.storeData(data);\n    LOGGER.info(data + \" is stored in Shard \" + shardId);\n    return shardId;\n  }\n\n  @Override\n  protected int allocateShard(Data data) {\n    var shardCount = shardMap.size();\n    var hash = data.getKey() % shardCount;\n    return hash == 0 ? hash + shardCount : hash;\n  }\n}\n"
  },
  {
    "path": "sharding/src/main/java/com/iluwatar/sharding/LookupShardManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\nimport java.security.SecureRandom;\nimport java.util.HashMap;\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * ShardManager with lookup strategy. In this strategy the sharding logic implements a map that\n * routes a request for data to the shard that contains that data by using the shard key.\n */\n@Slf4j\npublic class LookupShardManager extends ShardManager {\n\n  private final Map<Integer, Integer> lookupMap = new HashMap<>();\n\n  @Override\n  public int storeData(Data data) {\n    var shardId = allocateShard(data);\n    lookupMap.put(data.getKey(), shardId);\n    var shard = shardMap.get(shardId);\n    shard.storeData(data);\n    LOGGER.info(data + \" is stored in Shard \" + shardId);\n    return shardId;\n  }\n\n  @Override\n  protected int allocateShard(Data data) {\n    var key = data.getKey();\n    if (lookupMap.containsKey(key)) {\n      return lookupMap.get(key);\n    } else {\n      var shardCount = shardMap.size();\n      return new SecureRandom().nextInt(shardCount - 1) + 1;\n    }\n  }\n}\n"
  },
  {
    "path": "sharding/src/main/java/com/iluwatar/sharding/RangeShardManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * ShardManager with range strategy. This strategy groups related items together in the same shard,\n * and orders them by shard key.\n */\n@Slf4j\npublic class RangeShardManager extends ShardManager {\n\n  @Override\n  public int storeData(Data data) {\n    var shardId = allocateShard(data);\n    var shard = shardMap.get(shardId);\n    shard.storeData(data);\n    LOGGER.info(data + \" is stored in Shard \" + shardId);\n    return shardId;\n  }\n\n  @Override\n  protected int allocateShard(Data data) {\n    var type = data.getType();\n    return switch (type) {\n      case TYPE_1 -> 1;\n      case TYPE_2 -> 2;\n      case TYPE_3 -> 3;\n    };\n  }\n}\n"
  },
  {
    "path": "sharding/src/main/java/com/iluwatar/sharding/Shard.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport lombok.Getter;\n\n/** The Shard class stored data in a HashMap. */\npublic class Shard {\n\n  @Getter private final int id;\n\n  private final Map<Integer, Data> dataStore;\n\n  public Shard(final int id) {\n    this.id = id;\n    this.dataStore = new HashMap<>();\n  }\n\n  public void storeData(Data data) {\n    dataStore.put(data.getKey(), data);\n  }\n\n  public void clearData() {\n    dataStore.clear();\n  }\n\n  public Data getDataById(final int id) {\n    return dataStore.get(id);\n  }\n}\n"
  },
  {
    "path": "sharding/src/main/java/com/iluwatar/sharding/ShardManager.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Abstract class for ShardManager. */\n@Slf4j\npublic abstract class ShardManager {\n\n  protected Map<Integer, Shard> shardMap;\n\n  public ShardManager() {\n    shardMap = new HashMap<>();\n  }\n\n  /**\n   * Add a provided shard instance to shardMap.\n   *\n   * @param shard new shard instance.\n   * @return {@code true} if succeed to add the new instance. {@code false} if the shardId is\n   *     already existed.\n   */\n  public boolean addNewShard(final Shard shard) {\n    var shardId = shard.getId();\n    if (!shardMap.containsKey(shardId)) {\n      shardMap.put(shardId, shard);\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  /**\n   * Remove a shard instance by provided Id.\n   *\n   * @param shardId Id of shard instance to remove.\n   * @return {@code true} if removed. {@code false} if the shardId is not existed.\n   */\n  public boolean removeShardById(final int shardId) {\n    if (shardMap.containsKey(shardId)) {\n      shardMap.remove(shardId);\n      return true;\n    } else {\n      return false;\n    }\n  }\n\n  /**\n   * Get shard instance by provided shardId.\n   *\n   * @param shardId id of shard instance to get\n   * @return required shard instance\n   */\n  public Shard getShardById(final int shardId) {\n    return shardMap.get(shardId);\n  }\n\n  /**\n   * Store data in proper shard instance.\n   *\n   * @param data new data\n   * @return id of shard that the data is stored in\n   */\n  public abstract int storeData(final Data data);\n\n  /**\n   * Allocate proper shard to provided data.\n   *\n   * @param data new data\n   * @return id of shard that the data should be stored\n   */\n  protected abstract int allocateShard(final Data data);\n}\n"
  },
  {
    "path": "sharding/src/test/java/com/iluwatar/sharding/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for App class. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "sharding/src/test/java/com/iluwatar/sharding/HashShardManagerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for HashShardManager class. */\nclass HashShardManagerTest {\n\n  private HashShardManager hashShardManager;\n\n  /** Initialize hashShardManager instance. */\n  @BeforeEach\n  void setup() {\n    hashShardManager = new HashShardManager();\n    var shard1 = new Shard(1);\n    var shard2 = new Shard(2);\n    var shard3 = new Shard(3);\n    hashShardManager.addNewShard(shard1);\n    hashShardManager.addNewShard(shard2);\n    hashShardManager.addNewShard(shard3);\n  }\n\n  @Test\n  void testStoreData() {\n    var data = new Data(1, \"test\", Data.DataType.TYPE_1);\n    hashShardManager.storeData(data);\n    assertEquals(data, hashShardManager.getShardById(1).getDataById(1));\n  }\n}\n"
  },
  {
    "path": "sharding/src/test/java/com/iluwatar/sharding/LookupShardManagerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nimport java.util.Map;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for LookupShardManager class. */\nclass LookupShardManagerTest {\n\n  private LookupShardManager lookupShardManager;\n\n  /** Initialize lookupShardManager instance. */\n  @BeforeEach\n  void setup() {\n    lookupShardManager = new LookupShardManager();\n    var shard1 = new Shard(1);\n    var shard2 = new Shard(2);\n    var shard3 = new Shard(3);\n    lookupShardManager.addNewShard(shard1);\n    lookupShardManager.addNewShard(shard2);\n    lookupShardManager.addNewShard(shard3);\n  }\n\n  @Test\n  void testStoreData() {\n    try {\n      var data = new Data(1, \"test\", Data.DataType.TYPE_1);\n      lookupShardManager.storeData(data);\n      var field = LookupShardManager.class.getDeclaredField(\"lookupMap\");\n      field.setAccessible(true);\n      var lookupMap = (Map<Integer, Integer>) field.get(lookupShardManager);\n      var shardId = lookupMap.get(1);\n      var shard = lookupShardManager.getShardById(shardId);\n      assertEquals(data, shard.getDataById(1));\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Fail to modify field access.\");\n    }\n  }\n}\n"
  },
  {
    "path": "sharding/src/test/java/com/iluwatar/sharding/RangeShardManagerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for RangeShardManager class. */\nclass RangeShardManagerTest {\n\n  private RangeShardManager rangeShardManager;\n\n  /** Initialize rangeShardManager instance. */\n  @BeforeEach\n  void setup() {\n    rangeShardManager = new RangeShardManager();\n    var shard1 = new Shard(1);\n    var shard2 = new Shard(2);\n    var shard3 = new Shard(3);\n    rangeShardManager.addNewShard(shard1);\n    rangeShardManager.addNewShard(shard2);\n    rangeShardManager.addNewShard(shard3);\n  }\n\n  @Test\n  void testStoreData() {\n    var data = new Data(1, \"test\", Data.DataType.TYPE_1);\n    rangeShardManager.storeData(data);\n    assertEquals(data, rangeShardManager.getShardById(1).getDataById(1));\n  }\n}\n"
  },
  {
    "path": "sharding/src/test/java/com/iluwatar/sharding/ShardManagerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nimport java.util.Map;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for ShardManager class. */\nclass ShardManagerTest {\n\n  private ShardManager shardManager;\n\n  /** Initialize shardManager instance. */\n  @BeforeEach\n  void setup() {\n    shardManager = new TestShardManager();\n  }\n\n  @Test\n  void testAddNewShard() {\n    try {\n      var shard = new Shard(1);\n      shardManager.addNewShard(shard);\n      var field = ShardManager.class.getDeclaredField(\"shardMap\");\n      field.setAccessible(true);\n      var map = (Map<Integer, Shard>) field.get(shardManager);\n      assertEquals(1, map.size());\n      assertEquals(shard, map.get(1));\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Fail to modify field access.\");\n    }\n  }\n\n  @Test\n  void testRemoveShardById() {\n    try {\n      var shard = new Shard(1);\n      shardManager.addNewShard(shard);\n      boolean flag = shardManager.removeShardById(1);\n      var field = ShardManager.class.getDeclaredField(\"shardMap\");\n      field.setAccessible(true);\n      var map = (Map<Integer, Shard>) field.get(shardManager);\n      assertTrue(flag);\n      assertEquals(0, map.size());\n    } catch (IllegalAccessException | NoSuchFieldException e) {\n      fail(\"Fail to modify field access.\");\n    }\n  }\n\n  @Test\n  void testGetShardById() {\n    var shard = new Shard(1);\n    shardManager.addNewShard(shard);\n    var tmpShard = shardManager.getShardById(1);\n    assertEquals(shard, tmpShard);\n  }\n\n  static class TestShardManager extends ShardManager {\n\n    @Override\n    public int storeData(Data data) {\n      return 0;\n    }\n\n    @Override\n    protected int allocateShard(Data data) {\n      return 0;\n    }\n  }\n}\n"
  },
  {
    "path": "sharding/src/test/java/com/iluwatar/sharding/ShardTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.sharding;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Unit tests for Shard class. */\nclass ShardTest {\n\n  private Data data;\n\n  private Shard shard;\n\n  @BeforeEach\n  void setup() {\n    data = new Data(1, \"test\", Data.DataType.TYPE_1);\n    shard = new Shard(1);\n  }\n\n  @Test\n  void testStoreData() {\n    try {\n      shard.storeData(data);\n      var field = Shard.class.getDeclaredField(\"dataStore\");\n      field.setAccessible(true);\n      var dataMap = (Map<Integer, Data>) field.get(shard);\n      assertEquals(1, dataMap.size());\n      assertEquals(data, dataMap.get(1));\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Fail to modify field access.\");\n    }\n  }\n\n  @Test\n  void testClearData() {\n    try {\n      var dataMap = new HashMap<Integer, Data>();\n      dataMap.put(1, data);\n      var field = Shard.class.getDeclaredField(\"dataStore\");\n      field.setAccessible(true);\n      field.set(shard, dataMap);\n      shard.clearData();\n      dataMap = (HashMap<Integer, Data>) field.get(shard);\n      assertEquals(0, dataMap.size());\n    } catch (NoSuchFieldException | IllegalAccessException e) {\n      fail(\"Fail to modify field access.\");\n    }\n  }\n}\n"
  },
  {
    "path": "single-table-inheritance/README.md",
    "content": "---\ntitle: \"Single Table Inheritance Pattern in Java: Streamlining Object Mapping with Unified Table Structures\"\nshortTitle: Single Table Inheritance\ndescription: \"Discover how the Single Table Inheritance pattern simplifies database schema in Java applications. Learn its use, benefits, and implementation in our comprehensive guide.\"\ncategory: Data access\nlanguage: en\ntag:\n  - Data access\n  - Encapsulation\n  - Persistence\n  - Polymorphism\n---\n\n## Also known as\n\n* Class Table Inheritance\n* STI\n\n## Intent of Single Table Inheritance Design Pattern\n\nSingle Table Inheritance pattern simplifies database schema in Java applications.\n\nStreamline the storage of an inheritance hierarchy in a single database table, where rows represent objects of different classes and columns represent the union of all attributes.\n\n## Detailed Explanation of Single Table Inheritance Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a library system where books, magazines, and DVDs are all stored in a single inventory table. This table includes columns for attributes common to all items, such as `Title`, `Author`, `PublicationDate`, and `ItemType`, as well as columns specific to certain types, like `ISBN` for books, `IssueNumber` for magazines, and `Duration` for DVDs. Each row represents an item in the library, with some columns left null depending on the item type. This setup simplifies the database schema by keeping all inventory items in one table, akin to Single Table Inheritance in a database context.\n\nIn plain words\n\n> Single Table Inheritance stores an entire class hierarchy in a single database table, using a type discriminator column to distinguish between different subclasses.\n\nWikipedia says\n\n> Single table inheritance is a way to emulate object-oriented inheritance in a relational database. When mapping from a database table to an object in an object-oriented language, a field in the database identifies what class in the hierarchy the object belongs to. All fields of all the classes are stored in the same table, hence the name \"Single Table Inheritance\".\n\nFlowchart\n\n![Single Table Inheritance flowchart](./etc/single-table-inheritance-flowchart.png)\n\n## Programmatic Example of Single Table Inheritance Pattern in Java\n\nSingle Table Inheritance is a design pattern that maps an inheritance hierarchy of classes to a single database table. Each row in the table represents an instance of a class in the hierarchy. A special discriminator column is used to identify the class to which each row belongs.\n\nThis pattern is useful when classes in an inheritance hierarchy are not significantly different in terms of fields and behavior. It simplifies the database schema and can improve performance by avoiding joins.\n\nLet's see how this pattern is implemented in the provided code.\n\nThe base class in our hierarchy is `Vehicle`. This class has common properties that all vehicles share, such as `manufacturer` and `model`.\n\n```java\npublic abstract class Vehicle {\n  private String manufacturer;\n  private String model;\n  // other common properties...\n}\n```\n\nWe have two subclasses, `PassengerVehicle` and `TransportVehicle`, which extend `Vehicle` and add additional properties.\n\n```java\npublic abstract class PassengerVehicle extends Vehicle {\n  private int noOfPassengers;\n  // other properties specific to passenger vehicles...\n}\n\npublic abstract class TransportVehicle extends Vehicle {\n  private int loadCapacity;\n  // other properties specific to transport vehicles...\n}\n```\n\nFinally, we have concrete classes like `Car` and `Truck` that extend `PassengerVehicle` and `TransportVehicle` respectively.\n\n```java\npublic class Car extends PassengerVehicle {\n  private int trunkCapacity;\n  // other properties specific to cars...\n}\n\npublic class Truck extends TransportVehicle {\n  private int towingCapacity;\n  // other properties specific to trucks...\n}\n```\n\nIn this example, we're using Hibernate as our ORM. We map our class hierarchy to a single table using the `@Entity` and `@Inheritance` annotations.\n\n```java\n@Entity\n@Inheritance(strategy = InheritanceType.SINGLE_TABLE)\npublic abstract class Vehicle {\n  // properties...\n}\n```\n\nThe `@DiscriminatorColumn` annotation is used to specify the discriminator column in the table. This column will hold the class name for each row.\n\n```java\n@DiscriminatorColumn(name = \"vehicle_type\")\npublic abstract class Vehicle {\n  // properties...\n}\n```\n\nEach subclass specifies its discriminator value using the `@DiscriminatorValue` annotation.\n\n```java\n@DiscriminatorValue(\"CAR\")\npublic class Car extends PassengerVehicle {\n  // properties...\n}\n\n@DiscriminatorValue(\"TRUCK\")\npublic class Truck extends TransportVehicle {\n  // properties...\n}\n```\n\nThe `VehicleService` class provides methods for saving and retrieving vehicles. When we save a `Car` or `Truck` object, Hibernate will automatically set the discriminator column to the appropriate value. When we retrieve a vehicle, Hibernate will use the discriminator column to instantiate the correct class.\n\n```java\npublic class VehicleService {\n  public Vehicle saveVehicle(Vehicle vehicle) {\n    // save vehicle to database...\n  }\n\n  public Vehicle getVehicle(Long id) {\n    // retrieve vehicle from database...\n  }\n\n  public List<Vehicle> getAllVehicles() {\n    // retrieve all vehicles from database...\n  }\n}\n```\n\nFinally, here is the Spring Boot application that runs our example.\n\n```java\n@SpringBootApplication\n@AllArgsConstructor\npublic class SingleTableInheritance implements CommandLineRunner {\n\n  //Autowiring the VehicleService class to execute the business logic methods\n  private final VehicleService vehicleService;\n\n  public static void main(String[] args) {\n    SpringApplication.run(SingleTableInheritance.class, args);\n  }\n\n  @Override\n  public void run(String... args) {\n\n    Logger log = LoggerFactory.getLogger(SingleTableInheritance.class);\n\n    log.info(\"Saving Vehicles :- \");\n\n    // Saving Car to DB as a Vehicle\n    Vehicle vehicle1 = new Car(\"Tesla\", \"Model S\", 4, 825);\n    Vehicle car1 = vehicleService.saveVehicle(vehicle1);\n    log.info(\"Vehicle 1 saved : {}\", car1);\n\n    // Saving Truck to DB as a Vehicle\n    Vehicle vehicle2 = new Truck(\"Ford\", \"F-150\", 3325, 14000);\n    Vehicle truck1 = vehicleService.saveVehicle(vehicle2);\n    log.info(\"Vehicle 2 saved : {}\\n\", truck1);\n\n\n    log.info(\"Fetching Vehicles :- \");\n\n    // Fetching the Car from DB\n    Car savedCar1 = (Car) vehicleService.getVehicle(vehicle1.getVehicleId());\n    log.info(\"Fetching Car1 from DB : {}\", savedCar1);\n\n    // Fetching the Truck from DB\n    Truck savedTruck1 = (Truck) vehicleService.getVehicle(vehicle2.getVehicleId());\n    log.info(\"Fetching Truck1 from DB : {}\\n\", savedTruck1);\n\n    log.info(\"Fetching All Vehicles :- \");\n\n    // Fetching the Vehicles present in the DB\n    List<Vehicle> allVehiclesFromDb = vehicleService.getAllVehicles();\n    allVehiclesFromDb.forEach(s -> log.info(s.toString()));\n  }\n}\n```\n\nConsole output:\n\n```\n2024-05-27T12:29:49.949+03:00  INFO 56372 --- [           main] com.iluwatar.SingleTableInheritance      : Starting SingleTableInheritance using Java 17.0.4.1 with PID 56372 (/Users/ilkka.seppala/git/java-design-patterns/single-table-inheritance/target/classes started by ilkka.seppala in /Users/ilkka.seppala/git/java-design-patterns)\n2024-05-27T12:29:49.951+03:00  INFO 56372 --- [           main] com.iluwatar.SingleTableInheritance      : No active profile set, falling back to 1 default profile: \"default\"\n2024-05-27T12:29:50.154+03:00  INFO 56372 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.\n2024-05-27T12:29:50.176+03:00  INFO 56372 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 19 ms. Found 1 JPA repository interface.\n2024-05-27T12:29:50.315+03:00  INFO 56372 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]\n2024-05-27T12:29:50.345+03:00  INFO 56372 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 6.4.4.Final\n2024-05-27T12:29:50.360+03:00  INFO 56372 --- [           main] o.h.c.internal.RegionFactoryInitiator    : HHH000026: Second-level cache disabled\n2024-05-27T12:29:50.457+03:00  INFO 56372 --- [           main] o.s.o.j.p.SpringPersistenceUnitInfo      : No LoadTimeWeaver setup: ignoring JPA class transformer\n2024-05-27T12:29:50.468+03:00  INFO 56372 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...\n2024-05-27T12:29:50.541+03:00  INFO 56372 --- [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:sti user=SA\n2024-05-27T12:29:50.542+03:00  INFO 56372 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.\n2024-05-27T12:29:50.930+03:00  INFO 56372 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)\n2024-05-27T12:29:50.953+03:00  INFO 56372 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'\n2024-05-27T12:29:51.094+03:00  INFO 56372 --- [           main] com.iluwatar.SingleTableInheritance      : Started SingleTableInheritance in 1.435 seconds (process running for 1.678)\n2024-05-27T12:29:51.095+03:00  INFO 56372 --- [           main] com.iluwatar.SingleTableInheritance      : Saving Vehicles :- \n2024-05-27T12:29:51.114+03:00  INFO 56372 --- [           main] com.iluwatar.SingleTableInheritance      : Vehicle 1 saved : Car{PassengerVehicle(noOfPassengers=4)}\n2024-05-27T12:29:51.115+03:00  INFO 56372 --- [           main] com.iluwatar.SingleTableInheritance      : Vehicle 2 saved : Truck{ TransportVehicle(loadCapacity=3325), towingCapacity=14000}\n\n2024-05-27T12:29:51.115+03:00  INFO 56372 --- [           main] com.iluwatar.SingleTableInheritance      : Fetching Vehicles :- \n2024-05-27T12:29:51.129+03:00  INFO 56372 --- [           main] com.iluwatar.SingleTableInheritance      : Fetching Car1 from DB : Car{PassengerVehicle(noOfPassengers=0)}\n2024-05-27T12:29:51.130+03:00  INFO 56372 --- [           main] com.iluwatar.SingleTableInheritance      : Fetching Truck1 from DB : Truck{ TransportVehicle(loadCapacity=0), towingCapacity=14000}\n\n2024-05-27T12:29:51.130+03:00  INFO 56372 --- [           main] com.iluwatar.SingleTableInheritance      : Fetching All Vehicles :- \n2024-05-27T12:29:51.169+03:00  INFO 56372 --- [           main] com.iluwatar.SingleTableInheritance      : Car{PassengerVehicle(noOfPassengers=0)}\n2024-05-27T12:29:51.169+03:00  INFO 56372 --- [           main] com.iluwatar.SingleTableInheritance      : Truck{ TransportVehicle(loadCapacity=0), towingCapacity=14000}\n2024-05-27T12:29:51.172+03:00  INFO 56372 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'\n2024-05-27T12:29:51.173+03:00  INFO 56372 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...\n2024-05-27T12:29:51.174+03:00  INFO 56372 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.\n```\n\nThe Single Table Inheritance pattern is a simple and efficient way to map an inheritance hierarchy to a relational database. However, it can lead to sparse tables if subclasses have many unique fields. In such cases, other patterns like Class Table Inheritance or Concrete Table Inheritance might be more appropriate.\n\n## When to Use the Single Table Inheritance Pattern in Java\n\n* Use when you have a class hierarchy with subclasses that share a common base class and you want to store all instances of the hierarchy in a single table.\n* Ideal for small to medium-sized applications where the simplicity of a single table outweighs the performance cost of null fields for some subclasses.\n\n## Single Table Inheritance Pattern Tutorials\n\n* [Hibernate Tutorial 18 - Implementing Inheritance - Single Table Strategy (Java Brains)](https://www.youtube.com/watch?v=M5YrLtAHtOo)\n\n## Real-World Applications of Single Table Inheritance Pattern in Java\n\n* Hibernate and JPA implementations in Java applications often use Single Table Inheritance for ORM mapping.\n* Rails ActiveRecord supports Single Table Inheritance out of the box.\n\n## Benefits and Trade-offs of Single Table Inheritance Pattern\n\nBenefits:\n\nUsing the Single Table Inheritance pattern in Java ORM\n\n* Simplifies database schema by reducing the number of tables.\n* Easier to manage relationships and queries since all data is in one table.\n\nTrade-offs:\n\n* Can lead to sparsely populated tables with many null values.\n* May cause performance issues for large hierarchies due to table size and the need to filter by type.\n* Changes in the inheritance hierarchy require schema changes.\n\n## Related Java Design Patterns\n\n* Class Table Inheritance: Uses separate tables for each class in the hierarchy, reducing null values but increasing complexity in joins.\n* Concrete Table Inheritance: Each class in the hierarchy has its own table, reducing redundancy but increasing the number of tables.\n\n## References and Credits\n\n* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3wlDrze)\n* [Java Persistence with Hibernate](https://amzn.to/44tP1ox)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Single Table Inheritance (Martin Fowler)](https://www.martinfowler.com/eaaCatalog/singleTableInheritance.html)\n"
  },
  {
    "path": "single-table-inheritance/etc/single-table-inheritance.urm.puml",
    "content": "@startuml\npackage com.iluwatar.repository {\n  interface VehicleRepository {\n  }\n}\npackage com.iluwatar.service {\n  class VehicleService {\n    - vehicleRepository : VehicleRepository\n    + VehicleService(vehicleRepository : VehicleRepository)\n    + deleteVehicle(vehicle : Vehicle)\n    + getAllVehicles() : List<Vehicle>\n    + getVehicle(vehicleId : int) : Vehicle\n    + saveVehicle(vehicle : Vehicle) : Vehicle\n    + updateVehicle(vehicle : Vehicle) : Vehicle\n  }\n}\npackage com.iluwatar.entity {\n  class Car {\n    - engineCapacity : int\n    + Car()\n    + Car(manufacturer : String, model : String, noOfPassengers : int, engineCapacity : int)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getEngineCapacity() : int\n    + hashCode() : int\n    + setEngineCapacity(engineCapacity : int)\n    + toString() : String\n  }\n  class Freighter {\n    - flightLength : double\n    + Freighter()\n    + Freighter(manufacturer : String, model : String, countOfSeats : int, loadCapacity : int, flightLength : double)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getFlightLength() : double\n    + hashCode() : int\n    + setFlightLength(flightLength : double)\n    + toString() : String\n  }\n  abstract class PassengerVehicle {\n    - noOfPassengers : int\n    + PassengerVehicle()\n    + PassengerVehicle(manufacturer : String, model : String, noOfPassengers : int)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getNoOfPassengers() : int\n    + hashCode() : int\n    + setNoOfPassengers(noOfPassengers : int)\n    + toString() : String\n  }\n  class Train {\n    - noOfCarriages : int\n    + Train()\n    + Train(manufacturer : String, model : String, noOfPassengers : int, noOfCarriages : int)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getNoOfCarriages() : int\n    + hashCode() : int\n    + setNoOfCarriages(noOfCarriages : int)\n    + toString() : String\n  }\n  abstract class TransportVehicle {\n    - loadCapacity : int\n    + TransportVehicle()\n    + TransportVehicle(manufacturer : String, model : String, loadCapacity : int)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getLoadCapacity() : int\n    + hashCode() : int\n    + setLoadCapacity(loadCapacity : int)\n    + toString() : String\n  }\n  class Truck {\n    + towingCapacity : int\n    + Truck()\n    + Truck(manufacturer : String, model : String, loadCapacity : int, towingCapacity : int)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getTowingCapacity() : int\n    + hashCode() : int\n    + setTowingCapacity(towingCapacity : int)\n    + toString() : String\n  }\n  abstract class Vehicle {\n    - manufacturer : String\n    - model : String\n    - vehicleId : int\n    + Vehicle()\n    + Vehicle(manufacturer : String, model : String)\n    + Vehicle(vehicleId : int, manufacturer : String, model : String)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getManufacturer() : String\n    + getModel() : String\n    + getVehicleId() : int\n    + hashCode() : int\n    + setManufacturer(manufacturer : String)\n    + setModel(model : String)\n    + setVehicleId(vehicleId : int)\n    + toString() : String\n  }\n}\npackage com.iluwatar.abstractEntity {\n  abstract class PassengerVehicle {\n    - noOfPassengers : int\n    + PassengerVehicle()\n    + PassengerVehicle(manufacturer : String, model : String, noOfPassengers : int)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getNoOfPassengers() : int\n    + hashCode() : int\n    + setNoOfPassengers(noOfPassengers : int)\n    + toString() : String\n  }\n  abstract class TransportVehicle {\n    - loadCapacity : int\n    + TransportVehicle()\n    + TransportVehicle(manufacturer : String, model : String, loadCapacity : int)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getLoadCapacity() : int\n    + hashCode() : int\n    + setLoadCapacity(loadCapacity : int)\n    + toString() : String\n  }\n  abstract class Vehicle {\n    - manufacturer : String\n    - model : String\n    - vehicleId : int\n    + Vehicle()\n    + Vehicle(manufacturer : String, model : String)\n    + Vehicle(vehicleId : int, manufacturer : String, model : String)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getManufacturer() : String\n    + getModel() : String\n    + getVehicleId() : int\n    + hashCode() : int\n    + setManufacturer(manufacturer : String)\n    + setModel(model : String)\n    + setVehicleId(vehicleId : int)\n    + toString() : String\n  }\n}\npackage com.iluwatar {\n  class SingleTableInheritance {\n    - vehicleService : VehicleService\n    + SingleTableInheritance(vehicleService : VehicleService)\n    + main(args : String[]) {static}\n    + run(args : String[])\n  }\n}\nSingleTableInheritance -->  \"-vehicleService\" VehicleService\nVehicleService -->  \"-vehicleRepository\" VehicleRepository\nPassengerVehicle --|> Vehicle \nTransportVehicle --|> Vehicle \nCar --|> PassengerVehicle \nFreighter --|> TransportVehicle \nPassengerVehicle --|> Vehicle \nTrain --|> PassengerVehicle \nTransportVehicle --|> Vehicle \nTruck --|> TransportVehicle \n@enduml"
  },
  {
    "path": "single-table-inheritance/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>single-table-inheritance</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-data-jpa</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>jakarta.xml.bind</groupId>\n            <artifactId>jakarta.xml.bind-api</artifactId>\n            <version>4.0.2</version>\n        </dependency>\n        <dependency>\n            <groupId>com.h2database</groupId>\n            <artifactId>h2</artifactId>\n            <scope>runtime</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n</project>"
  },
  {
    "path": "single-table-inheritance/src/main/java/com/iluwatar/SingleTableInheritance.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar;\n\nimport com.iluwatar.entity.Car;\nimport com.iluwatar.entity.Truck;\nimport com.iluwatar.entity.Vehicle;\nimport com.iluwatar.service.VehicleService;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.boot.CommandLineRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * Single Table Inheritance pattern : <br>\n * It maps each instance of class in an inheritance tree into a single table. <br>\n *\n * <p>In case of current project, in order to specify the Single Table Inheritance to Hibernate we\n * annotate the main Vehicle root class with @Inheritance(strategy = InheritanceType.SINGLE_TABLE)\n * due to which a single root <b>Vehicle</b> class table will be created in the database and it will\n * have columns for all the fields of it's subclasses(Car, Freighter, Train, Truck). <br>\n * Additional to that, a new separate <b>\"vehicle_id\"</b> column would be added to the Vehicle table\n * to save the type of the subclass object that is being stored in the database. This value is\n * specified by the @DiscriminatorValue annotation value for each subclass in case of Hibernate.\n * <br>\n * <br>\n * Below is the main Spring Boot Application class from where the Program Runs.\n *\n * <p>It implements the CommandLineRunner to run the statements at the start of the application\n * program.\n */\n@SpringBootApplication\n@AllArgsConstructor\npublic class SingleTableInheritance implements CommandLineRunner {\n\n  // Autowiring the VehicleService class to execute the business logic methods\n  private final VehicleService vehicleService;\n\n  /**\n   * The entry point of the Spring Boot Application.\n   *\n   * @param args program runtime arguments\n   */\n  public static void main(String[] args) {\n    SpringApplication.run(SingleTableInheritance.class, args);\n  }\n\n  /**\n   * The starting point of the CommandLineRunner where the main program is run.\n   *\n   * @param args program runtime arguments\n   */\n  @Override\n  public void run(String... args) {\n\n    Logger log = LoggerFactory.getLogger(SingleTableInheritance.class);\n\n    log.info(\"Saving Vehicles :- \");\n\n    // Saving Car to DB as a Vehicle\n    Vehicle vehicle1 = new Car(\"Tesla\", \"Model S\", 4, 825);\n    Vehicle car1 = vehicleService.saveVehicle(vehicle1);\n    log.info(\"Vehicle 1 saved : {}\", car1);\n\n    // Saving Truck to DB as a Vehicle\n    Vehicle vehicle2 = new Truck(\"Ford\", \"F-150\", 3325, 14000);\n    Vehicle truck1 = vehicleService.saveVehicle(vehicle2);\n    log.info(\"Vehicle 2 saved : {}\\n\", truck1);\n\n    log.info(\"Fetching Vehicles :- \");\n\n    // Fetching the Car from DB\n    Car savedCar1 = (Car) vehicleService.getVehicle(vehicle1.getVehicleId());\n    log.info(\"Fetching Car1 from DB : {}\", savedCar1);\n\n    // Fetching the Truck from DB\n    Truck savedTruck1 = (Truck) vehicleService.getVehicle(vehicle2.getVehicleId());\n    log.info(\"Fetching Truck1 from DB : {}\\n\", savedTruck1);\n\n    log.info(\"Fetching All Vehicles :- \");\n\n    // Fetching the Vehicles present in the DB\n    List<Vehicle> allVehiclesFromDb = vehicleService.getAllVehicles();\n    allVehiclesFromDb.forEach(s -> log.info(s.toString()));\n  }\n}\n"
  },
  {
    "path": "single-table-inheritance/src/main/java/com/iluwatar/entity/Car.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.entity;\n\nimport jakarta.persistence.DiscriminatorValue;\nimport jakarta.persistence.Entity;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.NoArgsConstructor;\n\n/**\n * A class that extends the PassengerVehicle class and provides the concrete inheritance\n * implementation of the Car.\n *\n * @see PassengerVehicle PassengerVehicle\n * @see Vehicle Vehicle\n */\n@Data\n@NoArgsConstructor\n@EqualsAndHashCode(callSuper = true)\n@Entity\n@DiscriminatorValue(value = \"CAR\")\npublic class Car extends PassengerVehicle {\n\n  private int engineCapacity;\n\n  public Car(String manufacturer, String model, int noOfPassengers, int engineCapacity) {\n    super(manufacturer, model, noOfPassengers);\n    this.engineCapacity = engineCapacity;\n  }\n\n  // Overridden the toString method to specify the Vehicle object\n  @Override\n  public String toString() {\n    return \"Car{\" + super.toString() + '}';\n  }\n}\n"
  },
  {
    "path": "single-table-inheritance/src/main/java/com/iluwatar/entity/Freighter.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.entity;\n\nimport jakarta.persistence.DiscriminatorValue;\nimport jakarta.persistence.Entity;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.NoArgsConstructor;\n\n/**\n * A class that extends the TransportVehicle class and provides the concrete inheritance\n * implementation of the Car.\n *\n * @see TransportVehicle TransportVehicle\n * @see Vehicle Vehicle\n */\n@Data\n@NoArgsConstructor\n@EqualsAndHashCode(callSuper = true)\n@Entity\n@DiscriminatorValue(value = \"FREIGHTER\")\npublic class Freighter extends TransportVehicle {\n\n  private double flightLength;\n\n  public Freighter(String manufacturer, String model, int loadCapacity, double flightLength) {\n    super(manufacturer, model, loadCapacity);\n    this.flightLength = flightLength;\n  }\n\n  // Overridden the toString method to specify the Vehicle object\n  @Override\n  public String toString() {\n    return \"Freighter{ \" + super.toString() + \" ,\" + \"flightLength=\" + flightLength + '}';\n  }\n}\n"
  },
  {
    "path": "single-table-inheritance/src/main/java/com/iluwatar/entity/PassengerVehicle.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.entity;\n\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.NoArgsConstructor;\n\n/**\n * An abstract class that extends the Vehicle class and provides properties for the Passenger type\n * of Vehicles.\n *\n * @see Vehicle\n */\n@Data\n@NoArgsConstructor\n@EqualsAndHashCode(callSuper = true)\npublic abstract class PassengerVehicle extends Vehicle {\n\n  private int noOfPassengers;\n\n  protected PassengerVehicle(String manufacturer, String model, int noOfPassengers) {\n    super(manufacturer, model);\n    this.noOfPassengers = noOfPassengers;\n  }\n}\n"
  },
  {
    "path": "single-table-inheritance/src/main/java/com/iluwatar/entity/Train.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.entity;\n\nimport jakarta.persistence.DiscriminatorValue;\nimport jakarta.persistence.Entity;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.NoArgsConstructor;\n\n/**\n * A class that extends the PassengerVehicle class and provides the concrete inheritance\n * implementation of the Car.\n *\n * @see PassengerVehicle PassengerVehicle\n * @see Vehicle Vehicle\n */\n@Data\n@NoArgsConstructor\n@EqualsAndHashCode(callSuper = true)\n@Entity\n@DiscriminatorValue(value = \"TRAIN\")\npublic class Train extends PassengerVehicle {\n\n  private int noOfCarriages;\n\n  public Train(String manufacturer, String model, int noOfPassengers, int noOfCarriages) {\n    super(manufacturer, model, noOfPassengers);\n    this.noOfCarriages = noOfCarriages;\n  }\n\n  // Overridden the toString method to specify the Vehicle object\n  @Override\n  public String toString() {\n    return \"Train{\" + super.toString() + '}';\n  }\n}\n"
  },
  {
    "path": "single-table-inheritance/src/main/java/com/iluwatar/entity/TransportVehicle.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.entity;\n\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.NoArgsConstructor;\n\n/**\n * An abstract class that extends the Vehicle class and provides properties for the Transport type\n * of Vehicles.\n *\n * @see Vehicle\n */\n@Data\n@NoArgsConstructor\n@EqualsAndHashCode(callSuper = true)\npublic abstract class TransportVehicle extends Vehicle {\n\n  private int loadCapacity;\n\n  protected TransportVehicle(String manufacturer, String model, int loadCapacity) {\n    super(manufacturer, model);\n    this.loadCapacity = loadCapacity;\n  }\n}\n"
  },
  {
    "path": "single-table-inheritance/src/main/java/com/iluwatar/entity/Truck.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.entity;\n\nimport jakarta.persistence.DiscriminatorValue;\nimport jakarta.persistence.Entity;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\n/**\n * A class that extends the PassengerVehicle class and provides the concrete inheritance\n * implementation of the Car.\n *\n * @see TransportVehicle TransportVehicle\n * @see Vehicle Vehicle\n */\n@Data\n@NoArgsConstructor\n@Entity\n@DiscriminatorValue(value = \"TRUCK\")\npublic class Truck extends TransportVehicle {\n\n  private int towingCapacity;\n\n  public Truck(String manufacturer, String model, int loadCapacity, int towingCapacity) {\n    super(manufacturer, model, loadCapacity);\n    this.towingCapacity = towingCapacity;\n  }\n\n  // Overridden the toString method to specify the Vehicle object\n  @Override\n  public String toString() {\n    return \"Truck{ \" + super.toString() + \", \" + \"towingCapacity=\" + towingCapacity + '}';\n  }\n}\n"
  },
  {
    "path": "single-table-inheritance/src/main/java/com/iluwatar/entity/Vehicle.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.entity;\n\nimport jakarta.persistence.DiscriminatorColumn;\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.GenerationType;\nimport jakarta.persistence.Id;\nimport jakarta.persistence.Inheritance;\nimport jakarta.persistence.InheritanceType;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.NoArgsConstructor;\n\n/**\n * An abstract class that is the root of the Vehicle Inheritance hierarchy and basic provides\n * properties for all the vehicles.\n */\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@EqualsAndHashCode\n@Entity\n@Inheritance(strategy = InheritanceType.SINGLE_TABLE)\n@DiscriminatorColumn(name = \"VEHICLE_TYPE\")\npublic abstract class Vehicle {\n\n  @Id\n  @GeneratedValue(strategy = GenerationType.IDENTITY)\n  private int vehicleId;\n\n  private String manufacturer;\n\n  private String model;\n\n  protected Vehicle(String manufacturer, String model) {\n    this.manufacturer = manufacturer;\n    this.model = model;\n  }\n\n  @Override\n  public String toString() {\n    return \"Vehicle{\"\n        + \"vehicleId=\"\n        + vehicleId\n        + \", manufacturer='\"\n        + manufacturer\n        + '\\''\n        + \", model='\"\n        + model\n        + '}';\n  }\n}\n"
  },
  {
    "path": "single-table-inheritance/src/main/java/com/iluwatar/repository/VehicleRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.repository;\n\nimport com.iluwatar.entity.Vehicle;\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.stereotype.Repository;\n\n/**\n * A repository that is extending the JPA Repository to provide the default Spring DATA JPA methods\n * for the Vehicle class.\n */\n@Repository\npublic interface VehicleRepository extends JpaRepository<Vehicle, Integer> {}\n"
  },
  {
    "path": "single-table-inheritance/src/main/java/com/iluwatar/service/VehicleService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.service;\n\nimport com.iluwatar.entity.Vehicle;\nimport com.iluwatar.repository.VehicleRepository;\nimport java.util.List;\nimport lombok.AllArgsConstructor;\nimport org.springframework.stereotype.Service;\n\n/**\n * A service class that is used to provide the business logic for the Vehicle class and connect to\n * the database to perform the CRUD operations on the root Vehicle class.\n *\n * @see Vehicle\n */\n@Service\n@AllArgsConstructor\npublic class VehicleService {\n\n  private final VehicleRepository vehicleRepository;\n\n  /**\n   * A method to save all the vehicles to the database.\n   *\n   * @param vehicle Vehicle bbject\n   * @see Vehicle\n   */\n  public Vehicle saveVehicle(Vehicle vehicle) {\n    return vehicleRepository.save(vehicle);\n  }\n\n  /**\n   * A method to get a specific vehicle from vehicle id.\n   *\n   * @param vehicleId Vehicle Id\n   * @see Vehicle\n   */\n  public Vehicle getVehicle(int vehicleId) {\n    return vehicleRepository.findById(vehicleId).orElse(null);\n  }\n\n  /**\n   * A method to get all the vehicles saved in the database.\n   *\n   * @see Vehicle\n   */\n  public List<Vehicle> getAllVehicles() {\n    return vehicleRepository.findAll();\n  }\n\n  /**\n   * A method to update a vehicle in the database.\n   *\n   * @param vehicle Vehicle object\n   * @see Vehicle\n   */\n  public Vehicle updateVehicle(Vehicle vehicle) {\n    return vehicleRepository.save(vehicle);\n  }\n\n  /**\n   * A method to save all the vehicles to the database.\n   *\n   * @param vehicle Vehicle object\n   * @see Vehicle\n   */\n  public void deleteVehicle(Vehicle vehicle) {\n    vehicleRepository.delete(vehicle);\n  }\n}\n"
  },
  {
    "path": "single-table-inheritance/src/main/resources/application.properties",
    "content": "\n# H2 Database Configuration\nspring.datasource.url=jdbc:h2:mem:sti\nspring.datasource.username=sa\nspring.datasource.password=password\nspring.datasource.driverClassName=org.h2.Driver\nspring.jpa.hibernate.ddl-auto=update\n\n#Uncomment the below properties to see the SQL being generated in backend\n#spring.jpa.show-sql=true\n#spring.jpa.properties.hibernate.format_sql=true"
  },
  {
    "path": "singleton/README.md",
    "content": "---\ntitle: \"Singleton Pattern in Java: Implementing Global Access Points in Java Applications\"\nshortTitle: Singleton\ndescription: \"Explore the Singleton Pattern in Java with our comprehensive guide. Learn how to implement efficient object management for your Java applications, ensuring optimal use of resources and easy access with examples and detailed explanations.\"\ncategory: Creational\nlanguage: en\ntag:\n  - Gang of Four\n  - Instantiation\n  - Lazy initialization\n  - Resource management\n---\n\n## Also known as\n\n* Single Instance\n\n## Intent of Singleton Design Pattern\n\nEnsure a Java class only has one instance, and provide a global point of access to this singleton instance.\n\n## Detailed Explanation of Singleton Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy for the Singleton pattern is a government issuing a passport. In a country, each citizen can only be issued one valid passport at a time. The passport office ensures that no duplicate passports are issued to the same person. Whenever a citizen needs to travel, they must use this single passport, which serves as the unique, globally recognized identifier for their travel credentials. This controlled access and unique instance management mirrors how the Singleton pattern ensures efficient object management in Java applications.\n\nIn plain words\n\n> Ensures that only one object of a particular class is ever created.\n\nWikipedia says\n\n> In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system.\n\nSequence diagram\n\n![Singleton Pattern sequence diagram](./etc/singleton-sequence-diagram.png)\n\n## Programmatic Example of Singleton Pattern in Java\n\nJoshua Bloch, Effective Java 2nd Edition p.18\n\n> A single-element enum type is the best way to implement a singleton\n\n```java\npublic enum EnumIvoryTower {\n  INSTANCE\n}\n```\n\nThen in order to use:\n\n```java\n    var enumIvoryTower1 = EnumIvoryTower.INSTANCE;\n    var enumIvoryTower2 = EnumIvoryTower.INSTANCE;\n    LOGGER.info(\"enumIvoryTower1={}\", enumIvoryTower1);\n    LOGGER.info(\"enumIvoryTower2={}\", enumIvoryTower2);\n```\n\nThe console output\n\n```\nenumIvoryTower1=com.iluwatar.singleton.EnumIvoryTower@1221555852\nenumIvoryTower2=com.iluwatar.singleton.EnumIvoryTower@1221555852\n```\n\n## When to Use the Singleton Pattern in Java\n\nUse the Singleton pattern when\n\n* There must be exactly one instance of a class, and it must be accessible to clients from a well-known access point\n* When the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code\n\n## Real-World Applications of Singleton Pattern in Java\n\n* The logging class\n* Configuration classes in many applications\n* Connection pools\n* File manager\n* [java.lang.Runtime#getRuntime()](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime%28%29)\n* [java.awt.Desktop#getDesktop()](http://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#getDesktop--)\n* [java.lang.System#getSecurityManager()](http://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getSecurityManager--)\n\n## Benefits and Trade-offs of Singleton Pattern\n\nBenefits:\n\n* Controlled access to the single instance.\n* Reduced namespace pollution.\n* Allows refinement of operations and representation.\n* Permits a variable number of instances (more than one, if desired).\n* More flexible than class operations.\n\nTrade-offs:\n\n* Difficult to test due to global state.\n* Potentially more complex lifecycle management.\n* Can introduce bottlenecks if used in a concurrent context without careful synchronization.\n\n## Related Java Design Patterns\n\n* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): Often used to ensure a class only has one instance.\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Singleton pattern can be implemented using a Factory Method to encapsulate the creation logic.\n* [Prototype](https://java-design-patterns.com/patterns/prototype/): Avoids the need to create instances, can work alongside Singleton to manage unique instances.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "singleton/etc/singleton.urm.puml",
    "content": "@startuml\npackage com.iluwatar.singleton {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  enum EnumIvoryTower {\n    + INSTANCE {static}\n    + toString() : String\n    + valueOf(name : String) : EnumIvoryTower {static}\n    + values() : EnumIvoryTower[] {static}\n  }\n  class InitializingOnDemandHolderIdiom {\n    - InitializingOnDemandHolderIdiom()\n    + getInstance() : InitializingOnDemandHolderIdiom {static}\n  }\n  -class HelperHolder {\n    - INSTANCE : InitializingOnDemandHolderIdiom {static}\n    - HelperHolder()\n  }\n  class IvoryTower {\n    - INSTANCE : IvoryTower {static}\n    - IvoryTower()\n    + getInstance() : IvoryTower {static}\n  }\n  class ThreadSafeDoubleCheckLocking {\n    - flag : boolean {static}\n    - instance : ThreadSafeDoubleCheckLocking {static}\n    - ThreadSafeDoubleCheckLocking()\n    + getInstance() : ThreadSafeDoubleCheckLocking {static}\n  }\n  class ThreadSafeLazyLoadedIvoryTower {\n    - instance : ThreadSafeLazyLoadedIvoryTower {static}\n    - ThreadSafeLazyLoadedIvoryTower()\n    + getInstance() : ThreadSafeLazyLoadedIvoryTower {static}\n  }\n}\nIvoryTower -->  \"-INSTANCE\" IvoryTower\nThreadSafeDoubleCheckLocking -->  \"-instance\" ThreadSafeDoubleCheckLocking\nThreadSafeLazyLoadedIvoryTower -->  \"-instance\" ThreadSafeLazyLoadedIvoryTower\nHelperHolder ..+ InitializingOnDemandHolderIdiom\nHelperHolder -->  \"-INSTANCE\" InitializingOnDemandHolderIdiom\n@enduml"
  },
  {
    "path": "singleton/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>singleton</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.singleton.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "singleton/src/main/java/com/iluwatar/singleton/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Singleton pattern ensures that the class can have only one existing instance per Java classloader\n * instance and provides global access to it.\n *\n * <p>One of the risks of this pattern is that bugs resulting from setting a singleton up in a\n * distributed environment can be tricky to debug since it will work fine if you debug with a single\n * classloader. Additionally, these problems can crop up a while after the implementation of a\n * singleton, since they may start synchronous and only become async with time, so it may not be\n * clear why you are seeing certain changes in behavior.\n *\n * <p>There are many ways to implement the Singleton. The first one is the eagerly initialized\n * instance in {@link IvoryTower}. Eager initialization implies that the implementation is thread\n * safe. If you can afford to give up control of the instantiation moment, then this implementation\n * will suit you fine.\n *\n * <p>The other option to implement eagerly initialized Singleton is enum-based Singleton. The\n * example is found in {@link EnumIvoryTower}. At first glance, the code looks short and simple.\n * However, you should be aware of the downsides including committing to implementation strategy,\n * extending the enum class, serializability, and restrictions to coding. These are extensively\n * discussed in Stack Overflow:\n * http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing\n * -a-singleton-with-javas-enum\n *\n * <p>{@link ThreadSafeLazyLoadedIvoryTower} is a Singleton implementation that is initialized on\n * demand. The downside is that it is very slow to access since the whole access method is\n * synchronized.\n *\n * <p>Another Singleton implementation that is initialized on demand is found in {@link\n * ThreadSafeDoubleCheckLocking}. It is somewhat faster than {@link ThreadSafeLazyLoadedIvoryTower}\n * since it doesn't synchronize the whole access method but only the method internals on specific\n * conditions.\n *\n * <p>Yet another way to implement thread-safe lazily initialized Singleton can be found in {@link\n * InitializingOnDemandHolderIdiom}. However, this implementation requires at least Java 8 API level\n * to work.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    // eagerly initialized singleton\n    var ivoryTower1 = IvoryTower.getInstance();\n    var ivoryTower2 = IvoryTower.getInstance();\n    LOGGER.info(\"ivoryTower1={}\", ivoryTower1);\n    LOGGER.info(\"ivoryTower2={}\", ivoryTower2);\n\n    // lazily initialized singleton\n    var threadSafeIvoryTower1 = ThreadSafeLazyLoadedIvoryTower.getInstance();\n    var threadSafeIvoryTower2 = ThreadSafeLazyLoadedIvoryTower.getInstance();\n    LOGGER.info(\"threadSafeIvoryTower1={}\", threadSafeIvoryTower1);\n    LOGGER.info(\"threadSafeIvoryTower2={}\", threadSafeIvoryTower2);\n\n    // enum singleton\n    var enumIvoryTower1 = EnumIvoryTower.INSTANCE;\n    var enumIvoryTower2 = EnumIvoryTower.INSTANCE;\n    LOGGER.info(\"enumIvoryTower1={}\", enumIvoryTower1);\n    LOGGER.info(\"enumIvoryTower2={}\", enumIvoryTower2);\n\n    // double-checked locking\n    var dcl1 = ThreadSafeDoubleCheckLocking.getInstance();\n    LOGGER.info(dcl1.toString());\n    var dcl2 = ThreadSafeDoubleCheckLocking.getInstance();\n    LOGGER.info(dcl2.toString());\n\n    // initialize on demand holder idiom\n    var demandHolderIdiom = InitializingOnDemandHolderIdiom.getInstance();\n    LOGGER.info(demandHolderIdiom.toString());\n    var demandHolderIdiom2 = InitializingOnDemandHolderIdiom.getInstance();\n    LOGGER.info(demandHolderIdiom2.toString());\n\n    // initialize singleton using Bill Pugh's implementation\n    var billPughSingleton = BillPughImplementation.getInstance();\n    LOGGER.info(billPughSingleton.toString());\n    var billPughSingleton2 = BillPughImplementation.getInstance();\n    LOGGER.info(billPughSingleton2.toString());\n  }\n}\n"
  },
  {
    "path": "singleton/src/main/java/com/iluwatar/singleton/BillPughImplementation.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\n/**\n * Bill Pugh Singleton Implementation.\n *\n * <p>This implementation of the singleton design pattern takes advantage of the Java memory model's\n * guarantees about class initialization. Each class is initialized only once, when it is first\n * used. If the class hasn't been used yet, it won't be loaded into memory, and no memory will be\n * allocated for a static instance. This makes the singleton instance lazy-loaded and thread-safe.\n */\npublic final class BillPughImplementation {\n\n  /** Private constructor to prevent instantiation from outside the class. */\n  private BillPughImplementation() {\n    // to prevent instantiating by Reflection call\n    if (InstanceHolder.instance != null) {\n      throw new IllegalStateException(\"Already initialized.\");\n    }\n  }\n\n  /**\n   * The InstanceHolder is a static inner class, and it holds the Singleton instance. It is not\n   * loaded into memory until the getInstance() method is called.\n   */\n  private static class InstanceHolder {\n    /** Singleton instance of the class. */\n    private static BillPughImplementation instance = new BillPughImplementation();\n  }\n\n  /**\n   * Public accessor for the singleton instance.\n   *\n   * <p>When this method is called, the InstanceHolder is loaded into memory and creates the\n   * Singleton instance. This method provides a global access point for the singleton instance.\n   *\n   * @return an instance of the class.\n   */\n  // global access point\n  public static BillPughImplementation getInstance() {\n    return InstanceHolder.instance;\n  }\n}\n"
  },
  {
    "path": "singleton/src/main/java/com/iluwatar/singleton/EnumIvoryTower.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\n/**\n * Enum based singleton implementation. Effective Java 2nd Edition (Joshua Bloch) p. 18\n *\n * <p>This implementation is thread safe, however adding any other method and its thread safety is\n * developers responsibility.\n */\npublic enum EnumIvoryTower {\n\n  /** The singleton instance of the class, created by the Java enum singleton pattern. */\n  INSTANCE;\n\n  @Override\n  public String toString() {\n    return getDeclaringClass().getCanonicalName() + \"@\" + hashCode();\n  }\n}\n"
  },
  {
    "path": "singleton/src/main/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiom.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\n/**\n * The Initialize-on-demand-holder idiom is a secure way of creating a lazy initialized singleton\n * object in Java.\n *\n * <p>The technique is as lazy as possible and works in all known versions of Java. It takes\n * advantage of language guarantees about class initialization, and will therefore work correctly in\n * all Java-compliant compilers and virtual machines.\n *\n * <p>The inner class is referenced no earlier (and therefore loaded no earlier by the class loader)\n * than the moment that getInstance() is called. Thus, this solution is thread-safe without\n * requiring special language constructs (i.e. volatile or synchronized).\n */\npublic final class InitializingOnDemandHolderIdiom {\n\n  /** Private constructor. */\n  private InitializingOnDemandHolderIdiom() {\n    // to prevent instantiating by Reflection call\n    if (HelperHolder.INSTANCE != null) {\n      throw new IllegalStateException(\"Already initialized.\");\n    }\n  }\n\n  /**\n   * Singleton instance.\n   *\n   * @return Singleton instance\n   */\n  public static InitializingOnDemandHolderIdiom getInstance() {\n    return HelperHolder.INSTANCE;\n  }\n\n  /** Provides the lazy-loaded Singleton instance. */\n  private static class HelperHolder {\n\n    /** Singleton instance of the class. */\n    private static final InitializingOnDemandHolderIdiom INSTANCE =\n        new InitializingOnDemandHolderIdiom();\n  }\n}\n"
  },
  {
    "path": "singleton/src/main/java/com/iluwatar/singleton/IvoryTower.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\n/** Singleton class. Eagerly initialized static instance guarantees thread safety. */\npublic final class IvoryTower {\n\n  /** Private constructor so nobody can instantiate the class. */\n  private IvoryTower() {\n    // to prevent instantiating by Reflection call\n    if (INSTANCE != null) {\n      throw new IllegalStateException(\"Already initialized.\");\n    }\n  }\n\n  /** Static to class instance of the class. */\n  private static final IvoryTower INSTANCE = new IvoryTower();\n\n  /**\n   * To be called by user to obtain instance of the class.\n   *\n   * @return instance of the singleton.\n   */\n  public static IvoryTower getInstance() {\n    return INSTANCE;\n  }\n}\n"
  },
  {
    "path": "singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\n/**\n * Double check locking.\n *\n * <p>http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html\n *\n * <p>Broken under Java 1.4.\n */\npublic final class ThreadSafeDoubleCheckLocking {\n  /**\n   * Singleton instance of the class, declared as volatile to ensure atomic access by multiple\n   * threads.\n   */\n  private static volatile ThreadSafeDoubleCheckLocking instance;\n\n  /** private constructor to prevent client from instantiating. */\n  private ThreadSafeDoubleCheckLocking() {\n    // to prevent instantiating by Reflection call\n    if (instance != null) {\n      throw new IllegalStateException(\"Already initialized.\");\n    }\n  }\n\n  /**\n   * Public accessor.\n   *\n   * @return an instance of the class.\n   */\n  public static ThreadSafeDoubleCheckLocking getInstance() {\n    // local variable increases performance by 25 percent\n    // Joshua Bloch \"Effective Java, Second Edition\", p. 283-284\n\n    var result = instance;\n    // Check if singleton instance is initialized.\n    // If it is initialized then we can return the instance.\n    if (result == null) {\n      // It is not initialized, but we cannot be sure because some other thread might have\n      // initialized it in the meanwhile.\n      // So to make sure we need to lock on an object to get mutual exclusion.\n      synchronized (ThreadSafeDoubleCheckLocking.class) {\n        // Again assign the instance to local variable to check if it was initialized by some\n        // other thread while current thread was blocked to enter the locked zone.\n        // If it was initialized then we can return the previously created instance\n        // just like the previous null check.\n        result = instance;\n        if (result == null) {\n          // The instance is still not initialized, so we can safely\n          // (no other thread can enter this zone)\n          // create an instance and make it our singleton instance.\n          result = new ThreadSafeDoubleCheckLocking();\n          instance = result;\n        }\n      }\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\n/**\n * Thread-safe Singleton class. The instance is lazily initialized and thus needs synchronization\n * mechanism.\n */\npublic final class ThreadSafeLazyLoadedIvoryTower {\n\n  /**\n   * Singleton instance of the class, declared as volatile to ensure atomic access by multiple\n   * threads.\n   */\n  private static volatile ThreadSafeLazyLoadedIvoryTower instance;\n\n  /** Private constructor to prevent instantiation from outside the class. */\n  private ThreadSafeLazyLoadedIvoryTower() {\n    // Protect against instantiation via reflection\n    if (instance != null) {\n      throw new IllegalStateException(\"Already initialized.\");\n    }\n  }\n\n  /**\n   * The instance doesn't get created until the method is called for the first time.\n   *\n   * @return an instance of the class.\n   */\n  public static synchronized ThreadSafeLazyLoadedIvoryTower getInstance() {\n    if (instance == null) {\n      instance = new ThreadSafeLazyLoadedIvoryTower();\n    }\n    return instance;\n  }\n}\n"
  },
  {
    "path": "singleton/src/main/java/com/iluwatar/singleton/package-info.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n"
  },
  {
    "path": "singleton/src/test/java/com/iluwatar/singleton/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "singleton/src/test/java/com/iluwatar/singleton/BillPughImplementationTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\n/** BillPughImplementationTest */\npublic class BillPughImplementationTest extends SingletonTest<BillPughImplementation> {\n  /** Create a new singleton test instance using the given 'getInstance' method. */\n  public BillPughImplementationTest() {\n    super(BillPughImplementation::getInstance);\n  }\n}\n"
  },
  {
    "path": "singleton/src/test/java/com/iluwatar/singleton/EnumIvoryTowerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nimport org.junit.jupiter.api.Test;\n\n/** EnumIvoryTowerTest */\nclass EnumIvoryTowerTest extends SingletonTest<EnumIvoryTower> {\n\n  /** Create a new singleton test instance using the given 'getInstance' method. */\n  public EnumIvoryTowerTest() {\n    super(() -> EnumIvoryTower.INSTANCE);\n  }\n\n  /** Test creating new instance by reflection. */\n  @Override\n  @Test\n  void testCreatingNewInstanceByReflection() throws Exception {\n    // Java does not allow Enum instantiation\n    // http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9\n    assertThrows(ReflectiveOperationException.class, EnumIvoryTower.class::getDeclaredConstructor);\n  }\n}\n"
  },
  {
    "path": "singleton/src/test/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiomTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\n/** InitializingOnDemandHolderIdiomTest */\nclass InitializingOnDemandHolderIdiomTest extends SingletonTest<InitializingOnDemandHolderIdiom> {\n\n  /** Create a new singleton test instance using the given 'getInstance' method. */\n  public InitializingOnDemandHolderIdiomTest() {\n    super(InitializingOnDemandHolderIdiom::getInstance);\n  }\n}\n"
  },
  {
    "path": "singleton/src/test/java/com/iluwatar/singleton/IvoryTowerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\n/** IvoryTowerTest */\nclass IvoryTowerTest extends SingletonTest<IvoryTower> {\n\n  /** Create a new singleton test instance using the given 'getInstance' method. */\n  public IvoryTowerTest() {\n    super(IvoryTower::getInstance);\n  }\n}\n"
  },
  {
    "path": "singleton/src/test/java/com/iluwatar/singleton/SingletonTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\nimport static java.time.Duration.ofMillis;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertSame;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTimeout;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.ArrayList;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.Executors;\nimport java.util.function.Supplier;\nimport java.util.stream.Collectors;\nimport java.util.stream.IntStream;\nimport org.junit.jupiter.api.Test;\n\n/**\n * This class provides several test case that test singleton construction.\n *\n * <p>The first proves that multiple calls to the singleton getInstance object are the same when\n * called in the SAME thread. The second proves that multiple calls to the singleton getInstance\n * object are the same when called in the DIFFERENT thread.\n *\n * @param <S> Supplier method generating singletons\n */\nabstract class SingletonTest<S> {\n\n  /** The singleton's getInstance method. */\n  private final Supplier<S> singletonInstanceMethod;\n\n  /**\n   * Create a new singleton test instance using the given 'getInstance' method.\n   *\n   * @param singletonInstanceMethod The singleton's getInstance method\n   */\n  public SingletonTest(final Supplier<S> singletonInstanceMethod) {\n    this.singletonInstanceMethod = singletonInstanceMethod;\n  }\n\n  /** Test the singleton in a non-concurrent setting. */\n  @Test\n  void testMultipleCallsReturnTheSameObjectInSameThread() {\n    // Create several instances in the same calling thread\n    var instance1 = this.singletonInstanceMethod.get();\n    var instance2 = this.singletonInstanceMethod.get();\n    var instance3 = this.singletonInstanceMethod.get();\n    // now check they are equal\n    assertSame(instance1, instance2);\n    assertSame(instance1, instance3);\n    assertSame(instance2, instance3);\n  }\n\n  /** Test singleton instance in a concurrent setting. */\n  @Test\n  void testMultipleCallsReturnTheSameObjectInDifferentThreads() {\n    assertTimeout(\n        ofMillis(10000),\n        () -> {\n          // Create 10000 tasks and inside each callable instantiate the singleton class\n          final var tasks =\n              IntStream.range(0, 10000)\n                  .<Callable<S>>mapToObj(i -> this.singletonInstanceMethod::get)\n                  .collect(Collectors.toCollection(ArrayList::new));\n\n          // Use up to 8 concurrent threads to handle the tasks\n          final var executorService = Executors.newFixedThreadPool(8);\n          final var results = executorService.invokeAll(tasks);\n\n          // wait for all the threads to complete\n          final var expectedInstance = this.singletonInstanceMethod.get();\n          for (var res : results) {\n            final var instance = res.get();\n            assertNotNull(instance);\n            assertSame(expectedInstance, instance);\n          }\n\n          // tidy up the executor\n          executorService.shutdown();\n        });\n  }\n\n  /** Test creating new instance by reflection. */\n  @Test\n  void testCreatingNewInstanceByReflection() throws Exception {\n    var firstTimeInstantiated = this.singletonInstanceMethod.get();\n    var constructor = firstTimeInstantiated.getClass().getDeclaredConstructor();\n    constructor.setAccessible(true);\n    assertThrows(InvocationTargetException.class, () -> constructor.newInstance((Object[]) null));\n  }\n}\n"
  },
  {
    "path": "singleton/src/test/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLockingTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\n/** ThreadSafeDoubleCheckLockingTest */\nclass ThreadSafeDoubleCheckLockingTest extends SingletonTest<ThreadSafeDoubleCheckLocking> {\n\n  /** Create a new singleton test instance using the given 'getInstance' method. */\n  public ThreadSafeDoubleCheckLockingTest() {\n    super(ThreadSafeDoubleCheckLocking::getInstance);\n  }\n}\n"
  },
  {
    "path": "singleton/src/test/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTowerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.singleton;\n\n/** ThreadSafeLazyLoadedIvoryTowerTest */\nclass ThreadSafeLazyLoadedIvoryTowerTest extends SingletonTest<ThreadSafeLazyLoadedIvoryTower> {\n\n  /** Create a new singleton test instance using the given 'getInstance' method. */\n  public ThreadSafeLazyLoadedIvoryTowerTest() {\n    super(ThreadSafeLazyLoadedIvoryTower::getInstance);\n  }\n}\n"
  },
  {
    "path": "spatial-partition/README.md",
    "content": "---\ntitle: \"Spatial Partition Pattern in Java: Optimizing Spatial Queries for Enhanced Performance\"\nshortTitle: Spatial Partition\ndescription: \"Explore the Spatial Partition design pattern for Java, ideal for optimizing game development and simulations. Learn how it enhances performance by efficiently managing objects in space, with examples and practical applications.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Game programming\n  - Optimization\n  - Performance\n  - Resource management\n  - Scalability\n---\n\n## Also known as\n\n* Space Partitioning\n* Spatial Indexing\n\n## Intent of Spatial Partition Design Pattern\n\nEfficiently organize a large number of objects in space to optimize queries and operations.\n\n## Detailed Explanation of Spatial Partition Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine managing a large warehouse where items are constantly being moved, added, or retrieved. To optimize the search for specific items and manage space efficiently, the warehouse is divided into different sections or zones. Each zone contains shelves, and each shelf holds a specific category of items.\n>\n> This setup is analogous to the Spatial Partition design pattern in software, where a large space (the warehouse) is divided into manageable parts (zones) to optimize operations like searching for an item or checking inventory (spatial queries). By organizing the warehouse this way, it becomes easier to locate and manage items, much like how spatial partitioning helps in efficiently managing and querying objects in a large spatial environment.\n\nIn plain words\n\n> The Spatial Partition design pattern organizes objects in a defined space to optimize spatial queries and operations.\n\nWikipedia says\n\n> The Spatial Partition design pattern, also known as Space Partitioning, involves dividing a space into non-overlapping regions to manage and query spatial data efficiently. This method is widely used in computer graphics, particularly for optimizing tasks like collision detection, ray tracing, and rendering large scenes with numerous objects. Organizing objects into hierarchical structures like BSP trees, Quadtrees, or Octrees under the Spatial Partition pattern allows for more efficient spatial queries, a significant advantage in Java applications for complex graphic rendering and collision detection.\n>\n> For example, in ray tracing, space partitioning helps quickly determine the objects a ray might intersect by narrowing down the search space, leading to faster rendering times. Similarly, in game development, Quadtrees can efficiently manage 2D game environments by segmenting the space into smaller regions, facilitating quicker collision detection and rendering.\n\nFlowchart\n\n![Spatial Partition flowchart](./etc/spatial-partition-flowchart.png)\n\n## Programmatic Example of Spatial Partition Pattern in Java\n\nThe Spatial Partition design pattern in Java is a strategic approach for handling multiple objects in expansive game worlds or detailed simulation environments, boosting query efficiency and operational speed. It allows us to efficiently manage these objects and perform operations like collision detection or range queries. The pattern works by dividing the space into smaller, manageable regions, and each object is associated with the region it belongs to. This way, we can limit our operations to a specific region, instead of checking every object against every other object.\n\nIn the provided code, we have an example of a war game where the positions of players are updated every frame. The simple way to handle interactions on the battlefield is to check each player's position against every other player's position. However, this approach includes a lot of unnecessary checks between players who are too far apart to influence each other. The Spatial Partition pattern can help us optimize this operation.\n\nHere's a simplified version of the code with added comments to explain the Spatial Partition pattern:\n\n```java\n// This is the simple way to handle interactions on the battlefield\n// It includes a lot of unnecessary checks between players who are too far apart to influence each other\npublic void handleMeLee(Unit units[], int numUnits) {\n    for (var a = 0; a < numUnits - 1; a++) {\n        for (var b = a + 1; b < numUnits; b++) {\n            // We check if two units are at the same position\n            if (units[a].position() == units[b].position()) {\n                // If they are, we handle the attack\n                handleAttack(units[a], units[b]);\n            }\n        }\n    }\n}\n```\n\nThe above code has a time complexity of O(n^2), which can be quite inefficient when the number of units is large. The Spatial Partition pattern can help us reduce this complexity.\n\nIn the Spatial Partition pattern, we would divide the battlefield into smaller regions, and each unit would be associated with the region it belongs to. When we need to check for interactions, we would only need to check the units within the same region, significantly reducing the number of checks.\n\nHere's a simplified version of how this might look:\n\n```java\n// We first create a spatial partition (e.g., a grid or a quadtree)\nSpatialPartition partition = new SpatialPartition();\n\n// We then add each unit to the partition\nfor (Unit unit : units) {\n    partition.add(unit);\n}\n\n// When we need to handle interactions, we only check the units within the same region\nfor (Unit unit : units) {\n    List<Unit> nearbyUnits = partition.getUnitsInSameRegion(unit);\n    for (Unit nearbyUnit : nearbyUnits) {\n        if (unit.position() == nearbyUnit.position()) {\n            handleAttack(unit, nearbyUnit);\n        }\n    }\n}\n```\n\nIn this code, `SpatialPartition` is a class that represents the spatial partition. The `add` method is used to add a unit to the partition, and the `getUnitsInSameRegion` method is used to get all units in the same region as a given unit. The exact implementation of these methods would depend on the specific type of spatial partition used (e.g., grid, quadtree, etc.).\n\nThis way, we can reduce the time complexity of finding the units within a certain range from O(n^2) to O(nlogn), decreasing the computations required significantly in case of a large number of units.\n\n## When to Use the Spatial Partition Pattern in Java\n\n* Use when managing a large number of objects in a spatial environment, such as in games or simulations.\n* Useful for optimizing spatial queries like finding nearby objects or detecting collisions.\n\n## Spatial Partition Pattern Java Tutorials\n\n* [Coding Challenge #98.1: Quadtree - Part 1 (The Coding Train)](https://www.youtube.com/watch?v=OJxEcs0w_kE)\n\n## Real-World Applications of Spatial Partition Pattern in Java\n\n* Quadtree in 2D games for collision detection.\n* Octree in 3D environments for rendering and physics calculations.\n* KD-tree in spatial databases for efficient range searches.\n\n## Benefits and Trade-offs of Spatial Partition Pattern\n\nBenefits:\n\n* Significant performance improvements in spatial queries.\n* Reduces the complexity of managing objects in large spaces.\n* Scales well with an increasing number of objects.\n\nTrade-offs:\n\n* Increased complexity in implementation.\n* May require periodic rebalancing or restructuring as objects move.\n\n## Related Java Design Patterns\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): Helps manage hierarchical data structures like trees used in spatial partitioning.\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Can be used to manage memory efficiently for objects stored in spatial partitions.\n\n## References and Credits\n\n* [Game Programming Patterns](https://amzn.to/3K96fOn)\n* [Introduction to Algorithms](https://amzn.to/4aC5hW0)\n* [Real-Time Collision Detection](https://amzn.to/4as9gnW)\n* [Spatial Partition (Game Programming Patterns)](http://gameprogrammingpatterns.com/spatial-partition.html)\n"
  },
  {
    "path": "spatial-partition/etc/spatial-partition.urm.puml",
    "content": "@startuml\npackage com.iluwatar.spatialpartition {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n    ~ noSpatialPartition(height : int, width : int, numOfMovements : int, bubbles : Hashtable<Integer, Bubble>) {static}\n    ~ withSpatialPartition(height : int, width : int, numOfMovements : int, bubbles : Hashtable<Integer, Bubble>) {static}\n  }\n  class Bubble {\n    - LOGGER : Logger {static}\n    - RANDOM : Random {static}\n    ~ radius : int\n    ~ Bubble(x : int, y : int, id : int, radius : int)\n    ~ handleCollision(bubblesToCheck : ArrayList<Point<T>>, allBubbles : Hashtable<Integer, Bubble>)\n    ~ move()\n    ~ pop(allBubbles : Hashtable<Integer, Bubble>)\n    ~ touches(b : Bubble) : boolean\n  }\n  abstract class Point<T> {\n    + coordinateX : int\n    + coordinateY : int\n    + id : int\n    ~ Point<T>(x : int, y : int, id : int)\n    ~ handleCollision(ArrayList<Point<T>>, Hashtable<Integer, T>) {abstract}\n    ~ move() {abstract}\n    ~ touches(T) : boolean {abstract}\n  }\n  class QuadTree {\n    ~ boundary : Rect\n    ~ capacity : int\n    ~ divided : boolean\n    ~ northeast : QuadTree\n    ~ northwest : QuadTree\n    ~ points : Hashtable<Integer, Point<T>>\n    ~ southeast : QuadTree\n    ~ southwest : QuadTree\n    ~ QuadTree(boundary : Rect, capacity : int)\n    ~ divide()\n    ~ insert(p : Point<T>)\n    ~ query(r : Rect, relevantPoints : ArrayList<Point<T>>) : ArrayList<Point<T>>\n  }\n  class Rect {\n    ~ coordinateX : double\n    ~ coordinateY : double\n    ~ height : double\n    ~ width : double\n    ~ Rect(x : double, y : double, width : double, height : double)\n    ~ contains(p : Point<T>) : boolean\n    ~ intersects(other : Rect) : boolean\n  }\n  class SpatialPartitionBubbles {\n    ~ bubbles : Hashtable<Integer, Bubble>\n    ~ quadTree : QuadTree\n    ~ SpatialPartitionBubbles(bubbles : Hashtable<Integer, Bubble>, quadTree : QuadTree)\n    ~ handleCollisionsUsingQt(b : Bubble)\n  }\n  abstract class SpatialPartitionGeneric<T> {\n    ~ playerPositions : Hashtable<Integer, T>\n    ~ quadTree : QuadTree\n    + SpatialPartitionGeneric<T>()\n    ~ handleCollisionsUsingQt(T) {abstract}\n  }\n}\nSpatialPartitionBubbles -->  \"-quadTree\" QuadTree\nSpatialPartitionGeneric -->  \"-quadTree\" QuadTree\nQuadTree -->  \"-boundary\" Rect\nQuadTree -->  \"-northwest\" QuadTree\nQuadTree -->  \"-southwest\" QuadTree\nBubble --|> Point \nSpatialPartitionBubbles --|> SpatialPartitionGeneric \n@enduml"
  },
  {
    "path": "spatial-partition/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>spatial-partition</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.spatialpartition.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "spatial-partition/src/main/java/com/iluwatar/spatialpartition/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.spatialpartition;\n\nimport java.security.SecureRandom;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The idea behind the <b>Spatial Partition</b> design pattern is to enable efficient location of\n * objects by storing them in a data structure that is organised by their positions. This is\n * especially useful in the gaming world, where one may need to look up all the objects within a\n * certain boundary, or near a certain other object, repeatedly. The data structure can be used to\n * store moving and static objects, though in order to keep track of the moving objects, their\n * positions will have to be reset each time they move. This would mean having to create a new\n * instance of the data structure each frame, which would use up additional memory, and so this\n * pattern should only be used if one does not mind trading memory for speed and the number of\n * objects to keep track of is large to justify the use of the extra space.\n *\n * <p>In our example, we use <b>{@link QuadTree} data structure</b> which divides into 4 (quad)\n * sub-sections when the number of objects added to it exceeds a certain number (int field\n * capacity). There is also a <b>{@link Rect}</b> class to define the boundary of the quadtree. We\n * use an abstract class <b>{@link Point}</b> with x and y coordinate fields and also an id field so\n * that it can easily be put and looked up in the hashmap. This class has abstract methods to define\n * how the object moves (move()), when to check for collision with any object (touches(obj)) and how\n * to handle collision (handleCollision(obj)), and will be extended by any object whose position has\n * to be kept track of in the quadtree. The <b>{@link SpatialPartitionGeneric}</b> abstract class\n * has 2 fields - a hashmap containing all objects (we use hashmap for faster lookups, insertion and\n * deletion) and a quadtree, and contains an abstract method which defines how to handle\n * interactions between objects using the quadtree.\n *\n * <p>Using the quadtree data structure will reduce the time complexity of finding the objects\n * within a certain range from <b>O(n^2) to O(nlogn)</b>, increasing the speed of computations\n * immensely in case of large number of objects, which will have a positive effect on the rendering\n * speed of the game.\n */\n@Slf4j\npublic class App {\n\n  static void noSpatialPartition(int numOfMovements, Map<Integer, Bubble> bubbles) {\n    // all bubbles have to be checked for collision for all bubbles\n    var bubblesToCheck = bubbles.values();\n\n    // will run numOfMovement times or till all bubbles have popped\n    while (numOfMovements > 0 && !bubbles.isEmpty()) {\n      bubbles.forEach(\n          (i, bubble) -> {\n            // bubble moves, new position gets updated\n            // and collisions are checked with all bubbles in bubblesToCheck\n            bubble.move();\n            bubbles.replace(i, bubble);\n            bubble.handleCollision(bubblesToCheck, bubbles);\n          });\n      numOfMovements--;\n    }\n    // bubbles not popped\n    bubbles.keySet().forEach(key -> LOGGER.info(\"Bubble {} not popped\", key));\n  }\n\n  static void withSpatialPartition(\n      int height, int width, int numOfMovements, Map<Integer, Bubble> bubbles) {\n    // creating quadtree\n    var rect = new Rect(width / 2D, height / 2D, width, height);\n    var quadTree = new QuadTree(rect, 4);\n\n    // will run numOfMovement times or till all bubbles have popped\n    while (numOfMovements > 0 && !bubbles.isEmpty()) {\n      // quadtree updated each time\n      bubbles.values().forEach(quadTree::insert);\n      bubbles.forEach(\n          (i, bubble) -> {\n            // bubble moves, new position gets updated, quadtree used to reduce computations\n            bubble.move();\n            bubbles.replace(i, bubble);\n            var sp = new SpatialPartitionBubbles(bubbles, quadTree);\n            sp.handleCollisionsUsingQt(bubble);\n          });\n      numOfMovements--;\n    }\n    // bubbles not popped\n    bubbles.keySet().forEach(key -> LOGGER.info(\"Bubble {} not popped\", key));\n  }\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var bubbles1 = new ConcurrentHashMap<Integer, Bubble>();\n    var bubbles2 = new ConcurrentHashMap<Integer, Bubble>();\n    var rand = new SecureRandom();\n    for (int i = 0; i < 10000; i++) {\n      var b = new Bubble(rand.nextInt(300), rand.nextInt(300), i, rand.nextInt(2) + 1);\n      bubbles1.put(i, b);\n      bubbles2.put(i, b);\n      LOGGER.info(\n          \"Bubble {} with radius {} added at ({},{})\", i, b.radius, b.coordinateX, b.coordinateY);\n    }\n\n    var start1 = System.currentTimeMillis();\n    App.noSpatialPartition(20, bubbles1);\n    var end1 = System.currentTimeMillis();\n    var start2 = System.currentTimeMillis();\n    App.withSpatialPartition(300, 300, 20, bubbles2);\n    var end2 = System.currentTimeMillis();\n    LOGGER.info(\"Without spatial partition takes {} ms\", (end1 - start1));\n    LOGGER.info(\"With spatial partition takes {} ms\", (end2 - start2));\n  }\n}\n"
  },
  {
    "path": "spatial-partition/src/main/java/com/iluwatar/spatialpartition/Bubble.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.spatialpartition;\n\nimport java.security.SecureRandom;\nimport java.util.Collection;\nimport java.util.Map;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Bubble class extends Point. In this example, we create several bubbles in the field, let them\n * move and keep track of which ones have popped and which ones remain.\n */\n@Slf4j\npublic class Bubble extends Point<Bubble> {\n  private static final SecureRandom RANDOM = new SecureRandom();\n\n  final int radius;\n\n  Bubble(int x, int y, int id, int radius) {\n    super(x, y, id);\n    this.radius = radius;\n  }\n\n  void move() {\n    // moves by 1 unit in either direction\n    this.coordinateX += RANDOM.nextInt(3) - 1;\n    this.coordinateY += RANDOM.nextInt(3) - 1;\n  }\n\n  boolean touches(Bubble b) {\n    // distance between them is greater than sum of radii (both sides of equation squared)\n    return (this.coordinateX - b.coordinateX) * (this.coordinateX - b.coordinateX)\n            + (this.coordinateY - b.coordinateY) * (this.coordinateY - b.coordinateY)\n        <= (this.radius + b.radius) * (this.radius + b.radius);\n  }\n\n  void pop(Map<Integer, Bubble> allBubbles) {\n    LOGGER.info(\"Bubble {} popped at ({},{})!\", this.id, this.coordinateX, this.coordinateY);\n    allBubbles.remove(this.id);\n  }\n\n  void handleCollision(Collection<? extends Point> toCheck, Map<Integer, Bubble> allBubbles) {\n    var toBePopped = false; // if any other bubble collides with it, made true\n    for (var point : toCheck) {\n      var otherId = point.id;\n      if (allBubbles.get(otherId) != null // the bubble hasn't been popped yet\n          && this.id != otherId // the two bubbles are not the same\n          && this.touches(allBubbles.get(otherId))) { // the bubbles touch\n        allBubbles.get(otherId).pop(allBubbles);\n        toBePopped = true;\n      }\n    }\n    if (toBePopped) {\n      this.pop(allBubbles);\n    }\n  }\n}\n"
  },
  {
    "path": "spatial-partition/src/main/java/com/iluwatar/spatialpartition/Point.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.spatialpartition;\n\nimport java.util.Collection;\nimport java.util.Map;\n\n/**\n * The abstract Point class which will be extended by any object in the field whose location has to\n * be kept track of. Defined by x,y coordinates and an id for easy hashing into hashtable.\n *\n * @param <T> T will be type subclass\n */\npublic abstract class Point<T> {\n\n  public int coordinateX;\n  public int coordinateY;\n  public final int id;\n\n  Point(int x, int y, int id) {\n    this.coordinateX = x;\n    this.coordinateY = y;\n    this.id = id;\n  }\n\n  /** defines how the object moves. */\n  abstract void move();\n\n  /**\n   * defines conditions for interacting with an object obj.\n   *\n   * @param obj is another object on field which also extends Point\n   * @return whether the object can interact with the other or not\n   */\n  abstract boolean touches(T obj);\n\n  /**\n   * handling interactions/collisions with other objects.\n   *\n   * @param toCheck contains the objects which need to be checked\n   * @param all contains hashtable of all points on field at this time\n   */\n  abstract void handleCollision(Collection<? extends Point> toCheck, Map<Integer, T> all);\n}\n"
  },
  {
    "path": "spatial-partition/src/main/java/com/iluwatar/spatialpartition/QuadTree.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.spatialpartition;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * The quadtree data structure is being used to keep track of the objects' locations. It has the\n * insert(Point) and query(range) methods to insert a new object and find the objects within a\n * certain (rectangular) range respectively.\n */\npublic class QuadTree {\n  Rect boundary;\n  int capacity;\n  boolean divided;\n  Map<Integer, Point> points;\n  QuadTree northwest;\n  QuadTree northeast;\n  QuadTree southwest;\n  QuadTree southeast;\n\n  QuadTree(Rect boundary, int capacity) {\n    this.boundary = boundary;\n    this.capacity = capacity;\n    this.divided = false;\n    this.points = new HashMap<>();\n    this.northwest = null;\n    this.northeast = null;\n    this.southwest = null;\n    this.southeast = null;\n  }\n\n  void insert(Point p) {\n    if (this.boundary.contains(p)) {\n      if (this.points.size() < this.capacity) {\n        points.put(p.id, p);\n      } else {\n        if (!this.divided) {\n          this.divide();\n        }\n        if (this.northwest.boundary.contains(p)) {\n          this.northwest.insert(p);\n        } else if (this.northeast.boundary.contains(p)) {\n          this.northeast.insert(p);\n        } else if (this.southwest.boundary.contains(p)) {\n          this.southwest.insert(p);\n        } else if (this.southeast.boundary.contains(p)) {\n          this.southeast.insert(p);\n        }\n      }\n    }\n  }\n\n  void divide() {\n    var x = this.boundary.coordinateX;\n    var y = this.boundary.coordinateY;\n    var width = this.boundary.width;\n    var height = this.boundary.height;\n    var nw = new Rect(x - width / 4, y + height / 4, width / 2, height / 2);\n    this.northwest = new QuadTree(nw, this.capacity);\n    var ne = new Rect(x + width / 4, y + height / 4, width / 2, height / 2);\n    this.northeast = new QuadTree(ne, this.capacity);\n    var sw = new Rect(x - width / 4, y - height / 4, width / 2, height / 2);\n    this.southwest = new QuadTree(sw, this.capacity);\n    var se = new Rect(x + width / 4, y - height / 4, width / 2, height / 2);\n    this.southeast = new QuadTree(se, this.capacity);\n    this.divided = true;\n  }\n\n  Collection<Point> query(Rect r, Collection<Point> relevantPoints) {\n    // could also be a circle instead of a rectangle\n    if (this.boundary.intersects(r)) {\n      this.points.values().stream().filter(r::contains).forEach(relevantPoints::add);\n      if (this.divided) {\n        this.northwest.query(r, relevantPoints);\n        this.northeast.query(r, relevantPoints);\n        this.southwest.query(r, relevantPoints);\n        this.southeast.query(r, relevantPoints);\n      }\n    }\n    return relevantPoints;\n  }\n}\n"
  },
  {
    "path": "spatial-partition/src/main/java/com/iluwatar/spatialpartition/Rect.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.spatialpartition;\n\n/**\n * The Rect class helps in defining the boundary of the quadtree and is also used to define the\n * range within which objects need to be found in our example.\n */\npublic class Rect {\n  double coordinateX;\n  double coordinateY;\n  double width;\n  double height;\n\n  // (x,y) - centre of rectangle\n\n  Rect(double x, double y, double width, double height) {\n    this.coordinateX = x;\n    this.coordinateY = y;\n    this.width = width;\n    this.height = height;\n  }\n\n  boolean contains(Point p) {\n    return p.coordinateX >= this.coordinateX - this.width / 2\n        && p.coordinateX <= this.coordinateX + this.width / 2\n        && p.coordinateY >= this.coordinateY - this.height / 2\n        && p.coordinateY <= this.coordinateY + this.height / 2;\n  }\n\n  boolean intersects(Rect other) {\n    return !(this.coordinateX + this.width / 2 <= other.coordinateX - other.width / 2\n        || this.coordinateX - this.width / 2 >= other.coordinateX + other.width / 2\n        || this.coordinateY + this.height / 2 <= other.coordinateY - other.height / 2\n        || this.coordinateY - this.height / 2 >= other.coordinateY + other.height / 2);\n  }\n}\n"
  },
  {
    "path": "spatial-partition/src/main/java/com/iluwatar/spatialpartition/SpatialPartitionBubbles.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.spatialpartition;\n\nimport java.util.ArrayList;\nimport java.util.Map;\n\n/**\n * This class extends the generic SpatialPartition abstract class and is used in our example to keep\n * track of all the bubbles that collide, pop and stay un-popped.\n */\npublic class SpatialPartitionBubbles extends SpatialPartitionGeneric<Bubble> {\n\n  private final Map<Integer, Bubble> bubbles;\n  private final QuadTree bubblesQuadTree;\n\n  SpatialPartitionBubbles(Map<Integer, Bubble> bubbles, QuadTree bubblesQuadTree) {\n    this.bubbles = bubbles;\n    this.bubblesQuadTree = bubblesQuadTree;\n  }\n\n  void handleCollisionsUsingQt(Bubble b) {\n    // finding points within area of a square drawn with centre same as\n    // centre of bubble and length = radius of bubble\n    var rect = new Rect(b.coordinateX, b.coordinateY, 2D * b.radius, 2D * b.radius);\n    var quadTreeQueryResult = new ArrayList<Point>();\n    this.bubblesQuadTree.query(rect, quadTreeQueryResult);\n    // handling these collisions\n    b.handleCollision(quadTreeQueryResult, this.bubbles);\n  }\n}\n"
  },
  {
    "path": "spatial-partition/src/main/java/com/iluwatar/spatialpartition/SpatialPartitionGeneric.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.spatialpartition;\n\nimport java.util.Map;\n\n/**\n * This abstract class has 2 fields, one of which is a hashtable containing all objects that\n * currently exist on the field and a quadtree which keeps track of locations.\n *\n * @param <T> T will be type of object (that extends Point)\n */\npublic abstract class SpatialPartitionGeneric<T> {\n\n  Map<Integer, T> playerPositions;\n  QuadTree quadTree;\n\n  /**\n   * handles collisions for object obj using quadtree.\n   *\n   * @param obj is the object for which collisions need to be checked\n   */\n  abstract void handleCollisionsUsingQt(T obj);\n}\n"
  },
  {
    "path": "spatial-partition/src/test/java/com/iluwatar/spatialpartition/BubbleTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.spatialpartition;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport org.junit.jupiter.api.Test;\n\n/** Testing methods in Bubble class. */\nclass BubbleTest {\n\n  @Test\n  void moveTest() {\n    var b = new Bubble(10, 10, 1, 2);\n    var initialX = b.coordinateX;\n    var initialY = b.coordinateY;\n    b.move();\n    // change in x and y < |2|\n    assertTrue(b.coordinateX - initialX < 2 && b.coordinateX - initialX > -2);\n    assertTrue(b.coordinateY - initialY < 2 && b.coordinateY - initialY > -2);\n  }\n\n  @Test\n  void touchesTest() {\n    var b1 = new Bubble(0, 0, 1, 2);\n    var b2 = new Bubble(1, 1, 2, 1);\n    var b3 = new Bubble(10, 10, 3, 1);\n    // b1 touches b2 but not b3\n    assertTrue(b1.touches(b2));\n    assertFalse(b1.touches(b3));\n  }\n\n  @Test\n  void popTest() {\n    var b1 = new Bubble(10, 10, 1, 2);\n    var b2 = new Bubble(0, 0, 2, 2);\n    var bubbles = new HashMap<Integer, Bubble>();\n    bubbles.put(1, b1);\n    bubbles.put(2, b2);\n    b1.pop(bubbles);\n    // after popping, bubble no longer in hashMap containing all bubbles\n    assertNull(bubbles.get(1));\n    assertNotNull(bubbles.get(2));\n  }\n\n  @Test\n  void handleCollisionTest() {\n    var b1 = new Bubble(0, 0, 1, 2);\n    var b2 = new Bubble(1, 1, 2, 1);\n    var b3 = new Bubble(10, 10, 3, 1);\n    var bubbles = new HashMap<Integer, Bubble>();\n    bubbles.put(1, b1);\n    bubbles.put(2, b2);\n    bubbles.put(3, b3);\n    var bubblesToCheck = new ArrayList<Point>();\n    bubblesToCheck.add(b2);\n    bubblesToCheck.add(b3);\n    b1.handleCollision(bubblesToCheck, bubbles);\n    // b1 touches b2 and not b3, so b1, b2 will be popped\n    assertNull(bubbles.get(1));\n    assertNull(bubbles.get(2));\n    assertNotNull(bubbles.get(3));\n  }\n}\n"
  },
  {
    "path": "spatial-partition/src/test/java/com/iluwatar/spatialpartition/QuadTreeTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.spatialpartition;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Hashtable;\nimport java.util.Random;\nimport java.util.stream.Collectors;\nimport org.junit.jupiter.api.Test;\n\n/** Testing QuadTree class. */\nclass QuadTreeTest {\n\n  @Test\n  void queryTest() {\n    var points = new ArrayList<Point>();\n    var rand = new Random();\n    for (int i = 0; i < 20; i++) {\n      var p = new Bubble(rand.nextInt(300), rand.nextInt(300), i, rand.nextInt(2) + 1);\n      points.add(p);\n    }\n    var field = new Rect(150, 150, 300, 300); // size of field\n    var queryRange = new Rect(70, 130, 100, 100); // result = all points lying in this rectangle\n    // points found in the query range using quadtree and normal method is same\n    var points1 = QuadTreeTest.quadTreeTest(points, field, queryRange);\n    var points2 = QuadTreeTest.verify(points, queryRange);\n    assertEquals(points1, points2);\n  }\n\n  static Hashtable<Integer, Point> quadTreeTest(\n      Collection<Point> points, Rect field, Rect queryRange) {\n    // creating quadtree and inserting all points\n    var qTree = new QuadTree(queryRange, 4);\n    points.forEach(qTree::insert);\n\n    return qTree.query(field, new ArrayList<>()).stream()\n        .collect(Collectors.toMap(p -> p.id, p -> p, (a, b) -> b, Hashtable::new));\n  }\n\n  static Hashtable<Integer, Point> verify(Collection<Point> points, Rect queryRange) {\n    return points.stream()\n        .filter(queryRange::contains)\n        .collect(Collectors.toMap(point -> point.id, point -> point, (a, b) -> b, Hashtable::new));\n  }\n}\n"
  },
  {
    "path": "spatial-partition/src/test/java/com/iluwatar/spatialpartition/RectTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.spatialpartition;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** Testing Rect class. */\nclass RectTest {\n\n  @Test\n  void containsTest() {\n    var r = new Rect(10, 10, 20, 20);\n    var b1 = new Bubble(2, 2, 1, 1);\n    var b2 = new Bubble(30, 30, 2, 1);\n    // r contains b1 and not b2\n    assertTrue(r.contains(b1));\n    assertFalse(r.contains(b2));\n  }\n\n  @Test\n  void intersectsTest() {\n    var r1 = new Rect(10, 10, 20, 20);\n    var r2 = new Rect(15, 15, 20, 20);\n    var r3 = new Rect(50, 50, 20, 20);\n    // r1 intersects r2 and not r3\n    assertTrue(r1.intersects(r2));\n    assertFalse(r1.intersects(r3));\n  }\n}\n"
  },
  {
    "path": "spatial-partition/src/test/java/com/iluwatar/spatialpartition/SpatialPartitionBubblesTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.spatialpartition;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nimport java.util.HashMap;\nimport org.junit.jupiter.api.Test;\n\n/** Testing SpatialPartition_Bubbles class. */\nclass SpatialPartitionBubblesTest {\n\n  @Test\n  void handleCollisionsUsingQtTest() {\n    var b1 = new Bubble(10, 10, 1, 3);\n    var b2 = new Bubble(5, 5, 2, 1);\n    var b3 = new Bubble(9, 9, 3, 1);\n    var b4 = new Bubble(8, 8, 4, 2);\n    var bubbles = new HashMap<Integer, Bubble>();\n    bubbles.put(1, b1);\n    bubbles.put(2, b2);\n    bubbles.put(3, b3);\n    bubbles.put(4, b4);\n    var r = new Rect(10, 10, 20, 20);\n    var qt = new QuadTree(r, 4);\n    qt.insert(b1);\n    qt.insert(b2);\n    qt.insert(b3);\n    qt.insert(b4);\n    var sp = new SpatialPartitionBubbles(bubbles, qt);\n    sp.handleCollisionsUsingQt(b1);\n    // b1 touches b3 and b4 but not b2 - so b1,b3,b4 get popped\n    assertNull(bubbles.get(1));\n    assertNotNull(bubbles.get(2));\n    assertNull(bubbles.get(3));\n    assertNull(bubbles.get(4));\n  }\n}\n"
  },
  {
    "path": "special-case/README.md",
    "content": "---\ntitle: \"Special Case Pattern in Java: Simplifying Exception Handling with Predefined Cases\"\nshortTitle: Special Case\ndescription: \"Explore the Special Case design pattern in Java for handling exceptional cases without cluttering the main code logic. Learn its applicability, real-world examples, and benefits for clean, maintainable code.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Abstraction\n  - Code simplification\n  - Decoupling\n  - Error handling\n  - Polymorphism\n  - Runtime\n---\n\n## Also known as\n\n* Exceptional Case\n\n## Intent of Special Case Design Pattern\n\nThe Special Case design pattern in Java offers a robust framework for addressing unique or exceptional conditions in software development without complicating the main codebase.\n\n## Detailed Explanation of Special Case Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a toll booth system on a highway. Normally, vehicles pass through the booth, and the system charges a toll based on the vehicle type. However, there are special cases: emergency vehicles like ambulances and fire trucks, which should not be charged.\n>\n> For instance, in a toll management system, the Special Case pattern facilitates separate handling for emergency vehicles, ensuring a streamlined toll process without additional checks. The emergency vehicle class would override the toll calculation method to ensure no charge is applied, encapsulating this special behavior without cluttering the main toll calculation logic with conditional checks. This keeps the codebase clean and ensures the special case is handled consistently.\n\nIn plain words\n\n> The Special Case design pattern encapsulates and isolates exceptional conditions and specific scenarios to simplify the main code logic and enhance maintainability.\n\nIn [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR) Martin Fowler says:\n\n> If you’ll pardon the unresistable pun, I see [Null Object](https://java-design-patterns.com/patterns/null-object/) as special case of Special Case.\n\nSequnce diagram\n\n![Special Case sequence diagram](./etc/special-case-sequence-diagram.png)\n\n## Programmatic Example of Special Case Pattern in Java\n\nThe Special Case Pattern is a software design pattern that is used to handle a specific, often uncommon, case separately from the general case in the code. This pattern is useful when a class has behavior that requires conditional logic based on its state. Instead of cluttering the class with conditional logic, we can encapsulate the special behavior in a subclass.\n\nIn an e-commerce system, the presentation layer relies on the application layer to generate a specific view model. There is a successful scenario where the receipt view model includes actual purchase data, along with a few failure scenarios.\n\nThe `Db` class is a singleton that holds data for users, accounts, and products. It provides methods to seed data into the database and find data in the database.\n\n```java\n@RequiredArgsConstructor\n@Getter\npublic class Db {\n    // Singleton instance of Db\n    private static Db instance;\n\n    // Maps to hold data\n    private Map<String, User> userName2User;\n    private Map<User, Account> user2Account;\n    private Map<String, Product> itemName2Product;\n\n    // Singleton method to get instance of Db\n    public static synchronized Db getInstance() {\n        if (instance == null) {\n            Db newInstance = new Db();\n            newInstance.userName2User = new HashMap<>();\n            newInstance.user2Account = new HashMap<>();\n            newInstance.itemName2Product = new HashMap<>();\n            instance = newInstance;\n        }\n        return instance;\n    }\n\n    // Methods to seed data into Db\n    public void seedUser(String userName, Double amount) { /*...*/ }\n\n    public void seedItem(String itemName, Double price) { /*...*/ }\n\n    // Methods to find data in Db\n    public User findUserByUserName(String userName) { /*...*/ }\n\n    public Account findAccountByUser(User user) { /*...*/ }\n\n    public Product findProductByItemName(String itemName) { /*...*/ }\n}\n```\n\nNext, here are the presentation layer, the receipt view model interface and its implementation of successful scenario.\n\n```java\npublic interface ReceiptViewModel {\n    void show();\n}\n```\n\n```java\n@RequiredArgsConstructor\n@Getter\npublic class ReceiptDto implements ReceiptViewModel {\n    private static final Logger LOGGER = LoggerFactory.getLogger(ReceiptDto.class);\n\n    private final Double price;\n\n    @Override\n    public void show() {\n        LOGGER.info(String.format(\"Receipt: %s paid\", price));\n    }\n}\n```\n\nAnd here are the implementations of failure scenarios, which are the special cases.\n\n```java\npublic class DownForMaintenance implements ReceiptViewModel {\n    private static final Logger LOGGER = LoggerFactory.getLogger(DownForMaintenance.class);\n\n    @Override\n    public void show() {\n        LOGGER.info(\"Down for maintenance\");\n    }\n}\n```\n\n```java\npublic class InvalidUser implements ReceiptViewModel {\n    private static final Logger LOGGER = LoggerFactory.getLogger(InvalidUser.class);\n\n    private final String userName;\n\n    public InvalidUser(String userName) {\n        this.userName = userName;\n    }\n\n    @Override\n    public void show() {\n        LOGGER.info(\"Invalid user: \" + userName);\n    }\n}\n```\n\n```java\npublic class OutOfStock implements ReceiptViewModel {\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(OutOfStock.class);\n\n    private String userName;\n    private String itemName;\n\n    public OutOfStock(String userName, String itemName) {\n        this.userName = userName;\n        this.itemName = itemName;\n    }\n\n    @Override\n    public void show() {\n        LOGGER.info(\"Out of stock: \" + itemName + \" for user = \" + userName + \" to buy\");\n    }\n}\n```\n\n```java\npublic class InsufficientFunds implements ReceiptViewModel {\n    private static final Logger LOGGER = LoggerFactory.getLogger(InsufficientFunds.class);\n\n    private String userName;\n    private Double amount;\n    private String itemName;\n\n    public InsufficientFunds(String userName, Double amount, String itemName) {\n        this.userName = userName;\n        this.amount = amount;\n        this.itemName = itemName;\n    }\n\n    @Override\n    public void show() {\n        LOGGER.info(\"Insufficient funds: \" + amount + \" of user: \" + userName\n                + \" for buying item: \" + itemName);\n    }\n}\n```\n\nHere is the `App` and its `main` function that executes the different scenarios.\n\n```java\npublic class App {\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n    private static final String LOGGER_STRING = \"[REQUEST] User: {} buy product: {}\";\n    private static final String TEST_USER_1 = \"ignite1771\";\n    private static final String TEST_USER_2 = \"abc123\";\n    private static final String ITEM_TV = \"tv\";\n    private static final String ITEM_CAR = \"car\";\n    private static final String ITEM_COMPUTER = \"computer\";\n\n    public static void main(String[] args) {\n        // DB seeding\n        LOGGER.info(\"Db seeding: \" + \"1 user: {\\\"ignite1771\\\", amount = 1000.0}, \"\n                + \"2 products: {\\\"computer\\\": price = 800.0, \\\"car\\\": price = 20000.0}\");\n        Db.getInstance().seedUser(TEST_USER_1, 1000.0);\n        Db.getInstance().seedItem(ITEM_COMPUTER, 800.0);\n        Db.getInstance().seedItem(ITEM_CAR, 20000.0);\n\n        final var applicationServices = new ApplicationServicesImpl();\n        ReceiptViewModel receipt;\n\n        LOGGER.info(LOGGER_STRING, TEST_USER_2, ITEM_TV);\n        receipt = applicationServices.loggedInUserPurchase(TEST_USER_2, ITEM_TV);\n        receipt.show();\n        MaintenanceLock.getInstance().setLock(false);\n        LOGGER.info(LOGGER_STRING, TEST_USER_2, ITEM_TV);\n        receipt = applicationServices.loggedInUserPurchase(TEST_USER_2, ITEM_TV);\n        receipt.show();\n        LOGGER.info(LOGGER_STRING, TEST_USER_1, ITEM_TV);\n        receipt = applicationServices.loggedInUserPurchase(TEST_USER_1, ITEM_TV);\n        receipt.show();\n        LOGGER.info(LOGGER_STRING, TEST_USER_1, ITEM_CAR);\n        receipt = applicationServices.loggedInUserPurchase(TEST_USER_1, ITEM_CAR);\n        receipt.show();\n        LOGGER.info(LOGGER_STRING, TEST_USER_1, ITEM_COMPUTER);\n        receipt = applicationServices.loggedInUserPurchase(TEST_USER_1, ITEM_COMPUTER);\n        receipt.show();\n    }\n}\n```\n\nHere is the output from running the example.\n\n```\n11:23:48.669 [main] INFO com.iluwatar.specialcase.App -- Db seeding: 1 user: {\"ignite1771\", amount = 1000.0}, 2 products: {\"computer\": price = 800.0, \"car\": price = 20000.0}\n11:23:48.672 [main] INFO com.iluwatar.specialcase.App -- [REQUEST] User: abc123 buy product: tv\n11:23:48.672 [main] INFO com.iluwatar.specialcase.DownForMaintenance -- Down for maintenance\n11:23:48.672 [main] INFO com.iluwatar.specialcase.MaintenanceLock -- Maintenance lock is set to: false\n11:23:48.672 [main] INFO com.iluwatar.specialcase.App -- [REQUEST] User: abc123 buy product: tv\n11:23:48.673 [main] INFO com.iluwatar.specialcase.InvalidUser -- Invalid user: abc123\n11:23:48.674 [main] INFO com.iluwatar.specialcase.App -- [REQUEST] User: ignite1771 buy product: tv\n11:23:48.674 [main] INFO com.iluwatar.specialcase.OutOfStock -- Out of stock: tv for user = ignite1771 to buy\n11:23:48.674 [main] INFO com.iluwatar.specialcase.App -- [REQUEST] User: ignite1771 buy product: car\n11:23:48.676 [main] INFO com.iluwatar.specialcase.InsufficientFunds -- Insufficient funds: 1000.0 of user: ignite1771 for buying item: car\n11:23:48.676 [main] INFO com.iluwatar.specialcase.App -- [REQUEST] User: ignite1771 buy product: computer\n11:23:48.676 [main] INFO com.iluwatar.specialcase.ReceiptDto -- Receipt: 800.0 paid\n```\n\nIn conclusion, the Special Case Pattern helps to keep the code clean and easy to understand by separating the special case from the general case. It also promotes code reuse and makes the code easier to maintain.\n\n## When to Use the Special Case Pattern in Java\n\n* Use when you want to encapsulate and handle special cases or error conditions in a manner that avoids conditional logic scattered throughout the main codebase.\n* Useful in scenarios where certain operations have known exceptional cases that require different handling.\n\n## Real-World Applications of Special Case Pattern in Java\n\n* Implementing null object patterns to avoid null checks.\n* Handling specific business rules or validation logic in e-commerce applications.\n* Managing different file formats or protocols in data processing applications.\n\n## Benefits and Trade-offs of Special Case Pattern\n\nBenefits:\n\nAdopting the Special Case design pattern\n\n* Simplifies the main logic by removing special case handling from the core algorithms.\n* Enhances code readability and maintainability by isolating special cases.\n\nTrade-offs:\n\n* May introduce additional classes or interfaces, increasing the number of components in the system.\n* Requires careful design to ensure that special cases are correctly encapsulated and do not introduce unexpected behaviors.\n\n## Related Java Design Patterns\n\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Can be used to add special case behavior to objects dynamically without modifying their code.\n* [Null Object](https://java-design-patterns.com/patterns/null-object/): Used to provide a default behavior for null references, which is a specific type of special case.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Allows dynamic switching of special case behaviors by encapsulating them in different strategy classes.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Special Case (Martin Fowler)](https://www.martinfowler.com/eaaCatalog/specialCase.html)\n"
  },
  {
    "path": "special-case/etc/special-case.urm.puml",
    "content": "@startuml\nleft to right direction\npackage com.iluwatar.specialcase {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  interface ApplicationServices {\n    + loggedInUserPurchase(String, String) : ReceiptViewModel {abstract}\n  }\n  class ApplicationServicesImpl {\n    - domain : DomainServicesImpl\n    + ApplicationServicesImpl()\n    - isDownForMaintenance() : boolean\n    + loggedInUserPurchase(userName : String, itemName : String) : ReceiptViewModel\n  }\n  class Db {\n    - instance : Db {static}\n    - itemName2Product : Map<String, Product>\n    - user2Account : Map<User, Account>\n    - userName2User : Map<String, User>\n    + Db()\n    + findAccountByUser(user : User) : Account\n    + findProductByItemName(itemName : String) : Product\n    + findUserByUserName(userName : String) : User\n    + getInstance() : Db {static}\n    + seedItem(itemName : String, price : Double)\n    + seedUser(userName : String, amount : Double)\n  }\n  class Account {\n    - amount : Double\n    + Account(this$0 : Double)\n    + getAmount() : Double\n    + withdraw(price : Double) : MoneyTransaction\n  }\n  class Product {\n    - price : Double\n    + Product(this$0 : Double)\n    + getPrice() : Double\n  }\n  class User {\n    - userName : String\n    + User(this$0 : String)\n    + getUserName() : String\n    + purchase(item : Product) : ReceiptDto\n  }\n  interface DomainServices {\n  }\n  class DomainServicesImpl {\n    + DomainServicesImpl()\n    - purchase(user : User, account : Account, itemName : String) : ReceiptViewModel\n    + purchase(userName : String, itemName : String) : ReceiptViewModel\n  }\n  class DownForMaintenance {\n    - LOGGER : Logger {static}\n    + DownForMaintenance()\n    + show()\n  }\n  class InsufficientFunds {\n    - LOGGER : Logger {static}\n    - amount : Double\n    - itemName : String\n    - userName : String\n    + InsufficientFunds(userName : String, amount : Double, itemName : String)\n    + show()\n  }\n  class InvalidUser {\n    - LOGGER : Logger {static}\n    - userName : String\n    + InvalidUser(userName : String)\n    + show()\n  }\n  class MaintenanceLock {\n    - LOGGER : Logger {static}\n    - instance : MaintenanceLock {static}\n    - lock : boolean\n    + MaintenanceLock()\n    + getInstance() : MaintenanceLock {static}\n    + isLock() : boolean\n    + setLock(lock : boolean)\n  }\n  class MoneyTransaction {\n    - amount : Double\n    - price : Double\n    + MoneyTransaction(amount : Double, price : Double)\n  }\n  class OutOfStock {\n    - LOGGER : Logger {static}\n    - itemName : String\n    - userName : String\n    + OutOfStock(userName : String, itemName : String)\n    + show()\n  }\n  class ReceiptDto {\n    - LOGGER : Logger {static}\n    - price : Double\n    + ReceiptDto(price : Double)\n    + getPrice() : Double\n    + show()\n  }\n  interface ReceiptViewModel {\n    + show() {abstract}\n  }\n}\nUser --+ Db\nProduct --+ Db\nMaintenanceLock -->  \"-instance\" MaintenanceLock\nDb -->  \"-instance\" Db\nApplicationServicesImpl -->  \"-domain\" DomainServicesImpl\nAccount --+ Db\nApplicationServicesImpl ..|> ApplicationServices \nDomainServicesImpl ..|> DomainServices \nDownForMaintenance ..|> ReceiptViewModel \nInsufficientFunds ..|> ReceiptViewModel \nInvalidUser ..|> ReceiptViewModel \nOutOfStock ..|> ReceiptViewModel \nReceiptDto ..|> ReceiptViewModel \n@enduml\n"
  },
  {
    "path": "special-case/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>special-case</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.specialcase.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * The Special Case Pattern is a software design pattern that encapsulates particular cases into\n * subclasses that provide special behaviors.\n *\n * <p>In this example ({@link ReceiptViewModel}) encapsulates all particular cases.\n */\npublic class App {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n  private static final String LOGGER_STRING = \"[REQUEST] User: {} buy product: {}\";\n  private static final String TEST_USER_1 = \"ignite1771\";\n  private static final String TEST_USER_2 = \"abc123\";\n  private static final String ITEM_TV = \"tv\";\n  private static final String ITEM_CAR = \"car\";\n  private static final String ITEM_COMPUTER = \"computer\";\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n    // DB seeding\n    LOGGER.info(\n        \"Db seeding: \"\n            + \"1 user: {\\\"ignite1771\\\", amount = 1000.0}, \"\n            + \"2 products: {\\\"computer\\\": price = 800.0, \\\"car\\\": price = 20000.0}\");\n    Db.getInstance().seedUser(TEST_USER_1, 1000.0);\n    Db.getInstance().seedItem(ITEM_COMPUTER, 800.0);\n    Db.getInstance().seedItem(ITEM_CAR, 20000.0);\n\n    final var applicationServices = new ApplicationServicesImpl();\n    ReceiptViewModel receipt;\n\n    LOGGER.info(LOGGER_STRING, TEST_USER_2, ITEM_TV);\n    receipt = applicationServices.loggedInUserPurchase(TEST_USER_2, ITEM_TV);\n    receipt.show();\n    MaintenanceLock.getInstance().setLock(false);\n    LOGGER.info(LOGGER_STRING, TEST_USER_2, ITEM_TV);\n    receipt = applicationServices.loggedInUserPurchase(TEST_USER_2, ITEM_TV);\n    receipt.show();\n    LOGGER.info(LOGGER_STRING, TEST_USER_1, ITEM_TV);\n    receipt = applicationServices.loggedInUserPurchase(TEST_USER_1, ITEM_TV);\n    receipt.show();\n    LOGGER.info(LOGGER_STRING, TEST_USER_1, ITEM_CAR);\n    receipt = applicationServices.loggedInUserPurchase(TEST_USER_1, ITEM_CAR);\n    receipt.show();\n    LOGGER.info(LOGGER_STRING, TEST_USER_1, ITEM_COMPUTER);\n    receipt = applicationServices.loggedInUserPurchase(TEST_USER_1, ITEM_COMPUTER);\n    receipt.show();\n  }\n}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/ApplicationServices.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\n/** ApplicationServices interface to demonstrate special case pattern. */\npublic interface ApplicationServices {\n\n  ReceiptViewModel loggedInUserPurchase(String userName, String itemName);\n}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/ApplicationServicesImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\n/** Implementation of special case pattern. */\npublic class ApplicationServicesImpl implements ApplicationServices {\n\n  private DomainServicesImpl domain = new DomainServicesImpl();\n\n  @Override\n  public ReceiptViewModel loggedInUserPurchase(String userName, String itemName) {\n    if (isDownForMaintenance()) {\n      return new DownForMaintenance();\n    }\n    return this.domain.purchase(userName, itemName);\n  }\n\n  private boolean isDownForMaintenance() {\n    return MaintenanceLock.getInstance().isLock();\n  }\n}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/Db.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/** DB class for seeding user info. */\npublic class Db {\n\n  private static Db instance;\n  private Map<String, User> userName2User;\n  private Map<User, Account> user2Account;\n  private Map<String, Product> itemName2Product;\n\n  /**\n   * Get the instance of Db.\n   *\n   * @return singleton instance of Db class\n   */\n  public static synchronized Db getInstance() {\n    if (instance == null) {\n      Db newInstance = new Db();\n      newInstance.userName2User = new HashMap<>();\n      newInstance.user2Account = new HashMap<>();\n      newInstance.itemName2Product = new HashMap<>();\n      instance = newInstance;\n    }\n    return instance;\n  }\n\n  /**\n   * Seed a user into Db.\n   *\n   * @param userName of the user\n   * @param amount of the user's account\n   */\n  public void seedUser(String userName, Double amount) {\n    User user = new User(userName);\n    instance.userName2User.put(userName, user);\n    Account account = new Account(amount);\n    instance.user2Account.put(user, account);\n  }\n\n  /**\n   * Seed an item into Db.\n   *\n   * @param itemName of the item\n   * @param price of the item\n   */\n  public void seedItem(String itemName, Double price) {\n    Product item = new Product(price);\n    itemName2Product.put(itemName, item);\n  }\n\n  /**\n   * Find a user with the userName.\n   *\n   * @param userName of the user\n   * @return instance of User\n   */\n  public User findUserByUserName(String userName) {\n    if (!userName2User.containsKey(userName)) {\n      return null;\n    }\n    return userName2User.get(userName);\n  }\n\n  /**\n   * Find an account of the user.\n   *\n   * @param user in Db\n   * @return instance of Account of the user\n   */\n  public Account findAccountByUser(User user) {\n    if (!user2Account.containsKey(user)) {\n      return null;\n    }\n    return user2Account.get(user);\n  }\n\n  /**\n   * Find a product with the itemName.\n   *\n   * @param itemName of the item\n   * @return instance of Product\n   */\n  public Product findProductByItemName(String itemName) {\n    if (!itemName2Product.containsKey(itemName)) {\n      return null;\n    }\n    return itemName2Product.get(itemName);\n  }\n\n  /** User class to store user info. */\n  @RequiredArgsConstructor\n  @Getter\n  public class User {\n\n    private final String userName;\n\n    public ReceiptDto purchase(Product item) {\n      return new ReceiptDto(item.getPrice());\n    }\n  }\n\n  /** Account info. */\n  @RequiredArgsConstructor\n  @Getter\n  public static class Account {\n\n    private final Double amount;\n\n    /**\n     * Withdraw the price of the item from the account.\n     *\n     * @param price of the item\n     * @return instance of MoneyTransaction\n     */\n    public MoneyTransaction withdraw(Double price) {\n      if (price > amount) {\n        return null;\n      }\n      return new MoneyTransaction(amount, price);\n    }\n  }\n\n  /** Product info. */\n  @RequiredArgsConstructor\n  @Getter\n  public static class Product {\n\n    private final Double price;\n  }\n}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/DomainServices.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\n/** DomainServices interface. */\npublic interface DomainServices {}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/DomainServicesImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\n/** Implementation of DomainServices for special case. */\npublic class DomainServicesImpl implements DomainServices {\n\n  /**\n   * Domain purchase with userName and itemName, with validation for userName.\n   *\n   * @param userName of the user\n   * @param itemName of the item\n   * @return instance of ReceiptViewModel\n   */\n  public ReceiptViewModel purchase(String userName, String itemName) {\n    Db.User user = Db.getInstance().findUserByUserName(userName);\n    if (user == null) {\n      return new InvalidUser(userName);\n    }\n\n    Db.Account account = Db.getInstance().findAccountByUser(user);\n    return purchase(user, account, itemName);\n  }\n\n  /**\n   * Domain purchase with user, account and itemName, with validation for whether product is out of\n   * stock and whether user has insufficient funds in the account.\n   *\n   * @param user in Db\n   * @param account in Db\n   * @param itemName of the item\n   * @return instance of ReceiptViewModel\n   */\n  private ReceiptViewModel purchase(Db.User user, Db.Account account, String itemName) {\n    Db.Product item = Db.getInstance().findProductByItemName(itemName);\n    if (item == null) {\n      return new OutOfStock(user.getUserName(), itemName);\n    }\n\n    ReceiptDto receipt = user.purchase(item);\n    MoneyTransaction transaction = account.withdraw(receipt.getPrice());\n    if (transaction == null) {\n      return new InsufficientFunds(user.getUserName(), account.getAmount(), itemName);\n    }\n\n    return receipt;\n  }\n}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/DownForMaintenance.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** Down for Maintenance view for the ReceiptViewModel. */\npublic class DownForMaintenance implements ReceiptViewModel {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(DownForMaintenance.class);\n\n  @Override\n  public void show() {\n    LOGGER.info(\"Down for maintenance\");\n  }\n}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/InsufficientFunds.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** View representing insufficient funds. */\n@Slf4j\npublic class InsufficientFunds implements ReceiptViewModel {\n\n  private String userName;\n  private Double amount;\n  private String itemName;\n\n  /**\n   * Constructor of InsufficientFunds.\n   *\n   * @param userName of the user\n   * @param amount of the user's account\n   * @param itemName of the item\n   */\n  public InsufficientFunds(String userName, Double amount, String itemName) {\n    this.userName = userName;\n    this.amount = amount;\n    this.itemName = itemName;\n  }\n\n  @Override\n  public void show() {\n    LOGGER.info(\n        \"Insufficient funds: \"\n            + amount\n            + \" of user: \"\n            + userName\n            + \" for buying item: \"\n            + itemName);\n  }\n}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/InvalidUser.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** Receipt View representing invalid user. */\npublic class InvalidUser implements ReceiptViewModel {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(InvalidUser.class);\n\n  private final String userName;\n\n  public InvalidUser(String userName) {\n    this.userName = userName;\n  }\n\n  @Override\n  public void show() {\n    LOGGER.info(String.format(\"Invalid user: %s\", userName));\n  }\n}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/MaintenanceLock.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\nimport lombok.Getter;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** Acquire lock on the DB for maintenance. */\npublic class MaintenanceLock {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(MaintenanceLock.class);\n\n  private static MaintenanceLock instance;\n\n  @Getter private boolean lock = true;\n\n  /**\n   * Get the instance of MaintenanceLock.\n   *\n   * @return singleton instance of MaintenanceLock\n   */\n  public static synchronized MaintenanceLock getInstance() {\n    if (instance == null) {\n      instance = new MaintenanceLock();\n    }\n    return instance;\n  }\n\n  public void setLock(boolean lock) {\n    this.lock = lock;\n    LOGGER.info(\"Maintenance lock is set to: {}\", lock);\n  }\n}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/MoneyTransaction.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\nimport lombok.RequiredArgsConstructor;\n\n/** Represents the money transaction taking place at a given moment. */\n@RequiredArgsConstructor\npublic class MoneyTransaction {\n\n  private final Double amount;\n  private final Double price;\n}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/OutOfStock.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** Receipt view for showing out of stock message. */\npublic class OutOfStock implements ReceiptViewModel {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(OutOfStock.class);\n\n  private final String userName;\n  private final String itemName;\n\n  public OutOfStock(String userName, String itemName) {\n    this.userName = userName;\n    this.itemName = itemName;\n  }\n\n  @Override\n  public void show() {\n    LOGGER.info(String.format(\"Out of stock: %s for user = %s to buy\", itemName, userName));\n  }\n}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/ReceiptDto.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** Receipt view representing the transaction recceipt. */\n@RequiredArgsConstructor\n@Getter\npublic class ReceiptDto implements ReceiptViewModel {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(ReceiptDto.class);\n\n  private final Double price;\n\n  @Override\n  public void show() {\n    LOGGER.info(String.format(\"Receipt: %s paid\", price));\n  }\n}\n"
  },
  {
    "path": "special-case/src/main/java/com/iluwatar/specialcase/ReceiptViewModel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\n/** ReceiptViewModel interface. */\npublic interface ReceiptViewModel {\n\n  void show();\n}\n"
  },
  {
    "path": "special-case/src/test/java/com/iluwatar/specialcase/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "special-case/src/test/java/com/iluwatar/specialcase/SpecialCasesTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specialcase;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport ch.qos.logback.classic.Level;\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.read.ListAppender;\nimport java.util.List;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/** Special cases unit tests. (including the successful scenario {@link ReceiptDto}) */\nclass SpecialCasesTest {\n  private static ApplicationServices applicationServices;\n  private static ReceiptViewModel receipt;\n\n  @BeforeAll\n  static void beforeAll() {\n    Db.getInstance().seedUser(\"ignite1771\", 1000.0);\n    Db.getInstance().seedItem(\"computer\", 800.0);\n    Db.getInstance().seedItem(\"car\", 20000.0);\n\n    applicationServices = new ApplicationServicesImpl();\n  }\n\n  @BeforeEach\n  void beforeEach() {\n    MaintenanceLock.getInstance().setLock(false);\n  }\n\n  @Test\n  void testDownForMaintenance() {\n    final Logger LOGGER = (Logger) LoggerFactory.getLogger(DownForMaintenance.class);\n\n    ListAppender<ILoggingEvent> listAppender = new ListAppender<>();\n    listAppender.start();\n    LOGGER.addAppender(listAppender);\n\n    MaintenanceLock.getInstance().setLock(true);\n    receipt = applicationServices.loggedInUserPurchase(null, null);\n    receipt.show();\n\n    List<ILoggingEvent> loggingEventList = listAppender.list;\n    assertEquals(\"Down for maintenance\", loggingEventList.get(0).getMessage());\n    assertEquals(Level.INFO, loggingEventList.get(0).getLevel());\n  }\n\n  @Test\n  void testInvalidUser() {\n    final Logger LOGGER = (Logger) LoggerFactory.getLogger(InvalidUser.class);\n\n    ListAppender<ILoggingEvent> listAppender = new ListAppender<>();\n    listAppender.start();\n    LOGGER.addAppender(listAppender);\n\n    receipt = applicationServices.loggedInUserPurchase(\"a\", null);\n    receipt.show();\n\n    List<ILoggingEvent> loggingEventList = listAppender.list;\n    assertEquals(\"Invalid user: a\", loggingEventList.get(0).getMessage());\n    assertEquals(Level.INFO, loggingEventList.get(0).getLevel());\n  }\n\n  @Test\n  void testOutOfStock() {\n    final Logger LOGGER = (Logger) LoggerFactory.getLogger(OutOfStock.class);\n\n    ListAppender<ILoggingEvent> listAppender = new ListAppender<>();\n    listAppender.start();\n    LOGGER.addAppender(listAppender);\n\n    receipt = applicationServices.loggedInUserPurchase(\"ignite1771\", \"tv\");\n    receipt.show();\n\n    List<ILoggingEvent> loggingEventList = listAppender.list;\n    assertEquals(\n        \"Out of stock: tv for user = ignite1771 to buy\", loggingEventList.get(0).getMessage());\n    assertEquals(Level.INFO, loggingEventList.get(0).getLevel());\n  }\n\n  @Test\n  void testInsufficientFunds() {\n    final Logger LOGGER = (Logger) LoggerFactory.getLogger(InsufficientFunds.class);\n\n    ListAppender<ILoggingEvent> listAppender = new ListAppender<>();\n    listAppender.start();\n    LOGGER.addAppender(listAppender);\n\n    receipt = applicationServices.loggedInUserPurchase(\"ignite1771\", \"car\");\n    receipt.show();\n\n    List<ILoggingEvent> loggingEventList = listAppender.list;\n    assertEquals(\n        \"Insufficient funds: 1000.0 of user: ignite1771 for buying item: car\",\n        loggingEventList.get(0).getMessage());\n    assertEquals(Level.INFO, loggingEventList.get(0).getLevel());\n  }\n\n  @Test\n  void testReceiptDto() {\n    final Logger LOGGER = (Logger) LoggerFactory.getLogger(ReceiptDto.class);\n\n    ListAppender<ILoggingEvent> listAppender = new ListAppender<>();\n    listAppender.start();\n    LOGGER.addAppender(listAppender);\n\n    receipt = applicationServices.loggedInUserPurchase(\"ignite1771\", \"computer\");\n    receipt.show();\n\n    List<ILoggingEvent> loggingEventList = listAppender.list;\n    assertEquals(\"Receipt: 800.0 paid\", loggingEventList.get(0).getMessage());\n    assertEquals(Level.INFO, loggingEventList.get(0).getLevel());\n  }\n}\n"
  },
  {
    "path": "specification/README.md",
    "content": "---\ntitle: \"Specification Pattern in Java: Enhancing Business Rules with Decoupled Logic\"\nshortTitle: Specification\ndescription: \"Dive deep into the Specification design pattern in Java, a strategic solution for encapsulating business rules. Learn how to implement, combine, and apply this pattern effectively in your software development projects.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Business\n  - Domain\n  - Encapsulation\n  - Enterprise patterns\n  - Extensibility\n---\n\n## Also known as\n\n* Filter\n* Criteria\n\n## Intent of Specification Design Pattern\n\nEncapsulate business rules and criteria that an object must satisfy to enable checking these rules in various parts of the application.\n\n## Detailed Explanation of Specification Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine you are organizing a conference and need to filter attendees based on specific criteria such as registration status, payment completion, and session interests.\n> \n> Using the Specification design pattern, you would create separate specifications for each criterion (e.g., \"IsRegistered\", \"HasPaid\", \"IsInterestedInSessionX\"). These specifications can be combined dynamically to filter attendees who meet all the required criteria, such as those who are registered, have completed their payment, and are interested in a particular session. This approach allows for flexible and reusable business rules, ensuring that the filtering logic can be easily adjusted as needed without changing the underlying attendee objects.\n\nIn plain words\n\n> The Specification design pattern in Java enables the efficient encapsulation and reuse of business rules, offering a flexible and dynamic way to combine criteria for robust software development\n\nWikipedia says\n\n> In computer programming, the specification pattern is a particular software design pattern, whereby business rules can be recombined by chaining the business rules together using boolean logic.\n\nFlowchart\n\n![Specification Pattern flowchart](./etc/specification-flowchart.png)\n\n## Programmatic Example of Specification Pattern in Java\n\nLet's consider a creature pool example. We have a collection of creatures with specific properties. These properties might belong to a predefined, limited set (represented by enums like `Size`, `Movement`, and `Color`) or they might be continuous values (e.g., the mass of a `Creature`). In cases with continuous values, it's better to use a \"parameterized specification,\" where the property value is provided as an argument when the `Creature` is instantiated, allowing for greater flexibility. Additionally, predefined and/or parameterized properties can be combined using boolean logic, offering almost limitless selection possibilities (this is known as a \"composite specification,\" explained further below). The advantages and disadvantages of each approach are detailed in the table at the end of this document.\n\nFirst, here is interface `Creature`.\n\n```java\npublic interface Creature {\n    String getName();\n\n    Size getSize();\n\n    Movement getMovement();\n\n    Color getColor();\n\n    Mass getMass();\n}\n```\n\nAnd `Dragon` implementation looks like this.\n\n```java\npublic class Dragon extends AbstractCreature {\n\n  public Dragon() {\n    super(\"Dragon\", Size.LARGE, Movement.FLYING, Color.RED, new Mass(39300.0));\n  }\n}\n```\n\nNow that we want to select some subset of them, we use selectors. To select creatures that fly, we should use `MovementSelector`. The snippet also shows the base class `AbstractSelector`.\n\n```java\npublic abstract class AbstractSelector<T> implements Predicate<T> {\n\n    public AbstractSelector<T> and(AbstractSelector<T> other) {\n        return new ConjunctionSelector<>(this, other);\n    }\n\n    public AbstractSelector<T> or(AbstractSelector<T> other) {\n        return new DisjunctionSelector<>(this, other);\n    }\n\n    public AbstractSelector<T> not() {\n        return new NegationSelector<>(this);\n    }\n}\n```\n\n```java\npublic class MovementSelector extends AbstractSelector<Creature> {\n\n  private final Movement movement;\n\n  public MovementSelector(Movement m) {\n    this.movement = m;\n  }\n\n  @Override\n  public boolean test(Creature t) {\n    return t.getMovement().equals(movement);\n  }\n}\n```\n\nOn the other hand, when selecting creatures heavier than a chosen amount, we use `MassGreaterThanSelector`.\n\n```java\npublic class MassGreaterThanSelector extends AbstractSelector<Creature> {\n\n  private final Mass mass;\n\n  public MassGreaterThanSelector(double mass) {\n    this.mass = new Mass(mass);\n  }\n\n  @Override\n  public boolean test(Creature t) {\n    return t.getMass().greaterThan(mass);\n  }\n}\n```\n\nWith these building blocks in place, we can perform some searches.\n\n```java\n@Slf4j\npublic class App {\n\n  public static void main(String[] args) {\n    // initialize creatures list\n    var creatures = List.of(\n        new Goblin(),\n        new Octopus(),\n        new Dragon(),\n        new Shark(),\n        new Troll(),\n        new KillerBee()\n    );\n    // so-called \"hard-coded\" specification\n    LOGGER.info(\"Demonstrating hard-coded specification :\");\n    // find all walking creatures\n    LOGGER.info(\"Find all walking creatures\");\n    print(creatures, new MovementSelector(Movement.WALKING));\n    // find all dark creatures\n    LOGGER.info(\"Find all dark creatures\");\n    print(creatures, new ColorSelector(Color.DARK));\n    LOGGER.info(\"\\n\");\n    // so-called \"parameterized\" specification\n    LOGGER.info(\"Demonstrating parameterized specification :\");\n    // find all creatures heavier than 500kg\n    LOGGER.info(\"Find all creatures heavier than 600kg\");\n    print(creatures, new MassGreaterThanSelector(600.0));\n    // find all creatures heavier than 500kg\n    LOGGER.info(\"Find all creatures lighter than or weighing exactly 500kg\");\n    print(creatures, new MassSmallerThanOrEqSelector(500.0));\n    LOGGER.info(\"\\n\");\n    // so-called \"composite\" specification\n    LOGGER.info(\"Demonstrating composite specification :\");\n    // find all red and flying creatures\n    LOGGER.info(\"Find all red and flying creatures\");\n    var redAndFlying = new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING));\n    print(creatures, redAndFlying);\n    // find all creatures dark or red, non-swimming, and heavier than or equal to 400kg\n    LOGGER.info(\"Find all scary creatures\");\n    var scaryCreaturesSelector = new ColorSelector(Color.DARK)\n        .or(new ColorSelector(Color.RED)).and(new MovementSelector(Movement.SWIMMING).not())\n        .and(new MassGreaterThanSelector(400.0).or(new MassEqualSelector(400.0)));\n    print(creatures, scaryCreaturesSelector);\n  }\n\n  private static void print(List<? extends Creature> creatures, Predicate<Creature> selector) {\n    creatures.stream().filter(selector).map(Objects::toString).forEach(LOGGER::info);\n  }\n}\n```\n\nConsole output:\n\n```\n12:49:24.808 [main] INFO com.iluwatar.specification.app.App -- Demonstrating hard-coded specification :\n12:49:24.810 [main] INFO com.iluwatar.specification.app.App -- Find all walking creatures\n12:49:24.812 [main] INFO com.iluwatar.specification.app.App -- Goblin [size=small, movement=walking, color=green, mass=30.0kg]\n12:49:24.812 [main] INFO com.iluwatar.specification.app.App -- Troll [size=large, movement=walking, color=dark, mass=4000.0kg]\n12:49:24.812 [main] INFO com.iluwatar.specification.app.App -- Find all dark creatures\n12:49:24.815 [main] INFO com.iluwatar.specification.app.App -- Octopus [size=normal, movement=swimming, color=dark, mass=12.0kg]\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- Troll [size=large, movement=walking, color=dark, mass=4000.0kg]\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- \n\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- Demonstrating parameterized specification :\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- Find all creatures heavier than 600kg\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- Dragon [size=large, movement=flying, color=red, mass=39300.0kg]\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- Troll [size=large, movement=walking, color=dark, mass=4000.0kg]\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- Find all creatures lighter than or weighing exactly 500kg\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- Goblin [size=small, movement=walking, color=green, mass=30.0kg]\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- Octopus [size=normal, movement=swimming, color=dark, mass=12.0kg]\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- Shark [size=normal, movement=swimming, color=light, mass=500.0kg]\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- KillerBee [size=small, movement=flying, color=light, mass=6.7kg]\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- \n\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- Demonstrating composite specification :\n12:49:24.816 [main] INFO com.iluwatar.specification.app.App -- Find all red and flying creatures\n12:49:24.817 [main] INFO com.iluwatar.specification.app.App -- Dragon [size=large, movement=flying, color=red, mass=39300.0kg]\n12:49:24.817 [main] INFO com.iluwatar.specification.app.App -- Find all scary creatures\n12:49:24.818 [main] INFO com.iluwatar.specification.app.App -- Dragon [size=large, movement=flying, color=red, mass=39300.0kg]\n12:49:24.818 [main] INFO com.iluwatar.specification.app.App -- Troll [size=large, movement=walking, color=dark, mass=4000.0kg]\n```\n\nAdopting the Specification pattern significantly enhances the flexibility and reusability of business rules within Java applications, contributing to more maintainable code.\n\n## When to Use the Specification Pattern in Java\n\nApply the Java Specification pattern when\n\n* You need to filter objects based on different criteria.\n* The filtering criteria can change dynamically.\n* Ideal for use cases involving complex business rules that must be reused across different parts of an application.\n\n## Real-World Applications of Specification Pattern in Java\n\n* Validating user inputs in enterprise applications.\n* Filtering search results in e-commerce applications.\n* Business rule validation in domain-driven design (DDD).\n\n## Benefits and Trade-offs of Specification Pattern\n\nBenefits:\n\n* Enhances the flexibility and reusability of business rules.\n* Promotes [single responsibility principle](https://java-design-patterns.com/principles/#single-responsibility-principle) by separating business rules from the entities.\n* Facilitates unit testing of business rules.\n\nTrade-offs:\n\n* Can lead to a proliferation of small classes, increasing complexity.\n* Might introduce performance overhead due to the dynamic checking of specifications.\n\n## Related Java Design Patterns\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): Often used together with Specification to combine multiple specifications.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Can be used to add additional criteria to a specification dynamically.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Both patterns involve encapsulating a family of algorithms. Strategy encapsulates different strategies or algorithms, while Specification encapsulates business rules.\n\n## References and Credits\n\n* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3wlDrze)\n* [Implementing Domain-Driven Design](https://amzn.to/4dmBjrB)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Specifications (Martin Fowler)](http://martinfowler.com/apsupp/spec.pdf)\n"
  },
  {
    "path": "specification/etc/specification.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.creature.KillerBee\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/creature/KillerBee.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"127\" x=\"535\" y=\"361\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <enumeration id=\"2\" language=\"java\" name=\"com.iluwatar.property.Size\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/property/Size.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"423\" y=\"450\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.creature.Troll\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/creature/Troll.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"127\" x=\"702\" y=\"361\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.selector.SizeSelector\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/selector/SizeSelector.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"423\" y=\"179\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.selector.MovementSelector\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/selector/MovementSelector.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"230\" y=\"179\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.creature.Shark\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/creature/Shark.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"127\" x=\"869\" y=\"361\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.creature.Dragon\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/creature/Dragon.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"127\" x=\"1036\" y=\"361\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.creature.AbstractCreature\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/creature/AbstractCreature.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1101\" y=\"222\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"9\" language=\"java\" name=\"com.iluwatar.creature.Octopus\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/creature/Octopus.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"88\" width=\"127\" x=\"1203\" y=\"361\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"10\" language=\"java\" name=\"com.iluwatar.selector.ColorSelector\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/selector/ColorSelector.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1647\" y=\"223\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"11\" language=\"java\" name=\"com.iluwatar.creature.Creature\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/creature/Creature.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"717\" y=\"223\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <enumeration id=\"12\" language=\"java\" name=\"com.iluwatar.property.Movement\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/property/Movement.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"230\" y=\"450\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>  \n  <class id=\"13\" language=\"java\" name=\"com.iluwatar.creature.Goblin\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/creature/Goblin.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1447\" y=\"405\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>\n  <enumeration id=\"14\" language=\"java\" name=\"com.iluwatar.property.Color\" project=\"specification\" \n    file=\"/specification/src/main/java/com/iluwatar/property/Color.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"1416\" y=\"223\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </enumeration>\n  <generalization id=\"15\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </generalization>  \n  <generalization id=\"16\">    \n    <end type=\"SOURCE\" refId=\"6\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </generalization>  \n  <generalization id=\"17\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </generalization>  \n  <association id=\"18\">    \n    <end type=\"SOURCE\" refId=\"8\" navigable=\"false\">      \n      <attribute id=\"19\" name=\"size\"/>      \n      <multiplicity id=\"20\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"21\">    \n    <end type=\"SOURCE\" refId=\"8\" navigable=\"false\">      \n      <attribute id=\"22\" name=\"movement\"/>      \n      <multiplicity id=\"23\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"12\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"24\">    \n    <end type=\"SOURCE\" refId=\"9\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </generalization>  \n  <association id=\"25\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"26\" name=\"s\"/>      \n      <multiplicity id=\"27\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"28\">    \n    <end type=\"SOURCE\" refId=\"8\" navigable=\"false\">      \n      <attribute id=\"29\" name=\"color\"/>      \n      <multiplicity id=\"30\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"14\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"31\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </generalization>  \n  <realization id=\"32\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"11\"/>  \n  </realization>  \n  <generalization id=\"33\">    \n    <end type=\"SOURCE\" refId=\"13\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </generalization>\n  <association id=\"34\">\n    <end type=\"SOURCE\" refId=\"5\" navigable=\"false\">      \n      <attribute id=\"35\" name=\"m\"/>\n      <multiplicity id=\"36\" minimum=\"0\" maximum=\"1\"/>\n    </end>\n    <end type=\"TARGET\" refId=\"12\" navigable=\"true\"/>\n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"37\">    \n    <end type=\"SOURCE\" refId=\"10\" navigable=\"false\">      \n      <attribute id=\"38\" name=\"c\"/>      \n      <multiplicity id=\"39\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"14\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>\n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "specification/etc/specification.urm.puml",
    "content": "@startuml\npackage com.iluwatar.specification.creature {\n  abstract class AbstractCreature {\n    - color : Color\n    - mass : Mass\n    - movement : Movement\n    - name : String\n    - size : Size\n    + AbstractCreature(name : String, size : Size, movement : Movement, color : Color, mass : Mass)\n    + getColor() : Color\n    + getMass() : Mass\n    + getMovement() : Movement\n    + getName() : String\n    + getSize() : Size\n    + toString() : String\n  }\n  interface Creature {\n    + getColor() : Color {abstract}\n    + getMass() : Mass {abstract}\n    + getMovement() : Movement {abstract}\n    + getName() : String {abstract}\n    + getSize() : Size {abstract}\n  }\n  class Dragon {\n    + Dragon()\n    + Dragon(mass : Mass)\n  }\n  class Goblin {\n    + Goblin()\n    + Goblin(mass : Mass)\n  }\n  class KillerBee {\n    + KillerBee()\n    + KillerBee(mass : Mass)\n  }\n  class Octopus {\n    + Octopus()\n    + Octopus(mass : Mass)\n  }\n  class Shark {\n    + Shark()\n    + Shark(mass : Mass)\n  }\n  class Troll {\n    + Troll()\n    + Troll(mass : Mass)\n  }\n}\npackage com.iluwatar.specification.property {\n  enum Color {\n    + DARK {static}\n    + GREEN {static}\n    + LIGHT {static}\n    + RED {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Color {static}\n    + values() : Color[] {static}\n  }\n  class Mass {\n    - title : String\n    - value : double\n    + Mass(value : double)\n    + equals(obj : Object) : boolean\n    + greaterThan(other : Mass) : boolean\n    + greaterThanOrEq(other : Mass) : boolean\n    + smallerThan(other : Mass) : boolean\n    + smallerThanOrEq(other : Mass) : boolean\n    + toString() : String\n  }\n  enum Movement {\n    + FLYING {static}\n    + SWIMMING {static}\n    + WALKING {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Movement {static}\n    + values() : Movement[] {static}\n  }\n  enum Size {\n    + LARGE {static}\n    + NORMAL {static}\n    + SMALL {static}\n    - title : String\n    + toString() : String\n    + valueOf(name : String) : Size {static}\n    + values() : Size[] {static}\n  }\n}\npackage com.iluwatar.specification.selector {\n  abstract class AbstractSelector<T> {\n    + AbstractSelector<T>()\n    + and(other : AbstractSelector<T>) : AbstractSelector<T>\n    + not() : AbstractSelector<T>\n    + or(other : AbstractSelector<T>) : AbstractSelector<T>\n  }\n  class ColorSelector {\n    - color : Color\n    + ColorSelector(c : Color)\n    + test(t : Creature) : boolean\n  }\n  class ConjunctionSelector<T> {\n    - leafComponents : List<AbstractSelector<T>>\n    ~ ConjunctionSelector<T>(selectors : AbstractSelector<T>[])\n    + test(t : T) : boolean\n  }\n  class DisjunctionSelector<T> {\n    - leafComponents : List<AbstractSelector<T>>\n    ~ DisjunctionSelector<T>(selectors : AbstractSelector<T>[])\n    + test(t : T) : boolean\n  }\n  class MassEqualSelector {\n    - mass : Mass\n    + MassEqualSelector(mass : double)\n    + test(t : Creature) : boolean\n  }\n  class MassGreaterThanSelector {\n    - mass : Mass\n    + MassGreaterThanSelector(mass : double)\n    + test(t : Creature) : boolean\n  }\n  class MassSmallerThanOrEqSelector {\n    - mass : Mass\n    + MassSmallerThanOrEqSelector(mass : double)\n    + test(t : Creature) : boolean\n  }\n  class MovementSelector {\n    - movement : Movement\n    + MovementSelector(m : Movement)\n    + test(t : Creature) : boolean\n  }\n  class NegationSelector<T> {\n    - component : AbstractSelector<T>\n    ~ NegationSelector<T>(selector : AbstractSelector<T>)\n    + test(t : T) : boolean\n  }\n  class SizeSelector {\n    - size : Size\n    + SizeSelector(s : Size)\n    + test(t : Creature) : boolean\n  }\n}\npackage com.iluwatar.specification.app {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n}\nSizeSelector -->  \"-size\" Size\nAbstractCreature -->  \"-mass\" Mass\nMassEqualSelector -->  \"-mass\" Mass\nAbstractCreature -->  \"-color\" Color\nMassGreaterThanSelector -->  \"-mass\" Mass\nMovementSelector -->  \"-movement\" Movement\nNegationSelector -->  \"-component\" AbstractSelector\nAbstractCreature -->  \"-movement\" Movement\nMassSmallerThanOrEqSelector -->  \"-mass\" Mass\nAbstractCreature -->  \"-size\" Size\nColorSelector -->  \"-color\" Color\nAbstractCreature ..|> Creature \nDragon --|> AbstractCreature \nGoblin --|> AbstractCreature \nKillerBee --|> AbstractCreature \nOctopus --|> AbstractCreature \nShark --|> AbstractCreature \nTroll --|> AbstractCreature \nColorSelector --|> AbstractSelector \nConjunctionSelector --|> AbstractSelector \nDisjunctionSelector --|> AbstractSelector \nMassEqualSelector --|> AbstractSelector \nMassGreaterThanSelector --|> AbstractSelector \nMassSmallerThanOrEqSelector --|> AbstractSelector \nMovementSelector --|> AbstractSelector \nNegationSelector --|> AbstractSelector \nSizeSelector --|> AbstractSelector \n@enduml"
  },
  {
    "path": "specification/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>specification</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-params</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.specification.app.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/app/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.app;\n\nimport com.iluwatar.specification.creature.Creature;\nimport com.iluwatar.specification.creature.Dragon;\nimport com.iluwatar.specification.creature.Goblin;\nimport com.iluwatar.specification.creature.KillerBee;\nimport com.iluwatar.specification.creature.Octopus;\nimport com.iluwatar.specification.creature.Shark;\nimport com.iluwatar.specification.creature.Troll;\nimport com.iluwatar.specification.property.Color;\nimport com.iluwatar.specification.property.Movement;\nimport com.iluwatar.specification.selector.ColorSelector;\nimport com.iluwatar.specification.selector.MassEqualSelector;\nimport com.iluwatar.specification.selector.MassGreaterThanSelector;\nimport com.iluwatar.specification.selector.MassSmallerThanOrEqSelector;\nimport com.iluwatar.specification.selector.MovementSelector;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.function.Predicate;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The central idea of the Specification pattern is to separate the statement of how to match a\n * candidate, from the candidate object that it is matched against. As well as its usefulness in\n * selection, it is also valuable for validation and for building to order.\n *\n * <p>In this example we have a pool of creatures with different properties. We then have defined\n * separate selection rules (Specifications) that we apply to the collection and as output receive\n * only the creatures that match the selection criteria.\n *\n * <p>http://martinfowler.com/apsupp/spec.pdf\n */\n@Slf4j\npublic class App {\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n    // initialize creatures list\n    var creatures =\n        List.of(\n            new Goblin(), new Octopus(), new Dragon(), new Shark(), new Troll(), new KillerBee());\n    // so-called \"hard-coded\" specification\n    LOGGER.info(\"Demonstrating hard-coded specification :\");\n    // find all walking creatures\n    LOGGER.info(\"Find all walking creatures\");\n    print(creatures, new MovementSelector(Movement.WALKING));\n    // find all dark creatures\n    LOGGER.info(\"Find all dark creatures\");\n    print(creatures, new ColorSelector(Color.DARK));\n    LOGGER.info(\"\\n\");\n    // so-called \"parameterized\" specification\n    LOGGER.info(\"Demonstrating parameterized specification :\");\n    // find all creatures heavier than 500kg\n    LOGGER.info(\"Find all creatures heavier than 600kg\");\n    print(creatures, new MassGreaterThanSelector(600.0));\n    // find all creatures heavier than 500kg\n    LOGGER.info(\"Find all creatures lighter than or weighing exactly 500kg\");\n    print(creatures, new MassSmallerThanOrEqSelector(500.0));\n    LOGGER.info(\"\\n\");\n    // so-called \"composite\" specification\n    LOGGER.info(\"Demonstrating composite specification :\");\n    // find all red and flying creatures\n    LOGGER.info(\"Find all red and flying creatures\");\n    var redAndFlying = new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING));\n    print(creatures, redAndFlying);\n    // find all creatures dark or red, non-swimming, and heavier than or equal to 400kg\n    LOGGER.info(\"Find all scary creatures\");\n    var scaryCreaturesSelector =\n        new ColorSelector(Color.DARK)\n            .or(new ColorSelector(Color.RED))\n            .and(new MovementSelector(Movement.SWIMMING).not())\n            .and(new MassGreaterThanSelector(400.0).or(new MassEqualSelector(400.0)));\n    print(creatures, scaryCreaturesSelector);\n  }\n\n  private static void print(List<? extends Creature> creatures, Predicate<Creature> selector) {\n    creatures.stream().filter(selector).map(Objects::toString).forEach(LOGGER::info);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.creature;\n\nimport com.iluwatar.specification.property.Color;\nimport com.iluwatar.specification.property.Mass;\nimport com.iluwatar.specification.property.Movement;\nimport com.iluwatar.specification.property.Size;\n\n/** Base class for concrete creatures. */\npublic abstract class AbstractCreature implements Creature {\n\n  private final String name;\n  private final Size size;\n  private final Movement movement;\n  private final Color color;\n  private final Mass mass;\n\n  /** Constructor. */\n  public AbstractCreature(String name, Size size, Movement movement, Color color, Mass mass) {\n    this.name = name;\n    this.size = size;\n    this.movement = movement;\n    this.color = color;\n    this.mass = mass;\n  }\n\n  @Override\n  public String toString() {\n    return String.format(\n        \"%s [size=%s, movement=%s, color=%s, mass=%s]\", name, size, movement, color, mass);\n  }\n\n  @Override\n  public String getName() {\n    return name;\n  }\n\n  @Override\n  public Size getSize() {\n    return size;\n  }\n\n  @Override\n  public Movement getMovement() {\n    return movement;\n  }\n\n  @Override\n  public Color getColor() {\n    return color;\n  }\n\n  @Override\n  public Mass getMass() {\n    return mass;\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/creature/Creature.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.creature;\n\nimport com.iluwatar.specification.property.Color;\nimport com.iluwatar.specification.property.Mass;\nimport com.iluwatar.specification.property.Movement;\nimport com.iluwatar.specification.property.Size;\n\n/** Creature interface. */\npublic interface Creature {\n\n  String getName();\n\n  Size getSize();\n\n  Movement getMovement();\n\n  Color getColor();\n\n  Mass getMass();\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/creature/Dragon.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.creature;\n\nimport com.iluwatar.specification.property.Color;\nimport com.iluwatar.specification.property.Mass;\nimport com.iluwatar.specification.property.Movement;\nimport com.iluwatar.specification.property.Size;\n\n/** Dragon creature. */\npublic class Dragon extends AbstractCreature {\n\n  public Dragon() {\n    this(new Mass(39300.0));\n  }\n\n  public Dragon(Mass mass) {\n    super(\"Dragon\", Size.LARGE, Movement.FLYING, Color.RED, mass);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/creature/Goblin.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.creature;\n\nimport com.iluwatar.specification.property.Color;\nimport com.iluwatar.specification.property.Mass;\nimport com.iluwatar.specification.property.Movement;\nimport com.iluwatar.specification.property.Size;\n\n/** Goblin creature. */\npublic class Goblin extends AbstractCreature {\n\n  public Goblin() {\n    this(new Mass(30.0));\n  }\n\n  public Goblin(Mass mass) {\n    super(\"Goblin\", Size.SMALL, Movement.WALKING, Color.GREEN, mass);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.creature;\n\nimport com.iluwatar.specification.property.Color;\nimport com.iluwatar.specification.property.Mass;\nimport com.iluwatar.specification.property.Movement;\nimport com.iluwatar.specification.property.Size;\n\n/** KillerBee creature. */\npublic class KillerBee extends AbstractCreature {\n\n  public KillerBee() {\n    this(new Mass(6.7));\n  }\n\n  public KillerBee(Mass mass) {\n    super(\"KillerBee\", Size.SMALL, Movement.FLYING, Color.LIGHT, mass);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/creature/Octopus.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.creature;\n\nimport com.iluwatar.specification.property.Color;\nimport com.iluwatar.specification.property.Mass;\nimport com.iluwatar.specification.property.Movement;\nimport com.iluwatar.specification.property.Size;\n\n/** Octopus creature. */\npublic class Octopus extends AbstractCreature {\n\n  public Octopus() {\n    this(new Mass(12.0));\n  }\n\n  public Octopus(Mass mass) {\n    super(\"Octopus\", Size.NORMAL, Movement.SWIMMING, Color.DARK, mass);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/creature/Shark.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.creature;\n\nimport com.iluwatar.specification.property.Color;\nimport com.iluwatar.specification.property.Mass;\nimport com.iluwatar.specification.property.Movement;\nimport com.iluwatar.specification.property.Size;\n\n/** Shark creature. */\npublic class Shark extends AbstractCreature {\n\n  public Shark() {\n    this(new Mass(500.0));\n  }\n\n  public Shark(Mass mass) {\n    super(\"Shark\", Size.NORMAL, Movement.SWIMMING, Color.LIGHT, mass);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/creature/Troll.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.creature;\n\nimport com.iluwatar.specification.property.Color;\nimport com.iluwatar.specification.property.Mass;\nimport com.iluwatar.specification.property.Movement;\nimport com.iluwatar.specification.property.Size;\n\n/** Troll creature. */\npublic class Troll extends AbstractCreature {\n\n  public Troll() {\n    this(new Mass(4000.0));\n  }\n\n  public Troll(Mass mass) {\n    super(\"Troll\", Size.LARGE, Movement.WALKING, Color.DARK, mass);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/property/Color.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.property;\n\n/** Color property. */\npublic enum Color {\n  DARK(\"dark\"),\n  LIGHT(\"light\"),\n  GREEN(\"green\"),\n  RED(\"red\");\n\n  private final String title;\n\n  Color(String title) {\n    this.title = title;\n  }\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/property/Mass.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.property;\n\nimport lombok.EqualsAndHashCode;\n\n/** Mass property. */\n@EqualsAndHashCode\npublic class Mass {\n\n  private final double value;\n  private final String title;\n\n  public Mass(double value) {\n    this.value = value;\n    this.title = value + \"kg\"; // Implicit call to Double.toString(value)\n  }\n\n  public final boolean greaterThan(Mass other) {\n    return this.value > other.value;\n  }\n\n  public final boolean smallerThan(Mass other) {\n    return this.value < other.value;\n  }\n\n  public final boolean greaterThanOrEq(Mass other) {\n    return this.value >= other.value;\n  }\n\n  public final boolean smallerThanOrEq(Mass other) {\n    return this.value <= other.value;\n  }\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/property/Movement.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.property;\n\n/** Movement property. */\npublic enum Movement {\n  WALKING(\"walking\"),\n  SWIMMING(\"swimming\"),\n  FLYING(\"flying\");\n\n  private final String title;\n\n  Movement(String title) {\n    this.title = title;\n  }\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/property/Size.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.property;\n\n/** Size property. */\npublic enum Size {\n  SMALL(\"small\"),\n  NORMAL(\"normal\"),\n  LARGE(\"large\");\n\n  private final String title;\n\n  Size(String title) {\n    this.title = title;\n  }\n\n  @Override\n  public String toString() {\n    return title;\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/selector/AbstractSelector.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport java.util.function.Predicate;\n\n/** Base class for selectors. */\npublic abstract class AbstractSelector<T> implements Predicate<T> {\n\n  public AbstractSelector<T> and(AbstractSelector<T> other) {\n    return new ConjunctionSelector<>(this, other);\n  }\n\n  public AbstractSelector<T> or(AbstractSelector<T> other) {\n    return new DisjunctionSelector<>(this, other);\n  }\n\n  public AbstractSelector<T> not() {\n    return new NegationSelector<>(this);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/selector/ColorSelector.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport com.iluwatar.specification.creature.Creature;\nimport com.iluwatar.specification.property.Color;\n\n/** Color selector. */\npublic class ColorSelector extends AbstractSelector<Creature> {\n\n  private final Color color;\n\n  public ColorSelector(Color c) {\n    this.color = c;\n  }\n\n  @Override\n  public boolean test(Creature t) {\n    return t.getColor().equals(color);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/selector/ConjunctionSelector.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport java.util.List;\n\n/** A Selector defined as the conjunction (AND) of other (leaf) selectors. */\npublic class ConjunctionSelector<T> extends AbstractSelector<T> {\n\n  private final List<AbstractSelector<T>> leafComponents;\n\n  @SafeVarargs\n  ConjunctionSelector(AbstractSelector<T>... selectors) {\n    this.leafComponents = List.of(selectors);\n  }\n\n  /** Tests if *all* selectors pass the test. */\n  @Override\n  public boolean test(T t) {\n    return leafComponents.stream().allMatch(comp -> (comp.test(t)));\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/selector/DisjunctionSelector.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport java.util.List;\n\n/** A Selector defined as the disjunction (OR) of other (leaf) selectors. */\npublic class DisjunctionSelector<T> extends AbstractSelector<T> {\n\n  private final List<AbstractSelector<T>> leafComponents;\n\n  @SafeVarargs\n  DisjunctionSelector(AbstractSelector<T>... selectors) {\n    this.leafComponents = List.of(selectors);\n  }\n\n  /** Tests if *at least one* selector passes the test. */\n  @Override\n  public boolean test(T t) {\n    return leafComponents.stream().anyMatch(comp -> comp.test(t));\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/selector/MassEqualSelector.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport com.iluwatar.specification.creature.Creature;\nimport com.iluwatar.specification.property.Mass;\n\n/** Mass selector for values exactly equal than the parameter. */\npublic class MassEqualSelector extends AbstractSelector<Creature> {\n\n  private final Mass mass;\n\n  /** The use of a double as a parameter will spare some typing when instantiating this class. */\n  public MassEqualSelector(double mass) {\n    this.mass = new Mass(mass);\n  }\n\n  @Override\n  public boolean test(Creature t) {\n    return t.getMass().equals(mass);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/selector/MassGreaterThanSelector.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport com.iluwatar.specification.creature.Creature;\nimport com.iluwatar.specification.property.Mass;\n\n/** Mass selector for values greater than the parameter. */\npublic class MassGreaterThanSelector extends AbstractSelector<Creature> {\n\n  private final Mass mass;\n\n  /** The use of a double as a parameter will spare some typing when instantiating this class. */\n  public MassGreaterThanSelector(double mass) {\n    this.mass = new Mass(mass);\n  }\n\n  @Override\n  public boolean test(Creature t) {\n    return t.getMass().greaterThan(mass);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/selector/MassSmallerThanOrEqSelector.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport com.iluwatar.specification.creature.Creature;\nimport com.iluwatar.specification.property.Mass;\n\n/** Mass selector for values smaller or equal to the parameter. */\npublic class MassSmallerThanOrEqSelector extends AbstractSelector<Creature> {\n\n  private final Mass mass;\n\n  /** The use of a double as a parameter will spare some typing when instantiating this class. */\n  public MassSmallerThanOrEqSelector(double mass) {\n    this.mass = new Mass(mass);\n  }\n\n  @Override\n  public boolean test(Creature t) {\n    return t.getMass().smallerThanOrEq(mass);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/selector/MovementSelector.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport com.iluwatar.specification.creature.Creature;\nimport com.iluwatar.specification.property.Movement;\n\n/** Movement selector. */\npublic class MovementSelector extends AbstractSelector<Creature> {\n\n  private final Movement movement;\n\n  public MovementSelector(Movement m) {\n    this.movement = m;\n  }\n\n  @Override\n  public boolean test(Creature t) {\n    return t.getMovement().equals(movement);\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/selector/NegationSelector.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\n/**\n * A Selector defined as the negation (NOT) of a (leaf) selectors. This is of course only useful\n * when used in combination with other composite selectors.\n */\npublic class NegationSelector<T> extends AbstractSelector<T> {\n\n  private final AbstractSelector<T> component;\n\n  NegationSelector(AbstractSelector<T> selector) {\n    this.component = selector;\n  }\n\n  /** Tests if the selector fails the test (yes). */\n  @Override\n  public boolean test(T t) {\n    return !(component.test(t));\n  }\n}\n"
  },
  {
    "path": "specification/src/main/java/com/iluwatar/specification/selector/SizeSelector.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport com.iluwatar.specification.creature.Creature;\nimport com.iluwatar.specification.property.Size;\n\n/** Size selector. */\npublic class SizeSelector extends AbstractSelector<Creature> {\n\n  private final Size size;\n\n  public SizeSelector(Size s) {\n    this.size = s;\n  }\n\n  @Override\n  public boolean test(Creature t) {\n    return t.getSize().equals(size);\n  }\n}\n"
  },
  {
    "path": "specification/src/test/java/com/iluwatar/specification/app/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.app;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.creature;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport com.iluwatar.specification.property.Color;\nimport com.iluwatar.specification.property.Mass;\nimport com.iluwatar.specification.property.Movement;\nimport com.iluwatar.specification.property.Size;\nimport java.util.Collection;\nimport java.util.List;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\n\n/** CreatureTest */\nclass CreatureTest {\n\n  /**\n   * @return The tested {@link Creature} instance and its expected specs\n   */\n  public static Collection<Object[]> dataProvider() {\n    return List.of(\n        new Object[] {\n          new Dragon(), \"Dragon\", Size.LARGE, Movement.FLYING, Color.RED, new Mass(39300.0)\n        },\n        new Object[] {\n          new Goblin(), \"Goblin\", Size.SMALL, Movement.WALKING, Color.GREEN, new Mass(30.0)\n        },\n        new Object[] {\n          new KillerBee(), \"KillerBee\", Size.SMALL, Movement.FLYING, Color.LIGHT, new Mass(6.7)\n        },\n        new Object[] {\n          new Octopus(), \"Octopus\", Size.NORMAL, Movement.SWIMMING, Color.DARK, new Mass(12.0)\n        },\n        new Object[] {\n          new Shark(), \"Shark\", Size.NORMAL, Movement.SWIMMING, Color.LIGHT, new Mass(500.0)\n        },\n        new Object[] {\n          new Troll(), \"Troll\", Size.LARGE, Movement.WALKING, Color.DARK, new Mass(4000.0)\n        });\n  }\n\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testGetName(Creature testedCreature, String name) {\n    assertEquals(name, testedCreature.getName());\n  }\n\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testGetSize(Creature testedCreature, String name, Size size) {\n    assertEquals(size, testedCreature.getSize());\n  }\n\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testGetMovement(Creature testedCreature, String name, Size size, Movement movement) {\n    assertEquals(movement, testedCreature.getMovement());\n  }\n\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testGetColor(\n      Creature testedCreature, String name, Size size, Movement movement, Color color) {\n    assertEquals(color, testedCreature.getColor());\n  }\n\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testGetMass(\n      Creature testedCreature, String name, Size size, Movement movement, Color color, Mass mass) {\n    assertEquals(mass, testedCreature.getMass());\n  }\n\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testToString(\n      Creature testedCreature, String name, Size size, Movement movement, Color color, Mass mass) {\n    final var toString = testedCreature.toString();\n    assertNotNull(toString);\n    assertEquals(\n        String.format(\n            \"%s [size=%s, movement=%s, color=%s, mass=%s]\", name, size, movement, color, mass),\n        toString);\n  }\n}\n"
  },
  {
    "path": "specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.specification.creature.Creature;\nimport com.iluwatar.specification.property.Color;\nimport org.junit.jupiter.api.Test;\n\n/** ColorSelectorTest */\nclass ColorSelectorTest {\n\n  /** Verify if the color selector gives the correct results */\n  @Test\n  void testColor() {\n    final var greenCreature = mock(Creature.class);\n    when(greenCreature.getColor()).thenReturn(Color.GREEN);\n\n    final var redCreature = mock(Creature.class);\n    when(redCreature.getColor()).thenReturn(Color.RED);\n\n    final var greenSelector = new ColorSelector(Color.GREEN);\n    assertTrue(greenSelector.test(greenCreature));\n    assertFalse(greenSelector.test(redCreature));\n  }\n}\n"
  },
  {
    "path": "specification/src/test/java/com/iluwatar/specification/selector/CompositeSelectorsTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.specification.creature.Creature;\nimport com.iluwatar.specification.property.Mass;\nimport com.iluwatar.specification.property.Movement;\nimport org.junit.jupiter.api.Test;\n\nclass CompositeSelectorsTest {\n\n  /** Verify if the conjunction selector gives the correct results. */\n  @Test\n  void testAndComposition() {\n    final var swimmingHeavyCreature = mock(Creature.class);\n    when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING);\n    when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0));\n\n    final var swimmingLightCreature = mock(Creature.class);\n    when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING);\n    when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0));\n\n    final var lightAndSwimmingSelector =\n        new MassSmallerThanOrEqSelector(50.0).and(new MovementSelector(Movement.SWIMMING));\n    assertFalse(lightAndSwimmingSelector.test(swimmingHeavyCreature));\n    assertTrue(lightAndSwimmingSelector.test(swimmingLightCreature));\n  }\n\n  /** Verify if the disjunction selector gives the correct results. */\n  @Test\n  void testOrComposition() {\n    final var swimmingHeavyCreature = mock(Creature.class);\n    when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING);\n    when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0));\n\n    final var swimmingLightCreature = mock(Creature.class);\n    when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING);\n    when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0));\n\n    final var lightOrSwimmingSelector =\n        new MassSmallerThanOrEqSelector(50.0).or(new MovementSelector(Movement.SWIMMING));\n    assertTrue(lightOrSwimmingSelector.test(swimmingHeavyCreature));\n    assertTrue(lightOrSwimmingSelector.test(swimmingLightCreature));\n  }\n\n  /** Verify if the negation selector gives the correct results. */\n  @Test\n  void testNotComposition() {\n    final var swimmingHeavyCreature = mock(Creature.class);\n    when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING);\n    when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0));\n\n    final var swimmingLightCreature = mock(Creature.class);\n    when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING);\n    when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0));\n\n    final var heavySelector = new MassSmallerThanOrEqSelector(50.0).not();\n    assertTrue(heavySelector.test(swimmingHeavyCreature));\n    assertFalse(heavySelector.test(swimmingLightCreature));\n  }\n}\n"
  },
  {
    "path": "specification/src/test/java/com/iluwatar/specification/selector/MassSelectorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.specification.creature.Creature;\nimport com.iluwatar.specification.property.Mass;\nimport org.junit.jupiter.api.Test;\n\nclass MassSelectorTest {\n\n  /** Verify if the mass selector gives the correct results. */\n  @Test\n  void testMass() {\n    final var lightCreature = mock(Creature.class);\n    when(lightCreature.getMass()).thenReturn(new Mass(50.0));\n\n    final var heavyCreature = mock(Creature.class);\n    when(heavyCreature.getMass()).thenReturn(new Mass(2500.0));\n\n    final var lightSelector = new MassSmallerThanOrEqSelector(500.0);\n    assertTrue(lightSelector.test(lightCreature));\n    assertFalse(lightSelector.test(heavyCreature));\n  }\n}\n"
  },
  {
    "path": "specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.specification.creature.Creature;\nimport com.iluwatar.specification.property.Movement;\nimport org.junit.jupiter.api.Test;\n\n/** MovementSelectorTest */\nclass MovementSelectorTest {\n\n  /** Verify if the movement selector gives the correct results. */\n  @Test\n  void testMovement() {\n    final var swimmingCreature = mock(Creature.class);\n    when(swimmingCreature.getMovement()).thenReturn(Movement.SWIMMING);\n\n    final var flyingCreature = mock(Creature.class);\n    when(flyingCreature.getMovement()).thenReturn(Movement.FLYING);\n\n    final var swimmingSelector = new MovementSelector(Movement.SWIMMING);\n    assertTrue(swimmingSelector.test(swimmingCreature));\n    assertFalse(swimmingSelector.test(flyingCreature));\n  }\n}\n"
  },
  {
    "path": "specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.specification.selector;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nimport com.iluwatar.specification.creature.Creature;\nimport com.iluwatar.specification.property.Size;\nimport org.junit.jupiter.api.Test;\n\n/** SizeSelectorTest */\nclass SizeSelectorTest {\n\n  /** Verify if the size selector gives the correct results */\n  @Test\n  void testMovement() {\n    final var normalCreature = mock(Creature.class);\n    when(normalCreature.getSize()).thenReturn(Size.NORMAL);\n\n    final var smallCreature = mock(Creature.class);\n    when(smallCreature.getSize()).thenReturn(Size.SMALL);\n\n    final var normalSelector = new SizeSelector(Size.NORMAL);\n    assertTrue(normalSelector.test(normalCreature));\n    assertFalse(normalSelector.test(smallCreature));\n  }\n}\n"
  },
  {
    "path": "state/README.md",
    "content": "---\ntitle: \"State Pattern in Java: Enhancing Behavior Dynamics with State Encapsulation\"\nshortTitle: State\ndescription: \"Explore the State Pattern, a core component of Java design patterns that enables dynamic behavior change in objects with internal state shifts. Includes real-world examples, applicability, benefits, and detailed code snippets.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Decoupling\n  - Gang of Four\n  - State tracking\n---\n\n## Also known as\n\n* Objects for States\n\n## Intent of State Design Pattern\n\nEnable an object to alter its behavior dynamically as its internal state changes, optimizing Java application responsiveness.\n\n## Detailed Explanation of State Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a traffic light system at an intersection. The traffic light can be in one of three states: Green, Yellow, or Red. Depending on the current state, the traffic light's behavior changes:\n>\n> 1. **Green State**: Cars are allowed to pass through the intersection.\n> 2. **Yellow State**: Cars are warned that the light will soon turn red, so they should prepare to stop.\n> 3. **Red State**: Cars must stop and wait for the light to turn green.\n>\n> In this scenario, the traffic light uses the State design pattern. Each state (Green, Yellow, Red) is represented by a different object that defines what happens in that particular state. The traffic light (context) delegates the behavior to the current state object. When the state changes (e.g., from Green to Yellow), the traffic light updates its state object and changes its behavior accordingly. \n\nIn plain words\n\n> State pattern allows an object to change its behavior. \n\nWikipedia says\n\n> The state pattern is a behavioral software design pattern that allows an object to alter its behavior when its internal state changes. This pattern is close to the concept of finite-state machines. The state pattern can be interpreted as a strategy pattern, which is able to switch a strategy through invocations of methods defined in the pattern's interface.\n\nFlowchart\n\n![State flowchart](./etc/state-flowchart.png)\n\n## Programmatic Example of State Pattern in Java\n\nIn our programmatic example there is a mammoth with alternating moods.\n\nFirst, here is the state interface and its concrete implementations.\n\n```java\npublic interface State {\n\n  void onEnterState();\n\n  void observe();\n}\n```\n\n```java\n@Slf4j\npublic class PeacefulState implements State {\n\n  private final Mammoth mammoth;\n\n  public PeacefulState(Mammoth mammoth) {\n    this.mammoth = mammoth;\n  }\n\n  @Override\n  public void observe() {\n    LOGGER.info(\"{} is calm and peaceful.\", mammoth);\n  }\n\n  @Override\n  public void onEnterState() {\n    LOGGER.info(\"{} calms down.\", mammoth);\n  }\n}\n```\n\n```java\n@Slf4j\npublic class AngryState implements State {\n\n  private final Mammoth mammoth;\n\n  public AngryState(Mammoth mammoth) {\n    this.mammoth = mammoth;\n  }\n\n  @Override\n  public void observe() {\n    LOGGER.info(\"{} is furious!\", mammoth);\n  }\n\n  @Override\n  public void onEnterState() {\n    LOGGER.info(\"{} gets angry!\", mammoth);\n  }\n}\n```\n\nAnd here is the mammoth containing the state. The state changes via calls to `timePasses` method.\n\n```java\npublic class Mammoth {\n\n  private State state;\n\n  public Mammoth() {\n    state = new PeacefulState(this);\n  }\n\n  public void timePasses() {\n    if (state.getClass().equals(PeacefulState.class)) {\n      changeStateTo(new AngryState(this));\n    } else {\n      changeStateTo(new PeacefulState(this));\n    }\n  }\n\n  private void changeStateTo(State newState) {\n    this.state = newState;\n    this.state.onEnterState();\n  }\n\n  @Override\n  public String toString() {\n    return \"The mammoth\";\n  }\n\n  public void observe() {\n    this.state.observe();\n  }\n}\n```\n\nHere is the full example of how the mammoth behaves over time.\n\n```java\npublic static void main(String[] args) {\n\n    var mammoth = new Mammoth();\n    mammoth.observe();\n    mammoth.timePasses();\n    mammoth.observe();\n    mammoth.timePasses();\n    mammoth.observe();\n}\n```\n\nProgram output:\n\n```java\n    The mammoth gets angry!\n    The mammoth is furious!\n    The mammoth calms down.\n    The mammoth is calm and peaceful.\n```\n\n## When to Use the State Pattern in Java\n\n* An object's behavior depends on its state, and it must change its behavior at runtime depending on that state.\n* Operations have large, multipart conditional statements that depend on the object's state.\n\n## Real-World Applications of State Pattern in Java\n\n* `java.util.Iterator` in Java's Collections Framework uses different states for iteration.\n* TCP connection classes in network programming often implement states like `Established`, `Listen`, and `Closed`.\n\n## Benefits and Trade-offs of State Pattern\n\nBenefits:\n\n* Localizes state-specific behavior and partitions behavior for different states.\n* Makes state transitions explicit.\n* Reusable State objects can be efficiently shared among various contexts in Java, enhancing memory management and performance.\n\nTrade-offs:\n\n* Can result in a large number of classes for states.\n* Context class can become complicated with the state transition logic.\n\n## Related Java Design Patterns\n\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): State objects may be shared between different contexts.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): State objects are often singletons.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Both patterns have similar structures, but the State pattern's implementations depend on the context’s state.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "state/etc/state.urm.puml",
    "content": "@startuml\npackage com.iluwatar.state {\n  class AngryState {\n    - LOGGER : Logger {static}\n    - mammoth : Mammoth\n    + AngryState(mammoth : Mammoth)\n    + observe()\n    + onEnterState()\n  }\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Mammoth {\n    - state : State\n    + Mammoth()\n    - changeStateTo(newState : State)\n    + observe()\n    + timePasses()\n    + toString() : String\n  }\n  class PeacefulState {\n    - LOGGER : Logger {static}\n    - mammoth : Mammoth\n    + PeacefulState(mammoth : Mammoth)\n    + observe()\n    + onEnterState()\n  }\n  interface State {\n    + observe() {abstract}\n    + onEnterState() {abstract}\n  }\n}\nPeacefulState -->  \"-mammoth\" Mammoth\nAngryState -->  \"-mammoth\" Mammoth\nMammoth -->  \"-state\" State\nAngryState ..|> State \nPeacefulState ..|> State \n@enduml"
  },
  {
    "path": "state/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>state</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.state.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "state/src/main/java/com/iluwatar/state/AngryState.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.state;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Angry state. */\n@Slf4j\npublic class AngryState implements State {\n\n  private final Mammoth mammoth;\n\n  public AngryState(Mammoth mammoth) {\n    this.mammoth = mammoth;\n  }\n\n  @Override\n  public void observe() {\n    LOGGER.info(\"{} is furious!\", mammoth);\n  }\n\n  @Override\n  public void onEnterState() {\n    LOGGER.info(\"{} gets angry!\", mammoth);\n  }\n}\n"
  },
  {
    "path": "state/src/main/java/com/iluwatar/state/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.state;\n\n/**\n * In the State pattern, the container object has an internal state object that defines the current\n * behavior. The state object can be changed to alter the behavior.\n *\n * <p>This can be a cleaner way for an object to change its behavior at runtime without resorting to\n * large monolithic conditional statements and thus improves maintainability.\n *\n * <p>In this example the {@link Mammoth} changes its behavior as time passes by.\n */\npublic class App {\n\n  /** Program entry point. */\n  public static void main(String[] args) {\n\n    var mammoth = new Mammoth();\n    mammoth.observe();\n    mammoth.timePasses();\n    mammoth.observe();\n    mammoth.timePasses();\n    mammoth.observe();\n  }\n}\n"
  },
  {
    "path": "state/src/main/java/com/iluwatar/state/Mammoth.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.state;\n\n/** Mammoth has internal state that defines its behavior. */\npublic class Mammoth {\n\n  private State state;\n\n  public Mammoth() {\n    state = new PeacefulState(this);\n  }\n\n  /** Makes time pass for the mammoth. */\n  public void timePasses() {\n    if (state.getClass().equals(PeacefulState.class)) {\n      changeStateTo(new AngryState(this));\n    } else {\n      changeStateTo(new PeacefulState(this));\n    }\n  }\n\n  private void changeStateTo(State newState) {\n    this.state = newState;\n    this.state.onEnterState();\n  }\n\n  @Override\n  public String toString() {\n    return \"The mammoth\";\n  }\n\n  public void observe() {\n    this.state.observe();\n  }\n}\n"
  },
  {
    "path": "state/src/main/java/com/iluwatar/state/PeacefulState.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.state;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Peaceful state. */\n@Slf4j\npublic class PeacefulState implements State {\n\n  private final Mammoth mammoth;\n\n  public PeacefulState(Mammoth mammoth) {\n    this.mammoth = mammoth;\n  }\n\n  @Override\n  public void observe() {\n    LOGGER.info(\"{} is calm and peaceful.\", mammoth);\n  }\n\n  @Override\n  public void onEnterState() {\n    LOGGER.info(\"{} calms down.\", mammoth);\n  }\n}\n"
  },
  {
    "path": "state/src/main/java/com/iluwatar/state/State.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.state;\n\n/** State interface. */\npublic interface State {\n\n  void onEnterState();\n\n  void observe();\n}\n"
  },
  {
    "path": "state/src/test/java/com/iluwatar/state/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.state;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "state/src/test/java/com/iluwatar/state/MammothTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.state;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/** MammothTest */\nclass MammothTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /**\n   * Switch to a complete mammoth 'mood'-cycle and verify if the observed mood matches the expected\n   * value.\n   */\n  @Test\n  void testTimePasses() {\n    final var mammoth = new Mammoth();\n\n    mammoth.observe();\n    assertEquals(\"The mammoth is calm and peaceful.\", appender.getLastMessage());\n    assertEquals(1, appender.getLogSize());\n\n    mammoth.timePasses();\n    assertEquals(\"The mammoth gets angry!\", appender.getLastMessage());\n    assertEquals(2, appender.getLogSize());\n\n    mammoth.observe();\n    assertEquals(\"The mammoth is furious!\", appender.getLastMessage());\n    assertEquals(3, appender.getLogSize());\n\n    mammoth.timePasses();\n    assertEquals(\"The mammoth calms down.\", appender.getLastMessage());\n    assertEquals(4, appender.getLogSize());\n\n    mammoth.observe();\n    assertEquals(\"The mammoth is calm and peaceful.\", appender.getLastMessage());\n    assertEquals(5, appender.getLogSize());\n  }\n\n  /** Verify if {@link Mammoth#toString()} gives the expected value */\n  @Test\n  void testToString() {\n    final var toString = new Mammoth().toString();\n    assertNotNull(toString);\n    assertEquals(\"The mammoth\", toString);\n  }\n\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender() {\n      ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n\n    public String getLastMessage() {\n      return log.get(log.size() - 1).getFormattedMessage();\n    }\n  }\n}\n"
  },
  {
    "path": "step-builder/README.md",
    "content": "---\ntitle: \"Step Builder Pattern in Java: Crafting Fluent Interfaces for Complex Object Construction\"\nshortTitle: Step Builder\ndescription: \"Master the Step Builder pattern in Java to streamline complex object creation. Learn through detailed explanations and examples. Perfect for software developers aiming to enhance code readability and maintainability.\"\ncategory: Creational\nlanguage: en\ntag:\n  - Code simplification\n  - Domain\n  - Encapsulation\n  - Extensibility\n  - Instantiation\n  - Interface\n---\n\n## Also known as\n\n* Fluent Builder\n\n## Intent of Step Builder Design Pattern\n\nThe Step Builder pattern in Java is an advanced technique to create complex objects with clarity and flexibility. It is perfect for scenarios requiring meticulous step-by-step object construction.\n\n## Detailed Explanation of Step Builder Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a scenario where you are assembling a custom computer. The process involves several steps: selecting the CPU, choosing the motherboard, adding memory, picking a graphics card, and installing storage. Each step builds on the previous one, gradually creating a fully functional computer. This step-by-step assembly process mirrors the Step Builder design pattern, ensuring that each component is correctly chosen and installed in a structured manner, ultimately resulting in a custom-built computer that meets specific requirements and preferences.\n\nIn plain words\n\n> The Step Builder pattern constructs complex objects incrementally through a series of defined steps, ensuring clarity and flexibility in the creation process.\n\nWikipedia says\n\n> The Step Builder pattern is a variation of the Builder design pattern, designed to provide a flexible solution for constructing complex objects step-by-step. This pattern is particularly useful when an object requires multiple initialization steps, which can be done incrementally to ensure clarity and flexibility in the creation process.\n\nSequence diagram\n\n![Step Builder sequence diagram](./etc/step-builder-sequence-diagram.png)\n\n## Programmatic Example of Step Builder Pattern in Java\n\nThe Step Builder pattern in Java is an extension of the Builder pattern that guides the user through the creation of an object in a step-by-step manner. This pattern improves the user experience by only showing the next step methods available, and not showing the build method until it's the right time to build the object.\n\nLet's consider a `Character` class that has many attributes such as `name`, `fighterClass`, `wizardClass`, `weapon`, `spell`, and `abilities`.\n\n```java\n@Getter\n@Setter\npublic class Character {\n\n  private String name;\n  private String fighterClass;\n  private String wizardClass;\n  private String weapon;\n  private String spell;\n  private List<String> abilities;\n\n  public Character(String name) {\n    this.name = name;\n  }\n\n  // toString method omitted\n}\n```\n\nCreating an instance of this class can be complex due to the number of attributes. This is where the Step Builder pattern comes in handy.\n\nWe create a `CharacterStepBuilder` class that guides the user through the creation of a `Character` object.\n\n```java\npublic class CharacterStepBuilder {\n\n  // Builder steps and methods...\n\n  public static NameStep newBuilder() {\n    return new Steps();\n  }\n\n  // Steps implementation...\n}\n```\n\nThe `CharacterStepBuilder` class defines a series of nested interfaces, each representing a step in the construction process. Each interface declares a method for the next step, guiding the user through the construction of a `Character` object.\n\n```java\npublic interface NameStep {\n  ClassStep name(String name);\n}\n```\n\n```java\npublic interface ClassStep {\n  WeaponStep fighterClass(String fighterClass);\n  SpellStep wizardClass(String wizardClass);\n}\n\n// More steps...\n```\n\nThe `Steps` class implements all these interfaces and finally builds the `Character` object.\n\n```java\nprivate static class Steps implements NameStep, ClassStep, WeaponStep, SpellStep, BuildStep {\n\n  private String name;\n  private String fighterClass;\n  private String wizardClass;\n  private String weapon;\n  private String spell;\n  private List<String> abilities;\n\n  // Implement the methods for each step...\n\n  @Override\n  public Character build() {\n    return new Character(name, fighterClass, wizardClass, weapon, spell, abilities);\n  }\n}\n```\n\nNow, creating a `Character` object becomes a guided process:\n\n```java\npublic static void main(String[] args) {\n\n    var warrior = CharacterStepBuilder\n            .newBuilder()\n            .name(\"Amberjill\")\n            .fighterClass(\"Paladin\")\n            .withWeapon(\"Sword\")\n            .noAbilities()\n            .build();\n\n    LOGGER.info(warrior.toString());\n\n    var mage = CharacterStepBuilder\n            .newBuilder()\n            .name(\"Riobard\")\n            .wizardClass(\"Sorcerer\")\n            .withSpell(\"Fireball\")\n            .withAbility(\"Fire Aura\")\n            .withAbility(\"Teleport\")\n            .noMoreAbilities()\n            .build();\n\n    LOGGER.info(mage.toString());\n\n    var thief = CharacterStepBuilder\n            .newBuilder()\n            .name(\"Desmond\")\n            .fighterClass(\"Rogue\")\n            .noWeapon()\n            .build();\n\n    LOGGER.info(thief.toString());\n}\n```\n\nConsole output:\n\n```\n12:58:13.887 [main] INFO com.iluwatar.stepbuilder.App -- This is a Paladin named Amberjill armed with a Sword.\n12:58:13.889 [main] INFO com.iluwatar.stepbuilder.App -- This is a Sorcerer named Riobard armed with a Fireball and wielding [Fire Aura, Teleport] abilities.\n12:58:13.889 [main] INFO com.iluwatar.stepbuilder.App -- This is a Rogue named Desmond armed with a with nothing.\n```\n\n## When to Use the Step Builder Pattern in Java\n\nThe Step Builder pattern in Java is used\n\n* When constructing an object that requires multiple initialization steps.\n* When object construction is complex and involves many parameters.\n* When you want to provide a clear, readable, and maintainable way to construct an object in a step-by-step manner.\n\n## Step Builder Pattern Java Tutorials\n\n* [Step Builder (Marco Castigliego)](http://rdafbn.blogspot.co.uk/2012/07/step-builder-pattern_28.html)\n\n## Real-World Applications of Step Builder Pattern in Java\n\n* Complex configuration settings in Java applications.\n* Constructing objects for database records with multiple fields.\n* Building UI elements where each step configures a different part of the interface.\n\n## Benefits and Trade-offs of Step Builder Pattern\n\nBenefits:\n\n* Improves code readability and maintainability by providing a clear and concise way to construct objects.\n* Enhances flexibility in creating objects as it allows variations in the construction process.\n* Encourages immutability by separating the construction process from the object's representation.\n\nTrade-offs:\n\n* May result in more complex code due to the additional classes and interfaces required.\n* Can lead to verbose code when many steps are involved.\n\n## Related Java Design Patterns\n\n* [Builder](https://java-design-patterns.com/patterns/builder/): Both patterns help in constructing complex objects. Step Builder is a variation that emphasizes incremental step-by-step construction.\n* [Fluent Interface](https://java-design-patterns.com/patterns/fluentinterface/): Often used in conjunction with the Step Builder pattern to provide a fluent API for constructing objects.\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Sometimes used with the Step Builder pattern to encapsulate the creation logic of the builder itself.\n\n## References and Credits\n\n* [Clean Code: A Handbook of Agile Software Craftsmanship](https://amzn.to/3wRnjp5)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n"
  },
  {
    "path": "step-builder/etc/step-builder.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"true\" nesting-relationships=\"false\">  \n  <interface id=\"1\" language=\"java\" name=\"com.iluwatar.stepbuilder.CharacterStepBuilder.SpellStep\" \n    project=\"step-builder\" file=\"/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"301\" y=\"280\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.stepbuilder.CharacterStepBuilder.CharacterSteps\" \n    project=\"step-builder\" file=\"/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"95\" y=\"345\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.stepbuilder.CharacterStepBuilder\" project=\"step-builder\" \n    file=\"/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"92\" y=\"56\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"4\" language=\"java\" name=\"com.iluwatar.stepbuilder.CharacterStepBuilder.AbilityStep\" \n    project=\"step-builder\" file=\"/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"409\" y=\"418\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"5\" language=\"java\" name=\"com.iluwatar.stepbuilder.CharacterStepBuilder.ClassStep\" \n    project=\"step-builder\" file=\"/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"406\" y=\"163\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"6\" language=\"java\" name=\"com.iluwatar.stepbuilder.CharacterStepBuilder.WeaponStep\" \n    project=\"step-builder\" file=\"/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"509\" y=\"279\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"7\" language=\"java\" name=\"com.iluwatar.stepbuilder.CharacterStepBuilder.NameStep\" project=\"step-builder\" \n    file=\"/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"404\" y=\"49\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <interface id=\"8\" language=\"java\" name=\"com.iluwatar.stepbuilder.CharacterStepBuilder.BuildStep\" \n    project=\"step-builder\" file=\"/step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java\" \n    binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"412\" y=\"550\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"9\" language=\"java\" name=\"com.iluwatar.stepbuilder.Character\" project=\"step-builder\" \n    file=\"/step-builder/src/main/java/com/iluwatar/stepbuilder/Character.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"710\" y=\"217\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <realization id=\"10\">    \n    <bendpoint x=\"252\" y=\"168\"/>    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </realization>  \n  <realization id=\"11\">    \n    <bendpoint x=\"255\" y=\"419\"/>    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </realization>  \n  <realization id=\"12\">    \n    <bendpoint x=\"197\" y=\"123\"/>    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </realization>  \n  <dependency id=\"13\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </dependency>  \n  <dependency id=\"14\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </dependency>  \n  <realization id=\"15\">    \n    <bendpoint x=\"398\" y=\"346\"/>    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </realization>  \n  <dependency id=\"16\">    \n    <end type=\"SOURCE\" refId=\"7\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </dependency>  \n  <realization id=\"17\">    \n    <bendpoint x=\"261\" y=\"554\"/>    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </realization>  \n  <dependency id=\"18\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </dependency>  \n  <dependency id=\"19\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </dependency>  \n  <dependency id=\"20\">    \n    <bendpoint x=\"512\" y=\"477\"/>    \n    <end type=\"SOURCE\" refId=\"6\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </dependency>  \n  <dependency id=\"21\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </dependency>  \n  <realization id=\"22\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"1\"/>  \n  </realization>  \n  <dependency id=\"23\">    \n    <bendpoint x=\"597\" y=\"547\"/>    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"9\"/>  \n  </dependency>  \n  <dependency id=\"24\">    \n    <bendpoint x=\"97\" y=\"602\"/>    \n    <bendpoint x=\"712\" y=\"596\"/>    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"9\"/>  \n  </dependency>  \n  <dependency id=\"25\">    \n    <end type=\"SOURCE\" refId=\"5\"/>    \n    <end type=\"TARGET\" refId=\"6\"/>  \n  </dependency>  \n  <dependency id=\"26\">    \n    <end type=\"SOURCE\" refId=\"6\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </dependency>  \n  <dependency id=\"27\">    \n    <bendpoint x=\"303\" y=\"475\"/>    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"8\"/>  \n  </dependency>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "step-builder/etc/step-builder.urm.puml",
    "content": "@startuml\npackage com.iluwatar.stepbuilder {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Character {\n    - abilities : List<String>\n    - fighterClass : String\n    - name : String\n    - spell : String\n    - weapon : String\n    - wizardClass : String\n    + Character(name : String)\n    + getAbilities() : List<String>\n    + getFighterClass() : String\n    + getName() : String\n    + getSpell() : String\n    + getWeapon() : String\n    + getWizardClass() : String\n    + setAbilities(abilities : List<String>)\n    + setFighterClass(fighterClass : String)\n    + setName(name : String)\n    + setSpell(spell : String)\n    + setWeapon(weapon : String)\n    + setWizardClass(wizardClass : String)\n    + toString() : String\n  }\n  class CharacterStepBuilder {\n    - CharacterStepBuilder()\n    + newBuilder() : NameStep {static}\n  }\n  interface AbilityStep {\n    + noAbilities() : BuildStep {abstract}\n    + noMoreAbilities() : BuildStep {abstract}\n    + withAbility(String) : AbilityStep {abstract}\n  }\n  interface BuildStep {\n    + build() : Character {abstract}\n  }\n  -class CharacterSteps {\n    - abilities : List<String>\n    - fighterClass : String\n    - name : String\n    - spell : String\n    - weapon : String\n    - wizardClass : String\n    - CharacterSteps()\n    + build() : Character\n    + fighterClass(fighterClass : String) : WeaponStep\n    + name(name : String) : ClassStep\n    + noAbilities() : BuildStep\n    + noMoreAbilities() : BuildStep\n    + noSpell() : BuildStep\n    + noWeapon() : BuildStep\n    + withAbility(ability : String) : AbilityStep\n    + withSpell(spell : String) : AbilityStep\n    + withWeapon(weapon : String) : AbilityStep\n    + wizardClass(wizardClass : String) : SpellStep\n  }\n  interface ClassStep {\n    + fighterClass(String) : WeaponStep {abstract}\n    + wizardClass(String) : SpellStep {abstract}\n  }\n  interface NameStep {\n    + name(String) : ClassStep {abstract}\n  }\n  interface SpellStep {\n    + noSpell() : BuildStep {abstract}\n    + withSpell(String) : AbilityStep {abstract}\n  }\n  interface WeaponStep {\n    + noWeapon() : BuildStep {abstract}\n    + withWeapon(String) : AbilityStep {abstract}\n  }\n}\nWeaponStep ..+ CharacterStepBuilder\nAbilityStep ..+ CharacterStepBuilder\nClassStep ..+ CharacterStepBuilder\nCharacterSteps ..+ CharacterStepBuilder\nSpellStep ..+ CharacterStepBuilder\nBuildStep ..+ CharacterStepBuilder\nNameStep ..+ CharacterStepBuilder\nCharacterSteps ..|> NameStep \nCharacterSteps ..|> ClassStep \nCharacterSteps ..|> WeaponStep \nCharacterSteps ..|> SpellStep \nCharacterSteps ..|> AbilityStep \nCharacterSteps ..|> BuildStep \n@enduml"
  },
  {
    "path": "step-builder/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>step-builder</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.stepbuilder.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "step-builder/src/main/java/com/iluwatar/stepbuilder/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.stepbuilder;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Step Builder Pattern\n *\n * <p><b>Intent</b> <br>\n * An extension of the Builder pattern that fully guides the user through the creation of the object\n * with no chances of confusion. <br>\n * The user experience will be much more improved by the fact that he will only see the next step\n * methods available, NO build method until is the right time to build the object.\n *\n * <p><b>Implementation</b> <br>\n * The concept is simple:\n *\n * <ul>\n *   <li>Write creational steps inner classes or interfaces where each method knows what can be\n *       displayed next.\n *   <li>Implement all your steps interfaces in an inner static class.\n *   <li>Last step is the BuildStep, in charge of creating the object you need to build.\n * </ul>\n *\n * <p><b>Applicability</b> <br>\n * Use the Step Builder pattern when the algorithm for creating a complex object should be\n * independent of the parts that make up the object and how they're assembled the construction\n * process must allow different representations for the object that's constructed when in the\n * process of constructing the order is important. <br>\n *\n * @see <a\n *     href=\"http://rdafbn.blogspot.co.uk/2012/07/step-builder-pattern_28.html\">http://rdafbn.blogspot.co.uk/2012/07/step-builder-pattern_28.html</a>\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var warrior =\n        CharacterStepBuilder.newBuilder()\n            .name(\"Amberjill\")\n            .fighterClass(\"Paladin\")\n            .withWeapon(\"Sword\")\n            .noAbilities()\n            .build();\n\n    LOGGER.info(warrior.toString());\n\n    var mage =\n        CharacterStepBuilder.newBuilder()\n            .name(\"Riobard\")\n            .wizardClass(\"Sorcerer\")\n            .withSpell(\"Fireball\")\n            .withAbility(\"Fire Aura\")\n            .withAbility(\"Teleport\")\n            .noMoreAbilities()\n            .build();\n\n    LOGGER.info(mage.toString());\n\n    var thief =\n        CharacterStepBuilder.newBuilder().name(\"Desmond\").fighterClass(\"Rogue\").noWeapon().build();\n\n    LOGGER.info(thief.toString());\n  }\n}\n"
  },
  {
    "path": "step-builder/src/main/java/com/iluwatar/stepbuilder/Character.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.stepbuilder;\n\nimport java.util.List;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** The class with many parameters. */\n@Getter\n@Setter\npublic class Character {\n\n  private String name;\n  private String fighterClass;\n  private String wizardClass;\n  private String weapon;\n  private String spell;\n  private List<String> abilities;\n\n  public Character(String name) {\n    this.name = name;\n  }\n\n  @Override\n  public String toString() {\n    return new StringBuilder()\n        .append(\"This is a \")\n        .append(fighterClass != null ? fighterClass : wizardClass)\n        .append(\" named \")\n        .append(name)\n        .append(\" armed with a \")\n        .append(weapon != null ? weapon : spell != null ? spell : \"with nothing\")\n        .append(abilities != null ? \" and wielding \" + abilities + \" abilities\" : \"\")\n        .append('.')\n        .toString();\n  }\n}\n"
  },
  {
    "path": "step-builder/src/main/java/com/iluwatar/stepbuilder/CharacterStepBuilder.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.stepbuilder;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/** The Step Builder class. */\npublic final class CharacterStepBuilder {\n\n  private CharacterStepBuilder() {}\n\n  public static NameStep newBuilder() {\n    return new CharacterSteps();\n  }\n\n  /** First Builder Step in charge of the Character name. Next Step available : ClassStep */\n  public interface NameStep {\n    ClassStep name(String name);\n  }\n\n  /**\n   * This step is in charge of setting the Character class (fighter or wizard). Fighter choice :\n   * Next Step available : WeaponStep Wizard choice : Next Step available : SpellStep\n   */\n  public interface ClassStep {\n    WeaponStep fighterClass(String fighterClass);\n\n    SpellStep wizardClass(String wizardClass);\n  }\n\n  /**\n   * This step is in charge of the weapon. Weapon choice : Next Step available : AbilityStep No\n   * weapon choice : Next Step available : BuildStep\n   */\n  public interface WeaponStep {\n    AbilityStep withWeapon(String weapon);\n\n    BuildStep noWeapon();\n  }\n\n  /**\n   * This step is in charge of the spell. Spell choice : Next Step available : AbilityStep No spell\n   * choice : Next Step available : BuildStep\n   */\n  public interface SpellStep {\n    AbilityStep withSpell(String spell);\n\n    BuildStep noSpell();\n  }\n\n  /** This step is in charge of abilities. Next Step available : BuildStep */\n  public interface AbilityStep {\n    AbilityStep withAbility(String ability);\n\n    BuildStep noMoreAbilities();\n\n    BuildStep noAbilities();\n  }\n\n  /**\n   * This is the final step in charge of building the Character Object. Validation should be here.\n   */\n  public interface BuildStep {\n    Character build();\n  }\n\n  /** Step Builder implementation. */\n  private static class CharacterSteps\n      implements NameStep, ClassStep, WeaponStep, SpellStep, AbilityStep, BuildStep {\n\n    private String name;\n    private String fighterClass;\n    private String wizardClass;\n    private String weapon;\n    private String spell;\n    private final List<String> abilities = new ArrayList<>();\n\n    @Override\n    public ClassStep name(String name) {\n      this.name = name;\n      return this;\n    }\n\n    @Override\n    public WeaponStep fighterClass(String fighterClass) {\n      this.fighterClass = fighterClass;\n      return this;\n    }\n\n    @Override\n    public SpellStep wizardClass(String wizardClass) {\n      this.wizardClass = wizardClass;\n      return this;\n    }\n\n    @Override\n    public AbilityStep withWeapon(String weapon) {\n      this.weapon = weapon;\n      return this;\n    }\n\n    @Override\n    public BuildStep noWeapon() {\n      return this;\n    }\n\n    @Override\n    public AbilityStep withSpell(String spell) {\n      this.spell = spell;\n      return this;\n    }\n\n    @Override\n    public BuildStep noSpell() {\n      return this;\n    }\n\n    @Override\n    public AbilityStep withAbility(String ability) {\n      this.abilities.add(ability);\n      return this;\n    }\n\n    @Override\n    public BuildStep noMoreAbilities() {\n      return this;\n    }\n\n    @Override\n    public BuildStep noAbilities() {\n      return this;\n    }\n\n    @Override\n    public Character build() {\n      var character = new Character(name);\n\n      if (fighterClass != null) {\n        character.setFighterClass(fighterClass);\n      } else {\n        character.setWizardClass(wizardClass);\n      }\n\n      if (weapon != null) {\n        character.setWeapon(weapon);\n      } else {\n        character.setSpell(spell);\n      }\n\n      if (!abilities.isEmpty()) {\n        character.setAbilities(abilities);\n      }\n\n      return character;\n    }\n  }\n}\n"
  },
  {
    "path": "step-builder/src/test/java/com/iluwatar/stepbuilder/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.stepbuilder;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "step-builder/src/test/java/com/iluwatar/stepbuilder/CharacterStepBuilderTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.stepbuilder;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** CharacterStepBuilderTest */\nclass CharacterStepBuilderTest {\n\n  /** Build a new wizard {@link Character} and verify if it has the expected attributes */\n  @Test\n  void testBuildWizard() {\n    final var character =\n        CharacterStepBuilder.newBuilder()\n            .name(\"Merlin\")\n            .wizardClass(\"alchemist\")\n            .withSpell(\"poison\")\n            .withAbility(\"invisibility\")\n            .withAbility(\"wisdom\")\n            .noMoreAbilities()\n            .build();\n\n    assertEquals(\"Merlin\", character.getName());\n    assertEquals(\"alchemist\", character.getWizardClass());\n    assertEquals(\"poison\", character.getSpell());\n    assertNotNull(character.toString());\n\n    final var abilities = character.getAbilities();\n    assertNotNull(abilities);\n    assertEquals(2, abilities.size());\n    assertTrue(abilities.contains(\"invisibility\"));\n    assertTrue(abilities.contains(\"wisdom\"));\n  }\n\n  /**\n   * Build a new wizard {@link Character} without spell or abilities and verify if it has the\n   * expected attributes\n   */\n  @Test\n  void testBuildPoorWizard() {\n    final var character =\n        CharacterStepBuilder.newBuilder().name(\"Merlin\").wizardClass(\"alchemist\").noSpell().build();\n\n    assertEquals(\"Merlin\", character.getName());\n    assertEquals(\"alchemist\", character.getWizardClass());\n    assertNull(character.getSpell());\n    assertNull(character.getAbilities());\n    assertNotNull(character.toString());\n  }\n\n  /** Build a new wizard {@link Character} and verify if it has the expected attributes */\n  @Test\n  void testBuildWeakWizard() {\n    final var character =\n        CharacterStepBuilder.newBuilder()\n            .name(\"Merlin\")\n            .wizardClass(\"alchemist\")\n            .withSpell(\"poison\")\n            .noAbilities()\n            .build();\n\n    assertEquals(\"Merlin\", character.getName());\n    assertEquals(\"alchemist\", character.getWizardClass());\n    assertEquals(\"poison\", character.getSpell());\n    assertNull(character.getAbilities());\n    assertNotNull(character.toString());\n  }\n\n  /** Build a new warrior {@link Character} and verify if it has the expected attributes */\n  @Test\n  void testBuildWarrior() {\n    final var character =\n        CharacterStepBuilder.newBuilder()\n            .name(\"Cuauhtemoc\")\n            .fighterClass(\"aztec\")\n            .withWeapon(\"spear\")\n            .withAbility(\"speed\")\n            .withAbility(\"strength\")\n            .noMoreAbilities()\n            .build();\n\n    assertEquals(\"Cuauhtemoc\", character.getName());\n    assertEquals(\"aztec\", character.getFighterClass());\n    assertEquals(\"spear\", character.getWeapon());\n    assertNotNull(character.toString());\n\n    final var abilities = character.getAbilities();\n    assertNotNull(abilities);\n    assertEquals(2, abilities.size());\n    assertTrue(abilities.contains(\"speed\"));\n    assertTrue(abilities.contains(\"strength\"));\n  }\n\n  /**\n   * Build a new wizard {@link Character} without weapon and abilities and verify if it has the\n   * expected attributes\n   */\n  @Test\n  void testBuildPoorWarrior() {\n    final var character =\n        CharacterStepBuilder.newBuilder()\n            .name(\"Poor warrior\")\n            .fighterClass(\"none\")\n            .noWeapon()\n            .build();\n\n    assertEquals(\"Poor warrior\", character.getName());\n    assertEquals(\"none\", character.getFighterClass());\n    assertNull(character.getWeapon());\n    assertNull(character.getAbilities());\n    assertNotNull(character.toString());\n  }\n\n  /**\n   * Build a new warrior {@link Character} without any abilities, but with a weapon and verify if it\n   * has the expected attributes\n   */\n  @Test\n  void testBuildWeakWarrior() {\n    final var character =\n        CharacterStepBuilder.newBuilder()\n            .name(\"Weak warrior\")\n            .fighterClass(\"none\")\n            .withWeapon(\"Slingshot\")\n            .noAbilities()\n            .build();\n\n    assertEquals(\"Weak warrior\", character.getName());\n    assertEquals(\"none\", character.getFighterClass());\n    assertEquals(\"Slingshot\", character.getWeapon());\n    assertNull(character.getAbilities());\n    assertNotNull(character.toString());\n  }\n}\n"
  },
  {
    "path": "strangler/README.md",
    "content": "---\ntitle: \"Strangler Pattern in Java: Modernizing Legacy Systems with Incremental Updates\"\nshortTitle: Strangler\ndescription: \"Explore the Strangler design pattern for Java, a strategic approach to incrementally modernize legacy systems without disruption. Learn how it facilitates smooth transitions to new architectures, with real-world applications and code examples.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Migration\n  - Modernization\n  - Refactoring\n---\n\n## Also known as\n\n* Strangler Fig\n\n## Intent of Strangler Design Pattern\n\nThe Strangler Pattern incrementally replaces the legacy system by building a new system alongside the old one, eventually strangling the old system. Using the pattern offer a seamless transition from old to new systems.\n\n## Detailed Explanation of Strangler Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a city planning department that decides to modernize an old bridge that's crucial for daily commutes. Instead of demolishing the old bridge and causing major disruptions, they build a new, modern bridge next to it. As sections of the new bridge are completed, traffic is gradually diverted from the old bridge to the new one. Eventually, the entire flow of traffic moves to the new bridge, and the old bridge is either decommissioned or demolished. This way, the transition is smooth, and the city's daily activities are minimally affected. This approach mirrors the Strangler Design Pattern, where a legacy system is incrementally replaced by a new system, ensuring continuous operation during the transition.\n\nIn plain words\n\n> The Strangler Design Pattern incrementally replaces a legacy system by developing a new system alongside it and gradually migrating functionality until the old system is entirely replaced.\n\nWikipedia says\n\n> The Strangler Design Pattern involves incrementally migrating a legacy system by gradually replacing it with a new system. It wraps old code with new code, redirecting or logging uses of the old code to ensure a seamless transition. This pattern is named after the strangler fig plant, which grows around a host tree and eventually replaces it entirely. It's particularly useful for modernizing monolithic applications and transitioning them to microservices architecture with minimal risk and disruption.\n\nFlowchart\n\n![Strangler flowchart](./etc/strangler-flowchart.png)\n\n## Programmatic Example of Strangler Pattern in Java\n\nThe Strangler design pattern in Java is a software design pattern that incrementally migrates a legacy system by gradually replacing specific pieces of functionality with new applications and services. As features from the legacy system are replaced, the new system eventually replaces all the old system's features, strangling the old system and allowing you to decommission it.\n\nIn the provided code, we have an example of the Strangler pattern in action. The `OldArithmetic` class represents the legacy system, while the `HalfArithmetic` and `NewArithmetic` classes represent the new system at different stages of development.\n\nLet's break down the code to understand how the Strangler pattern is implemented.\n\n```java\npublic class OldArithmetic {\n  private final OldSource source;\n\n  public OldArithmetic(OldSource source) {\n    this.source = source;\n  }\n\n  // The sum and mul methods represent the functionality of the legacy system.\n  public int sum(int... nums) {\n    return source.accumulateSum(nums);\n  }\n\n  public int mul(int... nums) {\n    return source.accumulateMul(nums);\n  }\n}\n```\n\nThe `OldArithmetic` class represents the legacy system. It has two methods, `sum` and `mul`, which depend on the `OldSource` class.\n\n```java\npublic class HalfArithmetic {\n  private final HalfSource newSource;\n  private final OldSource oldSource;\n\n  public HalfArithmetic(HalfSource newSource, OldSource oldSource) {\n    this.newSource = newSource;\n    this.oldSource = oldSource;\n  }\n\n  // The sum method has been migrated to use the new source.\n  public int sum(int... nums) {\n    return newSource.accumulateSum(nums);\n  }\n\n  // The mul method still uses the old source.\n  public int mul(int... nums) {\n    return oldSource.accumulateMul(nums);\n  }\n\n  // The ifHasZero method is a new feature added in the new system.\n  public boolean ifHasZero(int... nums) {\n    return !newSource.ifNonZero(nums);\n  }\n}\n```\n\nThe `HalfArithmetic` class represents the system during the migration process. It depends on both the `OldSource` and `HalfSource` classes. The `sum` method has been migrated to use the new source, while the `mul` method still uses the old source. The `ifHasZero` method is a new feature added in the new system.\n\n```java\npublic class NewArithmetic {\n  private final NewSource source;\n\n  public NewArithmetic(NewSource source) {\n    this.source = source;\n  }\n\n  // All methods now use the new source.\n  public int sum(int... nums) {\n    return source.accumulateSum(nums);\n  }\n\n  public int mul(int... nums) {\n    return source.accumulateMul(nums);\n  }\n\n  public boolean ifHasZero(int... nums) {\n    return !source.ifNonZero(nums);\n  }\n}\n```\n\nThe `NewArithmetic` class represents the system after the migration process. It only depends on the `NewSource` class. All methods now use the new source.\n\nHere is the `main` method executing our example.\n\n```java\npublic static void main(final String[] args) {\n    final var nums = new int[]{1, 2, 3, 4, 5};\n    //Before migration\n    final var oldSystem = new OldArithmetic(new OldSource());\n    oldSystem.sum(nums);\n    oldSystem.mul(nums);\n    //In process of migration\n    final var halfSystem = new HalfArithmetic(new HalfSource(), new OldSource());\n    halfSystem.sum(nums);\n    halfSystem.mul(nums);\n    halfSystem.ifHasZero(nums);\n    //After migration\n    final var newSystem = new NewArithmetic(new NewSource());\n    newSystem.sum(nums);\n    newSystem.mul(nums);\n    newSystem.ifHasZero(nums);\n  }\n```\n\nConsole output:\n\n```\n13:02:25.030 [main] INFO com.iluwatar.strangler.OldArithmetic -- Arithmetic sum 1.0\n13:02:25.032 [main] INFO com.iluwatar.strangler.OldSource -- Source module 1.0\n13:02:25.032 [main] INFO com.iluwatar.strangler.OldArithmetic -- Arithmetic mul 1.0\n13:02:25.032 [main] INFO com.iluwatar.strangler.OldSource -- Source module 1.0\n13:02:25.032 [main] INFO com.iluwatar.strangler.HalfArithmetic -- Arithmetic sum 1.5\n13:02:25.032 [main] INFO com.iluwatar.strangler.HalfSource -- Source module 1.5\n13:02:25.033 [main] INFO com.iluwatar.strangler.HalfArithmetic -- Arithmetic mul 1.5\n13:02:25.033 [main] INFO com.iluwatar.strangler.OldSource -- Source module 1.0\n13:02:25.033 [main] INFO com.iluwatar.strangler.HalfArithmetic -- Arithmetic check zero 1.5\n13:02:25.033 [main] INFO com.iluwatar.strangler.HalfSource -- Source module 1.5\n13:02:25.034 [main] INFO com.iluwatar.strangler.NewArithmetic -- Arithmetic sum 2.0\n13:02:25.034 [main] INFO com.iluwatar.strangler.NewSource -- Source module 2.0\n13:02:25.034 [main] INFO com.iluwatar.strangler.NewArithmetic -- Arithmetic mul 2.0\n13:02:25.034 [main] INFO com.iluwatar.strangler.NewSource -- Source module 2.0\n13:02:25.034 [main] INFO com.iluwatar.strangler.NewArithmetic -- Arithmetic check zero 2.0\n13:02:25.035 [main] INFO com.iluwatar.strangler.NewSource -- Source module 2.0\n```\n\nThis is a typical example of the Strangler pattern. The legacy system (`OldArithmetic`) is gradually replaced by the new system (`HalfArithmetic` and `NewArithmetic`). The new system is developed incrementally, and at each stage, it strangles a part of the legacy system until the legacy system is completely replaced.\n\n## When to Use the Strangler Pattern in Java\n\n* Use when you need to replace a monolithic or legacy system incrementally.\n* Ideal for scenarios where the system cannot be replaced in one go due to risk or complexity.\n* Suitable when you need to modernize parts of an application while ensuring continuous operation.\n* Perfect for applications requiring updates with zero downtime, the Strangler pattern supports incremental updates in complex Java systems.\n\n## Strangler Pattern Java Tutorials\n\n* [Legacy Application Strangulation: Case Studies (Paul Hammant)](https://paulhammant.com/2013/07/14/legacy-application-strangulation-case-studies/)\n\n## Real-World Applications of Strangler Pattern in Java\n\n* Replacing a legacy monolithic application with a microservices architecture.\n* Transitioning from an on-premise system to a cloud-based system.\n* Incrementally migrating from an old database schema to a new one without downtime.\n\n## Benefits and Trade-offs of Strangler Pattern\n\nBenefits:\n\n* Reduces risk by allowing gradual replacement.\n* Enables continuous delivery and operation during migration.\n* Allows for testing and validating new components before full replacement.\n\nTrade-offs:\n\n* Requires managing interactions between new and old systems, which can be complex.\n* May introduce temporary performance overhead due to coexistence of old and new systems.\n* Potentially increases the initial development time due to the need for integration.\n\n## Related Java Design Patterns\n\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): Used to make new systems interact with the old system during the transition period.\n* [Facade](https://java-design-patterns.com/patterns/facade/): Can provide a unified interface to the old and new systems, simplifying client interactions.\n* Microservices: The target architecture in many cases where the Strangler Pattern is applied.\n\n## References and Credits\n\n* [Building Microservices](https://amzn.to/3UACtrU)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Refactoring: Improving the Design of Existing Code](https://amzn.to/3TVEgaB)\n* [Strangler pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/patterns/strangler)\n"
  },
  {
    "path": "strangler/etc/strangler.puml",
    "content": "@startuml\n\npackage com.iluwatar.strangler {\n    class App {\n        + main(args : String[]) {static}\n    }\n\n    class OldArithmetic {\n        - LOGGER : Logger {static}\n        - VERSION : String {static}\n        - source : OldSource\n        + sum(nums : int...)\n        + mul(nums : int...)\n    }\n\n    class HalfArithmetic {\n        - LOGGER : Logger {static}\n        - VERSION : String {static}\n        - oldSource : OldSource\n        - newSource : HalfSource\n        + sum(nums : int...)\n        + mul(nums : int...)\n        + ifHasZero(nums : int...)\n    }\n\n    class NewArithmetic {\n        - LOGGER : Logger {static}\n        - VERSION : String {static}\n        - source : NewSource\n        + sum(nums : int...)\n        + mul(nums : int...)\n        + ifHasZero(nums : int...)\n    }\n\n    class OldSource {\n        - LOGGER : Logger {static}\n        - VERSION : String {static}\n        + accumulateSum(nums : int...)\n        + accumulateMul(nums : int...)\n    }\n\n    class HalfSource {\n        - LOGGER : Logger {static}\n        - VERSION : String {static}\n        + accumulateSum(nums : int...)\n        + ifNonZero(nums : int...)\n    }\n\n    class NewSource {\n        - LOGGER : Logger {static}\n        - VERSION : String {static}\n        + accumulateSum(nums : int...)\n        + accumulateMul(nums : int...)\n        + ifNonZero(nums : int...)\n    }\n}\nOldArithmetic o--> OldSource\nHalfArithmetic o--> OldSource\nHalfArithmetic o--> HalfSource\nNewArithmetic o--> NewSource\n@enduml"
  },
  {
    "path": "strangler/etc/strangler.urm.puml",
    "content": "@startuml\npackage com.iluwatar.strangler {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class HalfArithmetic {\n    - LOGGER : Logger {static}\n    - VERSION : String {static}\n    - newSource : HalfSource\n    - oldSource : OldSource\n    + HalfArithmetic(newSource : HalfSource, oldSource : OldSource)\n    + ifHasZero(nums : int[]) : boolean\n    + mul(nums : int[]) : int\n    + sum(nums : int[]) : int\n  }\n  class HalfSource {\n    - LOGGER : Logger {static}\n    - VERSION : String {static}\n    + HalfSource()\n    + accumulateSum(nums : int[]) : int\n    + ifNonZero(nums : int[]) : boolean\n  }\n  class NewArithmetic {\n    - LOGGER : Logger {static}\n    - VERSION : String {static}\n    - source : NewSource\n    + NewArithmetic(source : NewSource)\n    + ifHasZero(nums : int[]) : boolean\n    + mul(nums : int[]) : int\n    + sum(nums : int[]) : int\n  }\n  class NewSource {\n    - LOGGER : Logger {static}\n    - VERSION : String {static}\n    + NewSource()\n    + accumulateMul(nums : int[]) : int\n    + accumulateSum(nums : int[]) : int\n    + ifNonZero(nums : int[]) : boolean\n  }\n  class OldArithmetic {\n    - LOGGER : Logger {static}\n    - VERSION : String {static}\n    - source : OldSource\n    + OldArithmetic(source : OldSource)\n    + mul(nums : int[]) : int\n    + sum(nums : int[]) : int\n  }\n  class OldSource {\n    - LOGGER : Logger {static}\n    - VERSION : String {static}\n    + OldSource()\n    + accumulateMul(nums : int[]) : int\n    + accumulateSum(nums : int[]) : int\n  }\n}\nOldArithmetic -->  \"-source\" OldSource\nNewArithmetic -->  \"-source\" NewSource\nHalfArithmetic -->  \"-newSource\" HalfSource\nHalfArithmetic -->  \"-oldSource\" OldSource\n@enduml"
  },
  {
    "path": "strangler/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>strangler</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.strangler.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "strangler/src/main/java/com/iluwatar/strangler/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\n/**\n * The Strangler pattern is a software design pattern that incrementally migrate a legacy system by\n * gradually replacing specific pieces of functionality with new applications and services. As\n * features from the legacy system are replaced, the new system eventually replaces all of the old\n * system's features, strangling the old system and allowing you to decommission it.\n *\n * <p>This pattern is not only about updating but also enhancement.\n *\n * <p>In this example, {@link OldArithmetic} indicates old system and its implementation depends on\n * its source ({@link OldSource}). Now we tend to update system with new techniques and new\n * features. In reality, the system may too complex, so usually need gradual migration. {@link\n * HalfArithmetic} indicates system in the process of migration, its implementation depends on old\n * one ({@link OldSource}) and under development one ({@link HalfSource}). The {@link HalfSource}\n * covers part of {@link OldSource} and add new functionality. You can release this version system\n * with new features, which also supports old version system functionalities. After whole migration,\n * the new system ({@link NewArithmetic}) only depends on new source ({@link NewSource}).\n */\npublic class App {\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(final String[] args) {\n    final var nums = new int[] {1, 2, 3, 4, 5};\n    // Before migration\n    final var oldSystem = new OldArithmetic(new OldSource());\n    oldSystem.sum(nums);\n    oldSystem.mul(nums);\n    // In process of migration\n    final var halfSystem = new HalfArithmetic(new HalfSource(), new OldSource());\n    halfSystem.sum(nums);\n    halfSystem.mul(nums);\n    halfSystem.ifHasZero(nums);\n    // After migration\n    final var newSystem = new NewArithmetic(new NewSource());\n    newSystem.sum(nums);\n    newSystem.mul(nums);\n    newSystem.ifHasZero(nums);\n  }\n}\n"
  },
  {
    "path": "strangler/src/main/java/com/iluwatar/strangler/HalfArithmetic.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * System under migration. Depends on old version source ({@link OldSource}) and developing one\n * ({@link HalfSource}).\n */\n@Slf4j\npublic class HalfArithmetic {\n  private static final String VERSION = \"1.5\";\n\n  private final HalfSource newSource;\n  private final OldSource oldSource;\n\n  public HalfArithmetic(HalfSource newSource, OldSource oldSource) {\n    this.newSource = newSource;\n    this.oldSource = oldSource;\n  }\n\n  /**\n   * Accumulate sum.\n   *\n   * @param nums numbers need to add together\n   * @return accumulate sum\n   */\n  public int sum(int... nums) {\n    LOGGER.info(\"Arithmetic sum {}\", VERSION);\n    return newSource.accumulateSum(nums);\n  }\n\n  /**\n   * Accumulate multiplication.\n   *\n   * @param nums numbers need to multiply together\n   * @return accumulate multiplication\n   */\n  public int mul(int... nums) {\n    LOGGER.info(\"Arithmetic mul {}\", VERSION);\n    return oldSource.accumulateMul(nums);\n  }\n\n  /**\n   * Check if it has any zero.\n   *\n   * @param nums numbers need to check\n   * @return if it has any zero, return true, else, return false\n   */\n  public boolean ifHasZero(int... nums) {\n    LOGGER.info(\"Arithmetic check zero {}\", VERSION);\n    return !newSource.ifNonZero(nums);\n  }\n}\n"
  },
  {
    "path": "strangler/src/main/java/com/iluwatar/strangler/HalfSource.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport java.util.Arrays;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Source under development. Replace part of old source and has added some new features. */\n@Slf4j\npublic class HalfSource {\n  private static final String VERSION = \"1.5\";\n\n  /** Implement accumulate sum with new technique. Replace old one in {@link OldSource} */\n  public int accumulateSum(int... nums) {\n    LOGGER.info(\"Source module {}\", VERSION);\n    return Arrays.stream(nums).reduce(0, Integer::sum);\n  }\n\n  /** Check if all number is not zero. New feature. */\n  public boolean ifNonZero(int... nums) {\n    LOGGER.info(\"Source module {}\", VERSION);\n    return Arrays.stream(nums).allMatch(num -> num != 0);\n  }\n}\n"
  },
  {
    "path": "strangler/src/main/java/com/iluwatar/strangler/NewArithmetic.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** System after whole migration. Only depends on new version source ({@link NewSource}). */\n@Slf4j\npublic class NewArithmetic {\n  private static final String VERSION = \"2.0\";\n\n  private final NewSource source;\n\n  public NewArithmetic(NewSource source) {\n    this.source = source;\n  }\n\n  /**\n   * Accumulate sum.\n   *\n   * @param nums numbers need to add together\n   * @return accumulate sum\n   */\n  public int sum(int... nums) {\n    LOGGER.info(\"Arithmetic sum {}\", VERSION);\n    return source.accumulateSum(nums);\n  }\n\n  /**\n   * Accumulate multiplication.\n   *\n   * @param nums numbers need to multiply together\n   * @return accumulate multiplication\n   */\n  public int mul(int... nums) {\n    LOGGER.info(\"Arithmetic mul {}\", VERSION);\n    return source.accumulateMul(nums);\n  }\n\n  /**\n   * Check if it has any zero.\n   *\n   * @param nums numbers need to check\n   * @return if it has any zero, return true, else, return false\n   */\n  public boolean ifHasZero(int... nums) {\n    LOGGER.info(\"Arithmetic check zero {}\", VERSION);\n    return !source.ifNonZero(nums);\n  }\n}\n"
  },
  {
    "path": "strangler/src/main/java/com/iluwatar/strangler/NewSource.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport java.util.Arrays;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * New source. Completely covers functionalities of old source with new techniques and also has some\n * new features.\n */\n@Slf4j\npublic class NewSource {\n  private static final String VERSION = \"2.0\";\n  public static final String SOURCE_MODULE = \"Source module {}\";\n\n  public int accumulateSum(int... nums) {\n    LOGGER.info(SOURCE_MODULE, VERSION);\n    return Arrays.stream(nums).reduce(0, Integer::sum);\n  }\n\n  /** Implement accumulate multiply with new technique. Replace old one in {@link OldSource} */\n  public int accumulateMul(int... nums) {\n    LOGGER.info(SOURCE_MODULE, VERSION);\n    return Arrays.stream(nums).reduce(1, (a, b) -> a * b);\n  }\n\n  public boolean ifNonZero(int... nums) {\n    LOGGER.info(SOURCE_MODULE, VERSION);\n    return Arrays.stream(nums).allMatch(num -> num != 0);\n  }\n}\n"
  },
  {
    "path": "strangler/src/main/java/com/iluwatar/strangler/OldArithmetic.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Old version system depends on old version source ({@link OldSource}). */\n@Slf4j\npublic class OldArithmetic {\n  private static final String VERSION = \"1.0\";\n\n  private final OldSource source;\n\n  public OldArithmetic(OldSource source) {\n    this.source = source;\n  }\n\n  /**\n   * Accumulate sum.\n   *\n   * @param nums numbers need to add together\n   * @return accumulate sum\n   */\n  public int sum(int... nums) {\n    LOGGER.info(\"Arithmetic sum {}\", VERSION);\n    return source.accumulateSum(nums);\n  }\n\n  /**\n   * Accumulate multiplication.\n   *\n   * @param nums numbers need to multiply together\n   * @return accumulate multiplication\n   */\n  public int mul(int... nums) {\n    LOGGER.info(\"Arithmetic mul {}\", VERSION);\n    return source.accumulateMul(nums);\n  }\n}\n"
  },
  {
    "path": "strangler/src/main/java/com/iluwatar/strangler/OldSource.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Old source with techniques out of date. */\n@Slf4j\npublic class OldSource {\n  private static final String VERSION = \"1.0\";\n\n  /** Implement accumulate sum with old technique. */\n  public int accumulateSum(int... nums) {\n    LOGGER.info(\"Source module {}\", VERSION);\n    var sum = 0;\n    for (final var num : nums) {\n      sum += num;\n    }\n    return sum;\n  }\n\n  /** Implement accumulate multiply with old technique. */\n  public int accumulateMul(int... nums) {\n    LOGGER.info(\"Source module {}\", VERSION);\n    var sum = 1;\n    for (final var num : nums) {\n      sum *= num;\n    }\n    return sum;\n  }\n}\n"
  },
  {
    "path": "strangler/src/test/java/com/iluwatar/strangler/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "strangler/src/test/java/com/iluwatar/strangler/HalfArithmeticTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test methods in HalfArithmetic */\nclass HalfArithmeticTest {\n  private static final HalfArithmetic arithmetic =\n      new HalfArithmetic(new HalfSource(), new OldSource());\n\n  @Test\n  void testSum() {\n    assertEquals(0, arithmetic.sum(-1, 0, 1));\n  }\n\n  @Test\n  void testMul() {\n    assertEquals(0, arithmetic.mul(-1, 0, 1));\n  }\n\n  @Test\n  void testIfHasZero() {\n    assertTrue(arithmetic.ifHasZero(-1, 0, 1));\n  }\n}\n"
  },
  {
    "path": "strangler/src/test/java/com/iluwatar/strangler/HalfSourceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test methods in HalfSource */\nclass HalfSourceTest {\n  private static final HalfSource source = new HalfSource();\n\n  @Test\n  void testAccumulateSum() {\n    assertEquals(0, source.accumulateSum(-1, 0, 1));\n  }\n\n  @Test\n  void testIfNonZero() {\n    assertFalse(source.ifNonZero(-1, 0, 1));\n  }\n}\n"
  },
  {
    "path": "strangler/src/test/java/com/iluwatar/strangler/NewArithmeticTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test methods in NewArithmetic */\nclass NewArithmeticTest {\n  private static final NewArithmetic arithmetic = new NewArithmetic(new NewSource());\n\n  @Test\n  void testSum() {\n    assertEquals(0, arithmetic.sum(-1, 0, 1));\n  }\n\n  @Test\n  void testMul() {\n    assertEquals(0, arithmetic.mul(-1, 0, 1));\n  }\n\n  @Test\n  void testIfHasZero() {\n    assertTrue(arithmetic.ifHasZero(-1, 0, 1));\n  }\n}\n"
  },
  {
    "path": "strangler/src/test/java/com/iluwatar/strangler/NewSourceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test methods in NewSource */\nclass NewSourceTest {\n  private static final NewSource source = new NewSource();\n\n  @Test\n  void testAccumulateSum() {\n    assertEquals(0, source.accumulateSum(-1, 0, 1));\n  }\n\n  @Test\n  void testAccumulateMul() {\n    assertEquals(0, source.accumulateMul(-1, 0, 1));\n  }\n\n  @Test\n  void testIfNonZero() {\n    assertFalse(source.ifNonZero(-1, 0, 1));\n  }\n}\n"
  },
  {
    "path": "strangler/src/test/java/com/iluwatar/strangler/OldArithmeticTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test methods in OldArithmetic */\nclass OldArithmeticTest {\n  private static final OldArithmetic arithmetic = new OldArithmetic(new OldSource());\n\n  @Test\n  void testSum() {\n    assertEquals(0, arithmetic.sum(-1, 0, 1));\n  }\n\n  @Test\n  void testMul() {\n    assertEquals(0, arithmetic.mul(-1, 0, 1));\n  }\n}\n"
  },
  {
    "path": "strangler/src/test/java/com/iluwatar/strangler/OldSourceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strangler;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test methods in OldSource */\nclass OldSourceTest {\n  private static final OldSource source = new OldSource();\n\n  @Test\n  void testAccumulateSum() {\n    assertEquals(0, source.accumulateSum(-1, 0, 1));\n  }\n\n  @Test\n  void testAccumulateMul() {\n    assertEquals(0, source.accumulateMul(-1, 0, 1));\n  }\n}\n"
  },
  {
    "path": "strategy/README.md",
    "content": "---\ntitle: \"Strategy Pattern in Java: Streamlining Object Behaviors with Interchangeable Algorithms\"\nshortTitle: Strategy\ndescription: \"Explore the Strategy design pattern in Java with a detailed guide and practical examples. Learn how to implement flexible and interchangeable algorithms effectively in your Java applications for enhanced design and maintenance.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Decoupling\n  - Extensibility\n  - Gang of Four\n  - Interface\n  - Polymorphism\n---\n\n## Also known as\n\n* Policy\n\n## Intent of Strategy Design Pattern\n\nDefine a family of algorithms in Java, encapsulate each one, and make them interchangeable to enhance software development using the Strategy design pattern. Strategy lets the algorithm vary independently of the clients that use it.\n\n## Detailed Explanation of Strategy Pattern with Real-World Examples\n\nReal-world example\n\n> A practical real-world example of the Strategy design pattern in Java is evident in car navigation systems, where algorithm flexibility is paramount. Different navigation algorithms (such as shortest route, fastest route, and scenic route) can be used to determine the best path from one location to another. Each algorithm encapsulates a specific strategy for calculating the route. The user (client) can switch between these algorithms based on their preferences without changing the navigation system itself. This allows for flexible and interchangeable navigation strategies within the same system. \n\nIn plain words\n\n> Strategy pattern allows choosing the best-suited algorithm at runtime.\n\nWikipedia says\n\n> In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral software design pattern that enables selecting an algorithm at runtime.\n\nFlowchart\n\n![Strategy flowchart](./etc/strategy-flowchart.png)\n\n## Programmatic Example of Strategy Pattern in Java\n\nSlaying dragons is a dangerous job. With experience, it becomes easier. Veteran dragonslayers have developed different fighting strategies against different types of dragons.\n\nLet's explore how to implement the `DragonSlayingStrategy` interface in Java, demonstrating various Strategy pattern applications.\n\n```java\n@FunctionalInterface\npublic interface DragonSlayingStrategy {\n\n  void execute();\n}\n```\n\n```java\n@Slf4j\npublic class MeleeStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"With your Excalibur you sever the dragon's head!\");\n  }\n}\n```\n\n```java\n@Slf4j\npublic class ProjectileStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"You shoot the dragon with the magical crossbow and it falls dead on the ground!\");\n  }\n}\n```\n\n```java\n@Slf4j\npublic class SpellStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\");\n  }\n}\n```\n\nAnd here is the mighty `DragonSlayer`, who can pick his fighting strategy based on the opponent.\n\n```java\npublic class DragonSlayer {\n\n  private DragonSlayingStrategy strategy;\n\n  public DragonSlayer(DragonSlayingStrategy strategy) {\n    this.strategy = strategy;\n  }\n\n  public void changeStrategy(DragonSlayingStrategy strategy) {\n    this.strategy = strategy;\n  }\n\n  public void goToBattle() {\n    strategy.execute();\n  }\n}\n```\n\nFinally, here's the `DragonSlayer` in action.\n\n```java\n@Slf4j\npublic class App {\n\n  private static final String RED_DRAGON_EMERGES = \"Red dragon emerges.\";\n  private static final String GREEN_DRAGON_SPOTTED = \"Green dragon spotted ahead!\";\n  private static final String BLACK_DRAGON_LANDS = \"Black dragon lands before you.\";\n\n  public static void main(String[] args) {\n    // GoF Strategy pattern\n    LOGGER.info(GREEN_DRAGON_SPOTTED);\n    var dragonSlayer = new DragonSlayer(new MeleeStrategy());\n    dragonSlayer.goToBattle();\n    LOGGER.info(RED_DRAGON_EMERGES);\n    dragonSlayer.changeStrategy(new ProjectileStrategy());\n    dragonSlayer.goToBattle();\n    LOGGER.info(BLACK_DRAGON_LANDS);\n    dragonSlayer.changeStrategy(new SpellStrategy());\n    dragonSlayer.goToBattle();\n\n    // Java 8 functional implementation Strategy pattern\n    LOGGER.info(GREEN_DRAGON_SPOTTED);\n    dragonSlayer = new DragonSlayer(\n        () -> LOGGER.info(\"With your Excalibur you sever the dragon's head!\"));\n    dragonSlayer.goToBattle();\n    LOGGER.info(RED_DRAGON_EMERGES);\n    dragonSlayer.changeStrategy(() -> LOGGER.info(\n        \"You shoot the dragon with the magical crossbow and it falls dead on the ground!\"));\n    dragonSlayer.goToBattle();\n    LOGGER.info(BLACK_DRAGON_LANDS);\n    dragonSlayer.changeStrategy(() -> LOGGER.info(\n        \"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\"));\n    dragonSlayer.goToBattle();\n\n    // Java 8 lambda implementation with enum Strategy pattern\n    LOGGER.info(GREEN_DRAGON_SPOTTED);\n    dragonSlayer.changeStrategy(LambdaStrategy.Strategy.MELEE_STRATEGY);\n    dragonSlayer.goToBattle();\n    LOGGER.info(RED_DRAGON_EMERGES);\n    dragonSlayer.changeStrategy(LambdaStrategy.Strategy.PROJECTILE_STRATEGY);\n    dragonSlayer.goToBattle();\n    LOGGER.info(BLACK_DRAGON_LANDS);\n    dragonSlayer.changeStrategy(LambdaStrategy.Strategy.SPELL_STRATEGY);\n    dragonSlayer.goToBattle();\n  }\n}\n```\n\nProgram output:\n\n```\n13:06:36.631 [main] INFO com.iluwatar.strategy.App -- Green dragon spotted ahead!\n13:06:36.634 [main] INFO com.iluwatar.strategy.MeleeStrategy -- With your Excalibur you sever the dragon's head!\n13:06:36.634 [main] INFO com.iluwatar.strategy.App -- Red dragon emerges.\n13:06:36.634 [main] INFO com.iluwatar.strategy.ProjectileStrategy -- You shoot the dragon with the magical crossbow and it falls dead on the ground!\n13:06:36.634 [main] INFO com.iluwatar.strategy.App -- Black dragon lands before you.\n13:06:36.634 [main] INFO com.iluwatar.strategy.SpellStrategy -- You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\n13:06:36.634 [main] INFO com.iluwatar.strategy.App -- Green dragon spotted ahead!\n13:06:36.634 [main] INFO com.iluwatar.strategy.App -- With your Excalibur you sever the dragon's head!\n13:06:36.634 [main] INFO com.iluwatar.strategy.App -- Red dragon emerges.\n13:06:36.635 [main] INFO com.iluwatar.strategy.App -- You shoot the dragon with the magical crossbow and it falls dead on the ground!\n13:06:36.635 [main] INFO com.iluwatar.strategy.App -- Black dragon lands before you.\n13:06:36.635 [main] INFO com.iluwatar.strategy.App -- You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\n13:06:36.635 [main] INFO com.iluwatar.strategy.App -- Green dragon spotted ahead!\n13:06:36.637 [main] INFO com.iluwatar.strategy.LambdaStrategy -- With your Excalibur you sever the dragon's head!\n13:06:36.637 [main] INFO com.iluwatar.strategy.App -- Red dragon emerges.\n13:06:36.637 [main] INFO com.iluwatar.strategy.LambdaStrategy -- You shoot the dragon with the magical crossbow and it falls dead on the ground!\n13:06:36.637 [main] INFO com.iluwatar.strategy.App -- Black dragon lands before you.\n13:06:36.637 [main] INFO com.iluwatar.strategy.LambdaStrategy -- You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\n```\n\n## When to Use the Strategy Pattern in Java\n\nUse the Strategy pattern when:\n\n* You need to use different variants of an algorithm within an object and want to switch algorithms at runtime.\n* There are multiple related classes that differ only in their behavior.\n* An algorithm uses data that clients shouldn't know about.\n* A class defines many behaviors and these appear as multiple conditional statements in its operations.\n\n## Strategy Pattern Java Tutorials\n\n* [Strategy Pattern Tutorial (DigitalOcean)](https://www.digitalocean.com/community/tutorials/strategy-design-pattern-in-java-example-tutorial)\n\n## Real-World Applications of Strategy Pattern in Java\n\n* Java's `java.util.Comparator` interface is a common example of the Strategy pattern.\n* In GUI frameworks, layout managers (such as those in Java's AWT and Swing) are strategies.\n\n## Benefits and Trade-offs of Strategy Pattern\n\nBenefits:\n\n* Families of related algorithms are reused.\n* An alternative to subclassing for extending behavior.\n* Avoids conditional statements for selecting desired behavior.\n* Allows clients to choose algorithm implementation.\n\nTrade-offs:\n\n* Clients must be aware of different Strategies.\n* Increase in the number of objects.\n\n## Related Java Design Patterns\n\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Enhances an object without changing its interface but is more concerned with responsibilities than algorithms.\n* [State](https://java-design-patterns.com/patterns/state/): Similar in structure but used to represent state-dependent behavior rather than interchangeable algorithms.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Functional Programming in Java](https://amzn.to/3JUIc5Q)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "strategy/etc/strategy.urm.puml",
    "content": "@startuml\npackage com.iluwatar.strategy {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class DragonSlayer {\n    - strategy : DragonSlayingStrategy\n    + DragonSlayer(strategy : DragonSlayingStrategy)\n    + changeStrategy(strategy : DragonSlayingStrategy)\n    + goToBattle()\n  }\n  interface DragonSlayingStrategy {\n    + execute() {abstract}\n  }\n  class LambdaStrategy {\n    - LOGGER : Logger {static}\n    + LambdaStrategy()\n  }\n  enum Strategy {\n    + MeleeStrategy {static}\n    + ProjectileStrategy {static}\n    + SpellStrategy {static}\n    - dragonSlayingStrategy : DragonSlayingStrategy\n    + execute()\n    + valueOf(name : String) : Strategy {static}\n    + values() : Strategy[] {static}\n  }\n  class MeleeStrategy {\n    - LOGGER : Logger {static}\n    + MeleeStrategy()\n    + execute()\n  }\n  class ProjectileStrategy {\n    - LOGGER : Logger {static}\n    + ProjectileStrategy()\n    + execute()\n  }\n  class SpellStrategy {\n    - LOGGER : Logger {static}\n    + SpellStrategy()\n    + execute()\n  }\n}\nStrategy ..+ LambdaStrategy\nStrategy -->  \"-dragonSlayingStrategy\" DragonSlayingStrategy\nDragonSlayer -->  \"-strategy\" DragonSlayingStrategy\nStrategy ..|> DragonSlayingStrategy \nMeleeStrategy ..|> DragonSlayingStrategy \nProjectileStrategy ..|> DragonSlayingStrategy \nSpellStrategy ..|> DragonSlayingStrategy \n@enduml"
  },
  {
    "path": "strategy/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>strategy</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-params</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.strategy.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "strategy/src/main/java/com/iluwatar/strategy/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strategy;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Strategy pattern (also known as the policy pattern) is a software design pattern that enables\n * an algorithm's behavior to be selected at runtime.\n *\n * <p>Before Java 8 the Strategies needed to be separate classes forcing the developer to write lots\n * of boilerplate code. With modern Java, it is easy to pass behavior with method references and\n * lambdas making the code shorter and more readable.\n *\n * <p>In this example ({@link DragonSlayingStrategy}) encapsulates an algorithm. The containing\n * object ({@link DragonSlayer}) can alter its behavior by changing its strategy.\n */\n@Slf4j\npublic class App {\n\n  private static final String RED_DRAGON_EMERGES = \"Red dragon emerges.\";\n  private static final String GREEN_DRAGON_SPOTTED = \"Green dragon spotted ahead!\";\n  private static final String BLACK_DRAGON_LANDS = \"Black dragon lands before you.\";\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    // GoF Strategy pattern\n    LOGGER.info(GREEN_DRAGON_SPOTTED);\n    var dragonSlayer = new DragonSlayer(new MeleeStrategy());\n    dragonSlayer.goToBattle();\n    LOGGER.info(RED_DRAGON_EMERGES);\n    dragonSlayer.changeStrategy(new ProjectileStrategy());\n    dragonSlayer.goToBattle();\n    LOGGER.info(BLACK_DRAGON_LANDS);\n    dragonSlayer.changeStrategy(new SpellStrategy());\n    dragonSlayer.goToBattle();\n\n    // Java 8 functional implementation Strategy pattern\n    LOGGER.info(GREEN_DRAGON_SPOTTED);\n    dragonSlayer =\n        new DragonSlayer(() -> LOGGER.info(\"With your Excalibur you sever the dragon's head!\"));\n    dragonSlayer.goToBattle();\n    LOGGER.info(RED_DRAGON_EMERGES);\n    dragonSlayer.changeStrategy(\n        () ->\n            LOGGER.info(\n                \"You shoot the dragon with the magical crossbow and it falls dead on the ground!\"));\n    dragonSlayer.goToBattle();\n    LOGGER.info(BLACK_DRAGON_LANDS);\n    dragonSlayer.changeStrategy(\n        () ->\n            LOGGER.info(\n                \"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\"));\n    dragonSlayer.goToBattle();\n\n    // Java 8 lambda implementation with enum Strategy pattern\n    LOGGER.info(GREEN_DRAGON_SPOTTED);\n    dragonSlayer.changeStrategy(LambdaStrategy.Strategy.MELEE_STRATEGY);\n    dragonSlayer.goToBattle();\n    LOGGER.info(RED_DRAGON_EMERGES);\n    dragonSlayer.changeStrategy(LambdaStrategy.Strategy.PROJECTILE_STRATEGY);\n    dragonSlayer.goToBattle();\n    LOGGER.info(BLACK_DRAGON_LANDS);\n    dragonSlayer.changeStrategy(LambdaStrategy.Strategy.SPELL_STRATEGY);\n    dragonSlayer.goToBattle();\n  }\n}\n"
  },
  {
    "path": "strategy/src/main/java/com/iluwatar/strategy/DragonSlayer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strategy;\n\n/** DragonSlayer uses different strategies to slay the dragon. */\npublic class DragonSlayer {\n\n  private DragonSlayingStrategy strategy;\n\n  public DragonSlayer(DragonSlayingStrategy strategy) {\n    this.strategy = strategy;\n  }\n\n  public void changeStrategy(DragonSlayingStrategy strategy) {\n    this.strategy = strategy;\n  }\n\n  public void goToBattle() {\n    strategy.execute();\n  }\n}\n"
  },
  {
    "path": "strategy/src/main/java/com/iluwatar/strategy/DragonSlayingStrategy.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strategy;\n\n/** Strategy interface. */\n@FunctionalInterface\npublic interface DragonSlayingStrategy {\n\n  void execute();\n}\n"
  },
  {
    "path": "strategy/src/main/java/com/iluwatar/strategy/LambdaStrategy.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strategy;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Lambda implementation for enum strategy pattern. */\n@Slf4j\npublic class LambdaStrategy {\n\n  /** Enum to demonstrate strategy pattern. */\n  public enum Strategy implements DragonSlayingStrategy {\n    MELEE_STRATEGY(() -> LOGGER.info(\"With your Excalibur you sever the dragon's head!\")),\n    PROJECTILE_STRATEGY(\n        () ->\n            LOGGER.info(\n                \"You shoot the dragon with the magical crossbow and it falls dead on the ground!\")),\n    SPELL_STRATEGY(\n        () ->\n            LOGGER.info(\n                \"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\"));\n\n    private final DragonSlayingStrategy dragonSlayingStrategy;\n\n    Strategy(DragonSlayingStrategy dragonSlayingStrategy) {\n      this.dragonSlayingStrategy = dragonSlayingStrategy;\n    }\n\n    @Override\n    public void execute() {\n      dragonSlayingStrategy.execute();\n    }\n  }\n}\n"
  },
  {
    "path": "strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strategy;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Melee strategy. */\n@Slf4j\npublic class MeleeStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"With your Excalibur you sever the dragon's head!\");\n  }\n}\n"
  },
  {
    "path": "strategy/src/main/java/com/iluwatar/strategy/ProjectileStrategy.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strategy;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Projectile strategy. */\n@Slf4j\npublic class ProjectileStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"You shoot the dragon with the magical crossbow and it falls dead on the ground!\");\n  }\n}\n"
  },
  {
    "path": "strategy/src/main/java/com/iluwatar/strategy/SpellStrategy.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strategy;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Spell strategy. */\n@Slf4j\npublic class SpellStrategy implements DragonSlayingStrategy {\n\n  @Override\n  public void execute() {\n    LOGGER.info(\"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\");\n  }\n}\n"
  },
  {
    "path": "strategy/src/test/java/com/iluwatar/strategy/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strategy;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "strategy/src/test/java/com/iluwatar/strategy/DragonSlayerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strategy;\n\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport org.junit.jupiter.api.Test;\n\n/** DragonSlayerTest */\nclass DragonSlayerTest {\n\n  /** Verify if the dragon slayer uses the strategy during battle. */\n  @Test\n  void testGoToBattle() {\n    final var strategy = mock(DragonSlayingStrategy.class);\n    final var dragonSlayer = new DragonSlayer(strategy);\n\n    dragonSlayer.goToBattle();\n    verify(strategy).execute();\n    verifyNoMoreInteractions(strategy);\n  }\n\n  /** Verify if the dragon slayer uses the new strategy during battle after a change of strategy. */\n  @Test\n  void testChangeStrategy() {\n    final var initialStrategy = mock(DragonSlayingStrategy.class);\n    final var dragonSlayer = new DragonSlayer(initialStrategy);\n\n    dragonSlayer.goToBattle();\n    verify(initialStrategy).execute();\n\n    final var newStrategy = mock(DragonSlayingStrategy.class);\n    dragonSlayer.changeStrategy(newStrategy);\n\n    dragonSlayer.goToBattle();\n    verify(newStrategy).execute();\n\n    verifyNoMoreInteractions(initialStrategy, newStrategy);\n  }\n}\n"
  },
  {
    "path": "strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.strategy;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.MethodSource;\nimport org.slf4j.LoggerFactory;\n\n/** DragonSlayingStrategyTest */\nclass DragonSlayingStrategyTest {\n\n  /**\n   * Assembles test parameters.\n   *\n   * @return The test parameters for each cycle\n   */\n  static Collection<Object[]> dataProvider() {\n    return List.of(\n        new Object[] {new MeleeStrategy(), \"With your Excalibur you sever the dragon's head!\"},\n        new Object[] {\n          new ProjectileStrategy(),\n          \"You shoot the dragon with the magical crossbow and it falls dead on the ground!\"\n        },\n        new Object[] {\n          new SpellStrategy(),\n          \"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!\"\n        });\n  }\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /** Test if executing the strategy gives the correct response. */\n  @ParameterizedTest\n  @MethodSource(\"dataProvider\")\n  void testExecute(DragonSlayingStrategy strategy, String expectedResult) {\n    strategy.execute();\n    assertEquals(expectedResult, appender.getLastMessage());\n    assertEquals(1, appender.getLogSize());\n  }\n\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender() {\n      ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n\n    public String getLastMessage() {\n      return log.get(log.size() - 1).getFormattedMessage();\n    }\n  }\n}\n"
  },
  {
    "path": "subclass-sandbox/README.md",
    "content": "---\ntitle: \"Subclass Sandbox Pattern in Java: Enhancing Code Reusability with Sandbox Techniques\"\nshortTitle: Subclass Sandbox\ndescription: \"Explore the Subclass Sandbox design pattern in Java, perfect for allowing flexible behavior customization in object-oriented programming. Ideal for game development and extending class behavior.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Abstraction\n  - Code simplification\n  - Decoupling\n  - Extensibility\n  - Game programming\n  - Polymorphism\n---\n\n## Also known as\n\n* Hook Method\n\n## Intent of Subclass Sandbox  Design Pattern\n\nThe Subclass Sandbox design pattern in Java allows subclasses to alter the core behavior of a class by providing specific implementations of certain methods while keeping the overall structure unchanged.\n  \n## Detailed Explanation of Subclass Sandbox  Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a cooking class where the instructor provides a standard recipe structure, including steps like \"prepare ingredients,\" \"cook,\" and \"serve.\" Each student follows this structure but can customize specific steps to create their unique dish. For example, one student might choose to prepare a salad, while another might prepare a stir-fry, both adhering to the same overarching recipe format. This way, the instructor ensures that all dishes are made following a consistent process, but students have the flexibility to personalize the key parts of their recipes. This mirrors the Subclass Sandbox pattern, where the core structure is defined by the superclass, and specific behaviors are customized in subclasses.\n\nIn plain words\n\n> The Subclass Sandbox pattern allows subclasses to customize specific behaviors within a predefined algorithm structure provided by the superclass.\n\n[gameprogrammingpatterns.com](https://gameprogrammingpatterns.com/) says\n\n> A base class defines an abstract sandbox method and several provided operations. Marking them protected makes it clear that they are for use by derived classes. Each derived sandboxed subclass implements the sandbox method using the provided operations.\n\nFlowchart\n\n![Subclass Sandbox flowchart](./etc/subclass-sandbox-flowchart.png)\n\n## Programmatic Example of Subclass Sandbox Pattern in Java\n\nUsing the Subclass Sandbox pattern, developers can create distinct functionalities within Java applications, enhancing game development and software design.\n\nSuppose you want to create various superpowers in a game, where each superpower needs to move with a sound effect and spawn particles. Should you create many classes with similar methods or derive them from a base class? The Subclass Sandbox pattern enables you to handle this efficiently by deriving these classes from a common base class.\n\nWe start with the base class `Superpower`. It contains an abstract sandbox method `active` and some provided operations.\n\n```java\npublic abstract class Superpower {\n\n  protected Logger logger;\n\n  protected abstract void activate();\n\n  protected void move(double x, double y, double z) {\n    logger.info(\"Move to ( \" + x + \", \" + y + \", \" + z + \" )\");\n  }\n\n  protected void playSound(String soundName, int volume) {\n    logger.info(\"Play \" + soundName + \" with volume \" + volume);\n  }\n\n  protected void spawnParticles(String particleType, int count) {\n    logger.info(\"Spawn \" + count + \" particle with type \" + particleType);\n  }\n}\n```\n\nNext, we are able to create derived sandboxed subclass that implements the sandbox method using the provided operations. Here is the first power:\n\n```java\npublic class SkyLaunch extends Superpower {\n\n  public SkyLaunch() {\n    super();\n    logger = LoggerFactory.getLogger(SkyLaunch.class);\n  }\n\n  @Override\n  protected void activate() {\n    move(0, 0, 20);\n    playSound(\"SKYLAUNCH_SOUND\", 1);\n    spawnParticles(\"SKYLAUNCH_PARTICLE\", 100);\n  }\n}\n```\n\nHere is the second power.\n\n```java\npublic class GroundDive extends Superpower {\n\n  public GroundDive() {\n    super();\n    logger = LoggerFactory.getLogger(GroundDive.class);\n  }\n\n  @Override\n  protected void activate() {\n    move(0, 0, -20);\n    playSound(\"GROUNDDIVE_SOUND\", 5);\n    spawnParticles(\"GROUNDDIVE_PARTICLE\", 20);\n  }\n}\n```\n\nFinally, here are the superpowers in active.\n\n```java\npublic static void main(String[] args) {\n    LOGGER.info(\"Use superpower: sky launch\");\n    var skyLaunch = new SkyLaunch();\n    skyLaunch.activate();\n    LOGGER.info(\"Use superpower: ground dive\");\n    var groundDive = new GroundDive();\n    groundDive.activate();\n}\n```\n\nProgram output:\n\n```\n13:10:23.177 [main] INFO com.iluwatar.subclasssandbox.App -- Use superpower: sky launch\n13:10:23.179 [main] INFO com.iluwatar.subclasssandbox.SkyLaunch -- Move to ( 0.0, 0.0, 20.0 )\n13:10:23.180 [main] INFO com.iluwatar.subclasssandbox.SkyLaunch -- Play SKYLAUNCH_SOUND with volume 1\n13:10:23.180 [main] INFO com.iluwatar.subclasssandbox.SkyLaunch -- Spawn 100 particle with type SKYLAUNCH_PARTICLE\n13:10:23.180 [main] INFO com.iluwatar.subclasssandbox.App -- Use superpower: ground dive\n13:10:23.180 [main] INFO com.iluwatar.subclasssandbox.GroundDive -- Move to ( 0.0, 0.0, -20.0 )\n13:10:23.180 [main] INFO com.iluwatar.subclasssandbox.GroundDive -- Play GROUNDDIVE_SOUND with volume 5\n13:10:23.180 [main] INFO com.iluwatar.subclasssandbox.GroundDive -- Spawn 20 particle with type GROUNDDIVE_PARTICLE\n```\n\n## When to Use the Subclass Sandbox Pattern in Java  \n\n* Use when you want to create a framework that allows users to define their own behaviors by extending classes.\n* Applicable in scenarios where you need to enforce a specific algorithm structure while allowing certain steps to be overridden.\n\n## Real-World Applications of Subclass Sandbox Pattern in Java\n\n* Template method pattern in GUI frameworks where the framework provides the structure and the subclasses implement the specifics.\n* Game development where the core game loop is defined, but specific behaviors are provided by subclassing.\n* Java libraries like the `AbstractList` where core methods are defined and certain behaviors can be customized by extending classes.\n\n## Benefits and Trade-offs of Subclass Sandbox Pattern\n\nBenefits:\n\nThe Subclass Sandbox pattern in Java\n\n* Encourages code reuse by allowing shared code in the superclass.\n* Simplifies the addition of new behaviors through subclassing.\n* Enhances code readability and maintainability by separating the algorithm's structure from specific implementations.\n\nTrade-offs:\n\n* Can lead to a large number of subclasses.\n* Requires careful design to ensure that the base class is flexible enough for various extensions.\n* Increases complexity in understanding the code flow due to multiple layers of inheritance.\n\n## Related Java Design Patterns\n\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Both involve interchangeable behaviors, but Strategy pattern uses composition over inheritance.\n* [Template Method](https://java-design-patterns.com/patterns/template-method/): Similar in enforcing a structure where certain steps can be overridden by subclasses.\n\n## References and Credits  \n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Game Programming Patterns](https://amzn.to/3K96fOn)\n* [Subclass Sandbox (Game Programming Patterns)](https://gameprogrammingpatterns.com/subclass-sandbox.html)\n"
  },
  {
    "path": "subclass-sandbox/etc/subclass-sandbox.urm.puml",
    "content": "@startuml\npackage com.iluwatar.subclasssandbox {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class GroundDive {\n    + GroundDive()\n    # activate()\n  }\n  class SkyLaunch {\n    + SkyLaunch()\n    # activate()\n  }\n  abstract class Superpower {\n    # logger : Logger\n    + Superpower()\n    # activate() {abstract}\n    # move(x : double, y : double, z : double)\n    # playSound(soundName : String, volume : int)\n    # spawnParticles(particleType : String, count : int)\n  }\n}\nGroundDive --|> Superpower \nSkyLaunch --|> Superpower \n@enduml"
  },
  {
    "path": "subclass-sandbox/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>subclass-sandbox</artifactId>\n  <properties>\n    <slf4j.version>2.0.17</slf4j.version>\n    <logback.version>1.5.18</logback.version>\n  </properties>\n  <dependencies>\n    <dependency>\n      <groupId>com.github.stefanbirkner</groupId>\n      <artifactId>system-lambda</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n      <version>${slf4j.version}</version>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n      <version>${logback.version}</version>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-core</artifactId>\n      <version>${logback.version}</version>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n</project>\n"
  },
  {
    "path": "subclass-sandbox/src/main/java/com/iluwatar/subclasssandbox/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.subclasssandbox;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The subclass sandbox pattern describes a basic idea, while not having a lot of detailed\n * mechanics. You will need the pattern when you have several similar subclasses. If you have to\n * make a tiny change, then change the base class, while all subclasses shouldn't have to be\n * touched. So the base class has to be able to provide all the operations a derived class needs to\n * perform.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Entry point of the main program.\n   *\n   * @param args Program runtime arguments.\n   */\n  public static void main(String[] args) {\n    LOGGER.info(\"Use superpower: sky launch\");\n    var skyLaunch = new SkyLaunch();\n    skyLaunch.activate();\n    LOGGER.info(\"Use superpower: ground dive\");\n    var groundDive = new GroundDive();\n    groundDive.activate();\n  }\n}\n"
  },
  {
    "path": "subclass-sandbox/src/main/java/com/iluwatar/subclasssandbox/GroundDive.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.subclasssandbox;\n\nimport org.slf4j.LoggerFactory;\n\n/** GroundDive superpower. */\npublic class GroundDive extends Superpower {\n\n  public GroundDive() {\n    super();\n    logger = LoggerFactory.getLogger(GroundDive.class);\n  }\n\n  @Override\n  protected void activate() {\n    move(0, 0, -20);\n    playSound(\"GROUNDDIVE_SOUND\", 5);\n    spawnParticles(\"GROUNDDIVE_PARTICLE\", 20);\n  }\n}\n"
  },
  {
    "path": "subclass-sandbox/src/main/java/com/iluwatar/subclasssandbox/SkyLaunch.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.subclasssandbox;\n\nimport org.slf4j.LoggerFactory;\n\n/** SkyLaunch superpower. */\npublic class SkyLaunch extends Superpower {\n\n  public SkyLaunch() {\n    super();\n    logger = LoggerFactory.getLogger(SkyLaunch.class);\n  }\n\n  @Override\n  protected void activate() {\n    move(0, 0, 20);\n    playSound(\"SKYLAUNCH_SOUND\", 1);\n    spawnParticles(\"SKYLAUNCH_PARTICLE\", 100);\n  }\n}\n"
  },
  {
    "path": "subclass-sandbox/src/main/java/com/iluwatar/subclasssandbox/Superpower.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.subclasssandbox;\n\nimport org.slf4j.Logger;\n\n/**\n * Superpower abstract class. In this class the basic operations of all types of superpowers are\n * provided as protected methods.\n */\npublic abstract class Superpower {\n\n  protected Logger logger;\n\n  /**\n   * Subclass of superpower should implement this sandbox method by calling the methods provided in\n   * this super class.\n   */\n  protected abstract void activate();\n\n  /**\n   * Move to (x, y, z).\n   *\n   * @param x X coordinate.\n   * @param y Y coordinate.\n   * @param z Z coordinate.\n   */\n  protected void move(double x, double y, double z) {\n    logger.info(\"Move to ( {}, {}, {} )\", x, y, z);\n  }\n\n  /**\n   * Play sound effect for the superpower.\n   *\n   * @param soundName Sound name.\n   * @param volume Value of volume.\n   */\n  protected void playSound(String soundName, int volume) {\n    logger.info(\"Play {} with volume {}\", soundName, volume);\n  }\n\n  /**\n   * Spawn particles for the superpower.\n   *\n   * @param particleType Particle type.\n   * @param count Count of particles to be spawned.\n   */\n  protected void spawnParticles(String particleType, int count) {\n    logger.info(\"Spawn {} particle with type {}\", count, particleType);\n  }\n}\n"
  },
  {
    "path": "subclass-sandbox/src/test/java/com/iluwatar/subclasssandbox/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.subclasssandbox;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** App unit tests. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "subclass-sandbox/src/test/java/com/iluwatar/subclasssandbox/GroundDiveTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.subclasssandbox;\n\nimport static com.github.stefanbirkner.systemlambda.SystemLambda.tapSystemOutNormalized;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.github.stefanbirkner.systemlambda.Statement;\nimport org.junit.jupiter.api.Test;\n\n/** GroundDive unit tests. */\nclass GroundDiveTest {\n\n  @Test\n  void testMove() throws Exception {\n    var groundDive = new GroundDive();\n    groundDive.move(1.0, 1.0, 1.0);\n    var outputLog = getLogContent(() -> groundDive.move(1.0, 1.0, 1.0));\n    var expectedLog = \"Move to ( 1.0, 1.0, 1.0 )\";\n    assertEquals(outputLog, expectedLog);\n  }\n\n  @Test\n  void testPlaySound() throws Exception {\n    var groundDive = new GroundDive();\n    var outputLog = getLogContent(() -> groundDive.playSound(\"SOUND_NAME\", 1));\n    var expectedLog = \"Play SOUND_NAME with volume 1\";\n    assertEquals(outputLog, expectedLog);\n  }\n\n  @Test\n  void testSpawnParticles() throws Exception {\n    var groundDive = new GroundDive();\n    final var outputLog = getLogContent(() -> groundDive.spawnParticles(\"PARTICLE_TYPE\", 100));\n    final var expectedLog = \"Spawn 100 particle with type PARTICLE_TYPE\";\n    assertEquals(outputLog, expectedLog);\n  }\n\n  @Test\n  void testActivate() throws Exception {\n    var groundDive = new GroundDive();\n    var logs = tapSystemOutNormalized(groundDive::activate).split(\"\\n\");\n    final var expectedSize = 3;\n    final var log1 = logs[0].split(\"--\")[1].trim();\n    final var expectedLog1 = \"Move to ( 0.0, 0.0, -20.0 )\";\n    final var log2 = getLogContent(logs[1]);\n    final var expectedLog2 = \"Play GROUNDDIVE_SOUND with volume 5\";\n    final var log3 = getLogContent(logs[2]);\n    final var expectedLog3 = \"Spawn 20 particle with type GROUNDDIVE_PARTICLE\";\n    assertEquals(logs.length, expectedSize);\n    assertEquals(log1, expectedLog1);\n    assertEquals(log2, expectedLog2);\n    assertEquals(log3, expectedLog3);\n  }\n\n  private String getLogContent(Statement statement) throws Exception {\n    var log = tapSystemOutNormalized(statement);\n    return getLogContent(log);\n  }\n\n  private String getLogContent(String log) {\n    return log.split(\"--\")[1].trim();\n  }\n}\n"
  },
  {
    "path": "subclass-sandbox/src/test/java/com/iluwatar/subclasssandbox/SkyLaunchTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.subclasssandbox;\n\nimport static com.github.stefanbirkner.systemlambda.SystemLambda.tapSystemOutNormalized;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.github.stefanbirkner.systemlambda.Statement;\nimport org.junit.jupiter.api.Test;\n\n/** SkyLaunch unit tests. */\nclass SkyLaunchTest {\n\n  @Test\n  void testMove() throws Exception {\n    var skyLaunch = new SkyLaunch();\n    var outputLog = getLogContent(() -> skyLaunch.move(1.0, 1.0, 1.0));\n    var expectedLog = \"Move to ( 1.0, 1.0, 1.0 )\";\n    assertEquals(outputLog, expectedLog);\n  }\n\n  @Test\n  void testPlaySound() throws Exception {\n    var skyLaunch = new SkyLaunch();\n    var outputLog = getLogContent(() -> skyLaunch.playSound(\"SOUND_NAME\", 1));\n    var expectedLog = \"Play SOUND_NAME with volume 1\";\n    assertEquals(outputLog, expectedLog);\n  }\n\n  @Test\n  void testSpawnParticles() throws Exception {\n    var skyLaunch = new SkyLaunch();\n    var outputLog = getLogContent(() -> skyLaunch.spawnParticles(\"PARTICLE_TYPE\", 100));\n    var expectedLog = \"Spawn 100 particle with type PARTICLE_TYPE\";\n    assertEquals(outputLog, expectedLog);\n  }\n\n  @Test\n  void testActivate() throws Exception {\n    var skyLaunch = new SkyLaunch();\n    var logs = tapSystemOutNormalized(skyLaunch::activate).split(\"\\n\");\n    final var expectedSize = 3;\n    final var log1 = getLogContent(logs[0]);\n    final var expectedLog1 = \"Move to ( 0.0, 0.0, 20.0 )\";\n    final var log2 = getLogContent(logs[1]);\n    final var expectedLog2 = \"Play SKYLAUNCH_SOUND with volume 1\";\n    final var log3 = getLogContent(logs[2]);\n    final var expectedLog3 = \"Spawn 100 particle with type SKYLAUNCH_PARTICLE\";\n    assertEquals(logs.length, expectedSize);\n    assertEquals(log1, expectedLog1);\n    assertEquals(log2, expectedLog2);\n    assertEquals(log3, expectedLog3);\n  }\n\n  private String getLogContent(Statement statement) throws Exception {\n    var log = tapSystemOutNormalized(statement);\n    return getLogContent(log);\n  }\n\n  private String getLogContent(String log) {\n    return log.split(\"--\")[1].trim();\n  }\n}\n"
  },
  {
    "path": "table-inheritance/README.md",
    "content": "---\ntitle: \"Table Inheritance Pattern in Java: Modeling Hierarchical Data in Relational Databases\"\nshortTitle: Table Inheritance\ndescription: \"Explore the Table Inheritance pattern in Java with real-world examples, database schema, and tutorials. Learn how to model class hierarchies elegantly in relational databases.\"\ncategory: Data access\nlanguage: en\ntag:\n    - Data access\n    - Database\n    - Inheritance\n    - Persistence\n    - Polymorphism\n---\n\n## Also known as\n\n* Class Table Inheritance\n* Joined Table Inheritance\n\n## Intent of Table Inheritance Pattern\n\nRepresent inheritance hierarchies in relational databases by mapping each class in a hierarchy to a database table.\n\n## Detailed Explanation of Table Inheritance Pattern with Real-World Examples\n\nReal-world example\n\n> A classic real-world analogy for the Table Inheritance (Joined Table) pattern is managing employee records in an organization: \n> Imagine a company's database storing information about employees. All employees have common attributes (name, employee ID, hire date), stored in a general \"Employee\" table. However, the company also has different types of employees: Full-time Employees (with a salary and benefits) and Contractors (hourly rate, contract duration). Each employee type has distinct data stored in separate specialized tables (\"FullTimeEmployee\" and \"Contractor\"), which reference the main \"Employee\" table. \n> This structure mirrors the Table Inheritance pattern—shared fields in a common table and unique fields split into subclass-specific tables.\n\nIn plain words\n\n> The Table Inheritance pattern maps each class within an inheritance hierarchy to its own database table, storing common attributes in a base table and subclass-specific attributes in separate joined tables.\n\nMartin Fowler says\n\n> Relational databases don't support inheritance, which creates a mismatch when mapping objects. To fix this, Table Inheritance uses a separate table for each class in the hierarchy while maintaining relationships through foreign keys, making it easier to link the classes together in the database.\n\nMind map\n\n![Table Inheritance Pattern Mind Map](./etc/table-inheritance-mind-map.png)\n\n## Programmatic Example of Table Inheritance Pattern in Java\n\nThe `Vehicle` class will be the superclass, and we will have subclasses `Car` and `Truck` that extend `Vehicle`. The superclass `Vehicle` stores common attributes, while subclasses store their own specific attributes.\n\n### Key Aspects of the Pattern:\n\n**Superclass (`Vehicle`):**\n\nThe superclass stores shared attributes:\n\n* `make`: Manufacturer of the vehicle.\n* `model`: Model of the vehicle.\n* `year`: Year of manufacture.\n* `id`: Unique identifier for the vehicle.\n\nThese common attributes will reside in a dedicated database table (`Vehicle` table).\n\n**Subclasses (`Car` and `Truck`):**\n\nEach subclass adds attributes specific to its type:\n\n* `Car`: `numberOfDoors`, indicating how many doors the car has.\n* `Truck`: `payloadCapacity`, representing how much payload the truck can carry.\n\nEach subclass stores these specific attributes in their respective tables (`Car` and `Truck` tables).\n\n**Foreign Key Relationship:**\n\nEach subclass table references the superclass table via a foreign key. The subclass's `id` links to the primary key of the superclass, thus connecting common and subclass-specific data.\n\n### Java Implementation Using JPA Annotations:\n\n```java\n@Setter\n@Getter\npublic class Vehicle {\n\n   private String make;\n   private String model;\n   private int year;\n   private int id;\n\n   public Vehicle(int year, String make, String model, int id) {\n      this.make = make;\n      this.model = model;\n      this.year = year;\n      this.id = id;\n   }\n\n   @Override\n   public String toString() {\n      return \"Vehicle{\"\n              + \"id=\"\n              + id\n              + \", make='\"\n              + make\n              + '\\''\n              + \", model='\"\n              + model\n              + '\\''\n              + \", year=\"\n              + year\n              + '}';\n   }\n}\n\n@Getter\npublic class Car extends Vehicle {\n   private int numDoors;\n\n   public Car(int year, String make, String model, int numDoors, int id) {\n      super(year, make, model, id);\n      if (numDoors <= 0) {\n         throw new IllegalArgumentException(\"Number of doors must be positive.\");\n      }\n      this.numDoors = numDoors;\n   }\n\n   public void setNumDoors(int doors) {\n      if (doors <= 0) {\n         throw new IllegalArgumentException(\"Number of doors must be positive.\");\n      }\n      this.numDoors = doors;\n   }\n\n   @Override\n   public String toString() {\n      return \"Car{\"\n              + \"id=\"\n              + getId()\n              + \", make='\"\n              + getMake()\n              + '\\''\n              + \", model='\"\n              + getModel()\n              + '\\''\n              + \", year=\"\n              + getYear()\n              + \", numberOfDoors=\"\n              + getNumDoors()\n              + '}';\n   }\n}\n\n@Getter\npublic class Truck extends Vehicle {\n   private double loadCapacity;\n\n   public Truck(int year, String make, String model, double loadCapacity, int id) {\n      super(year, make, model, id);\n      if (loadCapacity <= 0) {\n         throw new IllegalArgumentException(\"Load capacity must be positive.\");\n      }\n      this.loadCapacity = loadCapacity;\n   }\n\n   public void setLoadCapacity(double capacity) {\n      if (capacity <= 0) {\n         throw new IllegalArgumentException(\"Load capacity must be positive.\");\n      }\n      this.loadCapacity = capacity;\n   }\n\n   @Override\n   public String toString() {\n      return \"Truck{\"\n              + \"id=\"\n              + getId()\n              + \", make='\"\n              + getMake()\n              + '\\''\n              + \", model='\"\n              + getModel()\n              + '\\''\n              + \", year=\"\n              + getYear()\n              + \", payloadCapacity=\"\n              + getLoadCapacity()\n              + '}';\n   }\n}\n```\n\n### Explanation of the JPA annotations used above:\n\n* `@Entity`: Indicates that the class is a JPA entity mapped to a database table.\n* `@Inheritance(strategy = InheritanceType.JOINED)`: Configures joined table inheritance, meaning each class (superclass and subclasses) maps to its own table.\n* `@Table(name = \"XYZ\")`: Explicitly specifies the database table name for clarity.\n* `@Id`: Marks the primary key of the entity.\n* `@GeneratedValue(strategy = GenerationType.IDENTITY)`: Specifies auto-generation of primary key values by the database.\n\n### Database Structure Result:\n\nApplying this code will result in three database tables structured as follows:\n\n**Vehicle table**\n* id\n* make\n* model\n* year\n\n**Car table**\n* id (FK to Vehicle)\n* numberOfDoors\n\n**Truck table**\n* id (FK to Vehicle)\n* payloadCapacity\n\nThis approach clearly represents the Table Inheritance (Joined Table) pattern, with common attributes centrally managed in the superclass table and subclass-specific attributes cleanly separated in their own tables.\n\n## When to Use the Table Inheritance Pattern in Java\n\n* When persisting an inheritance hierarchy of Java classes in a relational database.\n* Suitable when classes share common attributes but also have distinct fields.\n* Beneficial when polymorphic queries across subclasses are frequent.\n\n## Table Inheritance Pattern Java Tutorials\n\n- [Software Patterns Lexicon: Class Table Inheritance](https://softwarepatternslexicon.com/patterns-sql/4/4/2/)\n- [Martin Fowler: Class Table Inheritance](http://thierryroussel.free.fr/java/books/martinfowler/www.martinfowler.com/isa/classTableInheritance.html)\n\n## Real-World Applications of Table Inheritance Pattern in Java\n\n* Hibernate ORM (`@Inheritance(strategy = InheritanceType.JOINED)` in Java)\n* EclipseLink (Joined Inheritance strategy in JPA)\n* Spring Data JPA applications modeling complex domain hierarchies.\n\n## Benefits and Trade-offs of Table Inheritance Pattern\n\nBenefits:\n\n * Normalized database schema reduces redundancy.\n * Clearly models class hierarchies at the database level.\n * Easier to implement polymorphic queries due to clear class distinctions.\n\nTrade-offs:\n\n * Increased complexity in database queries involving multiple joins.\n * Reduced performance for deep inheritance hierarchies due to costly joins.\n * Maintenance overhead increases with the complexity of inheritance structures.\n\n## Related Java Design Patterns\n\n* [Single Table Inheritance](https://java-design-patterns.com/patterns/single-table-inheritance/): Alternative strategy mapping an entire class hierarchy into a single database table, useful when fewer joins are preferred at the cost of nullable columns.\n* Concrete Table Inheritance – Each subclass has its own standalone table; related in providing an alternate approach to storing inheritance hierarchies.\n\n## References and Credits\n\n* [Java Persistence with Hibernate](https://amzn.to/44tP1ox)\n* [Object-Relational Mapping (Wikipedia)](https://en.wikipedia.org/wiki/Object-relational_mapping)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Pro JPA 2: Mastering the Java Persistence API](https://amzn.to/4b7UoMC)\n"
  },
  {
    "path": "table-inheritance/etc/table-inheritance.urm.puml",
    "content": "@startuml\npackage com.iluwatar.table.inheritance {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Car {\n    - numDoors : int\n    + Car(year : int, make : String, model : String, numDoors : int, id : int)\n    + getNumDoors() : int\n    + setNumDoors(doors : int)\n    + toString() : String\n  }\n  class Truck {\n    - loadCapacity : double\n    + Truck(year : int, make : String, model : String, loadCapacity : double, id : int)\n    + getLoadCapacity() : double\n    + setLoadCapacity(capacity : double)\n    + toString() : String\n  }\n  class Vehicle {\n    - id : int\n    - make : String\n    - model : String\n    - year : int\n    + Vehicle(year : int, make : String, model : String, id : int)\n    + getId() : int\n    + getMake() : String\n    + getModel() : String\n    + getYear() : int\n    + setId(id : int)\n    + setMake(make : String)\n    + setModel(model : String)\n    + setYear(year : int)\n    + toString() : String\n  }\n  class VehicleDatabase {\n    - carTable : Map<Integer, Car>\n    ~ logger : Logger\n    - truckTable : Map<Integer, Truck>\n    - vehicleTable : Map<Integer, Vehicle>\n    + VehicleDatabase()\n    + getCar(id : int) : Car\n    + getTruck(id : int) : Truck\n    + getVehicle(id : int) : Vehicle\n    + printAllVehicles()\n    + saveVehicle(vehicle : Vehicle)\n  }\n}\nCar --|> Vehicle \nTruck --|> Vehicle \n@enduml"
  },
  {
    "path": "table-inheritance/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>table-inheritance</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n\n\n</project>"
  },
  {
    "path": "table-inheritance/src/main/java/com/iluwatar/table/inheritance/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.table.inheritance;\n\nimport java.util.logging.Logger;\n\n/**\n * The main entry point of the application demonstrating the use of vehicles.\n *\n * <p>The Table Inheritance pattern models a class hierarchy in a relational database by creating\n * separate tables for each class in the hierarchy. These tables share a common primary key, which\n * in subclass tables also serves as a foreign key referencing the primary key of the base class\n * table. This linkage maintains relationships and effectively represents the inheritance structure.\n * This pattern enables the organization of complex data models, particularly when subclasses have\n * unique properties that must be stored in distinct tables.\n */\npublic class App {\n  /**\n   * Manages the storage and retrieval of Vehicle objects, including Cars and Trucks.\n   *\n   * <p>This example demonstrates the **Table Inheritance** pattern, where each vehicle type (Car\n   * and Truck) is stored in its own separate table. The `VehicleDatabase` simulates a simple\n   * database that manages these entities, with each subclass (Car and Truck) being stored in its\n   * respective table.\n   *\n   * <p>The `VehicleDatabase` contains the following tables: - `vehicleTable`: Stores all vehicle\n   * objects, including both `Car` and `Truck` objects. - `carTable`: Stores only `Car` objects,\n   * with fields specific to cars. - `truckTable`: Stores only `Truck` objects, with fields specific\n   * to trucks.\n   *\n   * <p>The example demonstrates: 1. Saving instances of `Car` and `Truck` to their respective\n   * tables in the database. 2. Retrieving vehicles (both cars and trucks) from the appropriate\n   * table based on their ID. 3. Printing all vehicles stored in the database. 4. Showing how to\n   * retrieve specific types of vehicles (`Car` or `Truck`) by their IDs.\n   *\n   * <p>In the **Table Inheritance** pattern, each subclass has its own table, making it easier to\n   * manage specific attributes of each subclass.\n   *\n   * @param args command-line arguments\n   */\n  public static void main(String[] args) {\n\n    final Logger logger = Logger.getLogger(App.class.getName());\n\n    VehicleDatabase database = new VehicleDatabase();\n\n    Car car = new Car(2020, \"Toyota\", \"Corolla\", 4, 1);\n    Truck truck = new Truck(2018, \"Ford\", \"F-150\", 60, 2);\n\n    database.saveVehicle(car);\n    database.saveVehicle(truck);\n\n    database.printAllVehicles();\n\n    Vehicle vehicle = database.getVehicle(car.getId());\n    Car retrievedCar = database.getCar(car.getId());\n    Truck retrievedTruck = database.getTruck(truck.getId());\n\n    logger.info(String.format(\"Retrieved Vehicle: %s\", vehicle));\n    logger.info(String.format(\"Retrieved Car: %s\", retrievedCar));\n    logger.info(String.format(\"Retrieved Truck: %s\", retrievedTruck));\n  }\n}\n"
  },
  {
    "path": "table-inheritance/src/main/java/com/iluwatar/table/inheritance/Car.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.table.inheritance;\n\nimport lombok.Getter;\n\n/** Represents a car with a specific number of doors. */\n@Getter\npublic class Car extends Vehicle {\n  private int numDoors;\n\n  /**\n   * Constructs a Car object.\n   *\n   * @param year the manufacturing year\n   * @param make the make of the car\n   * @param model the model of the car\n   * @param numDoors the number of doors\n   * @param id the unique identifier for the car\n   */\n  public Car(int year, String make, String model, int numDoors, int id) {\n    super(year, make, model, id);\n    if (numDoors <= 0) {\n      throw new IllegalArgumentException(\"Number of doors must be positive.\");\n    }\n    this.numDoors = numDoors;\n  }\n\n  /**\n   * Sets the number of doors for the car.\n   *\n   * @param doors the number of doors\n   */\n  public void setNumDoors(int doors) {\n    if (doors <= 0) {\n      throw new IllegalArgumentException(\"Number of doors must be positive.\");\n    }\n    this.numDoors = doors;\n  }\n\n  @Override\n  public String toString() {\n    return \"Car{\"\n        + \"id=\"\n        + getId()\n        + \", make='\"\n        + getMake()\n        + '\\''\n        + \", model='\"\n        + getModel()\n        + '\\''\n        + \", year=\"\n        + getYear()\n        + \", numberOfDoors=\"\n        + getNumDoors()\n        + '}';\n  }\n}\n"
  },
  {
    "path": "table-inheritance/src/main/java/com/iluwatar/table/inheritance/Truck.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.table.inheritance;\n\nimport lombok.Getter;\n\n/** Represents a truck, a type of vehicle with a specific load capacity. */\n@Getter\npublic class Truck extends Vehicle {\n  private double loadCapacity;\n\n  /**\n   * Constructs a Truck object with the given parameters.\n   *\n   * @param year the year of manufacture\n   * @param make the make of the truck\n   * @param model the model of the truck\n   * @param loadCapacity the load capacity of the truck\n   * @param id the unique ID of the truck\n   */\n  public Truck(int year, String make, String model, double loadCapacity, int id) {\n    super(year, make, model, id);\n    if (loadCapacity <= 0) {\n      throw new IllegalArgumentException(\"Load capacity must be positive.\");\n    }\n    this.loadCapacity = loadCapacity;\n  }\n\n  /**\n   * Sets the load capacity of the truck.\n   *\n   * @param capacity the new load capacity\n   */\n  public void setLoadCapacity(double capacity) {\n    if (capacity <= 0) {\n      throw new IllegalArgumentException(\"Load capacity must be positive.\");\n    }\n    this.loadCapacity = capacity;\n  }\n\n  /**\n   * Returns a string representation of the truck.\n   *\n   * @return a string with the truck's details\n   */\n  @Override\n  public String toString() {\n    return \"Truck{\"\n        + \"id=\"\n        + getId()\n        + \", make='\"\n        + getMake()\n        + '\\''\n        + \", model='\"\n        + getModel()\n        + '\\''\n        + \", year=\"\n        + getYear()\n        + \", payloadCapacity=\"\n        + getLoadCapacity()\n        + '}';\n  }\n}\n"
  },
  {
    "path": "table-inheritance/src/main/java/com/iluwatar/table/inheritance/Vehicle.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.table.inheritance;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Represents a generic vehicle with basic attributes like make, model, year, and ID. */\n@Setter\n@Getter\npublic class Vehicle {\n\n  private String make;\n  private String model;\n  private int year;\n  private int id;\n\n  /**\n   * Constructs a Vehicle object with the given parameters.\n   *\n   * @param year the year of manufacture\n   * @param make the make of the vehicle\n   * @param model the model of the vehicle\n   * @param id the unique ID of the vehicle\n   */\n  public Vehicle(int year, String make, String model, int id) {\n    this.make = make;\n    this.model = model;\n    this.year = year;\n    this.id = id;\n  }\n\n  /**\n   * Returns a string representation of the vehicle.\n   *\n   * @return a string with the vehicle's details\n   */\n  @Override\n  public String toString() {\n    return \"Vehicle{\"\n        + \"id=\"\n        + id\n        + \", make='\"\n        + make\n        + '\\''\n        + \", model='\"\n        + model\n        + '\\''\n        + \", year=\"\n        + year\n        + '}';\n  }\n}\n"
  },
  {
    "path": "table-inheritance/src/main/java/com/iluwatar/table/inheritance/VehicleDatabase.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.table.inheritance;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.logging.Logger;\n\n/** Manages the storage and retrieval of Vehicle objects, including Cars and Trucks. */\npublic class VehicleDatabase {\n\n  final Logger logger = Logger.getLogger(VehicleDatabase.class.getName());\n\n  private Map<Integer, Vehicle> vehicleTable = new HashMap<>();\n  private Map<Integer, Car> carTable = new HashMap<>();\n  private Map<Integer, Truck> truckTable = new HashMap<>();\n\n  /**\n   * Saves a vehicle to the database. If the vehicle is a Car or Truck, it is added to the\n   * respective table.\n   *\n   * @param vehicle the vehicle to save\n   */\n  public void saveVehicle(Vehicle vehicle) {\n    vehicleTable.put(vehicle.getId(), vehicle);\n    if (vehicle instanceof Car) {\n      carTable.put(vehicle.getId(), (Car) vehicle);\n    } else if (vehicle instanceof Truck) {\n      truckTable.put(vehicle.getId(), (Truck) vehicle);\n    }\n  }\n\n  /**\n   * Retrieves a vehicle by its ID.\n   *\n   * @param id the ID of the vehicle\n   * @return the vehicle with the given ID, or null if not found\n   */\n  public Vehicle getVehicle(int id) {\n    return vehicleTable.get(id);\n  }\n\n  /**\n   * Retrieves a car by its ID.\n   *\n   * @param id the ID of the car\n   * @return the car with the given ID, or null if not found\n   */\n  public Car getCar(int id) {\n    return carTable.get(id);\n  }\n\n  /**\n   * Retrieves a truck by its ID.\n   *\n   * @param id the ID of the truck\n   * @return the truck with the given ID, or null if not found\n   */\n  public Truck getTruck(int id) {\n    return truckTable.get(id);\n  }\n\n  /** Prints all vehicles in the database. */\n  public void printAllVehicles() {\n    for (Vehicle vehicle : vehicleTable.values()) {\n      logger.info(vehicle.toString());\n    }\n  }\n}\n"
  },
  {
    "path": "table-inheritance/src/test/java/com/iluwatar/table/inheritance/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.table.inheritance; /*\n                                         * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n                                         *\n                                         * The MIT License\n                                         * Copyright © 2014-2022 Ilkka Seppälä\n                                         *\n                                         * Permission is hereby granted, free of charge, to any person obtaining a copy\n                                         * of this software and associated documentation files (the \"Software\"), to deal\n                                         * in the Software without restriction, including without limitation the rights\n                                         * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n                                         * copies of the Software, and to permit persons to whom the Software is\n                                         * furnished to do so, subject to the following conditions:\n                                         *\n                                         * The above copyright notice and this permission notice shall be included in\n                                         * all copies or substantial portions of the Software.\n                                         *\n                                         * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n                                         * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n                                         * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n                                         * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n                                         * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n                                         * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n                                         * THE SOFTWARE.\n                                         */\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.PrintStream;\nimport java.util.logging.ConsoleHandler;\nimport java.util.logging.Handler;\nimport java.util.logging.Logger;\nimport org.junit.jupiter.api.Test;\n\n/** Tests if the main method runs without throwing exceptions and prints expected output. */\nclass AppTest {\n\n  @Test\n  void testAppMainMethod() {\n\n    ByteArrayOutputStream outContent = new ByteArrayOutputStream();\n    PrintStream printStream = new PrintStream(outContent);\n\n    System.setOut(printStream);\n\n    Logger logger = Logger.getLogger(App.class.getName());\n\n    Handler handler =\n        new ConsoleHandler() {\n          @Override\n          public void publish(java.util.logging.LogRecord recordObj) {\n            printStream.println(getFormatter().format(recordObj));\n          }\n        };\n    handler.setLevel(java.util.logging.Level.ALL);\n    logger.addHandler(handler);\n\n    App.main(new String[] {});\n\n    String output = outContent.toString();\n\n    assertTrue(output.contains(\"Retrieved Vehicle:\"));\n    assertTrue(output.contains(\"Toyota\")); // Car make\n    assertTrue(output.contains(\"Ford\")); // Truck make\n    assertTrue(output.contains(\"Retrieved Car:\"));\n    assertTrue(output.contains(\"Retrieved Truck:\"));\n  }\n}\n"
  },
  {
    "path": "table-inheritance/src/test/java/com/iluwatar/table/inheritance/VehicleDatabaseTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.table.inheritance; /*\n                                         * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n                                         *\n                                         * The MIT License\n                                         * Copyright © 2014-2022 Ilkka Seppälä\n                                         *\n                                         * Permission is hereby granted, free of charge, to any person obtaining a copy\n                                         * of this software and associated documentation files (the \"Software\"), to deal\n                                         * in the Software without restriction, including without limitation the rights\n                                         * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n                                         * copies of the Software, and to permit persons to whom the Software is\n                                         * furnished to do so, subject to the following conditions:\n                                         *\n                                         * The above copyright notice and this permission notice shall be included in\n                                         * all copies or substantial portions of the Software.\n                                         *\n                                         * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n                                         * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n                                         * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n                                         * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n                                         * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n                                         * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n                                         * THE SOFTWARE.\n                                         */\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/**\n * Unit tests for the {@link VehicleDatabase} class. Tests saving, retrieving, and printing vehicles\n * of different types.\n */\nclass VehicleDatabaseTest {\n\n  private VehicleDatabase vehicleDatabase;\n\n  /** Sets up a new instance of {@link VehicleDatabase} before each test. */\n  @BeforeEach\n  void setUp() {\n    vehicleDatabase = new VehicleDatabase();\n  }\n\n  /** Tests saving a {@link Car} to the database and retrieving it. */\n  @Test\n  void testSaveAndRetrieveCar() {\n    Car car = new Car(2020, \"Toyota\", \"Corolla\", 4, 1);\n    vehicleDatabase.saveVehicle(car);\n\n    Vehicle retrievedVehicle = vehicleDatabase.getVehicle(car.getId());\n    assertNotNull(retrievedVehicle);\n    assertEquals(car.getId(), retrievedVehicle.getId());\n    assertEquals(car.getMake(), retrievedVehicle.getMake());\n    assertEquals(car.getModel(), retrievedVehicle.getModel());\n    assertEquals(car.getYear(), retrievedVehicle.getYear());\n\n    Car retrievedCar = vehicleDatabase.getCar(car.getId());\n    assertNotNull(retrievedCar);\n    assertEquals(car.getNumDoors(), retrievedCar.getNumDoors());\n  }\n\n  /** Tests saving a {@link Truck} to the database and retrieving it. */\n  @Test\n  void testSaveAndRetrieveTruck() {\n    Truck truck = new Truck(2018, \"Ford\", \"F-150\", 60, 2);\n    vehicleDatabase.saveVehicle(truck);\n\n    Vehicle retrievedVehicle = vehicleDatabase.getVehicle(truck.getId());\n    assertNotNull(retrievedVehicle);\n    assertEquals(truck.getId(), retrievedVehicle.getId());\n    assertEquals(truck.getMake(), retrievedVehicle.getMake());\n    assertEquals(truck.getModel(), retrievedVehicle.getModel());\n    assertEquals(truck.getYear(), retrievedVehicle.getYear());\n\n    Truck retrievedTruck = vehicleDatabase.getTruck(truck.getId());\n    assertNotNull(retrievedTruck);\n    assertEquals(truck.getLoadCapacity(), retrievedTruck.getLoadCapacity());\n  }\n\n  /** Tests saving multiple vehicles to the database and printing them. */\n  @Test\n  void testPrintAllVehicles() {\n    Car car = new Car(2020, \"Toyota\", \"Corolla\", 4, 1);\n    Truck truck = new Truck(2018, \"Ford\", \"F-150\", 60, 2);\n    vehicleDatabase.saveVehicle(car);\n    vehicleDatabase.saveVehicle(truck);\n\n    vehicleDatabase.printAllVehicles();\n\n    Vehicle retrievedCar = vehicleDatabase.getVehicle(car.getId());\n    Vehicle retrievedTruck = vehicleDatabase.getVehicle(truck.getId());\n\n    assertNotNull(retrievedCar);\n    assertNotNull(retrievedTruck);\n  }\n\n  /** Tests the constructor of {@link Car} with valid values. */\n  @Test\n  void testCarConstructor() {\n    Car car = new Car(2020, \"Toyota\", \"Corolla\", 4, 1);\n    assertEquals(2020, car.getYear());\n    assertEquals(\"Toyota\", car.getMake());\n    assertEquals(\"Corolla\", car.getModel());\n    assertEquals(4, car.getNumDoors());\n    assertEquals(1, car.getId()); // Assuming the ID is auto-generated in the constructor\n  }\n\n  /** Tests the constructor of {@link Car} with invalid number of doors (negative value). */\n  @Test\n  void testCarConstructorWithInvalidNumDoors() {\n    IllegalArgumentException exception =\n        assertThrows(\n            IllegalArgumentException.class,\n            () -> {\n              new Car(2020, \"Toyota\", \"Corolla\", -4, 1);\n            });\n    assertEquals(\"Number of doors must be positive.\", exception.getMessage());\n  }\n\n  /** Tests the constructor of {@link Car} with zero doors. */\n  @Test\n  void testCarConstructorWithZeroDoors() {\n    IllegalArgumentException exception =\n        assertThrows(\n            IllegalArgumentException.class,\n            () -> {\n              new Car(2020, \"Toyota\", \"Corolla\", 0, 1);\n            });\n    assertEquals(\"Number of doors must be positive.\", exception.getMessage());\n  }\n\n  /** Tests the constructor of {@link Truck} with invalid load capacity (negative value). */\n  @Test\n  void testTruckConstructorWithInvalidLoadCapacity() {\n    IllegalArgumentException exception =\n        assertThrows(\n            IllegalArgumentException.class,\n            () -> {\n              new Truck(2018, \"Ford\", \"F-150\", -60, 2);\n            });\n    assertEquals(\"Load capacity must be positive.\", exception.getMessage());\n  }\n\n  /** Tests the constructor of {@link Truck} with zero load capacity. */\n  @Test\n  void testTruckConstructorWithZeroLoadCapacity() {\n    IllegalArgumentException exception =\n        assertThrows(\n            IllegalArgumentException.class,\n            () -> {\n              new Truck(2018, \"Ford\", \"F-150\", 0, 2);\n            });\n    assertEquals(\"Load capacity must be positive.\", exception.getMessage());\n  }\n\n  /** Tests setting invalid number of doors in {@link Car} using setter (negative value). */\n  @Test\n  void testSetInvalidNumDoors() {\n    Car car = new Car(2020, \"Toyota\", \"Corolla\", 4, 1);\n    IllegalArgumentException exception =\n        assertThrows(\n            IllegalArgumentException.class,\n            () -> {\n              car.setNumDoors(-2);\n            });\n    assertEquals(\"Number of doors must be positive.\", exception.getMessage());\n  }\n\n  /** Tests setting invalid load capacity in {@link Truck} using setter (negative value). */\n  @Test\n  void testSetInvalidLoadCapacity() {\n    Truck truck = new Truck(2018, \"Ford\", \"F-150\", 60, 2);\n    IllegalArgumentException exception =\n        assertThrows(\n            IllegalArgumentException.class,\n            () -> {\n              truck.setLoadCapacity(-10);\n            });\n    assertEquals(\"Load capacity must be positive.\", exception.getMessage());\n  }\n}\n"
  },
  {
    "path": "table-module/README.md",
    "content": "---\ntitle: \"Table Module Pattern in Java: Enhancing Maintainability with Organized Data Handling Modules\"\nshortTitle: Table Module\ndescription: \"Explore the Table Module pattern in Java with our in-depth guide. Learn how it simplifies database interaction by encapsulating data access logic, enhances code maintenance, and secures data operations.\"\ncategory: Data access\nlanguage: en\ntag:\n  - Data access\n  - Encapsulation\n  - Persistence\n---\n\n## Also known as\n\n* Record Set\n\n## Intent of Table Module Design Pattern\n\nThe Table Module pattern expertly encapsulates database table data access logic in a single, efficient module, ideal for Java applications.\n\n## Detailed Explanation of Table Module Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a library where all books are stored in a large database. The Table Module design pattern can be compared to a librarian who manages a specific section of the library, such as the fiction section. This librarian is responsible for all tasks related to that section: adding new books, updating book information, removing old books, and providing information about the books when requested. Just like the Table Module pattern encapsulates all the database access logic for a particular table, the librarian handles all operations related to the fiction section without exposing the complexities of how books are cataloged, stored, and managed to the library users. This makes it easier for the library users to interact with the fiction section, as they can rely on the librarian to efficiently manage and retrieve books without needing to understand the underlying details.\n\nIn plain words\n\n> The Table Module pattern centralizes and encapsulates database access logic for a specific table, simplifying data retrieval and manipulation while hiding database complexities.\n\nFlowchart\n\n![Table Module flowchart](./etc/table-module-flowchart.png)\n\n## Programmatic Example of Table Module Pattern in Java\n\nIn the user system example, the domain logic for user login and registration needs to be managed. By using the Table Module pattern, we can create an instance of the `UserTableModule` class to encapsulate and handle all business logic associated with the rows in the user table.\n\nHere is the basic `User` entity.\n\n```java\n@Setter\n@Getter\n@ToString\n@EqualsAndHashCode\n@AllArgsConstructor\npublic class User {\n  private int id;\n  private String username;\n  private String password;\n}\n```\n\nHere is the `UserTableModule` class.\n\n```java\npublic class UserTableModule {\n  private final DataSource dataSource;\n  private Connection connection = null;\n  private ResultSet resultSet = null;\n  private PreparedStatement preparedStatement = null;\n\n  public UserTableModule(final DataSource userDataSource) {\n    this.dataSource = userDataSource;\n  }\n  \n  public int login(final String username, final String password) throws SQLException {\n  \t\t// Method implementation\n  }\n\n  public int registerUser(final User user) throws SQLException {\n  \t\t// Method implementation\n  }\n}\n```\n\nIn the class `App`, we use an instance of the `UserTableModule` to handle user login and registration.\n\n```java\n@Slf4j\npublic final class App {\n    \n    private static final String DB_URL = \"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1\";\n\n    private App() {}\n\n    public static void main(final String[] args) throws SQLException {\n        // Create data source and create the user table.\n        final var dataSource = createDataSource();\n        createSchema(dataSource);\n        var userTableModule = new UserTableModule(dataSource);\n\n        // Initialize two users.\n        var user1 = new User(1, \"123456\", \"123456\");\n        var user2 = new User(2, \"test\", \"password\");\n\n        // Login and register using the instance of userTableModule.\n        userTableModule.registerUser(user1);\n        userTableModule.login(user1.getUsername(), user1.getPassword());\n        userTableModule.login(user2.getUsername(), user2.getPassword());\n        userTableModule.registerUser(user2);\n        userTableModule.login(user2.getUsername(), user2.getPassword());\n\n        deleteSchema(dataSource);\n    }\n\n    private static void deleteSchema(final DataSource dataSource)\n            throws SQLException {\n        try (var connection = dataSource.getConnection();\n             var statement = connection.createStatement()) {\n            statement.execute(UserTableModule.DELETE_SCHEMA_SQL);\n        }\n    }\n\n    private static void createSchema(final DataSource dataSource)\n            throws SQLException {\n        try (var connection = dataSource.getConnection();\n             var statement = connection.createStatement()) {\n            statement.execute(UserTableModule.CREATE_SCHEMA_SQL);\n        }\n    }\n\n    private static DataSource createDataSource() {\n        var dataSource = new JdbcDataSource();\n        dataSource.setURL(DB_URL);\n        return dataSource;\n    }\n}\n```\n\nIn this example, the `UserTableModule` class is responsible for encapsulating all interactions with the users table in the database. This includes the logic for logging in and registering users. The User class represents the user entity with attributes such as `id`, `username`, and `password`.\n\n1. **Initialization**: The `UserTableModule` is initialized with a `DataSource` object which is used to establish a connection to the database.\n2. **User Registration**: The `registerUser` method in `UserTableModule` handles the logic for registering a new user into the database.\n3. **User Login**: The `login` method manages the logic for authenticating a user based on their username and password.\n4. **Application Flow**: The `App` class demonstrates how to use the `UserTableModule` to register and log in users. The data source is created, the schema is set up, and users are registered and logged in with appropriate feedback.\n\nThe program output:\n\n```\n13:59:36.417 [main] INFO com.iluwatar.tablemodule.UserTableModule -- Register successfully!\n13:59:36.426 [main] INFO com.iluwatar.tablemodule.UserTableModule -- Login successfully!\n13:59:36.426 [main] INFO com.iluwatar.tablemodule.UserTableModule -- Fail to login!\n13:59:36.426 [main] INFO com.iluwatar.tablemodule.UserTableModule -- Register successfully!\n13:59:36.427 [main] INFO com.iluwatar.tablemodule.UserTableModule -- Login successfully!\n```\n\nThis example shows how the Table Module pattern centralizes database operations for the `users` table, making the application more modular and easier to maintain.\n\n## When to Use the Table Module Pattern in Java\n\n* Use when you need to manage data access logic for a database table in a centralized module.\n* Ideal for applications that interact heavily with database tables and require encapsulation of database queries.\n* Particularly suitable for dynamic systems, the Table Module pattern ensures scalable database management as your Java application's schema evolves.\n\n## Table Module Pattern Java Tutorials\n\n* [Architecture patterns: Domain model and friends (Inviqa)](https://inviqa.com/blog/architecture-patterns-domain-model-and-friends)\n\n## Real-World Applications of Table Module Pattern in Java\n\n* In enterprise applications where multiple modules need to interact with the same database tables.\n* Web applications that require CRUD operations on database tables.\n* Java-based ORM frameworks such as Hibernate or JPA utilize similar concepts for managing data access.\n\n## Benefits and Trade-offs of Table Module Pattern\n\nBenefits:\n\n* Centralizes and encapsulates data access logic, leading to easier maintenance.\n* Reduces code duplication by providing a single point of interaction for database tables.\n* Enhances code readability and reduces the risk of SQL injection attacks by encapsulating query logic.\n\nTrade-offs:\n\n* May lead to a large module if the table has many operations, potentially reducing readability.\n* Can become a bottleneck if not properly optimized, especially in high-load scenarios.\n\n## Related Java Design Patterns\n\n* Active Record: Unlike Table Module, Active Record combines data access and domain logic in the same class.\n* [Data Access Object (DAO)](https://java-design-patterns.com/patterns/dao/): Provides an abstract interface to some type of database or other persistence mechanism, often used alongside Table Module to separate low-level data access operations from high-level business logic.\n* [Data Mapper](https://java-design-patterns.com/patterns/data-mapper/): Separates the in-memory objects from the database, unlike Table Module which directly maps database tables.\n* [Domain Model](https://java-design-patterns.com/patterns/domain-model/): Represents the domain logic and behavior, often used in conjunction with Table Module to handle complex business rules and data interactions.\n* [Repository](https://java-design-patterns.com/patterns/repository/): Abstracts the data layer, allowing more complex queries, whereas Table Module is usually simpler and table-centric.\n* [Transaction Script](https://java-design-patterns.com/patterns/transaction-script/): Organizes business logic by procedures where each procedure handles a single request from the presentation layer, contrasting with the Table Module's data-centric approach.\n\n## References and Credits\n\n* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap)\n* [Java Persistence with Hibernate](https://amzn.to/44tP1ox)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "table-module/etc/table-module.urm.puml",
    "content": "@startuml\npackage com.iluwatar.tablemodule {\n  class App {\n    - DB_URL : String {static}\n    - LOGGER : Logger {static}\n    - App()\n    - createDataSource() : DataSource {static}\n    - createSchema(dataSource : DataSource) {static}\n    - deleteSchema(dataSource : DataSource) {static}\n    + main(args : String[]) {static}\n  }\n  class User {\n    - id : int\n    - password : String\n    - username : String\n    + User(id : int, username : String, password : String)\n    # canEqual(other : Object) : boolean\n    + equals(o : Object) : boolean\n    + getId() : int\n    + getPassword() : String\n    + getUsername() : String\n    + hashCode() : int\n    + setId(id : int)\n    + setPassword(password : String)\n    + setUsername(username : String)\n    + toString() : String\n  }\n  class UserTableModule {\n    + CREATE_SCHEMA_SQL : String {static}\n    + DELETE_SCHEMA_SQL : String {static}\n    - LOGGER : Logger {static}\n    - dataSource : DataSource\n    + UserTableModule(userDataSource : DataSource)\n    + login(username : String, password : String) : int\n    + registerUser(user : User) : int\n  }\n}\n@enduml"
  },
  {
    "path": "table-module/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>table-module</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>com.h2database</groupId>\n      <artifactId>h2</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.tablemodule.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "table-module/src/main/java/com/iluwatar/tablemodule/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tablemodule;\n\nimport java.sql.SQLException;\nimport javax.sql.DataSource;\nimport lombok.extern.slf4j.Slf4j;\nimport org.h2.jdbcx.JdbcDataSource;\n\n/**\n * Table Module pattern is a domain logic pattern. In Table Module a single class encapsulates all\n * the domain logic for all records stored in a table or view. It's important to note that there is\n * no translation of data between objects and rows, as it happens in Domain Model, hence\n * implementation is relatively simple when compared to the Domain Model pattern.\n *\n * <p>In this example we will use the Table Module pattern to implement register and login methods\n * for the records stored in the user table. The main method will initialise an instance of {@link\n * UserTableModule} and use it to handle the domain logic for the user table.\n */\n@Slf4j\npublic final class App {\n  private static final String DB_URL = \"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1\";\n\n  /** Private constructor. */\n  private App() {}\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args.\n   * @throws SQLException if any error occurs.\n   */\n  public static void main(final String[] args) throws SQLException {\n    // Create data source and create the user table.\n    final var dataSource = createDataSource();\n    createSchema(dataSource);\n    var userTableModule = new UserTableModule(dataSource);\n\n    // Initialize two users.\n    var user1 = new User(1, \"123456\", \"123456\");\n    var user2 = new User(2, \"test\", \"password\");\n\n    // Login and register using the instance of userTableModule.\n    userTableModule.registerUser(user1);\n    userTableModule.login(user1.getUsername(), user1.getPassword());\n    userTableModule.login(user2.getUsername(), user2.getPassword());\n    userTableModule.registerUser(user2);\n    userTableModule.login(user2.getUsername(), user2.getPassword());\n\n    deleteSchema(dataSource);\n  }\n\n  private static void deleteSchema(final DataSource dataSource) throws SQLException {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(UserTableModule.DELETE_SCHEMA_SQL);\n    }\n  }\n\n  private static void createSchema(final DataSource dataSource) throws SQLException {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(UserTableModule.CREATE_SCHEMA_SQL);\n    }\n  }\n\n  private static DataSource createDataSource() {\n    var dataSource = new JdbcDataSource();\n    dataSource.setURL(DB_URL);\n    return dataSource;\n  }\n}\n"
  },
  {
    "path": "table-module/src/main/java/com/iluwatar/tablemodule/User.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tablemodule;\n\nimport lombok.AllArgsConstructor;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\n/** A user POJO that represents the data that will be read from the data source. */\n@Setter\n@Getter\n@ToString\n@EqualsAndHashCode\n@AllArgsConstructor\npublic class User {\n  private int id;\n  private String username;\n  private String password;\n}\n"
  },
  {
    "path": "table-module/src/main/java/com/iluwatar/tablemodule/UserTableModule.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tablemodule;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport javax.sql.DataSource;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This class organizes domain logic with the user table in the database. A single instance of this\n * class contains the various procedures that will act on the data.\n */\n@Slf4j\npublic class UserTableModule {\n  /** Public element for creating schema. */\n  public static final String CREATE_SCHEMA_SQL =\n      \"CREATE TABLE IF NOT EXISTS USERS (ID NUMBER, USERNAME VARCHAR(30) \"\n          + \"UNIQUE,PASSWORD VARCHAR(30))\";\n\n  /** Public element for deleting schema. */\n  public static final String DELETE_SCHEMA_SQL = \"DROP TABLE USERS IF EXISTS\";\n\n  private final DataSource dataSource;\n\n  /**\n   * Public constructor.\n   *\n   * @param userDataSource the data source in the database\n   */\n  public UserTableModule(final DataSource userDataSource) {\n    this.dataSource = userDataSource;\n  }\n\n  /**\n   * Login using username and password.\n   *\n   * @param username the username of a user\n   * @param password the password of a user\n   * @return the execution result of the method\n   * @throws SQLException if any error\n   */\n  public int login(final String username, final String password) throws SQLException {\n    var sql = \"select count(*) from USERS where username=? and password=?\";\n    ResultSet resultSet = null;\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(sql)) {\n      var result = 0;\n      preparedStatement.setString(1, username);\n      preparedStatement.setString(2, password);\n      resultSet = preparedStatement.executeQuery();\n      while (resultSet.next()) {\n        result = resultSet.getInt(1);\n      }\n      if (result == 1) {\n        LOGGER.info(\"Login successfully!\");\n      } else {\n        LOGGER.info(\"Fail to login!\");\n      }\n      return result;\n    } finally {\n      if (resultSet != null) {\n        resultSet.close();\n      }\n    }\n  }\n\n  /**\n   * Register a new user.\n   *\n   * @param user a user instance\n   * @return the execution result of the method\n   * @throws SQLException if any error\n   */\n  public int registerUser(final User user) throws SQLException {\n    var sql = \"insert into USERS (username, password) values (?,?)\";\n    try (var connection = dataSource.getConnection();\n        var preparedStatement = connection.prepareStatement(sql)) {\n      preparedStatement.setString(1, user.getUsername());\n      preparedStatement.setString(2, user.getPassword());\n      var result = preparedStatement.executeUpdate();\n      LOGGER.info(\"Register successfully!\");\n      return result;\n    }\n  }\n}\n"
  },
  {
    "path": "table-module/src/test/java/com/iluwatar/tablemodule/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tablemodule;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that the table module example runs without errors. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "table-module/src/test/java/com/iluwatar/tablemodule/UserTableModuleTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tablemodule;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nimport java.sql.DriverManager;\nimport java.sql.SQLException;\nimport javax.sql.DataSource;\nimport org.h2.jdbcx.JdbcDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass UserTableModuleTest {\n  private static final String DB_URL = \"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1\";\n\n  private static DataSource createDataSource() {\n    var dataSource = new JdbcDataSource();\n    dataSource.setURL(DB_URL);\n    return dataSource;\n  }\n\n  @BeforeEach\n  void setUp() throws SQLException {\n    try (var connection = DriverManager.getConnection(DB_URL);\n        var statement = connection.createStatement()) {\n      statement.execute(UserTableModule.DELETE_SCHEMA_SQL);\n      statement.execute(UserTableModule.CREATE_SCHEMA_SQL);\n    }\n  }\n\n  @AfterEach\n  void tearDown() throws SQLException {\n    try (var connection = DriverManager.getConnection(DB_URL);\n        var statement = connection.createStatement()) {\n      statement.execute(UserTableModule.DELETE_SCHEMA_SQL);\n    }\n  }\n\n  @Test\n  void loginShouldFail() throws SQLException {\n    var dataSource = createDataSource();\n    var userTableModule = new UserTableModule(dataSource);\n    var user = new User(1, \"123456\", \"123456\");\n    assertEquals(0, userTableModule.login(user.getUsername(), user.getPassword()));\n  }\n\n  @Test\n  void loginShouldSucceed() throws SQLException {\n    var dataSource = createDataSource();\n    var userTableModule = new UserTableModule(dataSource);\n    var user = new User(1, \"123456\", \"123456\");\n    userTableModule.registerUser(user);\n    assertEquals(1, userTableModule.login(user.getUsername(), user.getPassword()));\n  }\n\n  @Test\n  void registerShouldFail() throws SQLException {\n    var dataSource = createDataSource();\n    var userTableModule = new UserTableModule(dataSource);\n    var user = new User(1, \"123456\", \"123456\");\n    userTableModule.registerUser(user);\n    assertThrows(SQLException.class, () -> userTableModule.registerUser(user));\n  }\n\n  @Test\n  void registerShouldSucceed() throws SQLException {\n    var dataSource = createDataSource();\n    var userTableModule = new UserTableModule(dataSource);\n    var user = new User(1, \"123456\", \"123456\");\n    assertEquals(1, userTableModule.registerUser(user));\n  }\n}\n"
  },
  {
    "path": "table-module/src/test/java/com/iluwatar/tablemodule/UserTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tablemodule;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass UserTest {\n  @Test\n  void testCanEqual() {\n    assertFalse((new User(1, \"janedoe\", \"iloveyou\")).canEqual(\"Other\"));\n  }\n\n  @Test\n  void testCanEqual2() {\n    var user = new User(1, \"janedoe\", \"iloveyou\");\n    assertTrue(user.canEqual(new User(1, \"janedoe\", \"iloveyou\")));\n  }\n\n  @Test\n  void testEquals1() {\n    var user = new User(1, \"janedoe\", \"iloveyou\");\n    assertNotEquals(user, new User(123, \"abcd\", \"qwerty\"));\n  }\n\n  @Test\n  void testEquals2() {\n    var user = new User(1, \"janedoe\", \"iloveyou\");\n    assertEquals(user, new User(1, \"janedoe\", \"iloveyou\"));\n  }\n\n  @Test\n  void testEquals3() {\n    var user = new User(123, \"janedoe\", \"iloveyou\");\n    assertNotEquals(user, new User(1, \"janedoe\", \"iloveyou\"));\n  }\n\n  @Test\n  void testEquals4() {\n    var user = new User(1, null, \"iloveyou\");\n    assertNotEquals(user, new User(1, \"janedoe\", \"iloveyou\"));\n  }\n\n  @Test\n  void testEquals5() {\n    var user = new User(1, \"iloveyou\", \"iloveyou\");\n    assertNotEquals(user, new User(1, \"janedoe\", \"iloveyou\"));\n  }\n\n  @Test\n  void testEquals6() {\n    var user = new User(1, \"janedoe\", \"janedoe\");\n    assertNotEquals(user, new User(1, \"janedoe\", \"iloveyou\"));\n  }\n\n  @Test\n  void testEquals7() {\n    var user = new User(1, \"janedoe\", null);\n    assertNotEquals(user, new User(1, \"janedoe\", \"iloveyou\"));\n  }\n\n  @Test\n  void testEquals8() {\n    var user = new User(1, null, \"iloveyou\");\n    assertEquals(user, new User(1, null, \"iloveyou\"));\n  }\n\n  @Test\n  void testEquals9() {\n    var user = new User(1, \"janedoe\", null);\n    assertEquals(user, new User(1, \"janedoe\", null));\n  }\n\n  @Test\n  void testHashCode1() {\n    assertEquals(-1758941372, (new User(1, \"janedoe\", \"iloveyou\")).hashCode());\n  }\n\n  @Test\n  void testHashCode2() {\n    assertEquals(-1332207447, (new User(1, null, \"iloveyou\")).hashCode());\n  }\n\n  @Test\n  void testHashCode3() {\n    assertEquals(-426522485, (new User(1, \"janedoe\", null)).hashCode());\n  }\n\n  @Test\n  void testSetId() {\n    var user = new User(1, \"janedoe\", \"iloveyou\");\n    user.setId(2);\n    assertEquals(2, user.getId());\n  }\n\n  @Test\n  void testSetPassword() {\n    var user = new User(1, \"janedoe\", \"tmp\");\n    user.setPassword(\"iloveyou\");\n    assertEquals(\"iloveyou\", user.getPassword());\n  }\n\n  @Test\n  void testSetUsername() {\n    var user = new User(1, \"tmp\", \"iloveyou\");\n    user.setUsername(\"janedoe\");\n    assertEquals(\"janedoe\", user.getUsername());\n  }\n\n  @Test\n  void testToString() {\n    var user = new User(1, \"janedoe\", \"iloveyou\");\n    assertEquals(\n        String.format(\n            \"User(id=%s, username=%s, password=%s)\",\n            user.getId(), user.getUsername(), user.getPassword()),\n        user.toString());\n  }\n}\n"
  },
  {
    "path": "template-method/README.md",
    "content": "---\ntitle: \"Template Method Pattern in Java: Streamlining Complex Algorithms with Predefined Scaffolds\"\nshortTitle: Template Method\ndescription: \"Discover the essentials of the Template Method pattern in Java, including how it simplifies code, promotes reusability, and allows flexibility in algorithm design. Perfect for developers looking to refine their object-oriented programming skills.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Abstraction\n  - Code simplification\n  - Decoupling\n  - Extensibility\n  - Gang of Four\n  - Inheritance\n  - Object composition\n  - Polymorphism\n  - Reusability\n---\n\n## Intent of Template method Design Pattern\n\nDefine the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.\n\n## Detailed Explanation of Template method Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world analogy for the Template Method pattern can be seen in the preparation of a cup of tea or coffee. The overall process (algorithm) is the same: boil water, brew the beverage, pour into cup, and add condiments. However, the specific steps of brewing the beverage differ. For tea, you steep the tea leaves in hot water, while for coffee, you brew ground coffee beans. The Template Method pattern encapsulates the invariant steps of the process (boiling water, pouring, adding condiments) in a base class, while allowing subclasses to define the specific brewing steps, thus ensuring the overall structure of making a hot drink is consistent while allowing customization where needed.\n\nIn plain words\n\n> The Java Template Method pattern outlines the core steps in the parent class, allowing child classes to tailor detailed implementations, enhancing code reusability and design flexibility in Java programming.\n\nWikipedia says\n\n> In object-oriented programming, the template method is one of the behavioral design patterns identified by Gamma et al. in the book Design Patterns. The template method is a method in a superclass, usually an abstract superclass, and defines the skeleton of an operation in terms of a number of high-level steps. These steps are themselves implemented by additional helper methods in the same class as the template method.\n\nSequence diagram\n\n![Template Method Pattern Sequence Diagram](./etc/template-method-sequence-diagram.png)\n\n## Programmatic Example of Template Method Pattern in Java\n\nOur programmatic example is about thieves and stealing. The general steps in stealing an item are the same. First, you pick the target, next you confuse him somehow and finally, you steal the item. However, there are many ways to implement these steps.\n\nLet's first introduce the template method class `StealingMethod` along with its concrete implementations `SubtleMethod` and `HitAndRunMethod`. To make sure that subclasses don’t override the template method, the template method (in our case method `steal`) should be declared `final`, otherwise the skeleton defined in the base class could be overridden in subclasses.\n\n```java\n@Slf4j\npublic abstract class StealingMethod {\n\n  protected abstract String pickTarget();\n\n  protected abstract void confuseTarget(String target);\n\n  protected abstract void stealTheItem(String target);\n\n  public final void steal() {\n    var target = pickTarget();\n    LOGGER.info(\"The target has been chosen as {}.\", target);\n    confuseTarget(target);\n    stealTheItem(target);\n  }\n}\n```\n\n```java\n@Slf4j\npublic class SubtleMethod extends StealingMethod {\n\n  @Override\n  protected String pickTarget() {\n    return \"shop keeper\";\n  }\n\n  @Override\n  protected void confuseTarget(String target) {\n    LOGGER.info(\"Approach the {} with tears running and hug him!\", target);\n  }\n\n  @Override\n  protected void stealTheItem(String target) {\n    LOGGER.info(\"While in close contact grab the {}'s wallet.\", target);\n  }\n}\n```\n\n```java\n@Slf4j\npublic class HitAndRunMethod extends StealingMethod {\n\n  @Override\n  protected String pickTarget() {\n    return \"old goblin woman\";\n  }\n\n  @Override\n  protected void confuseTarget(String target) {\n    LOGGER.info(\"Approach the {} from behind.\", target);\n  }\n\n  @Override\n  protected void stealTheItem(String target) {\n    LOGGER.info(\"Grab the handbag and run away fast!\");\n  }\n}\n```\n\nHere's the halfling thief class containing the template method.\n\n```java\npublic class HalflingThief {\n\n  private StealingMethod method;\n\n  public HalflingThief(StealingMethod method) {\n    this.method = method;\n  }\n\n  public void steal() {\n    method.steal();\n  }\n\n  public void changeMethod(StealingMethod method) {\n    this.method = method;\n  }\n}\n```\n\nAnd finally, we show how the halfling thief utilizes the different stealing methods.\n\n```java\npublic static void main(String[] args) {\n    var thief = new HalflingThief(new HitAndRunMethod());\n    thief.steal();\n    thief.changeMethod(new SubtleMethod());\n    thief.steal();\n}\n```\n\nThe program output:\n\n```\n11:06:01.721 [main] INFO com.iluwatar.templatemethod.StealingMethod -- The target has been chosen as old goblin woman.\n11:06:01.723 [main] INFO com.iluwatar.templatemethod.HitAndRunMethod -- Approach the old goblin woman from behind.\n11:06:01.723 [main] INFO com.iluwatar.templatemethod.HitAndRunMethod -- Grab the handbag and run away fast!\n11:06:01.723 [main] INFO com.iluwatar.templatemethod.StealingMethod -- The target has been chosen as shop keeper.\n11:06:01.723 [main] INFO com.iluwatar.templatemethod.SubtleMethod -- Approach the shop keeper with tears running and hug him!\n11:06:01.723 [main] INFO com.iluwatar.templatemethod.SubtleMethod -- While in close contact grab the shop keeper's wallet.\n```\n\n## When to Use the Template method Pattern in Java\n\nThe Template Method pattern should be used\n\n* To implement the invariant parts of an algorithm once and leave it up to subclasses to implement the behavior that can vary\n* When common behavior among subclasses should be factored and localized in a common class to avoid code duplication. This is a good example of \"refactoring to generalize\" as described by Opdyke and Johnson. You first identify the differences in the existing code and then separate the differences into new operations. Finally, you replace the differing code with a template method that calls one of these new operations\n* To control subclasses extensions. You can define a template method that calls \"hook\" operations at specific points, thereby permitting extensions only at those points\n\n## Template method Pattern Java Tutorials\n\n* [Template Method Design Pattern In Java (DigitalOcean)](https://www.digitalocean.com/community/tutorials/template-method-design-pattern-in-java)\n\n## Real-World Applications of Template method Pattern in Java\n\n* Java's AbstractList and AbstractSet classes in the Collections Framework use the Template Method pattern to define common algorithms for list and set operations.\n* Frameworks like JUnit use Template Method to define the setup and teardown process in test cases.\n\n## Benefits and Trade-offs of Template method Pattern\n\nBenefits:\n\n* Promotes code reuse by defining invariant parts of an algorithm in a base class.\n* Simplifies code maintenance by encapsulating common behavior in one place.\n* Enhances flexibility by allowing subclasses to override specific steps of an algorithm.\n\nTrade-offs:\n\n* Can lead to an increase in the number of classes, making the system more complex.\n* Requires careful design to ensure that the steps exposed to subclasses are useful and meaningful.\n\n## Related Java Design Patterns\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Often used with Template Method to create objects needed for specific steps of the algorithm.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): While Template Method defines the skeleton of an algorithm and lets subclasses implement specific steps, the Strategy Pattern defines a family of algorithms and makes them interchangeable.\n* [Subclass Sandbox](https://java-design-patterns.com/patterns/subclass-sandbox/): Complements Template Method by ensuring that subclasses can safely override specific steps of an algorithm without causing unintended side effects.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "template-method/etc/template-method.urm.puml",
    "content": "@startuml\npackage com.iluwatar.templatemethod {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class HalflingThief {\n    - method : StealingMethod\n    + HalflingThief(method : StealingMethod)\n    + changeMethod(method : StealingMethod)\n    + steal()\n  }\n  class HitAndRunMethod {\n    - LOGGER : Logger {static}\n    + HitAndRunMethod()\n    # confuseTarget(target : String)\n    # pickTarget() : String\n    # stealTheItem(target : String)\n  }\n  abstract class StealingMethod {\n    - LOGGER : Logger {static}\n    + StealingMethod()\n    # confuseTarget(String) {abstract}\n    # pickTarget() : String {abstract}\n    + steal()\n    # stealTheItem(String) {abstract}\n  }\n  class SubtleMethod {\n    - LOGGER : Logger {static}\n    + SubtleMethod()\n    # confuseTarget(target : String)\n    # pickTarget() : String\n    # stealTheItem(target : String)\n  }\n}\nHalflingThief -->  \"-method\" StealingMethod\nHitAndRunMethod --|> StealingMethod \nSubtleMethod --|> StealingMethod \n@enduml"
  },
  {
    "path": "template-method/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>template-method</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.templatemethod.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "template-method/src/main/java/com/iluwatar/templatemethod/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templatemethod;\n\n/**\n * Template Method defines a skeleton for an algorithm. The algorithm subclasses provide\n * implementation for the blank parts.\n *\n * <p>In this example {@link HalflingThief} contains {@link StealingMethod} that can be changed.\n * First the thief hits with {@link HitAndRunMethod} and then with {@link SubtleMethod}.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var thief = new HalflingThief(new HitAndRunMethod());\n    thief.steal();\n    thief.changeMethod(new SubtleMethod());\n    thief.steal();\n  }\n}\n"
  },
  {
    "path": "template-method/src/main/java/com/iluwatar/templatemethod/HalflingThief.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templatemethod;\n\n/** Halfling thief uses {@link StealingMethod} to steal. */\npublic class HalflingThief {\n\n  private StealingMethod method;\n\n  public HalflingThief(StealingMethod method) {\n    this.method = method;\n  }\n\n  public void steal() {\n    method.steal();\n  }\n\n  public void changeMethod(StealingMethod method) {\n    this.method = method;\n  }\n}\n"
  },
  {
    "path": "template-method/src/main/java/com/iluwatar/templatemethod/HitAndRunMethod.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templatemethod;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** HitAndRunMethod implementation of {@link StealingMethod}. */\n@Slf4j\npublic class HitAndRunMethod extends StealingMethod {\n\n  @Override\n  protected String pickTarget() {\n    return \"old goblin woman\";\n  }\n\n  @Override\n  protected void confuseTarget(String target) {\n    LOGGER.info(\"Approach the {} from behind.\", target);\n  }\n\n  @Override\n  protected void stealTheItem(String target) {\n    LOGGER.info(\"Grab the handbag and run away fast!\");\n  }\n}\n"
  },
  {
    "path": "template-method/src/main/java/com/iluwatar/templatemethod/StealingMethod.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templatemethod;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** StealingMethod defines skeleton for the algorithm. */\n@Slf4j\npublic abstract class StealingMethod {\n\n  protected abstract String pickTarget();\n\n  protected abstract void confuseTarget(String target);\n\n  protected abstract void stealTheItem(String target);\n\n  /** Steal. */\n  public final void steal() {\n    var target = pickTarget();\n    LOGGER.info(\"The target has been chosen as {}.\", target);\n    confuseTarget(target);\n    stealTheItem(target);\n  }\n}\n"
  },
  {
    "path": "template-method/src/main/java/com/iluwatar/templatemethod/SubtleMethod.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templatemethod;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** SubtleMethod implementation of {@link StealingMethod}. */\n@Slf4j\npublic class SubtleMethod extends StealingMethod {\n\n  @Override\n  protected String pickTarget() {\n    return \"shop keeper\";\n  }\n\n  @Override\n  protected void confuseTarget(String target) {\n    LOGGER.info(\"Approach the {} with tears running and hug him!\", target);\n  }\n\n  @Override\n  protected void stealTheItem(String target) {\n    LOGGER.info(\"While in close contact grab the {}'s wallet.\", target);\n  }\n}\n"
  },
  {
    "path": "template-method/src/test/java/com/iluwatar/templatemethod/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templatemethod;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templatemethod;\n\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.verify;\n\nimport org.junit.jupiter.api.Test;\n\n/** HalflingThiefTest */\nclass HalflingThiefTest {\n\n  /** Verify if the thief uses the provided stealing method */\n  @Test\n  void testSteal() {\n    final var method = spy(StealingMethod.class);\n    final var thief = new HalflingThief(method);\n    thief.steal();\n    verify(method).steal();\n  }\n\n  /** Verify if the thief uses the provided stealing method, and the new method after changing it */\n  @Test\n  void testChangeMethod() {\n    final var initialMethod = spy(StealingMethod.class);\n    final var thief = new HalflingThief(initialMethod);\n    thief.steal();\n    verify(initialMethod).steal();\n\n    final var newMethod = spy(StealingMethod.class);\n    thief.changeMethod(newMethod);\n    thief.steal();\n    verify(newMethod).steal();\n  }\n}\n"
  },
  {
    "path": "template-method/src/test/java/com/iluwatar/templatemethod/HitAndRunMethodTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templatemethod;\n\n/** HitAndRunMethodTest */\nclass HitAndRunMethodTest extends StealingMethodTest<HitAndRunMethod> {\n\n  /** Create a new test for the {@link HitAndRunMethod} */\n  public HitAndRunMethodTest() {\n    super(\n        new HitAndRunMethod(),\n        \"old goblin woman\",\n        \"The target has been chosen as old goblin woman.\",\n        \"Approach the old goblin woman from behind.\",\n        \"Grab the handbag and run away fast!\");\n  }\n}\n"
  },
  {
    "path": "template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templatemethod;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/**\n * StealingMethodTest\n *\n * @param <M> Type of StealingMethod\n */\npublic abstract class StealingMethodTest<M extends StealingMethod> {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /** The tested stealing method */\n  private final M method;\n\n  /** The expected target */\n  private final String expectedTarget;\n\n  /** The expected target picking result */\n  private final String expectedTargetResult;\n\n  /** The expected confusion method */\n  private final String expectedConfuseMethod;\n\n  /** The expected stealing method */\n  private final String expectedStealMethod;\n\n  /**\n   * Create a new test for the given stealing method, together with the expected results\n   *\n   * @param method The tested stealing method\n   * @param expectedTarget The expected target name\n   * @param expectedTargetResult The expected target picking result\n   * @param expectedConfuseMethod The expected confusion method\n   * @param expectedStealMethod The expected stealing method\n   */\n  public StealingMethodTest(\n      final M method,\n      String expectedTarget,\n      final String expectedTargetResult,\n      final String expectedConfuseMethod,\n      final String expectedStealMethod) {\n\n    this.method = method;\n    this.expectedTarget = expectedTarget;\n    this.expectedTargetResult = expectedTargetResult;\n    this.expectedConfuseMethod = expectedConfuseMethod;\n    this.expectedStealMethod = expectedStealMethod;\n  }\n\n  /** Verify if the thief picks the correct target */\n  @Test\n  void testPickTarget() {\n    assertEquals(expectedTarget, this.method.pickTarget());\n  }\n\n  /** Verify if the target confusing step goes as planned */\n  @Test\n  void testConfuseTarget() {\n    assertEquals(0, appender.getLogSize());\n\n    this.method.confuseTarget(this.expectedTarget);\n    assertEquals(this.expectedConfuseMethod, appender.getLastMessage());\n    assertEquals(1, appender.getLogSize());\n  }\n\n  /** Verify if the stealing step goes as planned */\n  @Test\n  void testStealTheItem() {\n    assertEquals(0, appender.getLogSize());\n\n    this.method.stealTheItem(this.expectedTarget);\n    assertEquals(this.expectedStealMethod, appender.getLastMessage());\n    assertEquals(1, appender.getLogSize());\n  }\n\n  /** Verify if the complete steal process goes as planned */\n  @Test\n  void testSteal() {\n    this.method.steal();\n\n    assertTrue(appender.logContains(this.expectedTargetResult));\n    assertTrue(appender.logContains(this.expectedConfuseMethod));\n    assertTrue(appender.logContains(this.expectedStealMethod));\n    assertEquals(3, appender.getLogSize());\n  }\n\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender() {\n      ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n\n    public String getLastMessage() {\n      return log.get(log.size() - 1).getFormattedMessage();\n    }\n\n    public boolean logContains(String message) {\n      return log.stream().anyMatch(event -> event.getFormattedMessage().equals(message));\n    }\n  }\n}\n"
  },
  {
    "path": "template-method/src/test/java/com/iluwatar/templatemethod/SubtleMethodTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templatemethod;\n\n/** SubtleMethodTest */\nclass SubtleMethodTest extends StealingMethodTest<SubtleMethod> {\n\n  /** Create a new test for the {@link SubtleMethod} */\n  public SubtleMethodTest() {\n    super(\n        new SubtleMethod(),\n        \"shop keeper\",\n        \"The target has been chosen as shop keeper.\",\n        \"Approach the shop keeper with tears running and hug him!\",\n        \"While in close contact grab the shop keeper's wallet.\");\n  }\n}\n"
  },
  {
    "path": "templateview/README.md",
    "content": "---\ntitle: \"Template View Pattern in Java: Streamlining Dynamic Webpage Rendering\"\nshortTitle: Template View\ndescription: \"Learn about the Template View design pattern in Java, which simplifies webpage rendering by separating static and dynamic content. Ideal for developers building reusable and maintainable UI components.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Abstraction\n  - Code simplification\n  - Decoupling\n  - Extensibility\n  - Gang of Four\n  - Inheritance\n  - Polymorphism\n  - Reusability\n---\n\n## Intent of Template View Design Pattern\n\nSeparate the structure and static parts of a webpage (or view) from its dynamic content. Template View ensures a consistent layout while allowing flexibility for different types of views.\n\n## Detailed Explanation of Template View Pattern with Real-World Examples\n\nReal-World Example\n\n> Think of a blog website where each post page follows the same layout with a header, footer, and main content area. While the header and footer remain consistent, the main content differs for each blog post. The Template View pattern encapsulates the shared layout (header and footer) in a base class while delegating the rendering of the main content to subclasses.\n\nIn Plain Words\n\n> The Template View pattern provides a way to define a consistent layout in a base class while letting subclasses implement the specific, dynamic content for different views.\n\nWikipedia Says\n\n> While not a classic Gang of Four pattern, Template View aligns closely with the Template Method pattern, applied specifically to rendering webpages or views. It defines a skeleton for rendering, delegating dynamic parts to subclasses while keeping the structure consistent.\n\nFlowchart\n\n![Template View Pattern Flowchart](./etc/template-view-flowchart.png)\n\n## Programmatic Example of Template View Pattern in Java\n\nOur example involves rendering different types of views (`HomePageView` and `ContactPageView`) with a common structure consisting of a header, dynamic content, and a footer.\n\n### The Abstract Base Class: TemplateView\n\nThe `TemplateView` class defines the skeleton for rendering a view. Subclasses provide implementations for rendering dynamic content.\n\n```java\n@Slf4j\npublic abstract class TemplateView {\n\n  public final void render() {\n    printHeader();\n    renderDynamicContent();\n    printFooter();\n  }\n\n  protected void printHeader() {\n    LOGGER.info(\"Rendering header...\");\n  }\n\n  protected abstract void renderDynamicContent();\n\n  protected void printFooter() {\n    LOGGER.info(\"Rendering footer...\");\n  }\n}\n```\n### Concrete Class: HomePageView\n```java\n@Slf4j\npublic class HomePageView extends TemplateView {\n\n  @Override\n  protected void renderDynamicContent() {\n    LOGGER.info(\"Welcome to the Home Page!\");\n  }\n}\n```\n### Concrete Class: ContactPageView\n```java\n@Slf4j\npublic class ContactPageView extends TemplateView {\n\n  @Override\n  protected void renderDynamicContent() {\n    LOGGER.info(\"Contact us at: contact@example.com\");\n  }\n}\n```\n### Application Class: App\nThe `App` class demonstrates rendering different views using the Template View pattern.\n```java\n@Slf4j\npublic class App {\n\n  public static void main(String[] args) {\n    TemplateView homePage = new HomePageView();\n    LOGGER.info(\"Rendering HomePage:\");\n    homePage.render();\n\n    TemplateView contactPage = new ContactPageView();\n    LOGGER.info(\"\\nRendering ContactPage:\");\n    contactPage.render();\n  }\n}\n```\n## Output of the Program\n```lessRendering HomePage:\nRendering header...\nWelcome to the Home Page!\nRendering footer...\n\nRendering ContactPage:\nRendering header...\nContact us at: contact@example.com\nRendering footer...\n```\n## When to Use the Template View Pattern in Java\n- When you want to enforce a consistent structure for rendering views while allowing flexibility in dynamic content. \n- When you need to separate the static layout (header, footer) from the dynamic parts of a view (main content). \n- To enhance code reusability and reduce duplication in rendering logic.\n\n## Benefits and Trade-offs of Template View Pattern\n**Benefits:**\n- Code Reusability: Centralizes shared layout logic in the base class.\n- Maintainability: Reduces duplication, making updates easier.\n- Flexibility: Allows subclasses to customize dynamic content.\n\n**Trade-offs:**\n- Increased Number of Classes: Requires creating separate classes for each type of view.\n- Design Overhead: Might be overkill for simple applications with few views.\n\n## Related Java Design Patterns\n- [Template Method](https://java-design-patterns.com/patterns/template-method/): A similar pattern focusing on defining a skeleton algorithm, allowing subclasses to implement specific steps.\n- [Strategy Pattern](https://java-design-patterns.com/patterns/strategy/): Offers flexibility in choosing dynamic behaviors at runtime instead of hardcoding them in subclasses.\n- [Decorator Pattern](https://java-design-patterns.com/patterns/decorator/): Can complement Template View for dynamically adding responsibilities to views.\n\n## Real World Applications of Template View Pattern\n- Web frameworks like Spring MVC and Django use this concept to render views consistently.\n- CMS platforms like WordPress follow this pattern for theme templates, separating layout from content.\n\n## References and Credits\n- [Effective Java](https://amzn.to/4cGk2Jz)\n- [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n- [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n- [Template Method Pattern](https://refactoring.guru/design-patterns/template-method)\n- [Basics of Django: Model-View-Template (MVT) Architecture](https://angelogentileiii.medium.com/basics-of-django-model-view-template-mvt-architecture-8585aecffbf6)\n"
  },
  {
    "path": "templateview/etc/template-view.urm.puml",
    "content": "@startuml\npackage com.iluwater.templateview {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n\n  abstract class TemplateView {\n    - LOGGER : Logger {static}\n    + TemplateView()\n    + render() : void {final}\n    # printHeader() : void\n    # renderDynamicContent() : void {abstract}\n    # printFooter() : void\n  }\n\n  class HomePageView {\n    - LOGGER : Logger {static}\n    + HomePageView()\n    + renderDynamicContent() : void\n  }\n\n  class ContactPageView {\n    - LOGGER : Logger {static}\n    + ContactPageView()\n    + renderDynamicContent() : void\n  }\n}\n\nApp --> TemplateView\nTemplateView <|-- HomePageView\nTemplateView <|-- ContactPageView\n@enduml\n"
  },
  {
    "path": "templateview/etc/templateview.urm.puml",
    "content": "@startuml\npackage com.iluwatar.templateview {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class ContactPageView {\n    - LOGGER : Logger {static}\n    + ContactPageView()\n    # renderDynamicContent()\n  }\n  class HomePageView {\n    - LOGGER : Logger {static}\n    + HomePageView()\n    # renderDynamicContent()\n  }\n  abstract class TemplateView {\n    - LOGGER : Logger {static}\n    + TemplateView()\n    # printFooter()\n    # printHeader()\n    + render()\n    # renderDynamicContent() {abstract}\n  }\n}\nContactPageView --|> TemplateView \nHomePageView --|> TemplateView \n@enduml"
  },
  {
    "path": "templateview/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>templateview</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.templateview.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "templateview/src/main/java/com/iluwatar/templateview/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templateview;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Template View defines a consistent layout for rendering views, delegating dynamic content\n * rendering to subclasses.\n *\n * <p>In this example, the {@link TemplateView} class provides the skeleton for rendering views with\n * a header, dynamic content, and a footer. Subclasses {@link HomePageView} and {@link\n * ContactPageView} define the specific dynamic content for their respective views.\n *\n * <p>The {@link App} class demonstrates the usage of the Template View Pattern by rendering\n * instances of {@link HomePageView} and {@link ContactPageView}.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    // Create and render the HomePageView\n    TemplateView homePage = new HomePageView();\n    LOGGER.info(\"Rendering HomePage:\");\n    homePage.render();\n\n    // Create and render the ContactPageView\n    TemplateView contactPage = new ContactPageView();\n    LOGGER.info(\"\\nRendering ContactPage:\");\n    contactPage.render();\n  }\n}\n"
  },
  {
    "path": "templateview/src/main/java/com/iluwatar/templateview/ContactPageView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templateview;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * ContactPageView implements the TemplateView and provides dynamic content specific to the contact\n * page.\n */\n@Slf4j\npublic class ContactPageView extends TemplateView {\n\n  /** Renders dynamic content for the contact page. */\n  @Override\n  protected void renderDynamicContent() {\n    LOGGER.info(\"Contact us at: contact@example.com\");\n  }\n}\n"
  },
  {
    "path": "templateview/src/main/java/com/iluwatar/templateview/HomePageView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templateview;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * HomePageView implements the TemplateView and provides dynamic content specific to the homepage.\n */\n@Slf4j\npublic class HomePageView extends TemplateView {\n  /** Renders dynamic content for the homepage. */\n  @Override\n  protected void renderDynamicContent() {\n    LOGGER.info(\"Welcome to the Home Page!\");\n  }\n}\n"
  },
  {
    "path": "templateview/src/main/java/com/iluwatar/templateview/TemplateView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templateview;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * TemplateView defines the skeleton for rendering views. Concrete subclasses will provide the\n * dynamic content for specific views.\n */\n@Slf4j\npublic abstract class TemplateView {\n\n  /** Render the common structure of the view, delegating dynamic content to subclasses. */\n  public final void render() {\n    printHeader();\n    renderDynamicContent();\n    printFooter();\n  }\n\n  /** Prints the common header of the view. */\n  protected void printHeader() {\n    LOGGER.info(\"Rendering header...\");\n  }\n\n  /** Subclasses must provide the implementation for rendering dynamic content. */\n  protected abstract void renderDynamicContent();\n\n  /** Prints the common footer of the view. */\n  protected void printFooter() {\n    LOGGER.info(\"Rendering footer...\");\n  }\n}\n"
  },
  {
    "path": "templateview/src/test/java/com/iluwatar/templateview/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templateview;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    // Verify that main() method executes without throwing exceptions\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "templateview/src/test/java/com/iluwatar/templateview/ContactPageViewTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templateview;\n\nimport static org.mockito.Mockito.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass ContactPageViewTest {\n\n  @Test\n  void testRenderDynamicContent() {\n    // Create a spy for ContactPageView\n    ContactPageView contactPage = spy(ContactPageView.class);\n\n    // Render dynamic content for ContactPageView\n    contactPage.renderDynamicContent();\n\n    // Verify that the correct message is logged\n    verify(contactPage).renderDynamicContent();\n  }\n}\n"
  },
  {
    "path": "templateview/src/test/java/com/iluwatar/templateview/HomePageViewTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templateview;\n\nimport static org.mockito.Mockito.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass HomePageViewTest {\n\n  @Test\n  void testRenderDynamicContent() {\n    // Create a spy for HomePageView\n    HomePageView homePage = spy(HomePageView.class);\n\n    // Render dynamic content for HomePageView\n    homePage.renderDynamicContent();\n\n    // Verify that the correct message is logged\n    verify(homePage).renderDynamicContent();\n  }\n}\n"
  },
  {
    "path": "templateview/src/test/java/com/iluwatar/templateview/TemplateViewTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.templateview;\n\nimport static org.mockito.Mockito.*;\n\nimport org.junit.jupiter.api.Test;\n\nclass TemplateViewTest {\n\n  @Test\n  void testRenderHomePage() {\n    // Create a spy for HomePageView\n    TemplateView homePage = spy(HomePageView.class);\n\n    // Call the render method\n    homePage.render();\n\n    // Verify that the steps of rendering are executed in the correct order\n    verify(homePage).printHeader(); // Header is printed\n    verify(homePage).renderDynamicContent(); // Dynamic content specific to home page\n    verify(homePage).printFooter(); // Footer is printed\n  }\n\n  @Test\n  void testRenderContactPage() {\n    // Create a spy for ContactPageView\n    TemplateView contactPage = spy(ContactPageView.class);\n\n    // Call the render method\n    contactPage.render();\n\n    // Verify that the steps of rendering are executed in the correct order\n    verify(contactPage).printHeader(); // Header is printed\n    verify(contactPage).renderDynamicContent(); // Dynamic content specific to contact page\n    verify(contactPage).printFooter(); // Footer is printed\n  }\n}\n"
  },
  {
    "path": "thread-pool-executor/README.md",
    "content": "---\ntitle: \"Thread-Pool Executor Pattern in Java: Efficient Concurrent Task Management\"\nshortTitle: Thread-Pool Executor\ndescription: \"Learn the Thread-Pool Executor pattern in Java with practical examples, class\ndiagrams, and implementation details. Understand how to manage concurrent tasks efficiently,\nimproving resource utilization and application performance.\"\ncategory: Concurrency\nlanguage: en\ntag:\n\n- Performance\n- Resource Management\n- Concurrency\n- Multithreading\n- Scalability\n\n---\n\n## Intent of Thread-Pool Executor Design Pattern\n\nThe Thread-Pool Executor pattern maintains a pool of worker threads to execute tasks concurrently,\noptimizing resource usage by reusing existing threads instead of creating new ones for each task.\n\n## Detailed Explanation of Thread-Pool Executor Pattern with Real-World Examples\n\n### Real-world example\n\n> Imagine a busy airport security checkpoint where instead of opening a new lane for each traveler,\n> a fixed number of security lanes (threads) are open to process all passengers. Each security\n> officer (thread) processes one passenger (task) at a time, and when finished, immediately calls the\n> next passenger in line. During peak travel times, passengers wait in a queue, but the system is much\n> more efficient than trying to open a new security lane for each individual traveler. The airport can\n> handle fluctuating passenger traffic throughout the day with consistent staffing, optimizing both\n> resource utilization and passenger throughput.\n\n### In plain words\n\n> Thread-Pool Executor keeps a set of reusable threads that process multiple tasks throughout their\n> lifecycle, rather than creating a new thread for each task.\n\n### Wikipedia says\n\n> A thread pool is a software design pattern for achieving concurrency of execution in a computer\n> program. Often also called a replicated workers or worker-crew model, a thread pool maintains\n> multiple threads waiting for tasks to be allocated for concurrent execution by the supervising\n> program.\n\n### Class diagram\n\n![Thread-pool-executor Class diagram](./etc/thread-pool-executor.urm.png)\n\n## Programmatic Example of Thread-Pool Executor Pattern in Java\n\nImagine a hotel front desk.\n\nThe number of employees (thread pool) is limited, but guests (tasks) keep arriving endlessly.\n\nThe Thread-Pool Executor pattern efficiently handles a large number of requests by reusing a small\nset of threads.\n\n```java\n@Slf4j\npublic class HotelFrontDesk {\n    public static void main(String[] args) throws InterruptedException, ExecutionException {\n        // Hire 3 front desk employees (threads)\n        ExecutorService frontDesk = Executors.newFixedThreadPool(3);\n\n        LOGGER.info(\"Hotel front desk operation started!\");\n\n        // 7 regular guests checking in (Runnable)\n        for (int i = 1; i <= 7; i++) {\n            String guestName = \"Guest-\" + i;\n            frontDesk.submit(() -> {\n                String employeeName = Thread.currentThread().getName();\n                LOGGER.info(\"{} is checking in {}...\", employeeName, guestName);\n                try {\n                    Thread.sleep(2000); // Simulate check-in time\n                } catch (InterruptedException e) {\n                    Thread.currentThread().interrupt();\n                }\n                LOGGER.info(\"{} has been successfully checked in!\", guestName);\n            });\n        }\n\n        // 3 VIP guests checking in (Callable with result)\n        Callable<String> vipGuest1 = createVipGuest(\"VIP-Guest-1\");\n        Callable<String> vipGuest2 = createVipGuest(\"VIP-Guest-2\");\n        Callable<String> vipGuest3 = createVipGuest(\"VIP-Guest-3\");\n\n        Future<String> vipResult1 = frontDesk.submit(vipGuest1);\n        Future<String> vipResult2 = frontDesk.submit(vipGuest2);\n        Future<String> vipResult3 = frontDesk.submit(vipGuest3);\n\n        // Shutdown after submitting all tasks\n        frontDesk.shutdown();\n\n        if (frontDesk.awaitTermination(1, TimeUnit.HOURS)) {\n            // Print VIP guests' check-in results\n            LOGGER.info(\"VIP Check-in Results:\");\n            LOGGER.info(vipResult1.get());\n            LOGGER.info(vipResult2.get());\n            LOGGER.info(vipResult3.get());\n            LOGGER.info(\"All guests have been successfully checked in. Front desk is now closed.\");\n        } else {\n            LOGGER.info(\"Check-in timeout. Forcefully shutting down the front desk.\");\n        }\n    }\n\n    private static Callable<String> createVipGuest(String vipGuestName) {\n        return () -> {\n            String employeeName = Thread.currentThread().getName();\n            LOGGER.info(\"{} is checking in VIP guest {}...\", employeeName, vipGuestName);\n            Thread.sleep(1000); // VIPs are faster to check in\n            return vipGuestName + \" has been successfully checked in!\";\n        };\n    }\n}\n```\n\nHere's the console output:\n\n```markdown\nHotel front desk operation started!\npool-1-thread-3 is checking in Guest-3...\npool-1-thread-2 is checking in Guest-2...\npool-1-thread-1 is checking in Guest-1...\nGuest-2 has been successfully checked in!\nGuest-1 has been successfully checked in!\nGuest-3 has been successfully checked in!\npool-1-thread-2 is checking in Guest-5...\npool-1-thread-3 is checking in Guest-4...\npool-1-thread-1 is checking in Guest-6...\nGuest-5 has been successfully checked in!\npool-1-thread-2 is checking in Guest-7...\nGuest-4 has been successfully checked in!\npool-1-thread-3 is checking in VIP guest VIP-Guest-1...\nGuest-6 has been successfully checked in!\npool-1-thread-1 is checking in VIP guest VIP-Guest-2...\npool-1-thread-3 is checking in VIP guest VIP-Guest-3...\nGuest-7 has been successfully checked in!\nVIP Check-in Results:\nVIP-Guest-1 has been successfully checked in!\nVIP-Guest-2 has been successfully checked in!\nVIP-Guest-3 has been successfully checked in!\nAll guests have been successfully checked in. Front desk is now closed.\n```\n\n**Note:** Since this example demonstrates asynchronous thread execution, **the actual output may vary between runs**. The order of execution and timing can differ due to thread scheduling, system load, and other factors that affect concurrent processing. The core behavior of the thread pool (limiting concurrent tasks to the number of threads and reusing threads) will remain consistent, but the exact sequence of log messages may change with each execution.\n\n## When to Use the Thread-Pool Executor Pattern in Java\n\n* When you need to limit the number of threads running simultaneously to avoid resource exhaustion\n* For applications that process a large number of short-lived independent tasks\n* To improve performance by reducing thread creation/destruction overhead\n* When implementing server applications that handle multiple client requests concurrently\n* To execute recurring tasks at fixed rates or with fixed delays\n\n## Thread-Pool Executor Pattern Java Tutorial\n\n* [Thread-Pool Executor Pattern Tutorial (Baeldung)](https://www.baeldung.com/thread-pool-java-and-guava)\n\n## Real-World Applications of Thread-Pool Executor Pattern in Java\n\n* Application servers like Tomcat and Jetty use thread pools to handle HTTP requests\n* Database connection pools in JDBC implementations\n* Background job processing frameworks like Spring Batch\n* Task scheduling systems like Quartz Scheduler\n* Java EE's Managed Executor Service for enterprise applications\n\n## Benefits and Trade-offs of Thread-Pool Executor Pattern\n\n### Benefits\n\n* Improves performance by reusing existing threads instead of creating new ones\n* Provides better resource management by limiting the number of active threads\n* Simplifies thread lifecycle management and cleanup\n* Facilitates easy implementation of task prioritization and scheduling\n* Enhances application stability by preventing resource exhaustion\n\n### Trade-offs\n\n* May lead to thread starvation if improperly configured (too few threads)\n* Potential for resource underutilization if improperly sized (too many threads)\n* Requires careful shutdown handling to prevent task loss or resource leaks\n\n## Related Java Design Patterns\n\n* [Master-Worker Pattern](https://java-design-patterns.com/patterns/master-worker/): Tasks between a\n  master and multiple workers.\n* [Producer-Consumer Pattern](https://java-design-patterns.com/patterns/producer-consumer/):\n  Separates task production and task consumption, typically using a blocking queue.\n* [Object Pool Pattern](https://java-design-patterns.com/patterns/object-pool/): Reuses a set of\n  objects (e.g., threads) instead of creating/destroying them repeatedly.\n\n## References and Credits\n\n* [Java Documentation for ThreadPoolExecutor](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ThreadPoolExecutor.html)\n* [Java Concurrency in Practice](https://jcip.net/) by Brian Goetz\n* [Effective Java](https://www.oreilly.com/library/view/effective-java-3rd/9780134686097/) by Joshua\n  Bloch\n"
  },
  {
    "path": "thread-pool-executor/etc/thread-pool-executor.urm.puml",
    "content": "@startuml\n\ninterface Runnable {\n  +run(): void\n}\n\ninterface Callable<T> {\n  +call(): T\n}\n\ninterface ExecutorService {\n  +submit(task: Runnable): Future<?>\n  +submit(task: Callable<T>): Future<T>\n  +shutdown(): void\n  +awaitTermination(timeout: long, unit: TimeUnit): boolean\n}\n\nclass ThreadPoolExecutor {\n  -corePoolSize: int\n  -maximumPoolSize: int\n  -keepAliveTime: long\n  -workQueue: BlockingQueue<Runnable>\n  +execute(task: Runnable): void\n  +submit(task: Callable<T>): Future<T>\n}\n\nclass ThreadPoolManager {\n  -executorService: ExecutorService\n  +ThreadPoolManager(numThreads: int)\n  +submitTask(task: Runnable): void\n  +submitCallable(task: Callable<T>): Future<T>\n  +shutdown(): void\n  +awaitTermination(timeout: long, unit: TimeUnit): boolean\n}\n\nclass Task {\n  -id: int\n  -name: String\n  -processingTime: long\n  +Task(id: int, name: String, processingTime: long)\n  +run(): void\n  +call(): TaskResult\n}\n\nclass TaskResult {\n  -taskId: int\n  -taskName: String\n  -executionTime: long\n  +TaskResult(taskId: int, taskName: String, executionTime: long)\n}\n\nclass App {\n  +main(args: String[]): void\n  -executeRunnableTasks(poolManager: ThreadPoolManager): void\n  -executeCallableTasks(poolManager: ThreadPoolManager): void\n}\n\nExecutorService <|-- ThreadPoolExecutor : implements\nTask ..|> Runnable : implements\nTask ..|> Callable : implements\nTask --> TaskResult : produces\nThreadPoolManager --> ExecutorService : wraps\nApp --> ThreadPoolManager : uses\nApp --> Task : creates\n\n@enduml"
  },
  {
    "path": "thread-pool-executor/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n        xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0\n                            http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n\n    <artifactId>thread-pool-executor</artifactId>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.threadpoolexecutor.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.threadpoolexecutor;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The Thread-Pool Executor pattern demonstrates how a pool of worker threads can be used to execute\n * tasks concurrently. This pattern is particularly useful in scenarios where you need to execute a\n * large number of independent tasks and want to limit the number of threads used.\n *\n * <p>In this example, a hotel front desk with a fixed number of employees processes guest\n * check-ins. Each employee is represented by a thread, and each check-in is a task.\n *\n * <p>Key benefits demonstrated:\n *\n * <ul>\n *   <li>Resource management - Limiting the number of concurrent threads\n *   <li>Efficiency - Reusing threads instead of creating new ones for each task\n *   <li>Responsiveness - Handling many requests with limited resources\n * </ul>\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program main entry point.\n   *\n   * @param args program runtime arguments\n   */\n  public static void main(String[] args) throws InterruptedException, ExecutionException {\n\n    FrontDeskService frontDesk = new FrontDeskService(5);\n    LOGGER.info(\"Hotel front desk operation started!\");\n\n    LOGGER.info(\"Processing 30 regular guest check-ins...\");\n    for (int i = 1; i <= 30; i++) {\n      frontDesk.submitGuestCheckIn(new GuestCheckInTask(\"Guest-\" + i));\n      Thread.sleep(100);\n    }\n\n    LOGGER.info(\"Processing 3 VIP guest check-ins...\");\n    List<Future<String>> vipResults = new ArrayList<>();\n\n    for (int i = 1; i <= 3; i++) {\n      Future<String> result =\n          frontDesk.submitVipGuestCheckIn(new VipGuestCheckInTask(\"VIP-Guest-\" + i));\n      vipResults.add(result);\n    }\n\n    frontDesk.shutdown();\n\n    if (frontDesk.awaitTermination(1, TimeUnit.HOURS)) {\n      LOGGER.info(\"VIP Check-in Results:\");\n      for (Future<String> result : vipResults) {\n        LOGGER.info(result.get());\n      }\n      LOGGER.info(\"All guests have been successfully checked in. Front desk is now closed.\");\n    } else {\n      LOGGER.warn(\"Check-in timeout. Forcefully shutting down the front desk.\");\n    }\n  }\n}\n"
  },
  {
    "path": "thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/FrontDeskService.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.threadpoolexecutor;\n\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * FrontDeskService represents the hotel's front desk with a fixed number of employees. This class\n * demonstrates the Thread-Pool Executor pattern using Java's ExecutorService.\n */\n@Slf4j\npublic class FrontDeskService {\n\n  private final ExecutorService executorService;\n  private final int numberOfEmployees;\n\n  /**\n   * Creates a new front desk with the specified number of employees.\n   *\n   * @param numberOfEmployees the number of employees (threads) at the front desk\n   */\n  public FrontDeskService(int numberOfEmployees) {\n    this.numberOfEmployees = numberOfEmployees;\n    this.executorService = Executors.newFixedThreadPool(numberOfEmployees);\n    LOGGER.info(\"Front desk initialized with {} employees.\", numberOfEmployees);\n  }\n\n  /**\n   * Submits a regular guest check-in task to an available employee.\n   *\n   * @param task the check-in task to submit\n   * @return a Future representing pending completion of the task\n   */\n  public Future<Void> submitGuestCheckIn(Runnable task) {\n    LOGGER.debug(\"Submitting regular guest check-in task\");\n    return executorService.submit(task, null);\n  }\n\n  /**\n   * Submits a VIP guest check-in task to an available employee.\n   *\n   * @param task the VIP check-in task to submit\n   * @param <T> the type of the task's result\n   * @return a Future representing pending completion of the task\n   */\n  public <T> Future<T> submitVipGuestCheckIn(Callable<T> task) {\n    LOGGER.debug(\"Submitting VIP guest check-in task\");\n    return executorService.submit(task);\n  }\n\n  /**\n   * Closes the front desk after all currently checked-in guests are processed. No new check-ins\n   * will be accepted.\n   */\n  public void shutdown() {\n    LOGGER.info(\"Front desk is closing - no new guests will be accepted.\");\n    executorService.shutdown();\n  }\n\n  /**\n   * Waits for all check-in processes to complete or until timeout.\n   *\n   * @param timeout the maximum time to wait\n   * @param unit the time unit of the timeout argument\n   * @return true if all tasks completed, false if timeout elapsed\n   * @throws InterruptedException if interrupted while waiting\n   */\n  public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {\n    LOGGER.info(\"Waiting for all check-ins to complete (max wait: {} {})\", timeout, unit);\n    return executorService.awaitTermination(timeout, unit);\n  }\n\n  /**\n   * Gets the number of employees at the front desk.\n   *\n   * @return the number of employees\n   */\n  public int getNumberOfEmployees() {\n    return numberOfEmployees;\n  }\n}\n"
  },
  {
    "path": "thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/GuestCheckInTask.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.threadpoolexecutor;\n\nimport lombok.AllArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * GuestCheckInTask represents a regular guest check-in process. Implements Runnable because it\n * performs an action without returning a result.\n */\n@Slf4j\n@AllArgsConstructor\npublic class GuestCheckInTask implements Runnable {\n\n  private final String guestName;\n\n  @Override\n  public void run() {\n    String employeeName = Thread.currentThread().getName();\n    LOGGER.info(\"{} is checking in {}...\", employeeName, guestName);\n    try {\n      Thread.sleep(2000);\n    } catch (InterruptedException e) {\n      Thread.currentThread().interrupt();\n      LOGGER.error(\"Check-in for {} was interrupted\", guestName);\n    }\n    LOGGER.info(\"{} has been successfully checked in!\", guestName);\n  }\n}\n"
  },
  {
    "path": "thread-pool-executor/src/main/java/com/iluwatar/threadpoolexecutor/VipGuestCheckInTask.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.threadpoolexecutor;\n\nimport java.util.concurrent.Callable;\nimport lombok.AllArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * VipGuestCheckInTask represents a VIP guest check-in process. Implements Callable because it\n * returns a result (check-in confirmation).\n */\n@Slf4j\n@AllArgsConstructor\npublic class VipGuestCheckInTask implements Callable<String> {\n\n  private final String vipGuestName;\n\n  @Override\n  public String call() throws Exception {\n    String employeeName = Thread.currentThread().getName();\n    LOGGER.info(\"{} is checking in VIP guest {}...\", employeeName, vipGuestName);\n\n    Thread.sleep(1000);\n\n    String result = vipGuestName + \" has been successfully checked in!\";\n    LOGGER.info(\"VIP check-in completed: {}\", result);\n    return result;\n  }\n}\n"
  },
  {
    "path": "thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.threadpoolexecutor;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n\n  @Test\n  void appStartsWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/FrontDeskServiceTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.threadpoolexecutor;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.RejectedExecutionException;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport org.junit.jupiter.api.Test;\n\nclass FrontDeskServiceTest {\n\n  /**\n   * Tests that the constructor correctly sets the number of employees (threads). This verifies the\n   * basic initialization of the thread pool.\n   */\n  @Test\n  void testConstructorSetsCorrectNumberOfEmployees() {\n    int expectedEmployees = 3;\n\n    FrontDeskService frontDesk = new FrontDeskService(expectedEmployees);\n\n    assertEquals(expectedEmployees, frontDesk.getNumberOfEmployees());\n  }\n\n  /**\n   * Tests that the submitGuestCheckIn method returns a non-null Future object. This verifies the\n   * basic task submission functionality.\n   */\n  @Test\n  void testSubmitGuestCheckInReturnsNonNullFuture() {\n    FrontDeskService frontDesk = new FrontDeskService(1);\n\n    Runnable task =\n        () -> {\n          // Task that completes quickly\n        };\n\n    Future<?> future = frontDesk.submitGuestCheckIn(task);\n\n    assertNotNull(future);\n  }\n\n  /**\n   * Tests that the submitVipGuestCheckIn method returns a non-null Future object. This verifies\n   * that tasks with return values can be submitted correctly.\n   */\n  @Test\n  void testSubmitVipGuestCheckInReturnsNonNullFuture() {\n    FrontDeskService frontDesk = new FrontDeskService(1);\n    Callable<String> task = () -> \"VIP Check-in complete\";\n\n    Future<String> future = frontDesk.submitVipGuestCheckIn(task);\n\n    assertNotNull(future);\n  }\n\n  /**\n   * Tests that the shutdown and awaitTermination methods work correctly. This verifies the basic\n   * shutdown functionality of the thread pool.\n   */\n  @Test\n  void testShutdownAndAwaitTermination() throws InterruptedException {\n    FrontDeskService frontDesk = new FrontDeskService(2);\n    CountDownLatch taskLatch = new CountDownLatch(1);\n\n    Runnable task = taskLatch::countDown;\n\n    frontDesk.submitGuestCheckIn(task);\n    frontDesk.shutdown();\n    boolean terminated = frontDesk.awaitTermination(1, TimeUnit.SECONDS);\n\n    assertTrue(terminated);\n    assertTrue(taskLatch.await(100, TimeUnit.MILLISECONDS));\n  }\n\n  /**\n   * Tests the thread pool's behavior under load with multiple tasks. This verifies that the thread\n   * pool limits concurrent execution to the number of threads, all submitted tasks are eventually\n   * completed, and threads are reused for multiple tasks.\n   */\n  @Test\n  void testMultipleTasksUnderLoad() throws InterruptedException {\n    FrontDeskService frontDesk = new FrontDeskService(2);\n    int taskCount = 10;\n    CountDownLatch tasksCompletedLatch = new CountDownLatch(taskCount);\n    AtomicInteger concurrentTasks = new AtomicInteger(0);\n    AtomicInteger maxConcurrentTasks = new AtomicInteger(0);\n\n    for (int i = 0; i < taskCount; i++) {\n      frontDesk.submitGuestCheckIn(\n          () -> {\n            try {\n              int current = concurrentTasks.incrementAndGet();\n              maxConcurrentTasks.updateAndGet(max -> Math.max(max, current));\n\n              Thread.sleep(100);\n\n              concurrentTasks.decrementAndGet();\n              tasksCompletedLatch.countDown();\n            } catch (InterruptedException e) {\n              Thread.currentThread().interrupt();\n            }\n          });\n    }\n\n    boolean allTasksCompleted = tasksCompletedLatch.await(2, TimeUnit.SECONDS);\n\n    frontDesk.shutdown();\n    frontDesk.awaitTermination(1, TimeUnit.SECONDS);\n\n    assertTrue(allTasksCompleted);\n    assertEquals(2, maxConcurrentTasks.get());\n    assertEquals(0, concurrentTasks.get());\n  }\n\n  /**\n   * Tests proper shutdown behavior under load. This verifies that after shutdown no new tasks are\n   * accepted, all previously submitted tasks are completed, and the executor terminates properly\n   * after all tasks complete.\n   */\n  @Test\n  void testProperShutdownUnderLoad() throws InterruptedException {\n    FrontDeskService frontDesk = new FrontDeskService(2);\n    int taskCount = 5;\n    CountDownLatch startedTasksLatch = new CountDownLatch(2);\n    CountDownLatch tasksCompletionLatch = new CountDownLatch(taskCount);\n\n    for (int i = 0; i < taskCount; i++) {\n      frontDesk.submitGuestCheckIn(\n          () -> {\n            try {\n              startedTasksLatch.countDown();\n              Thread.sleep(100);\n              tasksCompletionLatch.countDown();\n            } catch (InterruptedException e) {\n              Thread.currentThread().interrupt();\n            }\n          });\n    }\n\n    assertTrue(startedTasksLatch.await(1, TimeUnit.SECONDS));\n\n    frontDesk.shutdown();\n\n    assertThrows(\n        RejectedExecutionException.class,\n        () -> {\n          frontDesk.submitGuestCheckIn(() -> {});\n        });\n\n    boolean allTasksCompleted = tasksCompletionLatch.await(2, TimeUnit.SECONDS);\n\n    boolean terminated = frontDesk.awaitTermination(1, TimeUnit.SECONDS);\n\n    assertTrue(allTasksCompleted);\n    assertTrue(terminated);\n  }\n\n  /**\n   * Tests concurrent execution of different task types (regular and VIP). This verifies that both\n   * Runnable and Callable tasks can be processed concurrently, all tasks complete successfully, and\n   * Callable tasks return their results correctly.\n   */\n  @Test\n  void testConcurrentRegularAndVipTasks() throws Exception {\n    FrontDeskService frontDesk = new FrontDeskService(3);\n    int regularTaskCount = 4;\n    int vipTaskCount = 3;\n    CountDownLatch allTasksLatch = new CountDownLatch(regularTaskCount + vipTaskCount);\n\n    List<Future<?>> regularResults = new ArrayList<>();\n    for (int i = 0; i < regularTaskCount; i++) {\n      Future<?> result =\n          frontDesk.submitGuestCheckIn(\n              () -> {\n                try {\n                  Thread.sleep(50);\n                  allTasksLatch.countDown();\n                } catch (InterruptedException e) {\n                  Thread.currentThread().interrupt();\n                }\n              });\n      regularResults.add(result);\n    }\n\n    List<Future<String>> vipResults = new ArrayList<>();\n    for (int i = 0; i < vipTaskCount; i++) {\n      final int guestNum = i;\n      Future<String> result =\n          frontDesk.submitVipGuestCheckIn(\n              () -> {\n                Thread.sleep(25);\n                allTasksLatch.countDown();\n                return \"VIP-\" + guestNum + \" checked in\";\n              });\n      vipResults.add(result);\n    }\n\n    boolean allCompleted = allTasksLatch.await(2, TimeUnit.SECONDS);\n\n    frontDesk.shutdown();\n    frontDesk.awaitTermination(1, TimeUnit.SECONDS);\n\n    assertTrue(allCompleted);\n\n    for (Future<?> result : regularResults) {\n      assertTrue(result.isDone());\n    }\n\n    for (int i = 0; i < vipTaskCount; i++) {\n      Future<String> result = vipResults.get(i);\n      assertTrue(result.isDone());\n      assertEquals(\"VIP-\" + i + \" checked in\", result.get());\n    }\n  }\n}\n"
  },
  {
    "path": "thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/GuestCheckInTaskTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.threadpoolexecutor;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.util.concurrent.atomic.AtomicReference;\nimport org.junit.jupiter.api.Test;\n\nclass GuestCheckInTaskTest {\n\n  /**\n   * Tests that the task executes in the current thread when called directly. This verifies that the\n   * thread name inside the task matches the calling thread.\n   */\n  @Test\n  void testThreadNameInTask() {\n    String guestName = \"TestGuest\";\n    AtomicReference<String> capturedThreadName = new AtomicReference<>();\n\n    GuestCheckInTask task =\n        new GuestCheckInTask(guestName) {\n          @Override\n          public void run() {\n            capturedThreadName.set(Thread.currentThread().getName());\n          }\n        };\n\n    task.run();\n\n    assertEquals(Thread.currentThread().getName(), capturedThreadName.get());\n  }\n}\n"
  },
  {
    "path": "thread-pool-executor/src/test/java/com/iluwatar/threadpoolexecutor/VipGuestCheckInTaskTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.threadpoolexecutor;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nimport org.junit.jupiter.api.Test;\n\nclass VipGuestCheckInTaskTest {\n\n  /**\n   * Tests that the call method returns the expected result string. This verifies that the VIP\n   * check-in task correctly formats its result message.\n   */\n  @Test\n  void testCallReturnsExpectedResult() throws Exception {\n    String vipGuestName = \"TestVipGuest\";\n    VipGuestCheckInTask task = new VipGuestCheckInTask(vipGuestName);\n\n    String result = task.call();\n\n    assertNotNull(result);\n    assertEquals(\"TestVipGuest has been successfully checked in!\", result);\n  }\n}\n"
  },
  {
    "path": "throttling/README.md",
    "content": "---\ntitle: \"Throttling Pattern in Java: Optimizing Resource Usage in High-Demand Applications\"\nshortTitle: Throttling\ndescription: \"Explore the Throttling design pattern in Java to manage application stability and prevent system overload. Learn how rate limiting ensures consistent performance and system resilience. Ideal for developers and software architects.\"\ncategory: Resource management\nlanguage: en\ntag:\n  - API design\n  - Fault tolerance\n  - Performance\n  - Resilience\n  - Scalability\n---\n\n## Also known as\n\n* Rate Limiting\n\n## Intent of Throttling Design Pattern\n\nThe Throttling Pattern, also known as Rate Limiting, limits the number of requests a system can process within a given time frame to prevent overload and ensure stability. It is crucial for resource management in Java applications.\n\n## Detailed Explanation of Throttling Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a popular amusement park that limits the number of visitors who can enter per hour to prevent overcrowding. This ensures that all visitors can enjoy the park without long wait times and maintain a pleasant experience. Similarly, the Throttling design pattern in software controls the rate of requests to a system, preventing it from being overwhelmed and ensuring consistent performance for all users.\n\nIn plain words\n\n> Throttling pattern is used to rate-limit access to a resource.\n\n[Microsoft documentation](https://docs.microsoft.com/en-us/azure/architecture/patterns/throttling) says\n\n> Control the consumption of resources used by an instance of an application, an individual tenant, or an entire service. This can allow the system to continue to function and meet service level agreements, even when an increase in demand places an extreme load on resources.\n\nFlowchart\n\n![Throttling Pattern Flowchart](./etc/throttling-flowchart.png)\n\n## Programmatic Example of Throttling Pattern in Java\n\nIn this Java example, we demonstrate throttling. A young human and an old dwarf walk into a bar. They start ordering beers from the bartender. The bartender immediately sees that the young human shouldn't consume too many drinks too fast and refuses to serve if enough time has not passed. For the old dwarf, the serving rate can be higher.\n\n`BarCustomer` class presents the clients of the `Bartender` API. `CallsCount` tracks the number of calls per `BarCustomer`.\n\n```java\n@Getter\npublic class BarCustomer {\n\n    private final String name;\n    private final int allowedCallsPerSecond;\n\n    public BarCustomer(String name, int allowedCallsPerSecond, CallsCount callsCount) {\n        if (allowedCallsPerSecond < 0) {\n            throw new InvalidParameterException(\"Number of calls less than 0 not allowed\");\n        }\n        this.name = name;\n        this.allowedCallsPerSecond = allowedCallsPerSecond;\n        callsCount.addTenant(name);\n    }\n}\n```\n\n```java\n@Slf4j\npublic final class CallsCount {\n    private final Map<String, AtomicLong> tenantCallsCount = new ConcurrentHashMap<>();\n\n    public void addTenant(String tenantName) {\n        tenantCallsCount.putIfAbsent(tenantName, new AtomicLong(0));\n    }\n\n    public void incrementCount(String tenantName) {\n        tenantCallsCount.get(tenantName).incrementAndGet();\n    }\n\n    public long getCount(String tenantName) {\n        return tenantCallsCount.get(tenantName).get();\n    }\n\n    public void reset() {\n        tenantCallsCount.replaceAll((k, v) -> new AtomicLong(0));\n        LOGGER.info(\"reset counters\");\n    }\n}\n```\n\nNext, the service that the tenants are calling is introduced. To track the call count, a throttler timer is used.\n\n```java\npublic interface Throttler {\n    void start();\n}\n```\n\n```java\npublic class ThrottleTimerImpl implements Throttler {\n\n    private final int throttlePeriod;\n    private final CallsCount callsCount;\n\n    public ThrottleTimerImpl(int throttlePeriod, CallsCount callsCount) {\n        this.throttlePeriod = throttlePeriod;\n        this.callsCount = callsCount;\n    }\n\n    @Override\n    public void start() {\n        new Timer(true).schedule(new TimerTask() {\n            @Override\n            public void run() {\n                callsCount.reset();\n            }\n        }, 0, throttlePeriod);\n    }\n}\n```\n\n`Bartender` offers the `orderDrink` service to the `BarCustomer`s. The customers probably don't know that the beer serving rate is limited by their appearances.\n\n```java\nclass Bartender {\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(Bartender.class);\n    private final CallsCount callsCount;\n\n    public Bartender(Throttler timer, CallsCount callsCount) {\n        this.callsCount = callsCount;\n        timer.start();\n    }\n\n    public int orderDrink(BarCustomer barCustomer) {\n        var tenantName = barCustomer.getName();\n        var count = callsCount.getCount(tenantName);\n        if (count >= barCustomer.getAllowedCallsPerSecond()) {\n            LOGGER.error(\"I'm sorry {}, you've had enough for today!\", tenantName);\n            return -1;\n        }\n        callsCount.incrementCount(tenantName);\n        LOGGER.debug(\"Serving beer to {} : [{} consumed] \", barCustomer.getName(), count + 1);\n        return getRandomCustomerId();\n    }\n\n    private int getRandomCustomerId() {\n        return ThreadLocalRandom.current().nextInt(1, 10000);\n    }\n}\n```\n\nNow it is possible to see the full example in action. `BarCustomer` young human is rate-limited to 2 calls per second and the old dwarf to 4.\n\n```java\n@Slf4j\npublic class App {\n\n    public static void main(String[] args) {\n        var callsCount = new CallsCount();\n        var human = new BarCustomer(\"young human\", 2, callsCount);\n        var dwarf = new BarCustomer(\"dwarf soldier\", 4, callsCount);\n\n        var executorService = Executors.newFixedThreadPool(2);\n\n        executorService.execute(() -> makeServiceCalls(human, callsCount));\n        executorService.execute(() -> makeServiceCalls(dwarf, callsCount));\n\n        executorService.shutdown();\n        try {\n            if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {\n                executorService.shutdownNow();\n            }\n        } catch (InterruptedException e) {\n            executorService.shutdownNow();\n        }\n    }\n\n    private static void makeServiceCalls(BarCustomer barCustomer, CallsCount callsCount) {\n        var timer = new ThrottleTimerImpl(1000, callsCount);\n        var service = new Bartender(timer, callsCount);\n        // Sleep is introduced to keep the output in check and easy to view and analyze the results.\n        IntStream.range(0, 50).forEach(i -> {\n            service.orderDrink(barCustomer);\n            try {\n                Thread.sleep(100);\n            } catch (InterruptedException e) {\n                LOGGER.error(\"Thread interrupted: {}\", e.getMessage());\n            }\n        });\n    }\n}\n```\n\nAn excerpt from the example's console output:\n\n```\n18:46:36.218 [Timer-0] INFO com.iluwatar.throttling.CallsCount - reset counters\n18:46:36.218 [Timer-1] INFO com.iluwatar.throttling.CallsCount - reset counters\n18:46:36.242 [pool-1-thread-2] DEBUG com.iluwatar.throttling.Bartender - Serving beer to dwarf soldier : [1 consumed] \n18:46:36.242 [pool-1-thread-1] DEBUG com.iluwatar.throttling.Bartender - Serving beer to young human : [1 consumed] \n18:46:36.342 [pool-1-thread-2] DEBUG com.iluwatar.throttling.Bartender - Serving beer to dwarf soldier : [2 consumed] \n18:46:36.342 [pool-1-thread-1] DEBUG com.iluwatar.throttling.Bartender - Serving beer to young human : [2 consumed] \n18:46:36.443 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:36.443 [pool-1-thread-2] DEBUG com.iluwatar.throttling.Bartender - Serving beer to dwarf soldier : [3 consumed] \n18:46:36.544 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:36.544 [pool-1-thread-2] DEBUG com.iluwatar.throttling.Bartender - Serving beer to dwarf soldier : [4 consumed] \n18:46:36.645 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!\n18:46:36.645 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:36.745 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:36.745 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!\n18:46:36.846 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:36.846 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!\n18:46:36.947 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!\n18:46:36.947 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:37.048 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!\n18:46:37.048 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:37.148 [pool-1-thread-1] ERROR com.iluwatar.throttling.Bartender - I'm sorry young human, you've had enough for today!\n18:46:37.148 [pool-1-thread-2] ERROR com.iluwatar.throttling.Bartender - I'm sorry dwarf soldier, you've had enough for today!\n```\n\n## When to Use the Throttling Pattern in Java\n\n* You need to protect resources from being overwhelmed by too many requests.\n* You want to ensure fair usage of a service among multiple users.\n* You need to maintain the quality of service under high load conditions.\n\n## Real-World Applications of Throttling Pattern in Java\n\n* APIs of major cloud providers like AWS, Google Cloud, and Azure use throttling to manage resource usage.\n* Web services to prevent denial-of-service (DoS) attacks by limiting the number of requests from a single IP address.\n* Online platforms like social media sites and e-commerce websites to ensure even distribution of server load.\n\n## Benefits and Trade-offs of Throttling Pattern\n\nBenefits:\n\n* Prevents resource exhaustion, ensuring system stability.\n* Helps in maintaining consistent performance and quality of service.\n* Improves fault tolerance by avoiding system crashes under high load.\n\nTrade-offs:\n\n* May cause increased latency or delay in request processing.\n* Requires careful tuning to balance between resource protection and user experience.\n* Could lead to denial of service to legitimate users if not configured correctly.\n\n## Related Java Design Patterns\n\n* [Circuit Breaker](https://java-design-patterns.com/patterns/circuit-breaker/): Works in tandem with throttling to prevent repeated attempts to access an overloaded service.\n* Bulkhead: Isolates different parts of the system to limit the impact of throttling on other components.\n\n## References and Credits\n\n* [Throttling pattern (Microsoft)](https://docs.microsoft.com/en-us/azure/architecture/patterns/throttling)\n* [Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications](https://amzn.to/4dLvowg)\n"
  },
  {
    "path": "throttling/etc/throttling.urm.puml",
    "content": "@startuml\npackage com.iluwatar.throttling {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n    - makeServiceCalls(tenant : Tenant, callsCount : CallsCount) {static}\n  }\n  ~class B2BService {\n    - LOGGER : Logger {static}\n    - callsCount : CallsCount\n    + B2BService(timer : Throttler, callsCount : CallsCount)\n    + dummyCustomerApi(tenant : Tenant) : int\n    - getRandomCustomerId() : int\n  }\n  class CallsCount {\n    - LOGGER : Logger {static}\n    - tenantCallsCount : Map<String, AtomicLong>\n    + CallsCount()\n    + addTenant(tenantName : String)\n    + getCount(tenantName : String) : long\n    + incrementCount(tenantName : String)\n    + reset()\n  }\n  class Tenant {\n    - allowedCallsPerSecond : int\n    - name : String\n    + Tenant(name : String, allowedCallsPerSecond : int, callsCount : CallsCount)\n    + getAllowedCallsPerSecond() : int\n    + getName() : String\n  }\n}\npackage com.iluwatar.throttling.timer {\n  class ThrottleTimerImpl {\n    - callsCount : CallsCount\n    - throttlePeriod : int\n    + ThrottleTimerImpl(throttlePeriod : int, callsCount : CallsCount)\n    + start()\n  }\n  interface Throttler {\n    + start() {abstract}\n  }\n}\nB2BService -->  \"-callsCount\" CallsCount\nThrottleTimerImpl -->  \"-callsCount\" CallsCount\nThrottleTimerImpl ..|> Throttler \n@enduml"
  },
  {
    "path": "throttling/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>throttling</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.throttling.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "throttling/src/main/java/com/iluwatar/throttling/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.throttling;\n\nimport com.iluwatar.throttling.timer.ThrottleTimerImpl;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.IntStream;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Throttling pattern is a design pattern to throttle or limit the use of resources or even a\n * complete service by users or a particular tenant. This can allow systems to continue to function\n * and meet service level agreements, even when an increase in demand places load on resources.\n *\n * <p>In this example there is a {@link Bartender} serving beer to {@link BarCustomer}s. This is a\n * time based throttling, i.e. only a certain number of calls are allowed per second. ({@link\n * BarCustomer}) is the service tenant class having a name and the number of calls allowed. ({@link\n * Bartender}) is the service which is consumed by the tenants and is throttled.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Application entry point.\n   *\n   * @param args main arguments\n   */\n  public static void main(String[] args) {\n    var callsCount = new CallsCount();\n    var human = new BarCustomer(\"young human\", 2, callsCount);\n    var dwarf = new BarCustomer(\"dwarf soldier\", 4, callsCount);\n\n    var executorService = Executors.newFixedThreadPool(2);\n\n    executorService.execute(() -> makeServiceCalls(human, callsCount));\n    executorService.execute(() -> makeServiceCalls(dwarf, callsCount));\n\n    executorService.shutdown();\n    try {\n      if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {\n        executorService.shutdownNow();\n      }\n    } catch (InterruptedException e) {\n      executorService.shutdownNow();\n    }\n  }\n\n  /** Make calls to the bartender. */\n  private static void makeServiceCalls(BarCustomer barCustomer, CallsCount callsCount) {\n    var timer = new ThrottleTimerImpl(1000, callsCount);\n    var service = new Bartender(timer, callsCount);\n    // Sleep is introduced to keep the output in check and easy to view and analyze the results.\n    IntStream.range(0, 50)\n        .forEach(\n            i -> {\n              service.orderDrink(barCustomer);\n              try {\n                Thread.sleep(100);\n              } catch (InterruptedException e) {\n                LOGGER.error(\"Thread interrupted: {}\", e.getMessage());\n              }\n            });\n  }\n}\n"
  },
  {
    "path": "throttling/src/main/java/com/iluwatar/throttling/BarCustomer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.throttling;\n\nimport java.security.InvalidParameterException;\nimport lombok.Getter;\n\n/** BarCustomer is a tenant with a name and a number of allowed calls per second. */\n@Getter\npublic class BarCustomer {\n\n  private final String name;\n  private final int allowedCallsPerSecond;\n\n  /**\n   * Constructor.\n   *\n   * @param name Name of the BarCustomer\n   * @param allowedCallsPerSecond The number of calls allowed for this particular tenant.\n   * @throws InvalidParameterException If number of calls is less than 0, throws exception.\n   */\n  public BarCustomer(String name, int allowedCallsPerSecond, CallsCount callsCount) {\n    if (allowedCallsPerSecond < 0) {\n      throw new InvalidParameterException(\"Number of calls less than 0 not allowed\");\n    }\n    this.name = name;\n    this.allowedCallsPerSecond = allowedCallsPerSecond;\n    callsCount.addTenant(name);\n  }\n}\n"
  },
  {
    "path": "throttling/src/main/java/com/iluwatar/throttling/Bartender.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.throttling;\n\nimport com.iluwatar.throttling.timer.Throttler;\nimport java.util.concurrent.ThreadLocalRandom;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Bartender is a service which accepts a BarCustomer (tenant) and throttles the resource based on\n * the time given to the tenant.\n */\nclass Bartender {\n\n  private static final Logger LOGGER = LoggerFactory.getLogger(Bartender.class);\n  private final CallsCount callsCount;\n\n  public Bartender(Throttler timer, CallsCount callsCount) {\n    this.callsCount = callsCount;\n    timer.start();\n  }\n\n  /**\n   * Orders a drink from the bartender.\n   *\n   * @return customer id which is randomly generated\n   */\n  public int orderDrink(BarCustomer barCustomer) {\n    var tenantName = barCustomer.getName();\n    var count = callsCount.getCount(tenantName);\n    if (count >= barCustomer.getAllowedCallsPerSecond()) {\n      LOGGER.error(\"I'm sorry {}, you've had enough for today!\", tenantName);\n      return -1;\n    }\n    callsCount.incrementCount(tenantName);\n    LOGGER.debug(\"Serving beer to {} : [{} consumed] \", barCustomer.getName(), count + 1);\n    return getRandomCustomerId();\n  }\n\n  private int getRandomCustomerId() {\n    return ThreadLocalRandom.current().nextInt(1, 10000);\n  }\n}\n"
  },
  {
    "path": "throttling/src/main/java/com/iluwatar/throttling/CallsCount.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.throttling;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.atomic.AtomicLong;\nimport lombok.extern.slf4j.Slf4j;\n\n/** A class to keep track of the counter of different Tenants. */\n@Slf4j\npublic final class CallsCount {\n  private final Map<String, AtomicLong> tenantCallsCount = new ConcurrentHashMap<>();\n\n  /**\n   * Add a new tenant to the map.\n   *\n   * @param tenantName name of the tenant.\n   */\n  public void addTenant(String tenantName) {\n    tenantCallsCount.putIfAbsent(tenantName, new AtomicLong(0));\n  }\n\n  /**\n   * Increment the count of the specified tenant.\n   *\n   * @param tenantName name of the tenant.\n   */\n  public void incrementCount(String tenantName) {\n    tenantCallsCount.get(tenantName).incrementAndGet();\n  }\n\n  /**\n   * Get count of tenant based on tenant name.\n   *\n   * @param tenantName name of the tenant.\n   * @return the count of the tenant.\n   */\n  public long getCount(String tenantName) {\n    return tenantCallsCount.get(tenantName).get();\n  }\n\n  /** Resets the count of all the tenants in the map. */\n  public void reset() {\n    tenantCallsCount.replaceAll((k, v) -> new AtomicLong(0));\n    LOGGER.info(\"reset counters\");\n  }\n}\n"
  },
  {
    "path": "throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.throttling.timer;\n\nimport com.iluwatar.throttling.CallsCount;\nimport java.util.Timer;\nimport java.util.TimerTask;\n\n/** Implementation of throttler interface. This class resets the counter every second. */\npublic class ThrottleTimerImpl implements Throttler {\n\n  private final int throttlePeriod;\n  private final CallsCount callsCount;\n\n  public ThrottleTimerImpl(int throttlePeriod, CallsCount callsCount) {\n    this.throttlePeriod = throttlePeriod;\n    this.callsCount = callsCount;\n  }\n\n  /** A timer is initiated with this method. The timer runs every second and resets the counter. */\n  @Override\n  public void start() {\n    new Timer(true)\n        .schedule(\n            new TimerTask() {\n              @Override\n              public void run() {\n                callsCount.reset();\n              }\n            },\n            0,\n            throttlePeriod);\n  }\n}\n"
  },
  {
    "path": "throttling/src/main/java/com/iluwatar/throttling/timer/Throttler.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.throttling.timer;\n\n/** An interface for defining the structure of different types of throttling ways. */\npublic interface Throttler {\n\n  void start();\n}\n"
  },
  {
    "path": "throttling/src/test/java/com/iluwatar/throttling/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.throttling;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "throttling/src/test/java/com/iluwatar/throttling/BarCustomerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.throttling;\n\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nimport java.security.InvalidParameterException;\nimport org.junit.jupiter.api.Test;\n\n/** TenantTest to test the creation of Tenant with valid parameters. */\nclass BarCustomerTest {\n\n  @Test\n  void constructorTest() {\n    assertThrows(\n        InvalidParameterException.class, () -> new BarCustomer(\"sirBrave\", -1, new CallsCount()));\n  }\n}\n"
  },
  {
    "path": "throttling/src/test/java/com/iluwatar/throttling/BartenderTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.throttling;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport com.iluwatar.throttling.timer.Throttler;\nimport java.util.stream.IntStream;\nimport org.junit.jupiter.api.Test;\n\n/** B2BServiceTest class to test the B2BService */\nclass BartenderTest {\n\n  private final CallsCount callsCount = new CallsCount();\n\n  @Test\n  void dummyCustomerApiTest() {\n    var tenant = new BarCustomer(\"pirate\", 2, callsCount);\n    // In order to assure that throttling limits will not be reset, we use an empty throttling\n    // implementation\n    var timer = (Throttler) () -> {};\n    var service = new Bartender(timer, callsCount);\n\n    IntStream.range(0, 5).mapToObj(i -> tenant).forEach(service::orderDrink);\n    var counter = callsCount.getCount(tenant.getName());\n    assertEquals(2, counter, \"Counter limit must be reached\");\n  }\n}\n"
  },
  {
    "path": "tolerant-reader/README.md",
    "content": "---\ntitle: \"Tolerant Reader Pattern in Java: Enhancing API Resilience and Compatibility\"\nshortTitle: Tolerant Reader\ndescription: \"Discover how the Tolerant Reader pattern can boost your API's resilience by ignoring unrecognized data, ensuring backward compatibility and seamless integration. Learn through examples and best practices on implementing this robust communication mechanism.\"\ncategory: Resilience\nlanguage: en\ntag:\n  - API design\n  - Decoupling\n  - Fault tolerance\n  - Integration\n---\n\n## Also known as\n\n* Lenient Consumer\n\n## Intent of Tolerant Reader Design Pattern\n\nThe Tolerant Reader pattern enhances system resilience to changes in data structures by strategically ignoring unrecognized elements, promoting robust API design.\n\n## Detailed Explanation of Tolerant Reader Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine a postal system that delivers letters and packages to recipients. In this system, postal workers deliver mail regardless of additional information or stickers that might be present on the envelopes or packages. If a package has extra labels or instructions that the postal system does not recognize, the postal worker ignores these and focuses only on the essential information like the address. This approach ensures that the delivery process remains functional even when senders use different formats or include unnecessary details, similar to how the Tolerant Reader pattern works in software by ignoring unrecognized data elements to maintain functionality and compatibility.\n\nIn plain words\n\n> Utilize the Tolerant Reader pattern to establish robust and resilient communication between services, ensuring data compatibility and integration.\n\n[Robustness Principle](https://java-design-patterns.com/principles/#robustness-principle) says\n\n> Be conservative in what you do, be liberal in what you accept from others.\n\nSequence diagram\n\n![Tolerant Reader sequence diagrams](./etc/tolerant-reader-sequence-diagram.png)\n\n## Programmatic Example of Tolerant Reader Pattern in Java\n\nWe are persisting `RainbowFish` objects to file. Later on they need to be restored. What makes it problematic is that `RainbowFish` data structure is versioned and evolves over time. New version of `RainbowFish` needs to be able to restore old versions as well.\n\nHere's the versioned `RainbowFish`. Notice how the second version introduces additional properties.\n\n```java\n@Getter\n@RequiredArgsConstructor\npublic class RainbowFish implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    private final String name;\n    private final int age;\n    private final int lengthMeters;\n    private final int weightTons;\n}\n```\n\n```java\n@Getter\npublic class RainbowFishV2 extends RainbowFish {\n\n    @Serial\n    private static final long serialVersionUID = 1L;\n\n    private boolean sleeping;\n    private boolean hungry;\n    private boolean angry;\n\n    public RainbowFishV2(String name, int age, int lengthMeters, int weightTons) {\n        super(name, age, lengthMeters, weightTons);\n    }\n\n    public RainbowFishV2(String name, int age, int lengthMeters, int weightTons, boolean sleeping,\n                         boolean hungry, boolean angry) {\n        this(name, age, lengthMeters, weightTons);\n        this.sleeping = sleeping;\n        this.hungry = hungry;\n        this.angry = angry;\n    }\n}\n```\n\nNext we introduce the `RainbowFishSerializer`. This is the class that implements the Tolerant Reader pattern.\n\n```java\n@NoArgsConstructor\npublic final class RainbowFishSerializer {\n\n    public static void writeV1(RainbowFish rainbowFish, String filename) throws IOException {\n        var map = Map.of(\n                \"name\", rainbowFish.getName(),\n                \"age\", String.format(\"%d\", rainbowFish.getAge()),\n                \"lengthMeters\", String.format(\"%d\", rainbowFish.getLengthMeters()),\n                \"weightTons\", String.format(\"%d\", rainbowFish.getWeightTons())\n        );\n\n        try (var fileOut = new FileOutputStream(filename);\n             var objOut = new ObjectOutputStream(fileOut)) {\n            objOut.writeObject(map);\n        }\n    }\n\n    public static void writeV2(RainbowFishV2 rainbowFish, String filename) throws IOException {\n        var map = Map.of(\n                \"name\", rainbowFish.getName(),\n                \"age\", String.format(\"%d\", rainbowFish.getAge()),\n                \"lengthMeters\", String.format(\"%d\", rainbowFish.getLengthMeters()),\n                \"weightTons\", String.format(\"%d\", rainbowFish.getWeightTons()),\n                \"angry\", Boolean.toString(rainbowFish.getAngry()),\n                \"hungry\", Boolean.toString(rainbowFish.getHungry()),\n                \"sleeping\", Boolean.toString(rainbowFish.getSleeping())\n        );\n\n        try (var fileOut = new FileOutputStream(filename);\n             var objOut = new ObjectOutputStream(fileOut)) {\n            objOut.writeObject(map);\n        }\n    }\n\n    public static RainbowFish readV1(String filename) throws IOException, ClassNotFoundException {\n        Map<String, String> map;\n\n        try (var fileIn = new FileInputStream(filename);\n             var objIn = new ObjectInputStream(fileIn)) {\n            map = (Map<String, String>) objIn.readObject();\n        }\n\n        return new RainbowFish(\n                map.get(\"name\"),\n                Integer.parseInt(map.get(\"age\")),\n                Integer.parseInt(map.get(\"lengthMeters\")),\n                Integer.parseInt(map.get(\"weightTons\"))\n        );\n    }\n}\n```\n\nAnd finally, here's the full example in action.\n\n```java\npublic static void main(String[] args) throws IOException, ClassNotFoundException {\n    // Write V1\n    var fishV1 = new RainbowFish(\"Zed\", 10, 11, 12);\n    LOGGER.info(\"fishV1 name={} age={} length={} weight={}\", fishV1.getName(),\n            fishV1.getAge(), fishV1.getLengthMeters(), fishV1.getWeightTons());\n    RainbowFishSerializer.writeV1(fishV1, \"fish1.out\");\n    // Read V1\n    var deserializedRainbowFishV1 = RainbowFishSerializer.readV1(\"fish1.out\");\n    LOGGER.info(\"deserializedFishV1 name={} age={} length={} weight={}\",\n            deserializedRainbowFishV1.getName(), deserializedRainbowFishV1.getAge(),\n            deserializedRainbowFishV1.getLengthMeters(), deserializedRainbowFishV1.getWeightTons());\n    // Write V2\n    var fishV2 = new RainbowFishV2(\"Scar\", 5, 12, 15, true, true, true);\n    LOGGER.info(\n            \"fishV2 name={} age={} length={} weight={} sleeping={} hungry={} angry={}\",\n            fishV2.getName(), fishV2.getAge(), fishV2.getLengthMeters(), fishV2.getWeightTons(),\n            fishV2.isHungry(), fishV2.isAngry(), fishV2.isSleeping());\n    RainbowFishSerializer.writeV2(fishV2, \"fish2.out\");\n    // Read V2 with V1 method\n    var deserializedFishV2 = RainbowFishSerializer.readV1(\"fish2.out\");\n    LOGGER.info(\"deserializedFishV2 name={} age={} length={} weight={}\",\n            deserializedFishV2.getName(), deserializedFishV2.getAge(),\n            deserializedFishV2.getLengthMeters(), deserializedFishV2.getWeightTons());\n}\n```\n\nProgram output:\n\n```\n15:38:00.602 [main] INFO com.iluwatar.tolerantreader.App -- fishV1 name=Zed age=10 length=11 weight=12\n15:38:00.618 [main] INFO com.iluwatar.tolerantreader.App -- deserializedFishV1 name=Zed age=10 length=11 weight=12\n15:38:00.618 [main] INFO com.iluwatar.tolerantreader.App -- fishV2 name=Scar age=5 length=12 weight=15 sleeping=true hungry=true angry=true\n15:38:00.619 [main] INFO com.iluwatar.tolerantreader.App -- deserializedFishV2 name=Scar age=5 length=12 weight=15\n```\n\n## When to Use the Tolerant Reader Pattern in Java\n\n* Apply the Tolerant Reader pattern when your system consumes data from evolving external sources, maintaining efficiency and data integrity.\n* Applicable when backward compatibility is required in API design.\n* Suitable for integration scenarios where different systems exchange data and evolve independently.\n\n## Real-World Applications of Tolerant Reader Pattern in Java\n\n* JSON or XML parsers that skip unknown elements.\n* API clients in microservices architectures that interact with multiple versions of a service.\n\n## Benefits and Trade-offs of Tolerant Reader Pattern\n\nBenefits:\n\n* Increases the robustness and flexibility of the system.\n* Allows independent evolution of producers and consumers in a distributed system.\n* Simplifies versioning by enabling backward compatibility.\n\nTrade-offs:\n\n* May result in silent failures if important data is ignored.\n* Can complicate debugging and tracing of issues due to missing or unrecognized data.\n\n## Related Java Design Patterns\n\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): Both patterns deal with data transformation and integration, but the Adapter Pattern focuses on converting interfaces, while Tolerant Reader focuses on ignoring unrecognized data.\n* [Facade](https://java-design-patterns.com/patterns/facade/): Simplifies interactions with complex systems, similar to how Tolerant Reader simplifies data consumption by ignoring irrelevant data.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Can be used in conjunction with Tolerant Reader to dynamically switch between different data handling strategies.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Service Design Patterns: Fundamental Design Solutions for SOAP/WSDL and RESTful Web Services](https://amzn.to/4dNIfOx)\n* [Tolerant Reader (Martin Fowler)](http://martinfowler.com/bliki/TolerantReader.html)\n"
  },
  {
    "path": "tolerant-reader/etc/tolerant-reader.urm.puml",
    "content": "@startuml\npackage com.iluwatar.tolerantreader {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class RainbowFish {\n    - age : int\n    - lengthMeters : int\n    - name : String\n    - serialVersionUID : long {static}\n    - weightTons : int\n    + RainbowFish(name : String, age : int, lengthMeters : int, weightTons : int)\n    + getAge() : int\n    + getLengthMeters() : int\n    + getName() : String\n    + getWeightTons() : int\n  }\n  class RainbowFishSerializer {\n    - RainbowFishSerializer()\n    + readV1(filename : String) : RainbowFish {static}\n    + writeV1(rainbowFish : RainbowFish, filename : String) {static}\n    + writeV2(rainbowFish : RainbowFishV2, filename : String) {static}\n  }\n  class RainbowFishV2 {\n    - angry : boolean\n    - hungry : boolean\n    - serialVersionUID : long {static}\n    - sleeping : boolean\n    + RainbowFishV2(name : String, age : int, lengthMeters : int, weightTons : int)\n    + RainbowFishV2(name : String, age : int, lengthMeters : int, weightTons : int, sleeping : boolean, hungry : boolean, angry : boolean)\n    + getAngry() : boolean\n    + getHungry() : boolean\n    + getSleeping() : boolean\n  }\n}\nRainbowFishV2 --|> RainbowFish \n@enduml"
  },
  {
    "path": "tolerant-reader/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>tolerant-reader</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.tolerantreader.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "tolerant-reader/src/main/java/com/iluwatar/tolerantreader/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tolerantreader;\n\nimport java.io.IOException;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Tolerant Reader is an integration pattern that helps to create robust communication systems. The\n * idea is to be as tolerant as possible when reading data from another service. This way, when the\n * communication schema changes, the readers must not break.\n *\n * <p>In this example we use Java serialization to write representations of {@link RainbowFish}\n * objects to file. {@link RainbowFish} is the initial version which we can easily read and write\n * using {@link RainbowFishSerializer} methods. {@link RainbowFish} then evolves to {@link\n * RainbowFishV2} and we again write it to file with a method designed to do just that. However, the\n * reader client does not know about the new format and still reads with the method designed for V1\n * schema. Fortunately the reading method has been designed with the Tolerant Reader pattern and\n * does not break even though {@link RainbowFishV2} has new fields that are serialized.\n */\n@Slf4j\npublic class App {\n\n  /** Program entry point. */\n  public static void main(String[] args) throws IOException, ClassNotFoundException {\n    // Write V1\n    var fishV1 = new RainbowFish(\"Zed\", 10, 11, 12);\n    LOGGER.info(\n        \"fishV1 name={} age={} length={} weight={}\",\n        fishV1.getName(),\n        fishV1.getAge(),\n        fishV1.getLengthMeters(),\n        fishV1.getWeightTons());\n    RainbowFishSerializer.writeV1(fishV1, \"fish1.out\");\n    // Read V1\n    var deserializedRainbowFishV1 = RainbowFishSerializer.readV1(\"fish1.out\");\n    LOGGER.info(\n        \"deserializedFishV1 name={} age={} length={} weight={}\",\n        deserializedRainbowFishV1.getName(),\n        deserializedRainbowFishV1.getAge(),\n        deserializedRainbowFishV1.getLengthMeters(),\n        deserializedRainbowFishV1.getWeightTons());\n    // Write V2\n    var fishV2 = new RainbowFishV2(\"Scar\", 5, 12, 15, true, true, true);\n    LOGGER.info(\n        \"fishV2 name={} age={} length={} weight={} sleeping={} hungry={} angry={}\",\n        fishV2.getName(),\n        fishV2.getAge(),\n        fishV2.getLengthMeters(),\n        fishV2.getWeightTons(),\n        fishV2.isHungry(),\n        fishV2.isAngry(),\n        fishV2.isSleeping());\n    RainbowFishSerializer.writeV2(fishV2, \"fish2.out\");\n    // Read V2 with V1 method\n    var deserializedFishV2 = RainbowFishSerializer.readV1(\"fish2.out\");\n    LOGGER.info(\n        \"deserializedFishV2 name={} age={} length={} weight={}\",\n        deserializedFishV2.getName(),\n        deserializedFishV2.getAge(),\n        deserializedFishV2.getLengthMeters(),\n        deserializedFishV2.getWeightTons());\n  }\n}\n"
  },
  {
    "path": "tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFish.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tolerantreader;\n\nimport java.io.Serial;\nimport java.io.Serializable;\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/** RainbowFish is the initial schema. */\n@Getter\n@RequiredArgsConstructor\npublic class RainbowFish implements Serializable {\n\n  @Serial private static final long serialVersionUID = 1L;\n\n  private final String name;\n  private final int age;\n  private final int lengthMeters;\n  private final int weightTons;\n}\n"
  },
  {
    "path": "tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishSerializer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tolerantreader;\n\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.ObjectInputStream;\nimport java.io.ObjectOutputStream;\nimport java.util.Map;\nimport lombok.NoArgsConstructor;\n\n/**\n * RainbowFishSerializer provides methods for reading and writing {@link RainbowFish} objects to\n * file. Tolerant Reader pattern is implemented here by serializing maps instead of {@link\n * RainbowFish} objects. This way the reader does not break even though new properties are added to\n * the schema.\n */\n@NoArgsConstructor\npublic final class RainbowFishSerializer {\n\n  public static final String LENGTH_METERS = \"lengthMeters\";\n  public static final String WEIGHT_TONS = \"weightTons\";\n\n  /** Write V1 RainbowFish to file. */\n  public static void writeV1(RainbowFish rainbowFish, String filename) throws IOException {\n    var map =\n        Map.of(\n            \"name\",\n            rainbowFish.getName(),\n            \"age\",\n            String.format(\"%d\", rainbowFish.getAge()),\n            LENGTH_METERS,\n            String.format(\"%d\", rainbowFish.getLengthMeters()),\n            WEIGHT_TONS,\n            String.format(\"%d\", rainbowFish.getWeightTons()));\n\n    try (var fileOut = new FileOutputStream(filename);\n        var objOut = new ObjectOutputStream(fileOut)) {\n      objOut.writeObject(map);\n    }\n  }\n\n  /** Write V2 RainbowFish to file. */\n  public static void writeV2(RainbowFishV2 rainbowFish, String filename) throws IOException {\n    var map =\n        Map.of(\n            \"name\",\n            rainbowFish.getName(),\n            \"age\",\n            String.format(\"%d\", rainbowFish.getAge()),\n            LENGTH_METERS,\n            String.format(\"%d\", rainbowFish.getLengthMeters()),\n            WEIGHT_TONS,\n            String.format(\"%d\", rainbowFish.getWeightTons()),\n            \"angry\",\n            Boolean.toString(rainbowFish.isAngry()),\n            \"hungry\",\n            Boolean.toString(rainbowFish.isHungry()),\n            \"sleeping\",\n            Boolean.toString(rainbowFish.isSleeping()));\n\n    try (var fileOut = new FileOutputStream(filename);\n        var objOut = new ObjectOutputStream(fileOut)) {\n      objOut.writeObject(map);\n    }\n  }\n\n  /** Read V1 RainbowFish from file. */\n  public static RainbowFish readV1(String filename) throws IOException, ClassNotFoundException {\n    Map<String, String> map;\n\n    try (var fileIn = new FileInputStream(filename);\n        var objIn = new ObjectInputStream(fileIn)) {\n      map = (Map<String, String>) objIn.readObject();\n    }\n\n    return new RainbowFish(\n        map.get(\"name\"),\n        Integer.parseInt(map.get(\"age\")),\n        Integer.parseInt(map.get(LENGTH_METERS)),\n        Integer.parseInt(map.get(WEIGHT_TONS)));\n  }\n}\n"
  },
  {
    "path": "tolerant-reader/src/main/java/com/iluwatar/tolerantreader/RainbowFishV2.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tolerantreader;\n\nimport java.io.Serial;\nimport lombok.Getter;\n\n/** RainbowFishV2 is the evolved schema. */\n@Getter\npublic class RainbowFishV2 extends RainbowFish {\n\n  @Serial private static final long serialVersionUID = 1L;\n\n  private boolean sleeping;\n  private boolean hungry;\n  private boolean angry;\n\n  public RainbowFishV2(String name, int age, int lengthMeters, int weightTons) {\n    super(name, age, lengthMeters, weightTons);\n  }\n\n  /** Constructor. */\n  public RainbowFishV2(\n      String name,\n      int age,\n      int lengthMeters,\n      int weightTons,\n      boolean sleeping,\n      boolean hungry,\n      boolean angry) {\n    this(name, age, lengthMeters, weightTons);\n    this.sleeping = sleeping;\n    this.hungry = hungry;\n    this.angry = angry;\n  }\n}\n"
  },
  {
    "path": "tolerant-reader/src/test/java/com/iluwatar/tolerantreader/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tolerantreader;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport java.io.File;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n\n  @BeforeEach\n  @AfterEach\n  void cleanup() {\n    var file1 = new File(\"fish1.out\");\n    file1.delete();\n    var file2 = new File(\"fish2.out\");\n    file2.delete();\n  }\n}\n"
  },
  {
    "path": "tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishSerializerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tolerantreader;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotSame;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.io.TempDir;\n\n/** RainbowFishSerializerTest */\nclass RainbowFishSerializerTest {\n\n  /** Create a temporary folder, used to generate files in during this test */\n  @TempDir static Path testFolder;\n\n  @BeforeEach\n  void beforeEach() {\n    assertTrue(Files.isDirectory(testFolder));\n  }\n\n  /** Rainbow fish version 1 used during the tests */\n  private static final RainbowFish V1 = new RainbowFish(\"version1\", 1, 2, 3);\n\n  /** Rainbow fish version 2 used during the tests */\n  private static final RainbowFishV2 V2 = new RainbowFishV2(\"version2\", 4, 5, 6, true, false, true);\n\n  /** Verify if a fish, written as version 1 can be read back as version 1 */\n  @Test\n  void testWriteV1ReadV1() throws Exception {\n    final var outputPath = Files.createFile(testFolder.resolve(\"outputFile\"));\n    RainbowFishSerializer.writeV1(V1, outputPath.toString());\n\n    final var fish = RainbowFishSerializer.readV1(outputPath.toString());\n    assertNotSame(V1, fish);\n    assertEquals(V1.getName(), fish.getName());\n    assertEquals(V1.getAge(), fish.getAge());\n    assertEquals(V1.getLengthMeters(), fish.getLengthMeters());\n    assertEquals(V1.getWeightTons(), fish.getWeightTons());\n  }\n\n  /** Verify if a fish, written as version 2 can be read back as version 1 */\n  @Test\n  void testWriteV2ReadV1() throws Exception {\n    final var outputPath = Files.createFile(testFolder.resolve(\"outputFile2\"));\n    RainbowFishSerializer.writeV2(V2, outputPath.toString());\n\n    final var fish = RainbowFishSerializer.readV1(outputPath.toString());\n    assertNotSame(V2, fish);\n    assertEquals(V2.getName(), fish.getName());\n    assertEquals(V2.getAge(), fish.getAge());\n    assertEquals(V2.getLengthMeters(), fish.getLengthMeters());\n    assertEquals(V2.getWeightTons(), fish.getWeightTons());\n  }\n}\n"
  },
  {
    "path": "tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tolerantreader;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** RainbowFishTest */\nclass RainbowFishTest {\n\n  /** Verify if the getters of a {@link RainbowFish} return the expected values */\n  @Test\n  void testValues() {\n    final var fish = new RainbowFish(\"name\", 1, 2, 3);\n    assertEquals(\"name\", fish.getName());\n    assertEquals(1, fish.getAge());\n    assertEquals(2, fish.getLengthMeters());\n    assertEquals(3, fish.getWeightTons());\n  }\n}\n"
  },
  {
    "path": "tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishV2Test.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.tolerantreader;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.Test;\n\n/** RainbowFishV2Test */\nclass RainbowFishV2Test {\n\n  /** Verify if the getters of a {@link RainbowFish} return the expected values */\n  @Test\n  void testValues() {\n    final var fish = new RainbowFishV2(\"name\", 1, 2, 3, false, true, false);\n    assertEquals(\"name\", fish.getName());\n    assertEquals(1, fish.getAge());\n    assertEquals(2, fish.getLengthMeters());\n    assertEquals(3, fish.getWeightTons());\n    assertFalse(fish.isSleeping());\n    assertTrue(fish.isHungry());\n    assertFalse(fish.isAngry());\n  }\n}\n"
  },
  {
    "path": "trampoline/.gitignore",
    "content": "/target/\n.idea/\n"
  },
  {
    "path": "trampoline/README.md",
    "content": "---\ntitle: \"Trampoline Pattern in Java: Mastering Recursion Without Stack Overflow\"\nshortTitle: Trampoline\ndescription: \"Discover how to implement the Trampoline pattern in Java to efficiently manage recursive functions and prevent stack overflow errors, with real-world examples and programming insights.\"\ncategory: Functional\nlanguage: en\ntag:\n  - Code simplification\n  - Functional decomposition\n  - Performance\n  - Recursion\n---\n\n## Also known as\n\n* Bounce\n* Tail-Call Optimization\n\n## Intent of Trampoline Design Pattern\n\nThe Trampoline Pattern in Java optimizes recursive function calls by converting them into iterative loops, avoiding stack overflow errors.\n\n## Detailed Explanation of Trampoline Pattern with Real-World Examples\n\nReal-world example\n\n> Imagine you are organizing a relay race. Each runner passes the baton to the next runner until the race is complete. However, if each runner had to physically run back to the starting line to pass the baton to the next runner, the race would be inefficient and error-prone. Instead, runners pass the baton directly to the next runner in line, who continues the race seamlessly.\n>\n> The Trampoline pattern in programming works similarly by ensuring that each recursive step is handed off efficiently without having to return to the start, preventing a stack overflow (similar to our runners never having to backtrack).\n\nIn plain words\n\n> The Trampoline pattern in Java allows efficient recursion without running out of stack memory, optimizing deep recursive calls for better performance and stack safety.\n\nWikipedia says\n\n> In Java, trampoline refers to using reflection to avoid using inner classes, for example in event listeners. The time overhead of a reflection call is traded for the space overhead of an inner class. Trampolines in Java usually involve the creation of a GenericListener to pass events to an outer class.\n\nFlowchart\n\n![Trampoline Pattern Flowchart](./etc/trampoline-flowchart.png)\n\n## Programmatic Example of Trampoline Pattern in Java\n\nHere's the `Trampoline` implementation in Java.\n\nWhen `get` is called on the returned Trampoline, internally it will iterate calling `jump` on the returned `Trampoline` as long as the concrete instance returned is `Trampoline`, stopping once the returned instance is `done`.\n\n```java\npublic interface Trampoline<T> {\n\n  T get();\n\n  default Trampoline<T> jump() {\n    return this;\n  }\n\n  default T result() {\n    return get();\n  }\n\n  default boolean complete() {\n    return true;\n  }\n\n  static <T> Trampoline<T> done(final T result) {\n    return () -> result;\n  }\n\n  static <T> Trampoline<T> more(final Trampoline<Trampoline<T>> trampoline) {\n    return new Trampoline<T>() {\n      @Override\n      public boolean complete() {\n        return false;\n      }\n\n      @Override\n      public Trampoline<T> jump() {\n        return trampoline.result();\n      }\n\n      @Override\n      public T get() {\n        return trampoline(this);\n      }\n\n      T trampoline(final Trampoline<T> trampoline) {\n        return Stream.iterate(trampoline, Trampoline::jump)\n            .filter(Trampoline::complete)\n            .findFirst()\n            .map(Trampoline::result)\n            .orElseThrow();\n      }\n    };\n  }\n}\n```\n\nUsing the `Trampoline` to get Fibonacci values.\n\n```java\n@Slf4j\npublic class TrampolineApp {\n\n    public static void main(String[] args) {\n        LOGGER.info(\"Start calculating war casualties\");\n        var result = loop(10, 1).result();\n        LOGGER.info(\"The number of orcs perished in the war: {}\", result);\n\n    }\n\n    public static Trampoline<Integer> loop(int times, int prod) {\n        if (times == 0) {\n            return Trampoline.done(prod);\n        } else {\n            return Trampoline.more(() -> loop(times - 1, prod * times));\n        }\n    }\n}\n```\n\nProgram output:\n\n```\n19:22:24.462 [main] INFO com.iluwatar.trampoline.TrampolineApp - Start calculating war casualties\n19:22:24.472 [main] INFO com.iluwatar.trampoline.TrampolineApp - The number of orcs perished in the war: 3628800\n```\n\n## When to Use the Trampoline Pattern in Java\n\nUse the Trampoline pattern when\n\n* When dealing with algorithms that use recursion heavily and risk running into stack overflow errors.\n* When tail-call optimization is not supported by the Java language natively.\n\n## Trampoline Pattern Java Tutorials\n\n* [Laziness, trampolines, monoids and other functional amenities: This is not your father's Java(Mario Fusco)](https://www.slideshare.net/mariofusco/lazine)\n* [Trampoline.java (totallylazy)](https://github.com/bodar/totallylazy/blob/master/src/com/googlecode/totallylazy/Trampoline.java)\n* [Trampoline: Java Glossary (mindprod.com)](http://mindprod.com/jgloss/trampoline.html)\n* [Trampolining: A practical guide for awesome Java Developers (John McClean)](https://medium.com/@johnmcclean/trampolining-a-practical-guide-for-awesome-java-developers-4b657d9c3076)\n* [What is a trampoline function? (Stack Overflow)](https://stackoverflow.com/questions/189725/what-is-a-trampoline-function)\n\n## Real-World Applications of Trampoline Pattern in Java\n\n* Implementing algorithms that require deep recursion, such as certain tree traversals, combinatorial algorithms, and mathematical computations.\n* Functional programming libraries and frameworks where tail-call optimization is necessary for performance and stack safety.\n* [cyclops-react](https://github.com/aol/cyclops-react)\n\n## Benefits and Trade-offs of Trampoline Pattern\n\nBenefits:\n\n* Prevents stack overflow by converting deep recursion into iteration.\n* Enhances performance by avoiding the overhead of deep recursive calls.\n* Simplifies the code by making recursive calls look like a sequence of steps.\n\nTrade-offs:\n\n* May introduce additional complexity in terms of understanding and implementing the trampoline mechanism.\n* Requires converting naturally recursive algorithms into a continuation-passing style.\n\n## Related Java Design Patterns\n\n* [Iterator](https://java-design-patterns.com/patterns/iterator/): Both patterns aim to transform potentially recursive operations into iterative processes, though the iterator pattern is more general-purpose.\n* [State](https://java-design-patterns.com/patterns/state/): Like the Trampoline, the State pattern can also handle complex state transitions, which can sometimes involve recursive-like state changes.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): This pattern can be related in terms of defining a family of algorithms (or continuations in the case of the Trampoline) and making them interchangeable.\n\n## References and Credits\n\n* [Functional Programming in Java](https://amzn.to/3JUIc5Q)\n* [Functional Programming for Java Developers: Tools for Better Concurrency, Abstraction, and Agility](https://amzn.to/4dRu4rJ)\n* [Java 8 in Action: Lambdas, Streams, and functional-style programming](https://amzn.to/3QCmGXs)\n* [Modern Java in Action: Lambdas, streams, functional and reactive programming](https://amzn.to/3yxdu0g)\n"
  },
  {
    "path": "trampoline/etc/trampoline.urm.puml",
    "content": "@startuml\npackage com.iluwatar.trampoline {\n  interface Trampoline<T> {\n    + complete() : boolean\n    + done(result : T) : Trampoline<T> {static}\n    + get() : T {abstract}\n    + jump() : Trampoline<T>\n    + more(trampoline : Trampoline<Trampoline<T>>) : Trampoline<T> {static}\n    + result() : T\n  }\n  class TrampolineApp {\n    - log : Logger {static}\n    + TrampolineApp()\n    + loop(times : int, prod : int) : Trampoline<Integer> {static}\n    + main(args : String[]) {static}\n  }\n}\n@enduml"
  },
  {
    "path": "trampoline/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>trampoline</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-surefire-plugin</artifactId>\n        <configuration>\n          <skipTests>false</skipTests>\n        </configuration>\n      </plugin>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.trampoline.TrampolineApp</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "trampoline/src/main/java/com/iluwatar/trampoline/Trampoline.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.trampoline;\n\nimport java.util.stream.Stream;\n\n/**\n * Trampoline pattern allows to define recursive algorithms by iterative loop.\n *\n * <p>When get is called on the returned Trampoline, internally it will iterate calling ‘jump’ on\n * the returned Trampoline as long as the concrete instance returned is {@link #more(Trampoline)},\n * stopping once the returned instance is {@link #done(Object)}.\n *\n * <p>Essential we convert looping via recursion into iteration, the key enabling mechanism is the\n * fact that {@link #more(Trampoline)} is a lazy operation.\n *\n * @param <T> is type for returning result.\n */\npublic interface Trampoline<T> {\n  T get();\n\n  /**\n   * Jump to next stage.\n   *\n   * @return next stage\n   */\n  default Trampoline<T> jump() {\n    return this;\n  }\n\n  default T result() {\n    return get();\n  }\n\n  /**\n   * Checks if complete.\n   *\n   * @return true if complete\n   */\n  default boolean complete() {\n    return true;\n  }\n\n  /**\n   * Created a completed Trampoline.\n   *\n   * @param result Completed result\n   * @return Completed Trampoline\n   */\n  static <T> Trampoline<T> done(final T result) {\n    return () -> result;\n  }\n\n  /**\n   * Create a Trampoline that has more work to do.\n   *\n   * @param trampoline Next stage in Trampoline\n   * @return Trampoline with more work\n   */\n  static <T> Trampoline<T> more(final Trampoline<Trampoline<T>> trampoline) {\n    return new Trampoline<T>() {\n      @Override\n      public boolean complete() {\n        return false;\n      }\n\n      @Override\n      public Trampoline<T> jump() {\n        return trampoline.result();\n      }\n\n      @Override\n      public T get() {\n        return trampoline(this);\n      }\n\n      T trampoline(final Trampoline<T> trampoline) {\n        return Stream.iterate(trampoline, Trampoline::jump)\n            .filter(Trampoline::complete)\n            .findFirst()\n            .map(Trampoline::result)\n            .get();\n      }\n    };\n  }\n}\n"
  },
  {
    "path": "trampoline/src/main/java/com/iluwatar/trampoline/TrampolineApp.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.trampoline;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Trampoline pattern allows to define recursive algorithms by iterative loop.\n *\n * <p>It is possible to implement algorithms recursively in Java without blowing the stack and to\n * interleave the execution of functions without hard coding them together or even using threads.\n */\n@Slf4j\npublic class TrampolineApp {\n\n  /** Main program for showing pattern. It does loop with factorial function. */\n  public static void main(String[] args) {\n    LOGGER.info(\"Start calculating war casualties\");\n    var result = loop(10, 1).result();\n    LOGGER.info(\"The number of orcs perished in the war: {}\", result);\n  }\n\n  /** Manager for pattern. Define it with a factorial function. */\n  public static Trampoline<Integer> loop(int times, int prod) {\n    if (times == 0) {\n      return Trampoline.done(prod);\n    } else {\n      return Trampoline.more(() -> loop(times - 1, prod * times));\n    }\n  }\n}\n"
  },
  {
    "path": "trampoline/src/test/java/com/iluwatar/trampoline/TrampolineAppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.trampoline;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Test for trampoline pattern. */\nclass TrampolineAppTest {\n\n  @Test\n  void testTrampolineWithFactorialFunction() {\n    long result = TrampolineApp.loop(10, 1).result();\n    assertEquals(3_628_800, result);\n  }\n}\n"
  },
  {
    "path": "transaction-script/.gitignore",
    "content": "/target/\n.idea/\n"
  },
  {
    "path": "transaction-script/README.md",
    "content": "---\ntitle: \"Transaction Script Pattern in Java: Simplifying Business Logic with Consolidated Scripts\"\nshortTitle: Transaction Script\ndescription: \"Explore the Transaction Script design pattern for Java applications. Learn how to organize simple business logic into efficient scripts with real-world examples and improve your coding efficiency.\"\ncategory: Data access\nlanguage: en\ntag:\n  - Business\n  - Data access\n  - Domain\n  - Persistence\n  - Transactions\n---\n\n## Also known as\n\n* Scripted Transactions\n\n## Intent of Transaction Script Design Pattern\n\nThe Transaction Script pattern in Java organizes business logic by procedures where each procedure handles a single request from the presentation.\n\n## Detailed Explanation of Transaction Script Pattern with Real-World Examples\n\nReal-world example\n\n> An analogous real-world example of the Transaction Script design pattern can be seen in a bank teller's daily operations. Imagine a bank where each transaction, such as depositing money, withdrawing cash, or transferring funds between accounts, is handled by a specific script-like procedure. Each procedure takes in the necessary details (e.g., account numbers, amounts) and performs the transaction in a straightforward, step-by-step manner. This ensures that each transaction is processed correctly and independently, without the need for a complex system of rules and interactions. This simple, organized approach allows bank tellers to efficiently manage a variety of transactions throughout the day. \n\nIn plain words\n\n> Transaction Script organizes business logic into transactions that the system needs to carry out.\n\nWikipedia says\n\n> The Transaction Script design pattern is a straightforward way to organize business logic in applications, particularly suitable for scenarios where each request from the presentation layer can be handled by a single procedure. This pattern is often used in simple applications or in systems where rapid development and ease of understanding are crucial. Each transaction script is responsible for a particular task, such as processing an order or calculating a result, and typically interacts directly with the database.\n\nFlowchart\n\n![Transaction Script Pattern Flowchart](./etc/transaction-script-flowchart.png)\n\n## Programmatic Example of Transaction Script Pattern in Java\n\nOur Transaction Script pattern in Java example is about booking hotel rooms.\n\nThe `Hotel` class takes care of booking and cancelling room reservations.\n\n```java\n@Slf4j\npublic class Hotel {\n\n  private final HotelDaoImpl hotelDao;\n\n  public Hotel(HotelDaoImpl hotelDao) {\n    this.hotelDao = hotelDao;\n  }\n\n  public void bookRoom(int roomNumber) throws Exception {\n\n    Optional<Room> room = hotelDao.getById(roomNumber);\n\n    if (room.isEmpty()) {\n      throw new Exception(\"Room number: \" + roomNumber + \" does not exist\");\n    } else {\n      if (room.get().isBooked()) {\n        throw new Exception(\"Room already booked!\");\n      } else {\n        Room updateRoomBooking = room.get();\n        updateRoomBooking.setBooked(true);\n        hotelDao.update(updateRoomBooking);\n      }\n    }\n  }\n\n  public void cancelRoomBooking(int roomNumber) throws Exception {\n\n    Optional<Room> room = hotelDao.getById(roomNumber);\n\n    if (room.isEmpty()) {\n      throw new Exception(\"Room number: \" + roomNumber + \" does not exist\");\n    } else {\n      if (room.get().isBooked()) {\n        Room updateRoomBooking = room.get();\n        updateRoomBooking.setBooked(false);\n        int refundAmount = updateRoomBooking.getPrice();\n        hotelDao.update(updateRoomBooking);\n\n        LOGGER.info(\"Booking cancelled for room number: \" + roomNumber);\n        LOGGER.info(refundAmount + \" is refunded\");\n      } else {\n        throw new Exception(\"No booking for the room exists\");\n      }\n    }\n  }\n}\n```\n\nThe `Hotel` class has two methods, one for booking and cancelling a room respectively. Each one of them handles a single transaction in the system, making `Hotel` implement the Transaction Script pattern.\n\nThe `bookRoom` method consolidates all the needed steps like checking if the room is already booked or not, if not booked then books the room and updates the database by using the DAO. \n\nThe `cancelRoom` method consolidates steps like checking if the room is booked or not, if booked then calculates the refund amount and updates the database using the DAO.\n\nHere is the `App` class with `main` method for running the example.\n\n```java\npublic class App {\n\n  private static final String H2_DB_URL = \"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1\";\n  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n  public static void main(String[] args) throws Exception {\n\n    final var dataSource = createDataSource();\n    deleteSchema(dataSource);\n    createSchema(dataSource);\n    final var dao = new HotelDaoImpl(dataSource);\n\n    // Add rooms\n    addRooms(dao);\n\n    // Print room booking status\n    getRoomStatus(dao);\n\n    var hotel = new Hotel(dao);\n\n    // Book rooms\n    hotel.bookRoom(1);\n    hotel.bookRoom(2);\n    hotel.bookRoom(3);\n    hotel.bookRoom(4);\n    hotel.bookRoom(5);\n    hotel.bookRoom(6);\n\n    // Cancel booking for a few rooms\n    hotel.cancelRoomBooking(1);\n    hotel.cancelRoomBooking(3);\n    hotel.cancelRoomBooking(5);\n\n    getRoomStatus(dao);\n\n    deleteSchema(dataSource);\n  }\n\n  private static void getRoomStatus(HotelDaoImpl dao) throws Exception {\n    try (var customerStream = dao.getAll()) {\n      customerStream.forEach((customer) -> LOGGER.info(customer.toString()));\n    }\n  }\n\n  private static void deleteSchema(DataSource dataSource) throws java.sql.SQLException {\n    try (var connection = dataSource.getConnection();\n         var statement = connection.createStatement()) {\n      statement.execute(RoomSchemaSql.DELETE_SCHEMA_SQL);\n    }\n  }\n\n  private static void createSchema(DataSource dataSource) throws Exception {\n    try (var connection = dataSource.getConnection();\n         var statement = connection.createStatement()) {\n      statement.execute(RoomSchemaSql.CREATE_SCHEMA_SQL);\n    } catch (Exception e) {\n      throw new Exception(e.getMessage(), e);\n    }\n  }\n\n  private static DataSource createDataSource() {\n    var dataSource = new JdbcDataSource();\n    dataSource.setUrl(H2_DB_URL);\n    return dataSource;\n  }\n\n  private static void addRooms(HotelDaoImpl hotelDao) throws Exception {\n    for (var room : generateSampleRooms()) {\n      hotelDao.add(room);\n    }\n  }\n\n  private static List<Room> generateSampleRooms() {\n    final var room1 = new Room(1, \"Single\", 50, false);\n    final var room2 = new Room(2, \"Double\", 80, false);\n    final var room3 = new Room(3, \"Queen\", 120, false);\n    final var room4 = new Room(4, \"King\", 150, false);\n    final var room5 = new Room(5, \"Single\", 50, false);\n    final var room6 = new Room(6, \"Double\", 80, false);\n    return List.of(room1, room2, room3, room4, room5, room6);\n  }\n}\n```\n\nThe `App.java` file has the `main` entry point of the application. It demonstrates the use of the Transaction Script pattern in a hotel management context. Here's a step-by-step breakdown of what happens:\n\n1. A new H2 database data source is created using the `createDataSource()` method. This data source is used to interact with the in-memory H2 database.\n\n2. The existing schema (if any) in the database is deleted using the `deleteSchema(dataSource)` method. This is done to ensure a clean state before the application starts.\n\n3. A new schema is created in the database using the `createSchema(dataSource)` method. The schema includes the necessary tables and relationships for the application.\n\n4. An instance of `HotelDaoImpl` is created, which serves as the Data Access Object (DAO). This object is responsible for handling the database operations related to the hotel rooms.\n\n5. Sample rooms are added to the hotel using the `addRooms(dao)` method. This method generates a list of sample rooms and adds them to the hotel via the DAO.\n\n6. The booking status of all rooms is printed using the `getRoomStatus(dao)` method.\n\n7. An instance of `Hotel` is created with the DAO as a parameter. This object represents the hotel and provides methods to book and cancel room bookings.\n\n8. Several rooms are booked using the `hotel.bookRoom(roomNumber)` method.\n\n9. Some of the bookings are then cancelled using the `hotel.cancelRoomBooking(roomNumber)` method.\n\n10. The booking status of all rooms is printed again to reflect the changes.\n\n11. Finally, the schema in the database is deleted again using the `deleteSchema(dataSource)` method, cleaning up the state of the database.\n\nConsole output:\n\n```\n14:22:20.050 [main] INFO com.iluwatar.transactionscript.App -- Room(id=1, roomType=Single, price=50, booked=false)\n14:22:20.051 [main] INFO com.iluwatar.transactionscript.App -- Room(id=2, roomType=Double, price=80, booked=false)\n14:22:20.051 [main] INFO com.iluwatar.transactionscript.App -- Room(id=3, roomType=Queen, price=120, booked=false)\n14:22:20.051 [main] INFO com.iluwatar.transactionscript.App -- Room(id=4, roomType=King, price=150, booked=false)\n14:22:20.051 [main] INFO com.iluwatar.transactionscript.App -- Room(id=5, roomType=Single, price=50, booked=false)\n14:22:20.051 [main] INFO com.iluwatar.transactionscript.App -- Room(id=6, roomType=Double, price=80, booked=false)\n14:22:20.058 [main] INFO com.iluwatar.transactionscript.Hotel -- Booking cancelled for room number: 1\n14:22:20.058 [main] INFO com.iluwatar.transactionscript.Hotel -- 50 is refunded\n14:22:20.059 [main] INFO com.iluwatar.transactionscript.Hotel -- Booking cancelled for room number: 3\n14:22:20.059 [main] INFO com.iluwatar.transactionscript.Hotel -- 120 is refunded\n14:22:20.059 [main] INFO com.iluwatar.transactionscript.Hotel -- Booking cancelled for room number: 5\n14:22:20.059 [main] INFO com.iluwatar.transactionscript.Hotel -- 50 is refunded\n14:22:20.060 [main] INFO com.iluwatar.transactionscript.App -- Room(id=1, roomType=Single, price=50, booked=false)\n14:22:20.060 [main] INFO com.iluwatar.transactionscript.App -- Room(id=2, roomType=Double, price=80, booked=true)\n14:22:20.060 [main] INFO com.iluwatar.transactionscript.App -- Room(id=3, roomType=Queen, price=120, booked=false)\n14:22:20.060 [main] INFO com.iluwatar.transactionscript.App -- Room(id=4, roomType=King, price=150, booked=true)\n14:22:20.060 [main] INFO com.iluwatar.transactionscript.App -- Room(id=5, roomType=Single, price=50, booked=false)\n14:22:20.060 [main] INFO com.iluwatar.transactionscript.App -- Room(id=6, roomType=Double, price=80, booked=true)\n```\n\nThis pattern is suitable for simple business logic and can be easily understood and maintained.\n\n## When to Use the Transaction Script Pattern in Java\n\n* Use when business logic is simple and can be easily organized into individual procedures.\n* Suitable for applications with simple transaction requirements or where the logic doesn't justify complex architectures like Domain Model.\n\n## Transaction Script Pattern Java Tutorials\n\n* [Transaction Script Pattern (DZone)](https://dzone.com/articles/transaction-script-pattern#:~:text=Transaction%20Script%20(TS)%20is%20the,need%20big%20architecture%20behind%20them.)\n* [Transaction Script (InformIT)](https://www.informit.com/articles/article.aspx?p=1398617)\n\n## Real-World Applications of Transaction Script Pattern in Java\n\n* Early-stage startups and small-scale applications where rapid development is crucial.\n* Enterprise applications with well-defined procedures like banking transactions or e-commerce order processing.\n* Legacy systems where business logic is already written as scripts.\n\n## Benefits and Trade-offs of Transaction Script Pattern\n\nBenefits:\n\n* Leveraging the Transaction Script pattern enhances code simplicity and accelerates development cycles, especially in startup environments.\n* Simple and straightforward to implement.\n* Easy to understand and maintain for straightforward business logic.\n* Fast development cycle for small applications.\n\nTrade-offs:\n\n* Can lead to duplicated code if not carefully managed.\n* Not suitable for complex business logic; can become unmanageable as the application grows.\n* Harder to test in isolation compared to more structured approaches like Domain Model.\n\n## Related Java Design Patterns\n\n* [Domain Model](https://java-design-patterns.com/patterns/domain-model/): Unlike Transaction Script, Domain Model organizes business logic around the data model and is better suited for complex business rules.\n* [Service Layer](https://java-design-patterns.com/patterns/service-layer/): Often used together with Transaction Script to define an application's boundary and encapsulate the business logic.\n* [Table Module](https://java-design-patterns.com/patterns/table-module/): Similar to Transaction Script but organizes logic using a single class per table rather than a procedure per request.\n\n## References and Credits\n\n* [Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions](https://amzn.to/3WcFVui)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "transaction-script/etc/transaction-script.urm.puml",
    "content": "@startuml\npackage com.ashishtrivedi16.transaction-script {\n  class App {\n    - H2_DB_URL : String {static}\n    - LOGGER : Logger {static}\n    - addRooms(hotelDaoImpl : HotelDaoImpl) {static}\n    - createDataSource() : DataSource {static}\n    - createSchema(dataSource : DataSource) {static}\n    - deleteSchema(dataSource : DataSource) {static}\n    - getRoomsStatus(hotelDaoImpl : HotelDaoImpl) {static}\n    - generateSampleRooms() : List<Room> {static}\n    + main(args : String[]) {static}\n  }\n  class Room {\n    - id: Int\n    - roomType: String\n    - price: Int\n    - booked: Boolean\n    + Customer(id : int, roomType : String, price: Int, booked: Boolean)\n    + getId() : int\n    + getRoomType() : String\n    + getPrice() : Int\n    + isBooked() : Boolean\n    + setId(id : int)\n    + setRoomType(roomType : String)\n    + setPrice(price : Int)\n    + setBooked(booked : boolean)\n    + equals(that : Object) : boolean\n    + hashCode() : int\n    + toString() : String\n  }\n  interface HotelDao {\n    + add(Room) : boolean {abstract}\n    + delete(Room) : boolean {abstract}\n    + getAll() : Stream<Room> {abstract}\n    + getById(int) : Optional<Room> {abstract}\n    + update(Room) : boolean {abstract}\n  }\n  class RoomSchemaSql {\n    + CREATE_SCHEMA_SQL : String {static}\n    + DELETE_SCHEMA_SQL : String {static}\n    - RoomSchemaSql()\n  }\n  class HotelDaoImpl {\n    - dataSource : DataSource\n    + HotelDaoImpl(dataSource : DataSource)\n    + add(room : Room) : boolean\n    - createRoom(resultSet : ResultSet) : Room\n    + delete(room : Room) : boolean\n    + getAll() : Stream<Room>\n    + getById(id : int) : Optional<Room>\n    - getConnection() : Connection\n    - mutedClose(connection : Connection, statement : PreparedStatement, resultSet : ResultSet)\n    + update(room : Room) : boolean\n  }\n  class Hotel {\n  - LOGGER : Logger {static}\n  - hotelDao: HotelDaoImpl\n  + Hotel(hotelDao: HotelDaoImpl)\n  + bookRoom(roomNumber: Int)\n  + cancelRoomBooking(roomNumber: Int)\n  }\n}\nHotelDaoImpl ..|> HotelDao\n@enduml\n"
  },
  {
    "path": "transaction-script/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>transaction-script</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>com.h2database</groupId>\n      <artifactId>h2</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.transactionscript.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "transaction-script/src/main/java/com/iluwatar/transactionscript/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.transactionscript;\n\nimport java.util.List;\nimport javax.sql.DataSource;\nimport org.h2.jdbcx.JdbcDataSource;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Transaction Script (TS) is one of the simplest domain logic pattern. It needs less work to\n * implement than other domain logic patterns, and therefore it’s perfect fit for smaller\n * applications that don't need big architecture behind them.\n *\n * <p>In this example we will use the TS pattern to implement booking and cancellation methods for a\n * Hotel management App. The main method will initialise an instance of {@link Hotel} and add rooms\n * to it. After that it will book and cancel a couple of rooms and that will be printed by the\n * logger.\n *\n * <p>The thing we have to note here is that all the operations related to booking or cancelling a\n * room like checking the database if the room exists, checking the booking status or the room,\n * calculating refund price are all clubbed inside a single transaction script method.\n */\npublic class App {\n\n  private static final String H2_DB_URL = \"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1\";\n  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n  /**\n   * Program entry point. Initialises an instance of Hotel and adds rooms to it. Carries out booking\n   * and cancel booking transactions.\n   *\n   * @param args command line arguments\n   * @throws Exception if any error occurs\n   */\n  public static void main(String[] args) throws Exception {\n\n    final var dataSource = createDataSource();\n    deleteSchema(dataSource);\n    createSchema(dataSource);\n    final var dao = new HotelDaoImpl(dataSource);\n\n    // Add rooms\n    addRooms(dao);\n\n    // Print room booking status\n    getRoomStatus(dao);\n\n    var hotel = new Hotel(dao);\n\n    // Book rooms\n    hotel.bookRoom(1);\n    hotel.bookRoom(2);\n    hotel.bookRoom(3);\n    hotel.bookRoom(4);\n    hotel.bookRoom(5);\n    hotel.bookRoom(6);\n\n    // Cancel booking for a few rooms\n    hotel.cancelRoomBooking(1);\n    hotel.cancelRoomBooking(3);\n    hotel.cancelRoomBooking(5);\n\n    getRoomStatus(dao);\n\n    deleteSchema(dataSource);\n  }\n\n  private static void getRoomStatus(HotelDaoImpl dao) throws Exception {\n    try (var customerStream = dao.getAll()) {\n      customerStream.forEach((customer) -> LOGGER.info(customer.toString()));\n    }\n  }\n\n  private static void deleteSchema(DataSource dataSource) throws java.sql.SQLException {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(RoomSchemaSql.DELETE_SCHEMA_SQL);\n    }\n  }\n\n  private static void createSchema(DataSource dataSource) throws Exception {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(RoomSchemaSql.CREATE_SCHEMA_SQL);\n    } catch (Exception e) {\n      throw new Exception(e.getMessage(), e);\n    }\n  }\n\n  /**\n   * Get database.\n   *\n   * @return h2 datasource\n   */\n  private static DataSource createDataSource() {\n    var dataSource = new JdbcDataSource();\n    dataSource.setUrl(H2_DB_URL);\n    return dataSource;\n  }\n\n  private static void addRooms(HotelDaoImpl hotelDao) throws Exception {\n    for (var room : generateSampleRooms()) {\n      hotelDao.add(room);\n    }\n  }\n\n  /**\n   * Generate rooms.\n   *\n   * @return list of rooms\n   */\n  private static List<Room> generateSampleRooms() {\n    final var room1 = new Room(1, \"Single\", 50, false);\n    final var room2 = new Room(2, \"Double\", 80, false);\n    final var room3 = new Room(3, \"Queen\", 120, false);\n    final var room4 = new Room(4, \"King\", 150, false);\n    final var room5 = new Room(5, \"Single\", 50, false);\n    final var room6 = new Room(6, \"Double\", 80, false);\n    return List.of(room1, room2, room3, room4, room5, room6);\n  }\n}\n"
  },
  {
    "path": "transaction-script/src/main/java/com/iluwatar/transactionscript/Hotel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.transactionscript;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Hotel class to implement TS pattern. */\n@Slf4j\npublic class Hotel {\n\n  private final HotelDaoImpl hotelDao;\n\n  public Hotel(HotelDaoImpl hotelDao) {\n    this.hotelDao = hotelDao;\n  }\n\n  /**\n   * Book a room.\n   *\n   * @param roomNumber room to book\n   * @throws Exception if any error\n   */\n  public void bookRoom(int roomNumber) throws Exception {\n\n    var room = hotelDao.getById(roomNumber);\n\n    if (room.isEmpty()) {\n      throw new Exception(\"Room number: \" + roomNumber + \" does not exist\");\n    } else {\n      if (room.get().isBooked()) {\n        throw new Exception(\"Room already booked!\");\n      } else {\n        var updateRoomBooking = room.get();\n        updateRoomBooking.setBooked(true);\n        hotelDao.update(updateRoomBooking);\n      }\n    }\n  }\n\n  /**\n   * Cancel a room booking.\n   *\n   * @param roomNumber room to cancel booking\n   * @throws Exception if any error\n   */\n  public void cancelRoomBooking(int roomNumber) throws Exception {\n\n    var room = hotelDao.getById(roomNumber);\n\n    if (room.isEmpty()) {\n      throw new Exception(\"Room number: \" + roomNumber + \" does not exist\");\n    } else {\n      if (room.get().isBooked()) {\n        var updateRoomBooking = room.get();\n        updateRoomBooking.setBooked(false);\n        int refundAmount = updateRoomBooking.getPrice();\n        hotelDao.update(updateRoomBooking);\n\n        LOGGER.info(\"Booking cancelled for room number: \" + roomNumber);\n        LOGGER.info(refundAmount + \" is refunded\");\n      } else {\n        throw new Exception(\"No booking for the room exists\");\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "transaction-script/src/main/java/com/iluwatar/transactionscript/HotelDao.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.transactionscript;\n\nimport java.util.Optional;\nimport java.util.stream.Stream;\n\n/** DAO interface for hotel transactions. */\npublic interface HotelDao {\n\n  Stream<Room> getAll() throws Exception;\n\n  Optional<Room> getById(int id) throws Exception;\n\n  Boolean add(Room room) throws Exception;\n\n  Boolean update(Room room) throws Exception;\n\n  Boolean delete(Room room) throws Exception;\n}\n"
  },
  {
    "path": "transaction-script/src/main/java/com/iluwatar/transactionscript/HotelDaoImpl.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.transactionscript;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.util.Optional;\nimport java.util.Spliterator;\nimport java.util.Spliterators;\nimport java.util.function.Consumer;\nimport java.util.stream.Stream;\nimport java.util.stream.StreamSupport;\nimport javax.sql.DataSource;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Implementation of database operations for Hotel class. */\n@Slf4j\npublic class HotelDaoImpl implements HotelDao {\n\n  private final DataSource dataSource;\n\n  public HotelDaoImpl(DataSource dataSource) {\n    this.dataSource = dataSource;\n  }\n\n  @Override\n  public Stream<Room> getAll() throws Exception {\n    try {\n      var connection = getConnection();\n      var statement = connection.prepareStatement(\"SELECT * FROM ROOMS\"); // NOSONAR\n      var resultSet = statement.executeQuery(); // NOSONAR\n      return StreamSupport.stream(\n              new Spliterators.AbstractSpliterator<Room>(Long.MAX_VALUE, Spliterator.ORDERED) {\n\n                @Override\n                public boolean tryAdvance(Consumer<? super Room> action) {\n                  try {\n                    if (!resultSet.next()) {\n                      return false;\n                    }\n                    action.accept(createRoom(resultSet));\n                    return true;\n                  } catch (Exception e) {\n                    throw new RuntimeException(e); // NOSONAR\n                  }\n                }\n              },\n              false)\n          .onClose(\n              () -> {\n                try {\n                  mutedClose(connection, statement, resultSet);\n                } catch (Exception e) {\n                  LOGGER.error(e.getMessage());\n                }\n              });\n    } catch (Exception e) {\n      throw new Exception(e.getMessage(), e);\n    }\n  }\n\n  @Override\n  public Optional<Room> getById(int id) throws Exception {\n    ResultSet resultSet = null;\n\n    try (var connection = getConnection();\n        var statement = connection.prepareStatement(\"SELECT * FROM ROOMS WHERE ID = ?\")) {\n\n      statement.setInt(1, id);\n      resultSet = statement.executeQuery();\n      if (resultSet.next()) {\n        return Optional.of(createRoom(resultSet));\n      } else {\n        return Optional.empty();\n      }\n    } catch (Exception e) {\n      throw new Exception(e.getMessage(), e);\n    } finally {\n      if (resultSet != null) {\n        resultSet.close();\n      }\n    }\n  }\n\n  @Override\n  public Boolean add(Room room) throws Exception {\n    if (getById(room.getId()).isPresent()) {\n      return false;\n    }\n\n    try (var connection = getConnection();\n        var statement = connection.prepareStatement(\"INSERT INTO ROOMS VALUES (?,?,?,?)\")) {\n      statement.setInt(1, room.getId());\n      statement.setString(2, room.getRoomType());\n      statement.setInt(3, room.getPrice());\n      statement.setBoolean(4, room.isBooked());\n      statement.execute();\n      return true;\n    } catch (Exception e) {\n      throw new Exception(e.getMessage(), e);\n    }\n  }\n\n  @Override\n  public Boolean update(Room room) throws Exception {\n    try (var connection = getConnection();\n        var statement =\n            connection.prepareStatement(\n                \"UPDATE ROOMS SET ROOM_TYPE = ?, PRICE = ?, BOOKED = ?\" + \" WHERE ID = ?\")) {\n      statement.setString(1, room.getRoomType());\n      statement.setInt(2, room.getPrice());\n      statement.setBoolean(3, room.isBooked());\n      statement.setInt(4, room.getId());\n      return statement.executeUpdate() > 0;\n    } catch (Exception e) {\n      throw new Exception(e.getMessage(), e);\n    }\n  }\n\n  @Override\n  public Boolean delete(Room room) throws Exception {\n    try (var connection = getConnection();\n        var statement = connection.prepareStatement(\"DELETE FROM ROOMS WHERE ID = ?\")) {\n      statement.setInt(1, room.getId());\n      return statement.executeUpdate() > 0;\n    } catch (Exception e) {\n      throw new Exception(e.getMessage(), e);\n    }\n  }\n\n  private Connection getConnection() throws Exception {\n    return dataSource.getConnection();\n  }\n\n  private void mutedClose(Connection connection, PreparedStatement statement, ResultSet resultSet)\n      throws Exception {\n    try {\n      resultSet.close();\n      statement.close();\n      connection.close();\n    } catch (Exception e) {\n      throw new Exception(e.getMessage(), e);\n    }\n  }\n\n  private Room createRoom(ResultSet resultSet) throws Exception {\n    return new Room(\n        resultSet.getInt(\"ID\"),\n        resultSet.getString(\"ROOM_TYPE\"),\n        resultSet.getInt(\"PRICE\"),\n        resultSet.getBoolean(\"BOOKED\"));\n  }\n}\n"
  },
  {
    "path": "transaction-script/src/main/java/com/iluwatar/transactionscript/Room.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.transactionscript;\n\nimport lombok.AllArgsConstructor;\nimport lombok.EqualsAndHashCode;\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\n/** A room POJO that represents the data that will be read from the data source. */\n@Setter\n@Getter\n@ToString\n@EqualsAndHashCode\n@AllArgsConstructor\npublic class Room {\n\n  private int id;\n  private String roomType;\n  private int price;\n  private boolean booked;\n}\n"
  },
  {
    "path": "transaction-script/src/main/java/com/iluwatar/transactionscript/RoomSchemaSql.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.transactionscript;\n\n/** Customer Schema SQL Class. */\npublic final class RoomSchemaSql {\n\n  public static final String CREATE_SCHEMA_SQL =\n      \"CREATE TABLE ROOMS (ID NUMBER, ROOM_TYPE VARCHAR(100), PRICE INT, BOOKED VARCHAR(100))\";\n  public static final String DELETE_SCHEMA_SQL = \"DROP TABLE ROOMS IF EXISTS\";\n\n  private RoomSchemaSql() {}\n}\n"
  },
  {
    "path": "transaction-script/src/test/java/com/iluwatar/transactionscript/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.transactionscript;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests that Transaction script example runs without errors. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "transaction-script/src/test/java/com/iluwatar/transactionscript/HotelDaoImplTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.transactionscript;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assumptions.assumeTrue;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.SQLException;\nimport javax.sql.DataSource;\nimport org.h2.jdbcx.JdbcDataSource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\n/** Tests {@link HotelDaoImpl}. */\nclass HotelDaoImplTest {\n\n  private static final String DB_URL = \"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1\";\n  private HotelDaoImpl dao;\n  private Room existingRoom = new Room(1, \"Single\", 50, false);\n\n  /**\n   * Creates rooms schema.\n   *\n   * @throws SQLException if there is any error while creating schema.\n   */\n  @BeforeEach\n  void createSchema() throws SQLException {\n    try (var connection = DriverManager.getConnection(DB_URL);\n        var statement = connection.createStatement()) {\n      statement.execute(RoomSchemaSql.DELETE_SCHEMA_SQL);\n      statement.execute(RoomSchemaSql.CREATE_SCHEMA_SQL);\n    }\n  }\n\n  /** Represents the scenario where DB connectivity is present. */\n  @Nested\n  class ConnectionSuccess {\n\n    /**\n     * Setup for connection success scenario.\n     *\n     * @throws Exception if any error occurs.\n     */\n    @BeforeEach\n    void setUp() throws Exception {\n      var dataSource = new JdbcDataSource();\n      dataSource.setURL(DB_URL);\n      dao = new HotelDaoImpl(dataSource);\n      var result = dao.add(existingRoom);\n      Assertions.assertTrue(result);\n    }\n\n    /** Represents the scenario when DAO operations are being performed on a non-existing room. */\n    @Nested\n    class NonExistingRoom {\n\n      @Test\n      void addingShouldResultInSuccess() throws Exception {\n        try (var allRooms = dao.getAll()) {\n          assumeTrue(allRooms.count() == 1);\n        }\n\n        final var nonExistingRoom = new Room(2, \"Double\", 80, false);\n        var result = dao.add(nonExistingRoom);\n        Assertions.assertTrue(result);\n\n        assertRoomCountIs(2);\n        assertEquals(nonExistingRoom, dao.getById(nonExistingRoom.getId()).get());\n      }\n\n      @Test\n      void deletionShouldBeFailureAndNotAffectExistingRooms() throws Exception {\n        final var nonExistingRoom = new Room(2, \"Double\", 80, false);\n        var result = dao.delete(nonExistingRoom);\n\n        Assertions.assertFalse(result);\n        assertRoomCountIs(1);\n      }\n\n      @Test\n      void updationShouldBeFailureAndNotAffectExistingRooms() throws Exception {\n        final var nonExistingId = getNonExistingRoomId();\n        final var newRoomType = \"Double\";\n        final var newPrice = 80;\n        final var room = new Room(nonExistingId, newRoomType, newPrice, false);\n        var result = dao.update(room);\n\n        Assertions.assertFalse(result);\n        assertFalse(dao.getById(nonExistingId).isPresent());\n      }\n\n      @Test\n      void retrieveShouldReturnNoRoom() throws Exception {\n        assertFalse(dao.getById(getNonExistingRoomId()).isPresent());\n      }\n    }\n\n    /**\n     * Represents a scenario where DAO operations are being performed on an already existing room.\n     */\n    @Nested\n    class ExistingRoom {\n\n      @Test\n      void addingShouldResultInFailureAndNotAffectExistingRooms() throws Exception {\n        var existingRoom = new Room(1, \"Single\", 50, false);\n        var result = dao.add(existingRoom);\n\n        Assertions.assertFalse(result);\n        assertRoomCountIs(1);\n        assertEquals(existingRoom, dao.getById(existingRoom.getId()).get());\n      }\n\n      @Test\n      void deletionShouldBeSuccessAndRoomShouldBeNonAccessible() throws Exception {\n        var result = dao.delete(existingRoom);\n\n        Assertions.assertTrue(result);\n        assertRoomCountIs(0);\n        assertFalse(dao.getById(existingRoom.getId()).isPresent());\n      }\n\n      @Test\n      void updationShouldBeSuccessAndAccessingTheSameRoomShouldReturnUpdatedInformation()\n          throws Exception {\n        final var newRoomType = \"Double\";\n        final var newPrice = 80;\n        final var newBookingStatus = false;\n        final var Room = new Room(existingRoom.getId(), newRoomType, newPrice, newBookingStatus);\n        var result = dao.update(Room);\n\n        Assertions.assertTrue(result);\n\n        final var room = dao.getById(existingRoom.getId()).get();\n        assertEquals(newRoomType, room.getRoomType());\n        assertEquals(newPrice, room.getPrice());\n        assertEquals(newBookingStatus, room.isBooked());\n      }\n    }\n  }\n\n  /**\n   * Represents a scenario where DB connectivity is not present due to network issue, or DB service\n   * unavailable.\n   */\n  @Nested\n  class ConnectivityIssue {\n\n    private static final String EXCEPTION_CAUSE = \"Connection not available\";\n\n    /**\n     * setup a connection failure scenario.\n     *\n     * @throws SQLException if any error occurs.\n     */\n    @BeforeEach\n    void setUp() throws SQLException {\n      dao = new HotelDaoImpl(mockedDatasource());\n    }\n\n    private DataSource mockedDatasource() throws SQLException {\n      var mockedDataSource = mock(DataSource.class);\n      var mockedConnection = mock(Connection.class);\n      var exception = new SQLException(EXCEPTION_CAUSE);\n      doThrow(exception).when(mockedConnection).prepareStatement(Mockito.anyString());\n      doReturn(mockedConnection).when(mockedDataSource).getConnection();\n      return mockedDataSource;\n    }\n\n    @Test\n    void addingARoomFailsWithExceptionAsFeedbackToClient() {\n      assertThrows(Exception.class, () -> dao.add(new Room(2, \"Double\", 80, false)));\n    }\n\n    @Test\n    void deletingARoomFailsWithExceptionAsFeedbackToTheClient() {\n      assertThrows(Exception.class, () -> dao.delete(existingRoom));\n    }\n\n    @Test\n    void updatingARoomFailsWithFeedbackToTheClient() {\n      final var newRoomType = \"Double\";\n      final var newPrice = 80;\n      final var newBookingStatus = false;\n      assertThrows(\n          Exception.class,\n          () ->\n              dao.update(new Room(existingRoom.getId(), newRoomType, newPrice, newBookingStatus)));\n    }\n\n    @Test\n    void retrievingARoomByIdFailsWithExceptionAsFeedbackToClient() {\n      assertThrows(Exception.class, () -> dao.getById(existingRoom.getId()));\n    }\n\n    @Test\n    void retrievingAllRoomsFailsWithExceptionAsFeedbackToClient() {\n      assertThrows(Exception.class, () -> dao.getAll());\n    }\n  }\n\n  /**\n   * Delete room schema for fresh setup per test.\n   *\n   * @throws SQLException if any error occurs.\n   */\n  @AfterEach\n  void deleteSchema() throws SQLException {\n    try (var connection = DriverManager.getConnection(DB_URL);\n        var statement = connection.createStatement()) {\n      statement.execute(RoomSchemaSql.DELETE_SCHEMA_SQL);\n    }\n  }\n\n  private void assertRoomCountIs(int count) throws Exception {\n    try (var allRooms = dao.getAll()) {\n      assertEquals(count, allRooms.count());\n    }\n  }\n\n  /**\n   * An arbitrary number which does not correspond to an active Room id.\n   *\n   * @return an int of a room id which doesn't exist\n   */\n  private int getNonExistingRoomId() {\n    return 999;\n  }\n}\n"
  },
  {
    "path": "transaction-script/src/test/java/com/iluwatar/transactionscript/HotelTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.transactionscript;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.List;\nimport javax.sql.DataSource;\nimport lombok.SneakyThrows;\nimport org.h2.jdbcx.JdbcDataSource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests {@link Hotel} */\nclass HotelTest {\n\n  private static final String H2_DB_URL = \"jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1\";\n\n  private Hotel hotel;\n  private HotelDaoImpl dao;\n\n  @BeforeEach\n  void setUp() throws Exception {\n    final var dataSource = createDataSource();\n    deleteSchema(dataSource);\n    createSchema(dataSource);\n    dao = new HotelDaoImpl(dataSource);\n    addRooms(dao);\n    hotel = new Hotel(dao);\n  }\n\n  @Test\n  void bookingRoomShouldChangeBookedStatusToTrue() throws Exception {\n    hotel.bookRoom(1);\n    assertTrue(dao.getById(1).isPresent());\n    assertTrue(dao.getById(1).get().isBooked());\n  }\n\n  @Test\n  void bookingRoomWithInvalidIdShouldRaiseException() {\n    assertThrows(Exception.class, () -> hotel.bookRoom(getNonExistingRoomId()));\n  }\n\n  @Test\n  @SneakyThrows\n  void bookingRoomAgainShouldRaiseException() {\n    hotel.bookRoom(1);\n    assertThrows(Exception.class, () -> hotel.bookRoom(1), \"Room already booked!\");\n  }\n\n  @Test\n  void NotBookingRoomShouldNotChangeBookedStatus() throws Exception {\n    assertTrue(dao.getById(1).isPresent());\n    assertFalse(dao.getById(1).get().isBooked());\n  }\n\n  @Test\n  void cancelRoomBookingShouldChangeBookedStatus() throws Exception {\n    hotel.bookRoom(1);\n    assertTrue(dao.getById(1).isPresent());\n    assertTrue(dao.getById(1).get().isBooked());\n\n    hotel.cancelRoomBooking(1);\n    assertTrue(dao.getById(1).isPresent());\n    assertFalse(dao.getById(1).get().isBooked());\n  }\n\n  @Test\n  void cancelRoomBookingWithInvalidIdShouldRaiseException() {\n    assertThrows(Exception.class, () -> hotel.cancelRoomBooking(getNonExistingRoomId()));\n  }\n\n  @Test\n  void cancelRoomBookingForUnbookedRoomShouldRaiseException() {\n    assertThrows(Exception.class, () -> hotel.cancelRoomBooking(1));\n  }\n\n  private static void deleteSchema(DataSource dataSource) throws java.sql.SQLException {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(RoomSchemaSql.DELETE_SCHEMA_SQL);\n    }\n  }\n\n  private static void createSchema(DataSource dataSource) throws Exception {\n    try (var connection = dataSource.getConnection();\n        var statement = connection.createStatement()) {\n      statement.execute(RoomSchemaSql.CREATE_SCHEMA_SQL);\n    } catch (Exception e) {\n      throw new Exception(e.getMessage(), e);\n    }\n  }\n\n  public static DataSource createDataSource() {\n    JdbcDataSource dataSource = new JdbcDataSource();\n    dataSource.setUrl(H2_DB_URL);\n    return dataSource;\n  }\n\n  private static void addRooms(HotelDaoImpl hotelDao) throws Exception {\n    for (var room : generateSampleRooms()) {\n      hotelDao.add(room);\n    }\n  }\n\n  public static List<Room> generateSampleRooms() {\n    final var room1 = new Room(1, \"Single\", 50, false);\n    final var room2 = new Room(2, \"Double\", 80, false);\n    final var room3 = new Room(3, \"Queen\", 120, false);\n    final var room4 = new Room(4, \"King\", 150, false);\n    final var room5 = new Room(5, \"Single\", 50, false);\n    final var room6 = new Room(6, \"Double\", 80, false);\n    return List.of(room1, room2, room3, room4, room5, room6);\n  }\n\n  /**\n   * An arbitrary number which does not correspond to an active Room id.\n   *\n   * @return an int of a room id which doesn't exist\n   */\n  private int getNonExistingRoomId() {\n    return 999;\n  }\n}\n"
  },
  {
    "path": "transaction-script/src/test/java/com/iluwatar/transactionscript/RoomTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.transactionscript;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests {@link Room}. */\nclass RoomTest {\n\n  private Room room;\n  private static final int ID = 1;\n  private static final String ROOMTYPE = \"Single\";\n  private static final int PRICE = 50;\n  private static final boolean BOOKED = false;\n\n  @BeforeEach\n  void setUp() {\n    room = new Room(ID, ROOMTYPE, PRICE, BOOKED);\n  }\n\n  @Test\n  void getAndSetId() {\n    final var newId = 2;\n    room.setId(newId);\n    assertEquals(newId, room.getId());\n  }\n\n  @Test\n  void getAndSetRoomType() {\n    final var newRoomType = \"Double\";\n    room.setRoomType(newRoomType);\n    assertEquals(newRoomType, room.getRoomType());\n  }\n\n  @Test\n  void getAndSetLastName() {\n    final var newPrice = 60;\n    room.setPrice(newPrice);\n    assertEquals(newPrice, room.getPrice());\n  }\n\n  @Test\n  void notEqualWithDifferentId() {\n    final var newId = 2;\n    final var otherRoom = new Room(newId, ROOMTYPE, PRICE, BOOKED);\n    assertNotEquals(room, otherRoom);\n    assertNotEquals(room.hashCode(), otherRoom.hashCode());\n  }\n\n  @Test\n  void equalsWithSameObjectValues() {\n    final var otherRoom = new Room(ID, ROOMTYPE, PRICE, BOOKED);\n    assertEquals(room, otherRoom);\n    assertEquals(room.hashCode(), otherRoom.hashCode());\n  }\n\n  @Test\n  void equalsWithSameObjects() {\n    assertEquals(room, room);\n    assertEquals(room.hashCode(), room.hashCode());\n  }\n\n  @Test\n  void testToString() {\n    assertEquals(\n        String.format(\n            \"Room(id=%s, roomType=%s, price=%s, booked=%s)\",\n            room.getId(), room.getRoomType(), room.getPrice(), room.isBooked()),\n        room.toString());\n  }\n}\n"
  },
  {
    "path": "twin/.gitignore",
    "content": "/target/\n"
  },
  {
    "path": "twin/README.md",
    "content": "---\ntitle: \"Twin Pattern in Java: Doubling Functionality with Synchronized Twins\"\nshortTitle: Twin\ndescription: \"Explore the Twin design pattern in Java with examples. Learn how to implement flexible, decoupled systems without multiple inheritance for enhanced modularity and system resilience. Ideal for software developers looking to advance their coding practices.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Decoupling\n  - Object composition\n  - Performance\n  - Resilience\n---\n\n## Intent of Twin Design Pattern\n\nThe Twin design pattern in Java provides a way to handle multiple, related classes in a manner that allows them to work together without inheriting from a common base class.\n\n## Detailed Explanation of Twin Pattern with Real-World Examples\n\nReal-world example\n\n> An analogous real-world example of the Twin design pattern can be found in the relationship between a driver and a driving simulator. Imagine a driver (the first class) and a driving simulator (the second class) that both need to interact with the same set of vehicle controls (steering, acceleration, braking) and receive the same feedback (speed, engine status).\n>\n> Despite performing similar functions, the driver and the simulator cannot share a common base class because they operate in fundamentally different environments—one in the physical world and the other in a virtual environment. Instead, they are \"twinned\" to ensure consistent interaction with the vehicle controls and feedback mechanisms. This setup allows improvements or changes to be made to the simulator without affecting the driver and vice versa, maintaining the system's overall flexibility and resilience. \n\nIn plain words\n\n> It provides a way to form two closely coupled subclasses that can act as a twin class having two ends. \n\nWikipedia says\n\n> The Twin pattern is a software design pattern that allows developers to simulate multiple inheritance in languages that don't support it. Instead of creating a single class inheriting from multiple parents, two closely linked subclasses are created, each inheriting from one of the parents. These subclasses are mutually dependent, working together as a pair to achieve the desired functionality. This approach avoids the complications and inefficiencies often associated with multiple inheritance, while still allowing the reuse of functionalities from different classes.\n\nSequence diagram\n\n![Twin Pattern Sequence Diagram](./etc/twin-sequence-diagram.png)\n\n## Programmatic Example of Twin Pattern in Java\n\nConsider a game where a ball needs to function as both a `GameItem` and a `Thread`. Instead of inheriting from both, we use the Twin pattern with two closely linked objects: `BallItem` and `BallThread`.\n\nHere is the `GameItem` class:\n\n```java\n@Slf4j\npublic abstract class GameItem {\n  public void draw() {\n    LOGGER.info(\"draw\");\n    doDraw();\n  }\n  public abstract void doDraw();\n  public abstract void click();\n}\n```\n\n`BallItem` and `BallThread` subclasses:\n\n```java\n@Slf4j\npublic class BallItem extends GameItem {\n  private boolean isSuspended;\n  @Setter\n  private BallThread twin;\n\n  @Override\n  public void doDraw() {\n    LOGGER.info(\"doDraw\");\n  }\n\n  public void move() {\n    LOGGER.info(\"move\");\n  }\n\n  @Override\n  public void click() {\n    isSuspended = !isSuspended;\n    if (isSuspended) {\n      twin.suspendMe();\n    } else {\n      twin.resumeMe();\n    }\n  }\n}\n```\n\n```java\n@Slf4j\npublic class BallThread extends Thread {\n  @Setter\n  private BallItem twin;\n  private volatile boolean isSuspended;\n  private volatile boolean isRunning = true;\n\n  public void run() {\n    while (isRunning) {\n      if (!isSuspended) {\n        twin.draw();\n        twin.move();\n      }\n      try {\n        Thread.sleep(250);\n      } catch (InterruptedException e) {\n        throw new RuntimeException(e);\n      }\n    }\n  }\n\n  public void suspendMe() {\n    isSuspended = true;\n    LOGGER.info(\"Begin to suspend BallThread\");\n  }\n\n  public void resumeMe() {\n    isSuspended = false;\n    LOGGER.info(\"Begin to resume BallThread\");\n  }\n\n  public void stopMe() {\n    this.isRunning = false;\n    this.isSuspended = true;\n  }\n}\n```\n\nTo use these classes together:\n\n```java\npublic class App {\n\n    public static void main(String[] args) throws Exception {\n\n        var ballItem = new BallItem();\n        var ballThread = new BallThread();\n\n        ballItem.setTwin(ballThread);\n        ballThread.setTwin(ballItem);\n\n        ballThread.start();\n\n        waiting();\n\n        ballItem.click();\n\n        waiting();\n\n        ballItem.click();\n\n        waiting();\n\n        // exit\n        ballThread.stopMe();\n    }\n\n    private static void waiting() throws Exception {\n        Thread.sleep(750);\n    }\n}\n```\n\nLet's break down what happens in `App`.\n\n1. An instance of `BallItem` and `BallThread` are created.\n2. The `BallItem` and `BallThread` instances are set as twins of each other. This means that each instance has a reference to the other.\n3. The `BallThread` is started. This begins the execution of the `run` method in the `BallThread` class, which continuously calls the `draw` and `move` methods of the `BallItem` (its twin) as long as the `BallThread` is not suspended.\n4. The program waits for 750 milliseconds. This is done to allow the `BallThread` to execute its `run` method a few times.\n5. The `click` method of the `BallItem` is called. This toggles the `isSuspended` state of the `BallItem` and its twin `BallThread`. If the `BallThread` was running, it gets suspended. If it was suspended, it resumes running.\n6. Steps 4 and 5 are repeated twice. This means the `BallThread` is suspended and resumed once.\n7. Finally, the `stopMe` method of the `BallThread` is called to stop its execution.\n\nConsole output:\n\n```\n14:29:33.778 [Thread-0] INFO com.iluwatar.twin.GameItem -- draw\n14:29:33.780 [Thread-0] INFO com.iluwatar.twin.BallItem -- doDraw\n14:29:33.780 [Thread-0] INFO com.iluwatar.twin.BallItem -- move\n14:29:34.035 [Thread-0] INFO com.iluwatar.twin.GameItem -- draw\n14:29:34.035 [Thread-0] INFO com.iluwatar.twin.BallItem -- doDraw\n14:29:34.035 [Thread-0] INFO com.iluwatar.twin.BallItem -- move\n14:29:34.291 [Thread-0] INFO com.iluwatar.twin.GameItem -- draw\n14:29:34.291 [Thread-0] INFO com.iluwatar.twin.BallItem -- doDraw\n14:29:34.291 [Thread-0] INFO com.iluwatar.twin.BallItem -- move\n14:29:34.533 [main] INFO com.iluwatar.twin.BallThread -- Begin to suspend BallThread\n14:29:35.285 [main] INFO com.iluwatar.twin.BallThread -- Begin to resume BallThread\n14:29:35.308 [Thread-0] INFO com.iluwatar.twin.GameItem -- draw\n14:29:35.308 [Thread-0] INFO com.iluwatar.twin.BallItem -- doDraw\n14:29:35.308 [Thread-0] INFO com.iluwatar.twin.BallItem -- move\n14:29:35.564 [Thread-0] INFO com.iluwatar.twin.GameItem -- draw\n14:29:35.564 [Thread-0] INFO com.iluwatar.twin.BallItem -- doDraw\n14:29:35.565 [Thread-0] INFO com.iluwatar.twin.BallItem -- move\n14:29:35.817 [Thread-0] INFO com.iluwatar.twin.GameItem -- draw\n14:29:35.817 [Thread-0] INFO com.iluwatar.twin.BallItem -- doDraw\n14:29:35.817 [Thread-0] INFO com.iluwatar.twin.BallItem -- move\n```\n\nThis setup allows `BallItem` and `BallThread` to act together as a single cohesive unit in the game, leveraging the capabilities of both `GameItem` and `Thread` without multiple inheritance.\n\n## When to Use the Twin Pattern in Java\n\n* Use when you need to decouple classes that share common functionality but cannot inherit from a common base class due to various reasons such as the use of different frameworks or languages.\n* Useful in performance-critical applications where inheritance might introduce unnecessary overhead.\n* Applicable in systems requiring resilience through the ability to replace or update one of the twins without affecting the other.\n\n## Twin Pattern Java Tutorials\n\n* [Twin – A Design Pattern for Modeling Multiple Inheritance (Hanspeter Mössenböck)](http://www.ssw.uni-linz.ac.at/Research/Papers/Moe99/Paper.pdf)\n\n## Real-World Applications of Twin Pattern in Java\n\n* User interfaces where different frameworks are used for rendering and logic.\n* Systems integrating legacy code with new implementations where direct inheritance is not feasible.\n\n## Benefits and Trade-offs of Twin Pattern\n\nBenefits:\n\n* Reduces coupling between classes, promoting modularity and easier maintenance.\n* Improves flexibility and reuse of classes across different frameworks or languages.\n* Enhances performance by avoiding the overhead associated with inheritance.\n\nTrade-offs:\n\n* Can lead to code duplication if not managed properly.\n* Increased complexity in managing the interaction between twin classes.\n\n## Related Java Design Patterns\n\n* [Adapter](https://java-design-patterns.com/patterns/adapter/): Both patterns deal with compatibility issues, but Adapter focuses on converting interfaces while Twin deals with class collaboration without inheritance.\n* [Bridge](https://java-design-patterns.com/patterns/bridge/): Similar in decoupling abstraction from implementation, but Twin specifically avoids inheritance.\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): Manages object access, similar to how Twin handles interaction, but Proxy typically focuses on control and logging.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "twin/etc/twin.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.twin.BallThread\" project=\"twin\" \n    file=\"/twin/src/main/java/com/iluwatar/twin/BallThread.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"550\" y=\"316\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.twin.BallItem\" project=\"twin\" \n    file=\"/twin/src/main/java/com/iluwatar/twin/BallItem.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"285\" y=\"315\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.twin.GameItem\" project=\"twin\" \n    file=\"/twin/src/main/java/com/iluwatar/twin/GameItem.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"285\" y=\"84\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"java.lang.Thread\" project=\"twin\" \n    file=\"/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/jre/lib/rt.jar\" binary=\"true\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"550\" y=\"96\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"false\" package=\"false\" protected=\"false\" private=\"false\" static=\"true\"/>      \n      <operations public=\"false\" package=\"false\" protected=\"false\" private=\"false\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <generalization id=\"5\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"3\"/>  \n  </generalization>  \n  <association id=\"6\">    \n    <end type=\"SOURCE\" refId=\"2\" navigable=\"false\">      \n      <attribute id=\"7\" name=\"twin\"/>      \n      <multiplicity id=\"8\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"9\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"10\" name=\"threadQ\"/>      \n      <multiplicity id=\"11\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"4\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <association id=\"12\">    \n    <end type=\"SOURCE\" refId=\"1\" navigable=\"false\">      \n      <attribute id=\"13\" name=\"twin\"/>      \n      <multiplicity id=\"14\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"2\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"15\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"4\"/>  \n  </generalization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "twin/etc/twin.urm.puml",
    "content": "@startuml\npackage com.iluwatar.twin {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n    - waiting() {static}\n  }\n  class BallItem {\n    - LOGGER : Logger {static}\n    - isSuspended : boolean\n    - twin : BallThread\n    + BallItem()\n    + click()\n    + doDraw()\n    + move()\n    + setTwin(twin : BallThread)\n  }\n  abstract class GameItem {\n    - LOGGER : Logger {static}\n    + GameItem()\n    + click() {abstract}\n    + doDraw() {abstract}\n    + draw()\n  }\n}\nBallItem --|> GameItem \n@enduml"
  },
  {
    "path": "twin/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>twin</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.twin.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "twin/src/main/java/com/iluwatar/twin/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.twin;\n\n/**\n * Twin pattern is a design pattern which provides a standard solution to simulate multiple\n * inheritance in Java.\n *\n * <p>In this example, the essence of the Twin pattern is the {@link BallItem} class and {@link\n * BallThread} class represent the twin objects to coordinate with each other (via the twin\n * reference) like a single class inheriting from {@link GameItem} and {@link Thread}.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) throws Exception {\n\n    var ballItem = new BallItem();\n    var ballThread = new BallThread();\n\n    ballItem.setTwin(ballThread);\n    ballThread.setTwin(ballItem);\n\n    ballThread.start();\n\n    waiting();\n\n    ballItem.click();\n\n    waiting();\n\n    ballItem.click();\n\n    waiting();\n\n    // exit\n    ballThread.stopMe();\n  }\n\n  private static void waiting() throws Exception {\n    Thread.sleep(750);\n  }\n}\n"
  },
  {
    "path": "twin/src/main/java/com/iluwatar/twin/BallItem.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.twin;\n\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This class represents a Ball which extends {@link GameItem} and implements the logic for ball\n * item, like move and draw. It holds a reference of {@link BallThread} to delegate the suspend and\n * resume task.\n */\n@Slf4j\npublic class BallItem extends GameItem {\n\n  private boolean isSuspended;\n\n  @Setter private BallThread twin;\n\n  @Override\n  public void doDraw() {\n\n    LOGGER.info(\"doDraw\");\n  }\n\n  public void move() {\n    LOGGER.info(\"move\");\n  }\n\n  @Override\n  public void click() {\n\n    isSuspended = !isSuspended;\n\n    if (isSuspended) {\n      twin.suspendMe();\n    } else {\n      twin.resumeMe();\n    }\n  }\n}\n"
  },
  {
    "path": "twin/src/main/java/com/iluwatar/twin/BallThread.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.twin;\n\nimport lombok.Setter;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This class is a UI thread for drawing the {@link BallItem}, and provide the method for suspend\n * and resume. It holds the reference of {@link BallItem} to delegate the draw task.\n */\n@Slf4j\npublic class BallThread extends Thread {\n\n  @Setter private BallItem twin;\n\n  private volatile boolean isSuspended;\n\n  private volatile boolean isRunning = true;\n\n  /** Run the thread. */\n  public void run() {\n\n    while (isRunning) {\n      if (!isSuspended) {\n        twin.draw();\n        twin.move();\n      }\n      try {\n        Thread.sleep(250);\n      } catch (InterruptedException e) {\n        throw new RuntimeException(e);\n      }\n    }\n  }\n\n  public void suspendMe() {\n    isSuspended = true;\n    LOGGER.info(\"Begin to suspend BallThread\");\n  }\n\n  public void resumeMe() {\n    isSuspended = false;\n    LOGGER.info(\"Begin to resume BallThread\");\n  }\n\n  public void stopMe() {\n    this.isRunning = false;\n    this.isSuspended = true;\n  }\n}\n"
  },
  {
    "path": "twin/src/main/java/com/iluwatar/twin/GameItem.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.twin;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** GameItem is a common class which provides some common methods for game object. */\n@Slf4j\npublic abstract class GameItem {\n\n  /** Template method, do some common logic before draw. */\n  public void draw() {\n    LOGGER.info(\"draw\");\n    doDraw();\n  }\n\n  public abstract void doDraw();\n\n  public abstract void click();\n}\n"
  },
  {
    "path": "twin/src/test/java/com/iluwatar/twin/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.twin;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "twin/src/test/java/com/iluwatar/twin/BallItemTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.twin;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.inOrder;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.stream.IntStream;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/** BallItemTest */\nclass BallItemTest {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  @Test\n  void testClick() {\n    final var ballThread = mock(BallThread.class);\n    final var ballItem = new BallItem();\n    ballItem.setTwin(ballThread);\n\n    final var inOrder = inOrder(ballThread);\n\n    IntStream.range(0, 10)\n        .forEach(\n            i -> {\n              ballItem.click();\n              inOrder.verify(ballThread).suspendMe();\n              ballItem.click();\n              inOrder.verify(ballThread).resumeMe();\n            });\n\n    inOrder.verifyNoMoreInteractions();\n  }\n\n  @Test\n  void testDoDraw() {\n    final var ballItem = new BallItem();\n    final var ballThread = mock(BallThread.class);\n    ballItem.setTwin(ballThread);\n\n    ballItem.draw();\n    assertTrue(appender.logContains(\"draw\"));\n    assertTrue(appender.logContains(\"doDraw\"));\n\n    verifyNoMoreInteractions(ballThread);\n    assertEquals(2, appender.getLogSize());\n  }\n\n  @Test\n  void testMove() {\n    final var ballItem = new BallItem();\n    final var ballThread = mock(BallThread.class);\n    ballItem.setTwin(ballThread);\n\n    ballItem.move();\n    assertTrue(appender.logContains(\"move\"));\n\n    verifyNoMoreInteractions(ballThread);\n    assertEquals(1, appender.getLogSize());\n  }\n\n  /** Logging Appender Implementation */\n  static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender() {\n      ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public boolean logContains(String message) {\n      return log.stream().anyMatch(event -> event.getMessage().equals(message));\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n  }\n}\n"
  },
  {
    "path": "twin/src/test/java/com/iluwatar/twin/BallThreadTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.twin;\n\nimport static java.lang.Thread.UncaughtExceptionHandler;\nimport static java.lang.Thread.sleep;\nimport static java.time.Duration.ofMillis;\nimport static org.junit.jupiter.api.Assertions.assertTimeout;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.atLeastOnce;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport org.junit.jupiter.api.Test;\n\n/** BallThreadTest */\nclass BallThreadTest {\n\n  /** Verify if the {@link BallThread} can be resumed */\n  @Test\n  void testSuspend() {\n    assertTimeout(\n        ofMillis(5000),\n        () -> {\n          final var ballThread = new BallThread();\n\n          final var ballItem = mock(BallItem.class);\n          ballThread.setTwin(ballItem);\n\n          ballThread.start();\n          sleep(200);\n          verify(ballItem, atLeastOnce()).draw();\n          verify(ballItem, atLeastOnce()).move();\n          ballThread.suspendMe();\n\n          sleep(1000);\n\n          ballThread.stopMe();\n          ballThread.join();\n\n          verifyNoMoreInteractions(ballItem);\n        });\n  }\n\n  /** Verify if the {@link BallThread} can be resumed */\n  @Test\n  void testResume() {\n    assertTimeout(\n        ofMillis(5000),\n        () -> {\n          final var ballThread = new BallThread();\n\n          final var ballItem = mock(BallItem.class);\n          ballThread.setTwin(ballItem);\n\n          ballThread.suspendMe();\n          ballThread.start();\n\n          sleep(1000);\n\n          verifyNoMoreInteractions(ballItem);\n\n          ballThread.resumeMe();\n          sleep(300);\n          verify(ballItem, atLeastOnce()).draw();\n          verify(ballItem, atLeastOnce()).move();\n\n          ballThread.stopMe();\n          ballThread.join();\n\n          verifyNoMoreInteractions(ballItem);\n        });\n  }\n\n  /** Verify if the {@link BallThread} is interruptible */\n  @Test\n  void testInterrupt() {\n    assertTimeout(\n        ofMillis(5000),\n        () -> {\n          final var ballThread = new BallThread();\n          final var exceptionHandler = mock(UncaughtExceptionHandler.class);\n          ballThread.setUncaughtExceptionHandler(exceptionHandler);\n          ballThread.setTwin(mock(BallItem.class));\n          ballThread.start();\n          ballThread.interrupt();\n          ballThread.join();\n\n          verify(exceptionHandler).uncaughtException(eq(ballThread), any(RuntimeException.class));\n          verifyNoMoreInteractions(exceptionHandler);\n        });\n  }\n}\n"
  },
  {
    "path": "type-object/README.md",
    "content": "---\ntitle: \"Type Object Pattern in Java: Enhancing Flexibility with Dynamic Class Definitions\"\nshortTitle: Type Object\ndescription: \"Discover how the Type Object Pattern in Java allows for dynamic and flexible class creation without altering existing code. Ideal for developers looking to understand and apply this powerful design pattern in real-world Java applications.\"\ncategory: Creational\nlanguage: en\ntag:\n  - Abstraction\n  - Code simplification\n  - Data processing\n  - Game programming\n  - Extensibility\n  - Instantiation\n  - Object composition\n  - Polymorphism\n---\n\n## Also known as\n\n* Type Descriptor\n* Type Safe Enumeration\n\n## Intent of Type Object Design Pattern\n\nAllow creation of flexible and extensible sets of related types.\n\n## Detailed Explanation of Type Object Pattern with Real-World Examples\n\nReal-world example\n\n> An analogous real-world example of the Type Object pattern can be seen in a role-playing game (RPG) character customization system. In such a game, players can choose from various character classes like Warrior, Mage, and Archer, each with its unique set of abilities and attributes. The Type Object pattern allows the game to define these character classes and their behaviors dynamically. Instead of hardcoding the details of each class, the game uses a flexible system where new character types can be added or existing ones modified without changing the underlying game logic. This extensibility lets the developers introduce new character classes through updates or expansions, keeping the game fresh and engaging for players.\n\nIn plain words\n\n> Type Object pattern enables dynamic creation and management of flexible and extensible sets of related classes, ideal for Java developers seeking modularity without modifying existing codebase.\n\ngameprogrammingpatterns.com says\n\n> Define a type object class and a typed object class. Each type object instance represents a different logical type. Each typed object stores a reference to the type object that describes its type.\n\nFlowchart\n\n![Type Object Pattern Flowchart](./etc/type-object-flowchart.png)\n\n## Programmatic Example of Type Object Pattern in Java\n\nThe Type Object pattern is a design pattern that allows for the creation of flexible and reusable objects by creating a class with a field that represents the 'type' of the object. This design pattern proves invaluable for scenarios where anticipated Java types are undefined upfront, or when modifications or additions are required, ensuring efficient Java development without frequent recompilations.\n\nIn the provided code, the Type Object pattern is implemented in a mini candy-crush game. The game has many different candies, which may change over time as the game is upgraded.\n\nLet's break down the key components of this implementation:\n\n1. **Candy Class**: This class represents the 'type' object in this pattern. Each `Candy` has a `name`, `parent`, `points`, and `type`. The `type` is an enum that can be either `CRUSHABLE_CANDY` or `REWARD_FRUIT`.\n\n```java\nclass Candy {\n  String name;\n  Candy parent;\n  String parentName;\n  int points;\n  Type type;\n\n  Candy(String name, String parentName, Type type, int points) {\n    // constructor implementation\n  }\n\n  int getPoints() {\n    // implementation\n  }\n\n  Type getType() {\n    // implementation\n  }\n\n  void setPoints(int a) {\n    // implementation\n  }\n}\n```\n\n2. **JsonParser Class**: This class is responsible for parsing the JSON file that contains the details about the candies. It creates a `Candy` object for each candy in the JSON file and stores them in a `Hashtable`.\n\n```java\npublic class JsonParser {\n  Hashtable<String, Candy> candies;\n\n  JsonParser() {\n    this.candies = new Hashtable<>();\n  }\n\n  void parse() throws JsonParseException {\n    // implementation\n  }\n\n  void setParentAndPoints() {\n    // implementation\n  }\n}\n```\n\n3. **Cell Class**: This class represents a cell in the game matrix. Each cell contains a candy that can be crushed. It also contains information on how crushing can be done, how the matrix is to be reconfigured, and how points are to be gained.\n\n```java\nclass Cell {\n  Candy candy;\n  int positionX;\n  int positionY;\n\n  Cell() {\n    // implementation\n  }\n\n  Cell(Candy candy, int positionX, int positionY) {\n    // implementation\n  }\n\n  void crush(CellPool pool, Cell[][] cellMatrix) {\n    // implementation\n  }\n\n  // other methods...\n}\n```\n\n4. **CandyGame Class**: This class contains the rules for the continuation of the game.\n\n```java\nclass CandyGame {\n  Cell[][] cells;\n  CellPool pool;\n  int totalPoints;\n\n  CandyGame(int num, CellPool pool) {\n    // implementation\n  }\n\n  boolean continueRound() {\n    // implementation\n  }\n\n  // other methods...\n}\n```\n\n5. **CellPool Class**: This class is a pool that reuses the candy cells that have been crushed instead of creating new ones repeatedly.\n\n```java\nclass CellPool {\n  int pointer;\n  List<Cell> pool;\n  Candy[] randomCode;\n\n  CellPool(int num) {\n    // implementation\n  }\n\n  void addNewCell(Cell c) {\n    // implementation\n  }\n\n  Candy[] assignRandomCandytypes() {\n    // implementation\n  }\n\n  Cell getNewCell() {\n    // implementation\n  }\n}\n```\n\n6. **App Class**: This class contains the main method that starts the game.\n\n```java\n@Slf4j\npublic class App {\n  public static void main(String[] args) {\n      var givenTime = 50; //50ms\n      var toWin = 500; //points\n      var pointsWon = 0;\n      var numOfRows = 3;\n      var start = System.currentTimeMillis();\n      var end = System.currentTimeMillis();\n      var round = 0;\n      while (pointsWon < toWin && end - start < givenTime) {\n          round++;\n          var pool = new CellPool(numOfRows * numOfRows + 5);\n          var cg = new CandyGame(numOfRows, pool);\n          if (round > 1) {\n              LOGGER.info(\"Refreshing..\");\n          } else {\n              LOGGER.info(\"Starting game..\");\n          }\n          cg.printGameStatus();\n          end = System.currentTimeMillis();\n          cg.round((int) (end - start), givenTime);\n          pointsWon += cg.totalPoints;\n          end = System.currentTimeMillis();\n      }\n      LOGGER.info(\"Game Over\");\n      if (pointsWon >= toWin) {\n          LOGGER.info(\"\" + pointsWon);\n          LOGGER.info(\"You win!!\");\n      } else {\n          LOGGER.info(\"\" + pointsWon);\n          LOGGER.info(\"Sorry, you lose!\");\n      }\n  }\n}\n```\n\nLet's break down what happens in `App` class.\n\n1. The `main` method is the entry point of the application. It starts by initializing several variables:\n  - `givenTime` is set to 50 milliseconds. This is the time limit for the game.\n  - `toWin` is set to 500 points. This is the target score to win the game.\n  - `pointsWon` is initialized to 0. This variable keeps track of the total points won so far.\n  - `numOfRows` is set to 3. This is the number of rows in the game grid.\n  - `start` and `end` are both set to the current system time in milliseconds. These variables are used to track the elapsed time.\n  - `round` is initialized to 0. This variable keeps track of the current round number.\n\n2. The game enters a loop that continues until either the player has won enough points (`pointsWon >= toWin`) or the time limit has been reached (`end - start < givenTime`).\n\n3. At the start of each round, a new `CellPool` and `CandyGame` are created. The `CellPool` is initialized with a size based on the number of cells in the game grid (`numOfRows * numOfRows + 5`). The `CandyGame` is initialized with the number of rows and the `CellPool`.\n\n4. If it's not the first round, a message \"Refreshing..\" is logged. If it is the first round, a message \"Starting game..\" is logged.\n\n5. The current game status is printed by calling `cg.printGameStatus()`.\n\n6. The `end` time is updated to the current system time.\n\n7. The game round is played by calling `cg.round((int) (end - start), givenTime)`. The elapsed time and the time limit are passed as arguments.\n\n8. The points won in the round are added to the total points.\n\n9. The `end` time is updated again to the current system time.\n\n10. After the loop, a \"Game Over\" message is logged.\n\n11. If the total points won is greater than or equal to the target score, a winning message is logged. Otherwise, a losing message is logged.\n\nThis is a simplified version of a game similar to Candy Crush, where the player tries to score as many points as possible within a given time limit. The game is played in rounds, and the player's score and the elapsed time are tracked throughout the game.\n\nConsole output:\n\n```\n14:36:14.453 [main] INFO com.iluwatar.typeobject.App -- Starting game..\n14:36:14.455 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --        cherry       |\n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --        mango        |\n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --      orange gum     |\n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --      orange gum     |\n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --   purple popsicle   |\n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --   purple popsicle   |\n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --   green jellybean   |\n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --   green jellybean   |\n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame --        mango        |\n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.458 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.459 [main] INFO com.iluwatar.typeobject.CandyGame -- +20 points!\n...\n...\n...\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --   green jellybean   |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --        cherry       |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --   green jellybean   |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --   green jellybean   |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --   green jellybean   |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --        mango        |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --      orange gum     |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --   purple popsicle   |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --      orange gum     |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- +20 points!\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --      orange gum     |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --        cherry       |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --   green jellybean   |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --   purple popsicle   |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --   green jellybean   |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --        mango        |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --      orange gum     |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --   purple popsicle   |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame --      orange gum     |\n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.465 [main] INFO com.iluwatar.typeobject.CandyGame -- \n14:36:14.465 [main] INFO com.iluwatar.typeobject.App -- Game Over\n14:36:14.465 [main] INFO com.iluwatar.typeobject.App -- 660\n14:36:14.465 [main] INFO com.iluwatar.typeobject.App -- You win!!\n```\n\nIn this implementation, the Type Object pattern allows for the flexible creation of `Candy` objects. The type of each candy is determined at runtime by parsing a JSON file, which makes it easy to add, modify, or remove candy types without having to recompile the code.\n\n## When to Use the Type Object Pattern in Java\n\nThis pattern can be used when:\n\n* Use when you need to create an extensible set of related classes without modifying existing code.\n* Ideal for scenarios where types and their behaviors need to be defined at runtime or in a flexible manner.\n* Suitable for situations where the number of types is large and may change over time.\n* The difference between the different 'types' of objects is the data, not the behaviour.\n\n## Type Object Pattern Java Tutorials\n\n* [Types as Objects Pattern (Jon Pearce)](http://www.cs.sjsu.edu/~pearce/modules/patterns/analysis/top.htm)\n\n## Real-World Applications of Type Object Pattern in Java\n\n* Java Collections Framework: Utilizing various collection types like List, Set, and Map.\n* Graphics Libraries: Defining different shapes with specific properties and behaviors.\n* Game Development: Creating different types of characters or items with unique attributes and behaviors.\n\n## Benefits and Trade-offs of Type Object Pattern\n\nBenefits:\n\n* Increases flexibility and extensibility of the code.\n* Simplifies the addition of new types without modifying existing code.\n* Enhances code readability by organizing related behaviors and properties.\n\nTrade-offs:\n\n* Can increase complexity if not managed properly.\n* May lead to performance overhead due to dynamic type checking and handling.\n\n## Related Java Design Patterns\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Often used in conjunction with Type Object to create instances of the types.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Similar in that it defines a family of algorithms or behaviors, but focuses more on interchangeable behaviors.\n* [Prototype](https://java-design-patterns.com/patterns/prototype/): Can be used to create new instances by copying existing ones, supporting dynamic and flexible type creation.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n* [Type Object (Game Programming Patterns)](http://gameprogrammingpatterns.com/type-object.html)\n"
  },
  {
    "path": "type-object/etc/type-object.urm.puml",
    "content": "@startuml\npackage com.iluwatar.typeobject {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Candy {\n    ~ name : String\n    ~ parent : Candy\n    ~ parentName : String\n    - points : int\n    - type : Type\n    ~ Candy(name : String, parentName : String, type : Type, points : int)\n    ~ getName() : String\n    ~ getParent() : Candy\n    ~ getParentName() : String\n    ~ getPoints() : int\n    ~ getType() : Type\n    + setPoints(points : int)\n  }\n  ~enum Type {\n    + CRUSHABLE_CANDY {static}\n    + REWARD_FRUIT {static}\n    + valueOf(name : String) : Type {static}\n    + values() : Type[] {static}\n  }\n  class CandyGame {\n    - LOGGER : Logger {static}\n    ~ cells : Cell[][]\n    ~ pool : CellPool\n    ~ totalPoints : int\n    ~ CandyGame(num : int, pool : CellPool)\n    ~ adjacentCells(y : int, x : int) : List<Cell>\n    ~ continueRound() : boolean\n    ~ handleChange(points : int)\n    ~ numOfSpaces(num : int) : String {static}\n    ~ printGameStatus()\n    ~ round(timeSoFar : int, totalTime : int)\n  }\n  class Cell {\n    ~ candy : Candy\n    ~ positionX : int\n    ~ positionY : int\n    + Cell()\n    + Cell(candy : Candy, positionX : int, positionY : int)\n    ~ crush(pool : CellPool, cellMatrix : Cell[][])\n    ~ fillThisSpace(pool : CellPool, cellMatrix : Cell[][])\n    ~ handleCrush(c : Cell, pool : CellPool, cellMatrix : Cell[][])\n    ~ interact(c : Cell, pool : CellPool, cellMatrix : Cell[][]) : int\n  }\n  class CellPool {\n    + CANDY : String {static}\n    + FRUIT : String {static}\n    - LOGGER : Logger {static}\n    - RANDOM : SecureRandom {static}\n    ~ pointer : int\n    ~ pool : List<Cell>\n    ~ randomCode : Candy[]\n    ~ CellPool(num : int)\n    ~ addNewCell(c : Cell)\n    ~ assignRandomCandytypes() : Candy[]\n    ~ getNewCell() : Cell\n  }\n  class JsonParser {\n    ~ candies : Hashtable<String, Candy>\n    ~ JsonParser()\n    ~ parse()\n    ~ setParentAndPoints()\n  }\n}\nCandy -->  \"-type\" Type\nCell -->  \"-candy\" Candy\nCandy -->  \"-parent\" Candy\nCandyGame -->  \"-pool\" CellPool\nCellPool -->  \"-pool\" Cell\n@enduml"
  },
  {
    "path": "type-object/etc/typeobjectpattern.urm.puml",
    "content": "@startuml\npackage com.iluwatar.typeobject {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Candy {\n    ~ name : String\n    ~ parent : Candy\n    ~ parentName : String\n    - points : int\n    - type : Type\n    ~ Candy(name : String, parentName : String, type : Type, points : int)\n    ~ getPoints() : int\n    ~ getType() : Type\n    ~ setPoints(a : int)\n  }\n  ~enum Type {\n    + crushableCandy {static}\n    + rewardFruit {static}\n    + valueOf(name : String) : Type {static}\n    + values() : Type[] {static}\n  }\n  class CandyGame {\n    - LOGGER : Logger {static}\n    ~ cells : Cell[][]\n    ~ pool : CellPool\n    ~ totalPoints : int\n    ~ CandyGame(num : int, pool : CellPool)\n    ~ adjacentCells(y : int, x : int) : List<Cell>\n    ~ continueRound() : boolean\n    ~ handleChange(points : int)\n    ~ numOfSpaces(num : int) : String {static}\n    ~ printGameStatus()\n    ~ round(timeSoFar : int, totalTime : int)\n  }\n  class Cell {\n    ~ candy : Candy\n    ~ positionX : int\n    ~ positionY : int\n    ~ Cell()\n    ~ Cell(candy : Candy, positionX : int, positionY : int)\n    ~ crush(pool : CellPool, cellMatrix : Cell[][])\n    ~ fillThisSpace(pool : CellPool, cellMatrix : Cell[][])\n    ~ handleCrush(c : Cell, pool : CellPool, cellMatrix : Cell[][])\n    ~ interact(c : Cell, pool : CellPool, cellMatrix : Cell[][]) : int\n  }\n  class CellPool {\n    - RANDOM : Random {static}\n    ~ pointer : int\n    ~ pool : List<Cell>\n    ~ randomCode : Candy[]\n    ~ CellPool(num : int)\n    ~ addNewCell(c : Cell)\n    ~ assignRandomCandytypes() : Candy[]\n    ~ getNewCell() : Cell\n  }\n  class JsonParser {\n    ~ candies : Hashtable<String, Candy>\n    ~ JsonParser()\n    ~ parse()\n    ~ setParentAndPoints()\n  }\n}\nCell -->  \"-candy\" Candy\nType ..+ Candy\nCandy -->  \"-type\" Type\nCandy -->  \"-parent\" Candy\nCandyGame -->  \"-pool\" CellPool\nCellPool -->  \"-pool\" Cell\n@enduml"
  },
  {
    "path": "type-object/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>type-object</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>com.google.code.gson</groupId>\n      <artifactId>gson</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.typeobject.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "type-object/src/main/java/com/iluwatar/typeobject/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.typeobject;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * Type object pattern is the pattern we use when the OOP concept of creating a base class and\n * inheriting from it just doesn't work for the case in hand. This happens when we either don't know\n * what types we will need upfront, or want to be able to modify or add new types conveniently w/o\n * recompiling repeatedly. The pattern provides a solution by allowing flexible creation of required\n * objects by creating one class, which has a field which represents the 'type' of the object. In\n * this example, we have a mini candy-crush game in action. There are many different candies in the\n * game, which may change over time, as we may want to upgrade the game. To make the object creation\n * convenient, we have a class {@link Candy} which has a field name, parent, points and Type. We\n * have a json file {@link candy} which contains the details about the candies, and this is parsed\n * to get all the different candies in {@link JsonParser}. The {@link Cell} class is what the game\n * matrix is made of, which has the candies that are to be crushed, and contains information on how\n * crushing can be done, how the matrix is to be reconfigured and how points are to be gained. The\n * {@link CellPool} class is a pool which reuses the candy cells that have been crushed instead of\n * making new ones repeatedly. The {@link CandyGame} class has the rules for the continuation of the\n * game and the {@link App} class has the game itself.\n */\n@Slf4j\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n    var givenTime = 50; // 50ms\n    var toWin = 500; // points\n    var pointsWon = 0;\n    var numOfRows = 3;\n    var start = System.currentTimeMillis();\n    var end = System.currentTimeMillis();\n    var round = 0;\n    while (pointsWon < toWin && end - start < givenTime) {\n      round++;\n      var pool = new CellPool(numOfRows * numOfRows + 5);\n      var cg = new CandyGame(numOfRows, pool);\n      if (round > 1) {\n        LOGGER.info(\"Refreshing..\");\n      } else {\n        LOGGER.info(\"Starting game..\");\n      }\n      cg.printGameStatus();\n      end = System.currentTimeMillis();\n      cg.round((int) (end - start), givenTime);\n      pointsWon += cg.totalPoints;\n      end = System.currentTimeMillis();\n    }\n    LOGGER.info(\"Game Over\");\n    if (pointsWon >= toWin) {\n      LOGGER.info(\"\" + pointsWon);\n      LOGGER.info(\"You win!!\");\n    } else {\n      LOGGER.info(\"\" + pointsWon);\n      LOGGER.info(\"Sorry, you lose!\");\n    }\n  }\n}\n"
  },
  {
    "path": "type-object/src/main/java/com/iluwatar/typeobject/Candy.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.typeobject;\n\nimport lombok.AccessLevel;\nimport lombok.Getter;\nimport lombok.Setter;\n\n/**\n * The Candy class has a field type, which represents the 'type' of candy. The objects are created\n * by parsing the candy.json file.\n */\n@Getter(AccessLevel.PACKAGE)\npublic class Candy {\n\n  enum Type {\n    CRUSHABLE_CANDY,\n    REWARD_FRUIT\n  }\n\n  String name;\n  Candy parent;\n  String parentName;\n\n  @Setter private int points;\n  private final Type type;\n\n  Candy(String name, String parentName, Type type, int points) {\n    this.name = name;\n    this.parent = null;\n    this.type = type;\n    this.points = points;\n    this.parentName = parentName;\n  }\n}\n"
  },
  {
    "path": "type-object/src/main/java/com/iluwatar/typeobject/CandyGame.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.typeobject;\n\nimport com.iluwatar.typeobject.Candy.Type;\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The CandyGame class contains the rules for the continuation of the game and has the game matrix\n * (field 'cells') and totalPoints gained during the game.\n */\n@Slf4j\n@SuppressWarnings(\"java:S3776\") // \"Cognitive Complexity of methods should not be too high\"\npublic class CandyGame {\n  Cell[][] cells;\n  CellPool pool;\n  int totalPoints;\n\n  CandyGame(int num, CellPool pool) {\n    this.cells = new Cell[num][num];\n    this.pool = pool;\n    this.totalPoints = 0;\n    for (var i = 0; i < num; i++) {\n      for (var j = 0; j < num; j++) {\n        this.cells[i][j] = this.pool.getNewCell();\n        this.cells[i][j].positionX = j;\n        this.cells[i][j].positionY = i;\n      }\n    }\n  }\n\n  static String numOfSpaces(int num) {\n    return \" \".repeat(Math.max(0, num));\n  }\n\n  void printGameStatus() {\n    LOGGER.info(\"\");\n    for (Cell[] cell : cells) {\n      for (var j = 0; j < cells.length; j++) {\n        var candyName = cell[j].candy.name;\n        if (candyName.length() < 20) {\n          var totalSpaces = 20 - candyName.length();\n          LOGGER.info(\n              numOfSpaces(totalSpaces / 2)\n                  + cell[j].candy.name\n                  + numOfSpaces(totalSpaces - totalSpaces / 2)\n                  + \"|\");\n        } else {\n          LOGGER.info(candyName + \"|\");\n        }\n      }\n      LOGGER.info(\"\");\n    }\n    LOGGER.info(\"\");\n  }\n\n  List<Cell> adjacentCells(int y, int x) {\n    var adjacent = new ArrayList<Cell>();\n    if (y == 0) {\n      adjacent.add(this.cells[1][x]);\n    }\n    if (x == 0) {\n      adjacent.add(this.cells[y][1]);\n    }\n    if (y == cells.length - 1 && cells.length > 1) {\n      adjacent.add(this.cells[cells.length - 2][x]);\n    }\n\n    if (x == cells.length - 1 && cells.length > 1) {\n      adjacent.add(this.cells[y][cells.length - 2]);\n    }\n\n    if (y > 0 && y < cells.length - 1) {\n      adjacent.add(this.cells[y - 1][x]);\n      adjacent.add(this.cells[y + 1][x]);\n    }\n    if (y >= 0 && y < cells.length && x > 0 && x < cells[y].length - 1) {\n      adjacent.add(this.cells[y][x - 1]);\n      adjacent.add(this.cells[y][x + 1]);\n    }\n    return adjacent;\n  }\n\n  boolean continueRound() {\n    for (var i = 0; i < this.cells.length; i++) {\n      if (this.cells[cells.length - 1][i].candy.getType().equals(Type.REWARD_FRUIT)) {\n        return true;\n      }\n    }\n    for (var i = 0; i < this.cells.length; i++) {\n      for (var j = 0; j < this.cells.length; j++) {\n        if (!this.cells[i][j].candy.getType().equals(Type.REWARD_FRUIT)) {\n          var adj = adjacentCells(i, j);\n          for (Cell cell : adj) {\n            if (this.cells[i][j].candy.name.equals(cell.candy.name)) {\n              return true;\n            }\n          }\n        }\n      }\n    }\n    return false;\n  }\n\n  void handleChange(int points) {\n    LOGGER.info(\"+\" + points + \" points!\");\n    this.totalPoints += points;\n    printGameStatus();\n  }\n\n  void round(int timeSoFar, int totalTime) {\n    var start = System.currentTimeMillis();\n    var end = System.currentTimeMillis();\n    while (end - start + timeSoFar < totalTime && continueRound()) {\n      for (var i = 0; i < this.cells.length; i++) {\n        var points = 0;\n        var j = this.cells.length - 1;\n        while (this.cells[j][i].candy.getType().equals(Type.REWARD_FRUIT)) {\n          points = this.cells[j][i].candy.getPoints();\n          this.cells[j][i].crush(pool, this.cells);\n          handleChange(points);\n        }\n      }\n      for (var i = 0; i < this.cells.length; i++) {\n        var j = cells.length - 1;\n        var points = 0;\n        while (j > 0) {\n          points = this.cells[j][i].interact(this.cells[j - 1][i], this.pool, this.cells);\n          if (points != 0) {\n            handleChange(points);\n          } else {\n            j = j - 1;\n          }\n        }\n      }\n      for (Cell[] cell : this.cells) {\n        var j = 0;\n        var points = 0;\n        while (j < cells.length - 1) {\n          points = cell[j].interact(cell[j + 1], this.pool, this.cells);\n          if (points != 0) {\n            handleChange(points);\n          } else {\n            j = j + 1;\n          }\n        }\n      }\n      end = System.currentTimeMillis();\n    }\n  }\n}\n"
  },
  {
    "path": "type-object/src/main/java/com/iluwatar/typeobject/Cell.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.typeobject;\n\nimport com.iluwatar.typeobject.Candy.Type;\nimport lombok.AllArgsConstructor;\nimport lombok.NoArgsConstructor;\n\n/**\n * The Cell object is what the game matrix is made of and contains the candy which is to be crushed\n * or collected as reward.\n */\n@AllArgsConstructor\n@NoArgsConstructor\npublic class Cell {\n  Candy candy;\n  int positionX;\n  int positionY;\n\n  void crush(CellPool pool, Cell[][] cellMatrix) {\n    // take out from this position and put back in pool\n    pool.addNewCell(this);\n    this.fillThisSpace(pool, cellMatrix);\n  }\n\n  void fillThisSpace(CellPool pool, Cell[][] cellMatrix) {\n    for (var y = this.positionY; y > 0; y--) {\n      cellMatrix[y][this.positionX] = cellMatrix[y - 1][this.positionX];\n      cellMatrix[y][this.positionX].positionY = y;\n    }\n    var newC = pool.getNewCell();\n    cellMatrix[0][this.positionX] = newC;\n    cellMatrix[0][this.positionX].positionX = this.positionX;\n    cellMatrix[0][this.positionX].positionY = 0;\n  }\n\n  void handleCrush(Cell c, CellPool pool, Cell[][] cellMatrix) {\n    if (this.positionY >= c.positionY) {\n      this.crush(pool, cellMatrix);\n      c.crush(pool, cellMatrix);\n    } else {\n      c.crush(pool, cellMatrix);\n      this.crush(pool, cellMatrix);\n    }\n  }\n\n  int interact(Cell c, CellPool pool, Cell[][] cellMatrix) {\n    if (this.candy.getType().equals(Type.REWARD_FRUIT)\n        || c.candy.getType().equals(Type.REWARD_FRUIT)) {\n      return 0;\n    } else {\n      if (this.candy.name.equals(c.candy.name)) {\n        var pointsWon = this.candy.getPoints() + c.candy.getPoints();\n        handleCrush(c, pool, cellMatrix);\n        return pointsWon;\n      } else {\n        return 0;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "type-object/src/main/java/com/iluwatar/typeobject/CellPool.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.typeobject;\n\nimport com.google.gson.JsonParseException;\nimport com.iluwatar.typeobject.Candy.Type;\nimport java.security.SecureRandom;\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * The CellPool class allows the reuse of crushed cells instead of creation of new cells each time.\n * The reused cell is given a new candy to hold using the randomCode field which holds all the\n * candies available.\n */\n@Slf4j\npublic class CellPool {\n  private static final SecureRandom RANDOM = new SecureRandom();\n  public static final String FRUIT = \"fruit\";\n  public static final String CANDY = \"candy\";\n  List<Cell> pool;\n  int pointer;\n  Candy[] randomCode;\n\n  CellPool(int num) {\n    this.pool = new ArrayList<>(num);\n    try {\n      this.randomCode = assignRandomCandytypes();\n    } catch (Exception e) {\n      LOGGER.error(\"Error occurred: \", e);\n      // manually initialising this.randomCode\n      this.randomCode = new Candy[5];\n      randomCode[0] = new Candy(\"cherry\", FRUIT, Type.REWARD_FRUIT, 20);\n      randomCode[1] = new Candy(\"mango\", FRUIT, Type.REWARD_FRUIT, 20);\n      randomCode[2] = new Candy(\"purple popsicle\", CANDY, Type.CRUSHABLE_CANDY, 10);\n      randomCode[3] = new Candy(\"green jellybean\", CANDY, Type.CRUSHABLE_CANDY, 10);\n      randomCode[4] = new Candy(\"orange gum\", CANDY, Type.CRUSHABLE_CANDY, 10);\n    }\n    for (int i = 0; i < num; i++) {\n      var c = new Cell();\n      c.candy = randomCode[RANDOM.nextInt(randomCode.length)];\n      this.pool.add(c);\n    }\n    this.pointer = num - 1;\n  }\n\n  Cell getNewCell() {\n    var newCell = this.pool.remove(pointer);\n    pointer--;\n    return newCell;\n  }\n\n  void addNewCell(Cell c) {\n    c.candy = randomCode[RANDOM.nextInt(randomCode.length)]; // changing candytype to new\n    this.pool.add(c);\n    pointer++;\n  }\n\n  Candy[] assignRandomCandytypes() throws JsonParseException {\n    var jp = new JsonParser();\n    jp.parse();\n    var randomCode = new Candy[jp.candies.size() - 2]; // exclude generic types 'fruit' and 'candy'\n    var i = 0;\n    for (var e = jp.candies.keys(); e.hasMoreElements(); ) {\n      var s = e.nextElement();\n      if (!s.equals(FRUIT) && !s.equals(CANDY)) {\n        // not generic\n        randomCode[i] = jp.candies.get(s);\n        i++;\n      }\n    }\n    return randomCode;\n  }\n}\n"
  },
  {
    "path": "type-object/src/main/java/com/iluwatar/typeobject/JsonParser.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.typeobject;\n\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonObject;\nimport com.google.gson.JsonParseException;\nimport com.iluwatar.typeobject.Candy.Type;\nimport java.io.InputStreamReader;\nimport java.util.Hashtable;\n\n/** The JsonParser class helps parse the json file candy.json to get all the different candies. */\npublic class JsonParser {\n  Hashtable<String, Candy> candies;\n\n  JsonParser() {\n    this.candies = new Hashtable<>();\n  }\n\n  void parse() throws JsonParseException {\n    var is = this.getClass().getClassLoader().getResourceAsStream(\"candy.json\");\n    var reader = new InputStreamReader(is);\n    var json = (JsonObject) com.google.gson.JsonParser.parseReader(reader);\n    var array = (JsonArray) json.get(\"candies\");\n    for (var item : array) {\n      var candy = (JsonObject) item;\n      var name = candy.get(\"name\").getAsString();\n      var parentName = candy.get(\"parent\").getAsString();\n      var t = candy.get(\"type\").getAsString();\n      var type = Type.CRUSHABLE_CANDY;\n      if (t.equals(\"rewardFruit\")) {\n        type = Type.REWARD_FRUIT;\n      }\n      var points = candy.get(\"points\").getAsInt();\n      var c = new Candy(name, parentName, type, points);\n      this.candies.put(name, c);\n    }\n    setParentAndPoints();\n  }\n\n  void setParentAndPoints() {\n    for (var e = this.candies.keys(); e.hasMoreElements(); ) {\n      var c = this.candies.get(e.nextElement());\n      if (c.parentName == null) {\n        c.parent = null;\n      } else {\n        c.parent = this.candies.get(c.parentName);\n      }\n      if (c.getPoints() == 0 && c.parent != null) {\n        c.setPoints(c.parent.getPoints());\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "type-object/src/main/resources/candy.json",
    "content": "{\"candies\" : [\n  {\n    \"name\" : \"fruit\",\n    \"parent\" : \"null\",\n    \"type\" : \"rewardFruit\",\n    \"points\" : 20\n  },\n  {\n    \"name\" : \"candy\",\n    \"parent\" : \"null\",\n    \"type\" : \"crushableCandy\",\n    \"points\" : 10\n  },\n  {\n    \"name\" : \"cherry\",\n    \"parent\" : \"fruit\",\n    \"type\" : \"rewardFruit\",\n    \"points\" : 0\n  },\n  {\n    \"name\" : \"mango\",\n    \"parent\" : \"fruit\",\n    \"type\" : \"rewardFruit\",\n    \"points\" : 0\n  },\n  {\n    \"name\" : \"purple popsicle\",\n    \"parent\" : \"candy\",\n    \"type\" : \"crushableCandy\",\n    \"points\" : 0\n  },\n  {\n    \"name\" : \"green jellybean\",\n    \"parent\" : \"candy\",\n    \"type\" : \"crushableCandy\",\n    \"points\" : 0\n  },\n  {\n    \"name\" : \"orange gum\",\n    \"parent\" : \"candy\",\n    \"type\" : \"crushableCandy\",\n    \"points\" : 0\n  }\n  ]\n}\n"
  },
  {
    "path": "type-object/src/test/java/com/iluwatar/typeobject/CandyGameTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.typeobject;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.typeobject.Candy.Type;\nimport org.junit.jupiter.api.Test;\n\n/** The CandyGameTest class tests the methods in the {@link CandyGame} class. */\nclass CandyGameTest {\n\n  @Test\n  void adjacentCellsTest() {\n    var cg = new CandyGame(3, new CellPool(9));\n    var arr1 = cg.adjacentCells(0, 0);\n    var arr2 = cg.adjacentCells(1, 2);\n    var arr3 = cg.adjacentCells(1, 1);\n    assertTrue(arr1.size() == 2 && arr2.size() == 3 && arr3.size() == 4);\n  }\n\n  @Test\n  void continueRoundTest() {\n    var matrix = new Cell[2][2];\n    var c1 = new Candy(\"green jelly\", \"jelly\", Type.CRUSHABLE_CANDY, 5);\n    var c2 = new Candy(\"purple jelly\", \"jelly\", Type.CRUSHABLE_CANDY, 5);\n    var c3 = new Candy(\"green apple\", \"apple\", Type.REWARD_FRUIT, 10);\n    matrix[0][0] = new Cell(c1, 0, 0);\n    matrix[0][1] = new Cell(c2, 1, 0);\n    matrix[1][0] = new Cell(c3, 0, 1);\n    matrix[1][1] = new Cell(c2, 1, 1);\n    var p = new CellPool(4);\n    var cg = new CandyGame(2, p);\n    cg.cells = matrix;\n    var fruitInLastRow = cg.continueRound();\n    matrix[1][0].crush(p, matrix);\n    matrix[0][0] = new Cell(c3, 0, 0);\n    var matchingCandy = cg.continueRound();\n    matrix[0][1].crush(p, matrix);\n    matrix[0][1] = new Cell(c3, 1, 0);\n    var noneLeft = cg.continueRound();\n    assertTrue(fruitInLastRow && matchingCandy && !noneLeft);\n  }\n}\n"
  },
  {
    "path": "type-object/src/test/java/com/iluwatar/typeobject/CellPoolTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.typeobject;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.Hashtable;\nimport org.junit.jupiter.api.Test;\n\n/** The CellPoolTest class tests the methods in the {@link CellPool} class. */\nclass CellPoolTest {\n\n  @Test\n  void assignRandomCandyTypesTest() {\n    var cp = new CellPool(10);\n    var ht = new Hashtable<String, Boolean>();\n    var parentTypes = 0;\n    for (var i = 0; i < cp.randomCode.length; i++) {\n      ht.putIfAbsent(cp.randomCode[i].name, true);\n      if (cp.randomCode[i].name.equals(\"fruit\") || cp.randomCode[i].name.equals(\"candy\")) {\n        parentTypes++;\n      }\n    }\n    assertTrue(ht.size() == 5 && parentTypes == 0);\n  }\n}\n"
  },
  {
    "path": "type-object/src/test/java/com/iluwatar/typeobject/CellTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.typeobject;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport com.iluwatar.typeobject.Candy.Type;\nimport org.junit.jupiter.api.Test;\n\n/** The CellTest class tests the methods in the {@link Cell} class. */\nclass CellTest {\n\n  @Test\n  void interactTest() {\n    var c1 = new Candy(\"green jelly\", \"jelly\", Type.CRUSHABLE_CANDY, 5);\n    var c2 = new Candy(\"green apple\", \"apple\", Type.REWARD_FRUIT, 10);\n    var matrix = new Cell[4][4];\n    matrix[0][0] = new Cell(c1, 0, 0);\n    matrix[0][1] = new Cell(c1, 1, 0);\n    matrix[0][2] = new Cell(c2, 2, 0);\n    matrix[0][3] = new Cell(c1, 3, 0);\n    var cp = new CellPool(5);\n    var points1 = matrix[0][0].interact(matrix[0][1], cp, matrix);\n    var points2 = matrix[0][2].interact(matrix[0][3], cp, matrix);\n    assertTrue(points1 > 0 && points2 == 0);\n  }\n\n  @Test\n  void crushTest() {\n    var c1 = new Candy(\"green jelly\", \"jelly\", Type.CRUSHABLE_CANDY, 5);\n    var c2 = new Candy(\"purple candy\", \"candy\", Type.CRUSHABLE_CANDY, 5);\n    var matrix = new Cell[4][4];\n    matrix[0][0] = new Cell(c1, 0, 0);\n    matrix[1][0] = new Cell(c2, 0, 1);\n    matrix[1][0].crush(new CellPool(5), matrix);\n    assertEquals(\"green jelly\", matrix[1][0].candy.name);\n  }\n}\n"
  },
  {
    "path": "unit-of-work/README.md",
    "content": "---\ntitle: \"Unit of Work Pattern in Java: Orchestrating Efficient Transaction Management\"\nshortTitle: Unit of Work\ndescription: \"Discover how the Unit of Work pattern can streamline your Java applications. This guide offers a comprehensive explanation, real-world applications, and code examples to enhance your project’s efficiency and maintain data integrity.\"\ncategory: Data access\nlanguage: en\ntag:\n  - Data access\n  - Decoupling\n  - Persistence\n  - Transactions\n---\n\n## Intent of Unit Of Work Design Pattern\n\nLearn how the Java Unit of Work pattern expertly manages and maintains a list of objects impacted by business transactions, coordinating database changes and solving concurrency issues effectively.\n\n## Detailed Explanation of Unit Of Work Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a library scenario where a librarian meticulously tracks all books borrowed and returned, utilizing the Unit of Work design pattern to update the inventory system efficiently. Instead of updating the library's inventory system every time a single transaction occurs, the librarian keeps a list of all the changes and updates the system once at the end of the day. This approach ensures that all changes are processed together, maintaining the integrity of the inventory and reducing the number of individual updates needed. This is analogous to the Unit of Work pattern in software, where all changes to a set of objects are tracked and committed as a single transaction to maintain consistency and efficiency. \n\nIn plain words\n\n> The Unit of Work pattern tracks changes to objects during a transaction and commits all changes as a single unit to ensure consistency and efficiency. \n\n[MartinFowler.com](https://martinfowler.com/eaaCatalog/unitOfWork.html) says\n\n> Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.\n\nFlowchart\n\n![Unit of Work Pattern Flowchart](./etc/unit-of-work-flowchart.png)\n\n## Programmatic Example of Unit of Work Pattern in Java\n\nArms dealer has a database containing weapon information. Merchants all over the town are constantly updating this information causing a high load on the database server. To make the load more manageable we apply to Unit of Work pattern to send many small updates in batches.\n\nHere's the `Weapon` entity that is being persisted in the database.\n\n```java\n@Getter\n@RequiredArgsConstructor\npublic class Weapon {\n    private final Integer id;\n    private final String name;\n}\n```\n\nThe essence of the implementation is the `ArmsDealer` implementing the Unit of Work pattern. It maintains a map of database operations (`context`) that need to be done and when `commit` is called it applies them in a single batch.\n\n```java\npublic interface IUnitOfWork<T> {\n    \n  String INSERT = \"INSERT\";\n  String DELETE = \"DELETE\";\n  String MODIFY = \"MODIFY\";\n\n  void registerNew(T entity);\n\n  void registerModified(T entity);\n\n  void registerDeleted(T entity);\n\n  void commit();\n}\n```\n\n```java\n@Slf4j\n@RequiredArgsConstructor\npublic class ArmsDealer implements IUnitOfWork<Weapon> {\n\n    private final Map<String, List<Weapon>> context;\n    private final WeaponDatabase weaponDatabase;\n\n    @Override\n    public void registerNew(Weapon weapon) {\n        LOGGER.info(\"Registering {} for insert in context.\", weapon.getName());\n        register(weapon, UnitActions.INSERT.getActionValue());\n    }\n\n    @Override\n    public void registerModified(Weapon weapon) {\n        LOGGER.info(\"Registering {} for modify in context.\", weapon.getName());\n        register(weapon, UnitActions.MODIFY.getActionValue());\n\n    }\n\n    @Override\n    public void registerDeleted(Weapon weapon) {\n        LOGGER.info(\"Registering {} for delete in context.\", weapon.getName());\n        register(weapon, UnitActions.DELETE.getActionValue());\n    }\n\n    private void register(Weapon weapon, String operation) {\n        var weaponsToOperate = context.get(operation);\n        if (weaponsToOperate == null) {\n            weaponsToOperate = new ArrayList<>();\n        }\n        weaponsToOperate.add(weapon);\n        context.put(operation, weaponsToOperate);\n    }\n\n    @Override\n    public void commit() {\n        if (context == null || context.isEmpty()) {\n            return;\n        }\n        LOGGER.info(\"Commit started\");\n        if (context.containsKey(UnitActions.INSERT.getActionValue())) {\n            commitInsert();\n        }\n\n        if (context.containsKey(UnitActions.MODIFY.getActionValue())) {\n            commitModify();\n        }\n        if (context.containsKey(UnitActions.DELETE.getActionValue())) {\n            commitDelete();\n        }\n        LOGGER.info(\"Commit finished.\");\n    }\n\n    private void commitInsert() {\n        var weaponsToBeInserted = context.get(UnitActions.INSERT.getActionValue());\n        for (var weapon : weaponsToBeInserted) {\n            LOGGER.info(\"Inserting a new weapon {} to sales rack.\", weapon.getName());\n            weaponDatabase.insert(weapon);\n        }\n    }\n\n    private void commitModify() {\n        var modifiedWeapons = context.get(UnitActions.MODIFY.getActionValue());\n        for (var weapon : modifiedWeapons) {\n            LOGGER.info(\"Scheduling {} for modification work.\", weapon.getName());\n            weaponDatabase.modify(weapon);\n        }\n    }\n\n    private void commitDelete() {\n        var deletedWeapons = context.get(UnitActions.DELETE.getActionValue());\n        for (var weapon : deletedWeapons) {\n            LOGGER.info(\"Scrapping {}.\", weapon.getName());\n            weaponDatabase.delete(weapon);\n        }\n    }\n}\n```\n\nHere is how the whole app is put together.\n\n```java\npublic static void main(String[] args) {\n    // create some weapons\n    var enchantedHammer = new Weapon(1, \"enchanted hammer\");\n    var brokenGreatSword = new Weapon(2, \"broken great sword\");\n    var silverTrident = new Weapon(3, \"silver trident\");\n\n    // create repository\n    var weaponRepository = new ArmsDealer(new HashMap<>(),\n            new WeaponDatabase());\n\n    // perform operations on the weapons\n    weaponRepository.registerNew(enchantedHammer);\n    weaponRepository.registerModified(silverTrident);\n    weaponRepository.registerDeleted(brokenGreatSword);\n    weaponRepository.commit();\n}\n```\n\nHere is the console output.\n\n```\n21:39:21.984 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Registering enchanted hammer for insert in context.\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Registering silver trident for modify in context.\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Registering broken great sword for delete in context.\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Commit started\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Inserting a new weapon enchanted hammer to sales rack.\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Scheduling silver trident for modification work.\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Scrapping broken great sword.\n21:39:21.989 [main] INFO com.iluwatar.unitofwork.ArmsDealer - Commit finished.\n```\n\n## When to Use the Unit Of Work Pattern in Java\n\n* The Unit of Work pattern is ideal for managing multiple database operations in Java that must be executed as a single transaction, ensuring data consistency and integrity.\n* Ideal in scenarios where changes to the business objects must be tracked and saved in a coordinated manner.\n* Useful when working with object-relational mapping (ORM) frameworks in Java such as Hibernate.\n\n## Unit Of Work Pattern Java Tutorials\n\n* [Repository and Unit of Work Pattern (Wolfgang Ofner)](https://www.programmingwithwolfgang.com/repository-and-unit-of-work-pattern/)\n* [Unit Of Work Design Pattern (Code Project)](https://www.codeproject.com/Articles/581487/Unit-of-Work-Design-Pattern)\n* [Unit of Work - a Design Pattern (Mono)](https://mono.software/2017/01/13/unit-of-work-a-design-pattern/)\n\n## Real-World Applications of Unit of Work Pattern in Java\n\n* Implementations in Java-based ORM frameworks like Hibernate.\n* Enterprise applications where multiple database operations need to be atomic.\n* Complex transactional systems where multiple objects are modified and persisted together.\n\n## Benefits and Trade-offs of Unit Of Work Pattern\n\nBenefits:\n\n* Ensures data integrity by managing transactions effectively.\n* Reduces the number of database calls by batching them together.\n* Simplifies the persistence logic by decoupling transaction management from the business logic.\n\nTrade-offs:\n\n* Can introduce complexity in managing the life cycle of objects within the unit of work.\n* Potential performance overhead if not managed properly, especially with large datasets.\n\n## Related Java Design Patterns\n\n* [Identity Map](https://java-design-patterns.com/patterns/identity-map/): Helps to ensure that each object is only loaded once per transaction, reducing redundancy and improving performance.\n* [Repository](https://java-design-patterns.com/patterns/repository/): Often used in conjunction with Unit of Work to abstract the persistence logic and provide a cleaner way to access data.\n* [Transaction Script](https://java-design-patterns.com/patterns/transaction-script/): While different in its procedural approach, it can complement Unit of Work by managing transactional logic at a higher level.\n\n## References and Credits\n\n* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3wlDrze)\n* [Java Persistence with Hibernate](https://amzn.to/44tP1ox)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [Unit Of Work (Martin Fowler)](https://martinfowler.com/eaaCatalog/unitOfWork.html)\n"
  },
  {
    "path": "unit-of-work/etc/unit-of-work.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.2.1\" icons=\"true\" always-add-relationships=\"false\" generalizations=\"true\" realizations=\"true\" \n  associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.unitofwork.WeaponDatabase\" project=\"unit-of-work\"\n    file=\"/unit-of-work/src/main/java/com/iluwatar/unitofwork/StudentDatabase.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"170\" y=\"406\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"2\" language=\"java\" name=\"com.iluwatar.unitofwork.IUnitOfWork\" project=\"unit-of-work\" \n    file=\"/unit-of-work/src/main/java/com/iluwatar/unitofwork/IUnitOfWork.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"356\" y=\"433\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.unitofwork.App\" project=\"unit-of-work\" \n    file=\"/unit-of-work/src/main/java/com/iluwatar/unitofwork/App.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"88\" y=\"85\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.unitofwork.ArmsDealer\" project=\"unit-of-work\"\n    file=\"/unit-of-work/src/main/java/com/iluwatar/unitofwork/StudentRepository.java\" binary=\"false\" \n    corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"377\" y=\"166\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"5\" language=\"java\" name=\"com.iluwatar.unitofwork.Weapon\" project=\"unit-of-work\"\n    file=\"/unit-of-work/src/main/java/com/iluwatar/unitofwork/Student.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"696\" y=\"130\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <realization id=\"6\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"2\"/>  \n  </realization>  \n  <association id=\"7\">    \n    <end type=\"SOURCE\" refId=\"4\" navigable=\"false\">      \n      <attribute id=\"8\" name=\"studentDatabase\"/>      \n      <multiplicity id=\"9\" minimum=\"0\" maximum=\"1\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"1\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "unit-of-work/etc/unit-of-work.urm.puml",
    "content": "@startuml\npackage com.iluwatar.unitofwork {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  interface IUnitOfWork<T> {\n    + DELETE : String {static}\n    + INSERT : String {static}\n    + MODIFY : String {static}\n    + commit() {abstract}\n    + registerDeleted(T) {abstract}\n    + registerModified(T) {abstract}\n    + registerNew(T) {abstract}\n  }\n  class Student {\n    - address : String\n    - id : Integer\n    - name : String\n    + Student(id : Integer, name : String, address : String)\n    + getAddress() : String\n    + getId() : Integer\n    + getName() : String\n  }\n  class StudentDatabase {\n    + StudentDatabase()\n    + delete(student : Student)\n    + insert(student : Student)\n    + modify(student : Student)\n  }\n  class StudentRepository {\n    - LOGGER : Logger {static}\n    - context : Map<String, List<Student>>\n    - studentDatabase : StudentDatabase\n    + StudentRepository(context : Map<String, List<Student>>, studentDatabase : StudentDatabase)\n    + commit()\n    - commitDelete()\n    - commitInsert()\n    - commitModify()\n    - register(student : Student, operation : String)\n    + registerDeleted(student : Student)\n    + registerModified(student : Student)\n    + registerNew(student : Student)\n  }\n}\nStudentRepository -->  \"-studentDatabase\" StudentDatabase\nStudentRepository ..|> IUnitOfWork \n@enduml"
  },
  {
    "path": "unit-of-work/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>unit-of-work</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.unitofwork.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "unit-of-work/src/main/java/com/iluwatar/unitofwork/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.unitofwork;\n\nimport java.util.HashMap;\n\n/** {@link App} Application demonstrating unit of work pattern. */\npublic class App {\n  /**\n   * Program entry point.\n   *\n   * @param args no argument sent\n   */\n  public static void main(String[] args) {\n    // create some weapons\n    var enchantedHammer = new Weapon(1, \"enchanted hammer\");\n    var brokenGreatSword = new Weapon(2, \"broken great sword\");\n    var silverTrident = new Weapon(3, \"silver trident\");\n\n    // create repository\n    var weaponRepository = new ArmsDealer(new HashMap<>(), new WeaponDatabase());\n\n    // perform operations on the weapons\n    weaponRepository.registerNew(enchantedHammer);\n    weaponRepository.registerModified(silverTrident);\n    weaponRepository.registerDeleted(brokenGreatSword);\n    weaponRepository.commit();\n  }\n}\n"
  },
  {
    "path": "unit-of-work/src/main/java/com/iluwatar/unitofwork/ArmsDealer.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.unitofwork;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport lombok.RequiredArgsConstructor;\nimport lombok.extern.slf4j.Slf4j;\n\n/** {@link ArmsDealer} Weapon repository that supports unit of work for weapons. */\n@Slf4j\n@RequiredArgsConstructor\npublic class ArmsDealer implements UnitOfWork<Weapon> {\n\n  private final Map<String, List<Weapon>> context;\n  private final WeaponDatabase weaponDatabase;\n\n  @Override\n  public void registerNew(Weapon weapon) {\n    LOGGER.info(\"Registering {} for insert in context.\", weapon.getName());\n    register(weapon, UnitActions.INSERT.getActionValue());\n  }\n\n  @Override\n  public void registerModified(Weapon weapon) {\n    LOGGER.info(\"Registering {} for modify in context.\", weapon.getName());\n    register(weapon, UnitActions.MODIFY.getActionValue());\n  }\n\n  @Override\n  public void registerDeleted(Weapon weapon) {\n    LOGGER.info(\"Registering {} for delete in context.\", weapon.getName());\n    register(weapon, UnitActions.DELETE.getActionValue());\n  }\n\n  private void register(Weapon weapon, String operation) {\n    var weaponsToOperate = context.get(operation);\n    if (weaponsToOperate == null) {\n      weaponsToOperate = new ArrayList<>();\n    }\n    weaponsToOperate.add(weapon);\n    context.put(operation, weaponsToOperate);\n  }\n\n  /** All UnitOfWork operations are batched and executed together on commit only. */\n  @Override\n  public void commit() {\n    if (context == null || context.isEmpty()) {\n      return;\n    }\n    LOGGER.info(\"Commit started\");\n    if (context.containsKey(UnitActions.INSERT.getActionValue())) {\n      commitInsert();\n    }\n\n    if (context.containsKey(UnitActions.MODIFY.getActionValue())) {\n      commitModify();\n    }\n    if (context.containsKey(UnitActions.DELETE.getActionValue())) {\n      commitDelete();\n    }\n    LOGGER.info(\"Commit finished.\");\n  }\n\n  private void commitInsert() {\n    var weaponsToBeInserted = context.get(UnitActions.INSERT.getActionValue());\n    for (var weapon : weaponsToBeInserted) {\n      LOGGER.info(\"Inserting a new weapon {} to sales rack.\", weapon.getName());\n      weaponDatabase.insert(weapon);\n    }\n  }\n\n  private void commitModify() {\n    var modifiedWeapons = context.get(UnitActions.MODIFY.getActionValue());\n    for (var weapon : modifiedWeapons) {\n      LOGGER.info(\"Scheduling {} for modification work.\", weapon.getName());\n      weaponDatabase.modify(weapon);\n    }\n  }\n\n  private void commitDelete() {\n    var deletedWeapons = context.get(UnitActions.DELETE.getActionValue());\n    for (var weapon : deletedWeapons) {\n      LOGGER.info(\"Scrapping {}.\", weapon.getName());\n      weaponDatabase.delete(weapon);\n    }\n  }\n}\n"
  },
  {
    "path": "unit-of-work/src/main/java/com/iluwatar/unitofwork/UnitActions.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.unitofwork;\n\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/** Enum representing unit actions. */\n@Getter\n@RequiredArgsConstructor\npublic enum UnitActions {\n  INSERT(\"INSERT\"),\n  DELETE(\"DELETE\"),\n  MODIFY(\"MODIFY\");\n\n  private final String actionValue;\n}\n"
  },
  {
    "path": "unit-of-work/src/main/java/com/iluwatar/unitofwork/UnitOfWork.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.unitofwork;\n\n/**\n * UnitOfWork interface.\n *\n * @param <T> Any generic entity\n */\npublic interface UnitOfWork<T> {\n\n  /** Any register new operation occurring on UnitOfWork is only going to be performed on commit. */\n  void registerNew(T entity);\n\n  /**\n   * Any register modify operation occurring on UnitOfWork is only going to be performed on commit.\n   */\n  void registerModified(T entity);\n\n  /**\n   * Any register delete operation occurring on UnitOfWork is only going to be performed on commit.\n   */\n  void registerDeleted(T entity);\n\n  /** All UnitOfWork operations batched together executed in commit only. */\n  void commit();\n}\n"
  },
  {
    "path": "unit-of-work/src/main/java/com/iluwatar/unitofwork/Weapon.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.unitofwork;\n\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\n/** {@link Weapon} is an entity. */\n@Getter\n@RequiredArgsConstructor\npublic class Weapon {\n\n  private final Integer id;\n  private final String name;\n}\n"
  },
  {
    "path": "unit-of-work/src/main/java/com/iluwatar/unitofwork/WeaponDatabase.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.unitofwork;\n\n/** Act as database for weapon records. */\npublic class WeaponDatabase {\n\n  public void insert(Weapon weapon) {\n    // Some insert logic to DB\n  }\n\n  public void modify(Weapon weapon) {\n    // Some modify logic to DB\n  }\n\n  public void delete(Weapon weapon) {\n    // Some delete logic to DB\n  }\n}\n"
  },
  {
    "path": "unit-of-work/src/test/java/com/iluwatar/unitofwork/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.unitofwork;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** AppTest */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "unit-of-work/src/test/java/com/iluwatar/unitofwork/ArmsDealerTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.unitofwork;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport org.junit.jupiter.api.Test;\n\n/** tests {@link ArmsDealer} */\nclass ArmsDealerTest {\n  private final Weapon weapon1 = new Weapon(1, \"battle ram\");\n  private final Weapon weapon2 = new Weapon(1, \"wooden lance\");\n\n  private final Map<String, List<Weapon>> context = new HashMap<>();\n  private final WeaponDatabase weaponDatabase = mock(WeaponDatabase.class);\n  private final ArmsDealer armsDealer = new ArmsDealer(context, weaponDatabase);\n\n  @Test\n  void shouldSaveNewStudentWithoutWritingToDb() {\n    armsDealer.registerNew(weapon1);\n    armsDealer.registerNew(weapon2);\n\n    assertEquals(2, context.get(UnitActions.INSERT.getActionValue()).size());\n    verifyNoMoreInteractions(weaponDatabase);\n  }\n\n  @Test\n  void shouldSaveDeletedStudentWithoutWritingToDb() {\n    armsDealer.registerDeleted(weapon1);\n    armsDealer.registerDeleted(weapon2);\n\n    assertEquals(2, context.get(UnitActions.DELETE.getActionValue()).size());\n    verifyNoMoreInteractions(weaponDatabase);\n  }\n\n  @Test\n  void shouldSaveModifiedStudentWithoutWritingToDb() {\n    armsDealer.registerModified(weapon1);\n    armsDealer.registerModified(weapon2);\n\n    assertEquals(2, context.get(UnitActions.MODIFY.getActionValue()).size());\n    verifyNoMoreInteractions(weaponDatabase);\n  }\n\n  @Test\n  void shouldSaveAllLocalChangesToDb() {\n    context.put(UnitActions.INSERT.getActionValue(), List.of(weapon1));\n    context.put(UnitActions.MODIFY.getActionValue(), List.of(weapon1));\n    context.put(UnitActions.DELETE.getActionValue(), List.of(weapon1));\n\n    armsDealer.commit();\n\n    verify(weaponDatabase, times(1)).insert(weapon1);\n    verify(weaponDatabase, times(1)).modify(weapon1);\n    verify(weaponDatabase, times(1)).delete(weapon1);\n  }\n\n  @Test\n  void shouldNotWriteToDbIfContextIsNull() {\n    var weaponRepository = new ArmsDealer(null, weaponDatabase);\n\n    weaponRepository.commit();\n\n    verifyNoMoreInteractions(weaponDatabase);\n  }\n\n  @Test\n  void shouldNotWriteToDbIfNothingToCommit() {\n    var weaponRepository = new ArmsDealer(new HashMap<>(), weaponDatabase);\n\n    weaponRepository.commit();\n\n    verifyNoMoreInteractions(weaponDatabase);\n  }\n\n  @Test\n  void shouldNotInsertToDbIfNoRegisteredStudentsToBeCommitted() {\n    context.put(UnitActions.MODIFY.getActionValue(), List.of(weapon1));\n    context.put(UnitActions.DELETE.getActionValue(), List.of(weapon1));\n\n    armsDealer.commit();\n\n    verify(weaponDatabase, never()).insert(weapon1);\n  }\n\n  @Test\n  void shouldNotModifyToDbIfNotRegisteredStudentsToBeCommitted() {\n    context.put(UnitActions.INSERT.getActionValue(), List.of(weapon1));\n    context.put(UnitActions.DELETE.getActionValue(), List.of(weapon1));\n\n    armsDealer.commit();\n\n    verify(weaponDatabase, never()).modify(weapon1);\n  }\n\n  @Test\n  void shouldNotDeleteFromDbIfNotRegisteredStudentsToBeCommitted() {\n    context.put(UnitActions.INSERT.getActionValue(), List.of(weapon1));\n    context.put(UnitActions.MODIFY.getActionValue(), List.of(weapon1));\n\n    armsDealer.commit();\n\n    verify(weaponDatabase, never()).delete(weapon1);\n  }\n}\n"
  },
  {
    "path": "update-method/README.md",
    "content": "---\ntitle: \"Update Method Pattern in Java: Enhancing Game Loop Efficiency with Systematic Updates\"\nshortTitle: Update Method\ndescription: \"Explore the Update Method design pattern for Java, ideal for real-time games and applications. Learn how it optimizes performance by updating objects frame-by-frame to maintain synchronized, efficient operations.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Abstraction\n  - Data processing\n  - Decoupling\n  - Event-driven\n  - Game programming\n  - Polymorphism\n---\n\n## Also known as\n\n* Update Mechanism\n\n## Intent of Update Method Design Pattern\n\nThe Update Method pattern in Java simulates a collection of independent objects by telling each to process one frame of behavior at a time.\n\n## Detailed Explanation of Update Method Pattern with Real-World Examples\n\nReal-world example\n\n> A real-world example of the Update Method design pattern is a weather monitoring system. In this system, multiple display devices (such as a mobile app, a website widget, and a wall-mounted digital display) need to show the current weather conditions. These displays subscribe to updates from a central weather station, which collects data from various sensors (temperature, humidity, wind speed, etc.). When the weather station detects new data, it triggers an update method that pushes the new information to all subscribed display devices, ensuring they all show the latest weather conditions simultaneously. This ensures that all displays are synchronized and updated without the need for each device to independently check for updates.\n\nIn plain words\n\n> The Update Method design pattern processes system object behavior one frame at a time\n\ngameprogrammingpatterns.com says\n\n> The game world maintains a collection of objects. Each object implements an update method that simulates one frame of the object’s behavior. Each frame, the game updates every object in the collection.\n\nSequence diagram\n\n![Update Method Sequence Diagram](./etc/update-method-sequence-diagram.png)\n\n## Programmatic Example of Update Method Pattern in Java\n\nThe Update Method design pattern is a behavioral pattern that simulates a collection of independent game or application objects by telling each to process one frame of behavior at a time. This pattern is commonly used in game development, where each object in the game world needs to be updated once per frame.\n\nThe `World` class represents the game world. It maintains a list of entities (`List<Entity> entities`) and a boolean flag (`isRunning`) to indicate whether the game is running.\n\n```java\npublic class World {\n\n  protected List<Entity> entities;\n  protected volatile boolean isRunning;\n\n  public World() {\n    entities = new ArrayList<>();\n    isRunning = false;\n  }\n  // Other properties and methods...\n}\n```\n\nThe `gameLoop` method is the main game loop. It continuously processes user input, updates the game state, and renders the next frame as long as the game is running.\n\n```java\nprivate void gameLoop() {\n  while (isRunning) {\n    processInput();\n    update();\n    render();\n  }\n}\n```\n\nThe `processInput` method simulates handling user input. In this case, it simply introduces a random time lag to simulate real-life game situations.\n\n```java\nprivate void processInput() {\n  try {\n    int lag = new SecureRandom().nextInt(200) + 50;\n    Thread.sleep(lag);\n  } catch (InterruptedException e) {\n    LOGGER.error(e.getMessage());\n    Thread.currentThread().interrupt();\n  }\n}\n```\n\nThe `update` method is where the Update Method pattern is implemented. It iterates over all entities in the game world and calls their `update` method, allowing each entity to process one frame of behavior.\n\n```java\nprivate void update() {\n  for (var entity : entities) {\n    entity.update();\n  }\n}\n```\n\nThe `render` method is responsible for rendering the next frame. In this example, it does nothing as it's not related to the pattern.\n\n```java\nprivate void render() {\n  // Does Nothing\n}\n```\n\nThe `run` and `stop` methods are used to start and stop the game loop.\n\n```java\npublic void run() {\n  LOGGER.info(\"Start game.\");\n  isRunning = true;\n  var thread = new Thread(this::gameLoop);\n  thread.start();\n}\n\npublic void stop() {\n  LOGGER.info(\"Stop game.\");\n  isRunning = false;\n}\n```\n\nThe `addEntity` method is used to add new entities to the game world.\n\n```java\npublic void addEntity(Entity entity) {\n  entities.add(entity);\n}\n```\n\nIn the `App` class, we can see how the `World` class and its methods are used to create a game world, add entities to it, and start the game loop.\n\n```java\n@Slf4j\npublic class App {\n\n    private static final int GAME_RUNNING_TIME = 2000;\n\n    public static void main(String[] args) {\n        try {\n            var world = new World();\n            var skeleton1 = new Skeleton(1, 10);\n            var skeleton2 = new Skeleton(2, 70);\n            var statue = new Statue(3, 20);\n            world.addEntity(skeleton1);\n            world.addEntity(skeleton2);\n            world.addEntity(statue);\n            world.run();\n            Thread.sleep(GAME_RUNNING_TIME);\n            world.stop();\n        } catch (InterruptedException e) {\n            LOGGER.error(e.getMessage());\n        }\n    }\n}\n```\n\nConsole output:\n\n```\n14:46:33.181 [main] INFO com.iluwatar.updatemethod.World -- Start game.\n14:46:33.280 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 11.\n14:46:33.281 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 71.\n14:46:33.452 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 12.\n14:46:33.452 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 72.\n14:46:33.621 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 13.\n14:46:33.621 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 73.\n14:46:33.793 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 14.\n14:46:33.793 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 74.\n14:46:33.885 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 15.\n14:46:33.885 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 75.\n14:46:34.113 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 16.\n14:46:34.113 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 76.\n14:46:34.324 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 17.\n14:46:34.324 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 77.\n14:46:34.574 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 18.\n14:46:34.575 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 78.\n14:46:34.730 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 19.\n14:46:34.731 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 79.\n14:46:34.803 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 20.\n14:46:34.803 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 80.\n14:46:34.979 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 21.\n14:46:34.979 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 81.\n14:46:35.045 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 22.\n14:46:35.046 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 82.\n14:46:35.187 [main] INFO com.iluwatar.updatemethod.World -- Stop game.\n14:46:35.288 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 1 is on position 23.\n14:46:35.289 [Thread-0] INFO com.iluwatar.updatemethod.Skeleton -- Skeleton 2 is on position 83.\n```\n\nThis is a basic implementation of the Update Method pattern. In a real-world application, the `Entity` class would likely have additional methods and properties, and the `update` method would contain more complex logic to simulate the entity's behavior.\n\n## When to Use the Update Method Pattern in Java\n\nUpdate Method works well when:\n\n* Typically applied in scenarios where multiple objects need synchronous updates without the overhead of manual synchronization, making it a go-to for advanced Java developers.\n* The application has a number of objects or systems that need to run simultaneously.\n* Each object’s behavior is mostly independent of the others.\n* The objects need to be simulated over time.\n\n## Real-World Applications of Update Method Pattern in Java\n\n* Real-time games and data processing applications where world objects need to be updated once per frame.\n\n## Benefits and Trade-offs of Update Method Pattern\n\nBenefits:\n\n* Each entity encapsulates its own behavior\n* Makes it easy to add and remove entities\n* Keeps the main loop uncluttered\n\nTrade-offs:\n\n* Increases complexity due to yielding control every frame\n* The state needs to be stored to enable resuming updates after each frame\n* Entities are simulated each frame, but they are not truly concurrent\n\n## Related Java Design Patterns\n\n* [Component](https://java-design-patterns.com/patterns/component/): Often used in game development to allow entities to be composed of various components, each potentially having its own update method.\n* [Game Loop](https://java-design-patterns.com/patterns/game-loop/): Continuously updates game state and renders the game, which may include the Update Method for various game objects.\n\n## References and Credits\n\n* [Game Programming Patterns](https://amzn.to/3wLTbvr)\n* [Game Programming Patterns - Update Method](http://gameprogrammingpatterns.com/update-method.html)\n"
  },
  {
    "path": "update-method/etc/update-method.urm.puml",
    "content": "@startuml\npackage com.iluwatar.updatemethod {\n  class App {\n    - GAME_RUNNING_TIME : int {static}\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  abstract class Entity {\n    # id : int\n    # logger : Logger\n    # position : int\n    + Entity(id : int)\n    + getPosition() : int\n    + setPosition(position : int)\n    + update() {abstract}\n  }\n  class Skeleton {\n    - PATROLLING_LEFT_BOUNDING : int {static}\n    - PATROLLING_RIGHT_BOUNDING : int {static}\n    # patrollingLeft : boolean\n    + Skeleton(id : int)\n    + Skeleton(id : int, position : int)\n    + update()\n  }\n  class Statue {\n    # delay : int\n    # frames : int\n    + Statue(id : int)\n    + Statue(id : int, delay : int)\n    - shootLightning()\n    + update()\n  }\n  class World {\n    - LOGGER : Logger {static}\n    # entities : List<Entity>\n    # isRunning : boolean\n    + World()\n    + addEntity(entity : Entity)\n    - gameLoop()\n    - processInput()\n    - render()\n    + run()\n    + stop()\n    - update()\n  }\n}\nWorld -->  \"-entities\" Entity\nSkeleton --|> Entity \nStatue --|> Entity \n@enduml\n"
  },
  {
    "path": "update-method/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <parent>\n    <artifactId>java-design-patterns</artifactId>\n    <groupId>com.iluwatar</groupId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <modelVersion>4.0.0</modelVersion>\n  <artifactId>update-method</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.updatemethod.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "update-method/src/main/java/com/iluwatar/updatemethod/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.updatemethod;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * This pattern simulate a collection of independent objects by telling each to process one frame of\n * behavior at a time. The game world maintains a collection of objects. Each object implements an\n * update method that simulates one frame of the object’s behavior. Each frame, the game updates\n * every object in the collection.\n */\n@Slf4j\npublic class App {\n\n  private static final int GAME_RUNNING_TIME = 2000;\n\n  /**\n   * Program entry point.\n   *\n   * @param args runtime arguments\n   */\n  public static void main(String[] args) {\n    try {\n      var world = new World();\n      var skeleton1 = new Skeleton(1, 10);\n      var skeleton2 = new Skeleton(2, 70);\n      var statue = new Statue(3, 20);\n      world.addEntity(skeleton1);\n      world.addEntity(skeleton2);\n      world.addEntity(statue);\n      world.run();\n      Thread.sleep(GAME_RUNNING_TIME);\n      world.stop();\n    } catch (InterruptedException e) {\n      LOGGER.error(e.getMessage());\n    }\n  }\n}\n"
  },
  {
    "path": "update-method/src/main/java/com/iluwatar/updatemethod/Entity.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.updatemethod;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/** Abstract class for all the entity types. */\npublic abstract class Entity {\n\n  protected final Logger logger = LoggerFactory.getLogger(this.getClass());\n\n  protected int id;\n\n  @Getter @Setter protected int position;\n\n  public Entity(int id) {\n    this.id = id;\n    this.position = 0;\n  }\n\n  public abstract void update();\n}\n"
  },
  {
    "path": "update-method/src/main/java/com/iluwatar/updatemethod/Skeleton.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.updatemethod;\n\n/**\n * Skeletons are always patrolling on the game map. Initially all the skeletons patrolling to the\n * right, and after them reach the bounding, it will start patrolling to the left. For each frame,\n * one skeleton will move 1 position step.\n */\npublic class Skeleton extends Entity {\n\n  private static final int PATROLLING_LEFT_BOUNDING = 0;\n\n  private static final int PATROLLING_RIGHT_BOUNDING = 100;\n\n  protected boolean patrollingLeft;\n\n  /**\n   * Constructor of Skeleton.\n   *\n   * @param id id of skeleton\n   */\n  public Skeleton(int id) {\n    super(id);\n    patrollingLeft = false;\n  }\n\n  /**\n   * Constructor of Skeleton.\n   *\n   * @param id id of skeleton\n   * @param position position of skeleton\n   */\n  public Skeleton(int id, int position) {\n    super(id);\n    this.position = position;\n    patrollingLeft = false;\n  }\n\n  @Override\n  public void update() {\n    if (patrollingLeft) {\n      position -= 1;\n      if (position == PATROLLING_LEFT_BOUNDING) {\n        patrollingLeft = false;\n      }\n    } else {\n      position += 1;\n      if (position == PATROLLING_RIGHT_BOUNDING) {\n        patrollingLeft = true;\n      }\n    }\n    logger.info(\"Skeleton {} is on position {}.\", id, position);\n  }\n}\n"
  },
  {
    "path": "update-method/src/main/java/com/iluwatar/updatemethod/Statue.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.updatemethod;\n\n/** Statues shoot lightning at regular intervals. */\npublic class Statue extends Entity {\n\n  protected int frames;\n\n  protected int delay;\n\n  /**\n   * Constructor of Statue.\n   *\n   * @param id id of statue\n   */\n  public Statue(int id) {\n    super(id);\n    this.frames = 0;\n    this.delay = 0;\n  }\n\n  /**\n   * Constructor of Statue.\n   *\n   * @param id id of statue\n   * @param delay the number of frames between two lightning\n   */\n  public Statue(int id, int delay) {\n    super(id);\n    this.frames = 0;\n    this.delay = delay;\n  }\n\n  @Override\n  public void update() {\n    if (++frames == delay) {\n      shootLightning();\n      frames = 0;\n    }\n  }\n\n  private void shootLightning() {\n    logger.info(\"Statue {} shoots lightning!\", id);\n  }\n}\n"
  },
  {
    "path": "update-method/src/main/java/com/iluwatar/updatemethod/World.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.updatemethod;\n\nimport java.security.SecureRandom;\nimport java.util.ArrayList;\nimport java.util.List;\nimport lombok.extern.slf4j.Slf4j;\n\n/** The game world class. Maintain all the objects existed in the game frames. */\n@Slf4j\npublic class World {\n\n  protected List<Entity> entities;\n\n  protected volatile boolean isRunning;\n\n  public World() {\n    entities = new ArrayList<>();\n    isRunning = false;\n  }\n\n  /**\n   * Main game loop. This loop will always run until the game is over. For each loop it will process\n   * user input, update internal status, and render the next frames. For more detail please refer to\n   * the game-loop pattern.\n   */\n  private void gameLoop() {\n    while (isRunning) {\n      processInput();\n      update();\n      render();\n    }\n  }\n\n  /**\n   * Handle any user input that has happened since the last call. In order to simulate the situation\n   * in real-life game, here we add a random time lag. The time lag ranges from 50 ms to 250 ms.\n   */\n  private void processInput() {\n    try {\n      int lag = new SecureRandom().nextInt(200) + 50;\n      Thread.sleep(lag);\n    } catch (InterruptedException e) {\n      LOGGER.error(e.getMessage());\n      Thread.currentThread().interrupt();\n    }\n  }\n\n  /**\n   * Update internal status. The update method pattern invoke update method for each entity in the\n   * game.\n   */\n  private void update() {\n    for (var entity : entities) {\n      entity.update();\n    }\n  }\n\n  /** Render the next frame. Here we do nothing since it is not related to the pattern. */\n  private void render() {\n    // Does Nothing\n  }\n\n  /** Run game loop. */\n  public void run() {\n    LOGGER.info(\"Start game.\");\n    isRunning = true;\n    var thread = new Thread(this::gameLoop);\n    thread.start();\n  }\n\n  /** Stop game loop. */\n  public void stop() {\n    LOGGER.info(\"Stop game.\");\n    isRunning = false;\n  }\n\n  public void addEntity(Entity entity) {\n    entities.add(entity);\n  }\n}\n"
  },
  {
    "path": "update-method/src/test/java/com/iluwatar/updatemethod/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.updatemethod;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "update-method/src/test/java/com/iluwatar/updatemethod/SkeletonTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.updatemethod;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nclass SkeletonTest {\n\n  private static Skeleton skeleton;\n\n  @BeforeAll\n  public static void setup() {\n    skeleton = new Skeleton(1);\n  }\n\n  @AfterAll\n  public static void tearDown() {\n    skeleton = null;\n  }\n\n  @Test\n  void testUpdateForPatrollingLeft() {\n    skeleton.patrollingLeft = true;\n    skeleton.setPosition(50);\n    skeleton.update();\n    assertEquals(49, skeleton.getPosition());\n  }\n\n  @Test\n  void testUpdateForPatrollingRight() {\n    skeleton.patrollingLeft = false;\n    skeleton.setPosition(50);\n    skeleton.update();\n    assertEquals(51, skeleton.getPosition());\n  }\n\n  @Test\n  void testUpdateForReverseDirectionFromLeftToRight() {\n    skeleton.patrollingLeft = true;\n    skeleton.setPosition(1);\n    skeleton.update();\n    assertEquals(0, skeleton.getPosition());\n    assertFalse(skeleton.patrollingLeft);\n  }\n\n  @Test\n  void testUpdateForReverseDirectionFromRightToLeft() {\n    skeleton.patrollingLeft = false;\n    skeleton.setPosition(99);\n    skeleton.update();\n    assertEquals(100, skeleton.getPosition());\n    assertTrue(skeleton.patrollingLeft);\n  }\n}\n"
  },
  {
    "path": "update-method/src/test/java/com/iluwatar/updatemethod/StatueTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.updatemethod;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nclass StatueTest {\n\n  private static Statue statue;\n\n  @BeforeAll\n  public static void setup() {\n    statue = new Statue(1, 20);\n  }\n\n  @AfterAll\n  public static void tearDown() {\n    statue = null;\n  }\n\n  @Test\n  void testUpdateForPendingShoot() {\n    statue.frames = 10;\n    statue.update();\n    assertEquals(11, statue.frames);\n  }\n\n  @Test\n  void testUpdateForShooting() {\n    statue.frames = 19;\n    statue.update();\n    assertEquals(0, statue.frames);\n  }\n}\n"
  },
  {
    "path": "update-method/src/test/java/com/iluwatar/updatemethod/WorldTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.updatemethod;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nclass WorldTest {\n\n  private static World world;\n\n  @BeforeAll\n  public static void setup() {\n    world = new World();\n  }\n\n  @AfterAll\n  public static void tearDown() {\n    world = null;\n  }\n\n  @Test\n  void testRun() {\n    world.run();\n    assertTrue(world.isRunning);\n  }\n\n  @Test\n  void testStop() {\n    world.stop();\n    assertFalse(world.isRunning);\n  }\n\n  @Test\n  void testAddEntity() {\n    var entity = new Skeleton(1);\n    world.addEntity(entity);\n    assertEquals(entity, world.entities.get(0));\n  }\n}\n"
  },
  {
    "path": "value-object/README.md",
    "content": "---\ntitle: \"Value Object Pattern in Java: Enhancing Performance with Immutable Data Types\"\nshortTitle: Value Object\ndescription: \"Explore the Value Object pattern in Java with our in-depth guide. Learn how immutable objects enhance performance and memory efficiency in software design. Ideal for developers looking to optimize Java applications.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Data access\n  - Data binding\n  - Domain\n  - Encapsulation\n  - Enterprise patterns\n  - Immutable\n  - Optimization\n  - Performance\n  - Persistence\n---\n\n## Also known as\n\n* Embedded Value\n* Immutable Object\n* Inline Value\n* Integrated Value\n\n## Intent of Value Object Design Pattern\n\nThe Value Object pattern in Java creates immutable objects that represent a descriptive aspect of the domain with no conceptual identity. It aims to enhance performance and reduce memory overhead by storing frequently accessed immutable data directly within the object that uses it, rather than separately.\n\n## Detailed Explanation of Value Object Pattern with Real-World Examples\n\nReal-world example\n\n> Consider the case of a business card. In our example, a BusinessCard class is implemented as a Value Object to demonstrate immutable data handling and efficiency in Java applications. In the real world, a business card contains information such as the person's name, job title, phone number, and email address. This information represents a specific and complete set of attributes describing the contact details of an individual but doesn't have an identity itself beyond this information.\n>\n> In a software system, you can create a `BusinessCard` class as a Value Object. This class would be immutable, meaning once a `BusinessCard` object is created with a person's details, those details cannot change. If you need a different business card, you create a new instance rather than modifying the existing one. The equality of two `BusinessCard` objects would be based on their contained data rather than their memory addresses, ensuring that two business cards with the same details are considered equal. This mirrors how business cards in real life are used and compared based on their content, not on the physical card itself.\n\nIn plain words\n\n> Value objects are equal when their attributes have the same value.\n\nWikipedia says\n\n> In computer science, a value object is a small object that represents a simple entity whose equality is not based on identity: i.e. two value objects are equal when they have the same value, not necessarily being the same object.\n\nFlowchart\n\n![Value Object Pattern Flowchart](./etc/value-object-flowchart.png)\n\n## Programmatic Example of Value Object Pattern in Java\n\nThere is a class for hero statistics in a role-playing game. The statistics contain attributes such as strength, intelligence, and luck. The statistics of different heroes should be equal when all the attributes are equal.\n\nHere is the `HeroStat` class that is the value object. Notice the use of [Lombok's `@Value`](https://projectlombok.org/features/Value) annotation.\n\n```java\n@Value(staticConstructor = \"valueOf\")\n@ToString\nclass HeroStat {\n    int strength;\n    int intelligence;\n    int luck;\n}\n```\n\nThe example creates three different `HeroStat`s and compares their equality.\n\n```java\npublic static void main(String[] args) {\n    var statA = HeroStat.valueOf(10, 5, 0);\n    var statB = HeroStat.valueOf(10, 5, 0);\n    var statC = HeroStat.valueOf(5, 1, 8);\n\n    LOGGER.info(\"statA: {}\", statA);\n    LOGGER.info(\"statB: {}\", statB);\n    LOGGER.info(\"statC: {}\", statC);\n\n    LOGGER.info(\"Are statA and statB equal? {}\", statA.equals(statB));\n    LOGGER.info(\"Are statA and statC equal? {}\", statA.equals(statC));\n}\n```\n\nHere's the console output.\n\n```\n20:11:12.199 [main] INFO com.iluwatar.value.object.App - HeroStat(strength=10, intelligence=5, luck=0)\n20:11:12.202 [main] INFO com.iluwatar.value.object.App - HeroStat(strength=10, intelligence=5, luck=0)\n20:11:12.202 [main] INFO com.iluwatar.value.object.App - HeroStat(strength=5, intelligence=1, luck=8)\n20:11:12.202 [main] INFO com.iluwatar.value.object.App - Is statA and statB equal : true\n20:11:12.203 [main] INFO com.iluwatar.value.object.App - Is statA and statC equal : false\n```\n\n## When to Use the Value Object Pattern in Java\n\nUse the Value Object when\n\n* Apply the Value Object pattern when you need high-performance Java applications with reduced memory overhead, especially in systems requiring efficient data management.\n* When representing a set of attributes that together describe an entity but without an identity.\n* When the equality of the objects is based on the value of the properties, not the identity.\n* When you need to ensure that objects cannot be altered once created.\n* An application requires high performance and the data involved is immutable.\n* Memory footprint reduction is critical, especially in environments with limited resources.\n* Objects frequently access a particular piece of immutable data.\n\n## Value Object Pattern Java Tutorials\n\n* [VALJOs - Value Java Objects (Stephen Colebourne)](http://blog.joda.org/2014/03/valjos-value-java-objects.html)\n\n## Real-World Applications of Value Object Pattern in Java\n\n* Implementing complex data types like monetary values, measurements, and other domain-specific values.\n* [java.util.Optional](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html)\n* [java.time.LocalDate](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html)\n* [java.awt.Color](https://docs.oracle.com/javase/8/docs/api/java/awt/Color.html)\n* [joda-time, money, beans](http://www.joda.org/)\n\n## Benefits and Trade-offs of Value Object Pattern\n\nBenefits:\n\n* Simplifies code by making objects immutable.\n* Thread-safe as the object's state cannot change after creation.\n* Easier to reason about and maintain.\n* Reduces the memory overhead by avoiding separate allocations for immutable data.\n* Improves performance by minimizing memory accesses and reducing cache misses.\n\nTrade-offs:\n\n* Creating a new object for every change can be less efficient for complex objects.\n* Increased memory usage due to the creation of multiple objects representing different states.\n* Increases complexity in object design and can lead to tightly coupled systems.\n* Modifying the embedded value necessitates changes across all objects that embed this value, which can complicate maintenance.\n\n## Related Java Design Patterns\n\n* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Often used to create instances of value objects.\n* [Flyweight](https://java-design-patterns.com/patterns/flyweight/): Shares objects to support large quantities using a minimal amount of memory, somewhat similar in intent but different in implementation.\n* [Builder](https://java-design-patterns.com/patterns/builder/): Can be used to construct complex value objects step by step.\n* [Prototype](https://java-design-patterns.com/patterns/prototype/): Can be used to clone existing value objects, though cloning is less common with immutable objects.\n* [Singleton](https://java-design-patterns.com/patterns/singleton/): Ensures a class has only one instance and provides a global point of access to it, can be used to manage a shared embedded value.\n\n## References and Credits\n\n* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3wlDrze)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n* [ValueObject (Martin Fowler)](https://martinfowler.com/bliki/ValueObject.html)\n"
  },
  {
    "path": "value-object/etc/value-object.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.9\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"true\" nesting-relationships=\"true\" router=\"FAN\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.value.object.HeroStat\" project=\"value-object\" \n    file=\"/value-object/src/main/java/com/iluwatar/value/object/HeroStat.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"-1\" width=\"-1\" x=\"520\" y=\"337\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "value-object/etc/value-object.urm.puml",
    "content": "@startuml\npackage com.iluwatar.value.object {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class HeroStat {\n    - intelligence : int\n    - luck : int\n    - strength : int\n    - HeroStat(strength : int, intelligence : int, luck : int)\n    + equals(obj : Object) : boolean\n    + getIntelligence() : int\n    + getLuck() : int\n    + getStrength() : int\n    + hashCode() : int\n    + toString() : String\n    + valueOf(strength : int, intelligence : int, luck : int) : HeroStat {static}\n  }\n}\n@enduml"
  },
  {
    "path": "value-object/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>value-object</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.value.object.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "value-object/src/main/java/com/iluwatar/value/object/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.value.object;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/**\n * A Value Object are objects which follow value semantics rather than reference semantics. This\n * means value objects' equality are not based on identity. Two value objects are equal when they\n * have the same value, not necessarily being the same object.\n *\n * <p>Value Objects must override equals(), hashCode() to check the equality with values. Value\n * Objects should be immutable so declare members final. Obtain instances by static factory methods.\n * The elements of the state must be other values, including primitive types. Provide methods,\n * typically simple getters, to get the elements of the state. A Value Object must check equality\n * with equals() not ==\n *\n * <p>For more specific and strict rules to implement value objects check the rules from Stephen\n * Colebourne's term VALJO : http://blog.joda.org/2014/03/valjos-value-java-objects.html\n */\n@Slf4j\npublic class App {\n\n  /** This example creates three HeroStats (value objects) and checks equality between those. */\n  public static void main(String[] args) {\n    var statA = HeroStat.valueOf(10, 5, 0);\n    var statB = HeroStat.valueOf(10, 5, 0);\n    var statC = HeroStat.valueOf(5, 1, 8);\n\n    LOGGER.info(\"statA: {}\", statA);\n    LOGGER.info(\"statB: {}\", statB);\n    LOGGER.info(\"statC: {}\", statC);\n\n    LOGGER.info(\"Are statA and statB equal? {}\", statA.equals(statB));\n    LOGGER.info(\"Are statA and statC equal? {}\", statA.equals(statC));\n  }\n}\n"
  },
  {
    "path": "value-object/src/main/java/com/iluwatar/value/object/HeroStat.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.value.object;\n\nimport lombok.ToString;\nimport lombok.Value;\n\n/**\n * HeroStat is a value object.\n *\n * @see <a href=\"http://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html\">\n *     http://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html </a>\n */\n@Value(staticConstructor = \"valueOf\")\n@ToString\nclass HeroStat {\n\n  int strength;\n  int intelligence;\n  int luck;\n}\n"
  },
  {
    "path": "value-object/src/test/java/com/iluwatar/value/object/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.value.object;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "value-object/src/test/java/com/iluwatar/value/object/HeroStatTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.value.object;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nimport org.junit.jupiter.api.Test;\n\n/** Unit test for HeroStat. */\nclass HeroStatTest {\n\n  /**\n   * Tester for equals() and hashCode() methods of a class. Using guava's EqualsTester.\n   *\n   * @see <a\n   *     href=\"http://static.javadoc.io/com.google.guava/guava-testlib/19.0/com/google/common/testing/EqualsTester.html\">\n   *     http://static.javadoc.io/com.google.guava/guava-testlib/19.0/com/google/common/testing/EqualsTester.html\n   *     </a>\n   */\n  @Test\n  void testEquals() {\n    var heroStatA = HeroStat.valueOf(3, 9, 2);\n    var heroStatB = HeroStat.valueOf(3, 9, 2);\n    assertEquals(heroStatA, heroStatB);\n  }\n\n  /**\n   * The toString() for two equal values must be the same. For two non-equal values it must be\n   * different.\n   */\n  @Test\n  void testToString() {\n    var heroStatA = HeroStat.valueOf(3, 9, 2);\n    var heroStatB = HeroStat.valueOf(3, 9, 2);\n    var heroStatC = HeroStat.valueOf(3, 9, 8);\n    assertEquals(heroStatA.toString(), heroStatB.toString());\n    assertNotEquals(heroStatA.toString(), heroStatC.toString());\n  }\n}\n"
  },
  {
    "path": "version-number/README.md",
    "content": "---\ntitle: \"Version Number Pattern in Java: Implementing Robust Version Management in Java Applications\"\nshortTitle: Version Number\ndescription: \"Explore the Version Number pattern in Java to manage concurrent data access and maintain data integrity. Learn how to implement it effectively with examples and best practices.\"\ncategory: Data access\nlanguage: en\ntag:\n  - Compatibility\n  - Data access\n  - Persistence\n  - State tracking\n  - Versioning\n---\n\n## Also known as\n\n* Entity Versioning\n* Versioning\n\n## Intent of Version Number Design Pattern\n\nEnsure data consistency and integrity in Java applications by tracking changes with version numbers—a crucial component of concurrent data management.\n\n## Detailed Explanation of Version Number Pattern with Real-World Examples\n\nReal-world example\n\n> Consider a library system where multiple librarians can update the details of books simultaneously. Each book entry in the library's database has a version number. When a librarian wants to update a book's details, the system checks the version number of the entry. If the version number matches the current version in the database, the update proceeds, and the version number is incremented. If the version number has changed, it means another librarian has already updated the book details, prompting the system to notify the librarian of the conflict and suggesting a review of the latest changes. This ensures that updates do not overwrite each other unintentionally, maintaining data integrity and consistency.\n\nIn plain words\n\n> The Version Number pattern in Java provides robust protection against concurrent updates, ensuring reliable data versioning in distributed systems.\n\nWikipedia says\n\n> The Version Number pattern is a technique used to manage concurrent access to data in databases and other data stores. It involves associating a version number with each record, which is incremented every time the record is updated. This pattern helps ensure that when multiple users or processes attempt to update the same data simultaneously, conflicts can be detected and resolved.\n\nFlowchart\n\n![Version Number Pattern Flowchart](./etc/version-number-flowchart.png)\n\n## Programmatic Example of Version Number Pattern in Java\n\nAlice and Bob are working on the book, which stored in the database. Our heroes are making changes simultaneously, and we need some mechanism to prevent them from overwriting each other.\n\nWe have a `Book` entity, which is versioned, and has a copy-constructor:\n\n```java\n@Getter\n@Setter\npublic class Book {\n    \n    private long id;\n    private String title = \"\";\n    private String author = \"\";\n    private long version = 0; // version number\n\n    public Book(Book book) {\n        this.id = book.id;\n        this.title = book.title;\n        this.author = book.author;\n        this.version = book.version;\n    }\n}\n```\n\nWe also have `BookRepository`, which implements concurrency control:\n\n```java\npublic class BookRepository {\n    \n  private final Map<Long, Book> collection = new HashMap<>();\n\n  public void update(Book book) throws BookNotFoundException, VersionMismatchException {\n    if (!collection.containsKey(book.getId())) {\n      throw new BookNotFoundException(\"Not found book with id: \" + book.getId());\n    }\n\n    var latestBook = collection.get(book.getId());\n    if (book.getVersion() != latestBook.getVersion()) {\n      throw new VersionMismatchException(\n        \"Tried to update stale version \" + book.getVersion()\n          + \" while actual version is \" + latestBook.getVersion()\n      );\n    }\n\n    // update version, including client representation - modify by reference here\n    book.setVersion(book.getVersion() + 1);\n\n    // save book copy to repository\n    collection.put(book.getId(), new Book(book));\n  }\n\n  public Book get(long bookId) throws BookNotFoundException {\n    if (!collection.containsKey(bookId)) {\n      throw new BookNotFoundException(\"Not found book with id: \" + bookId);\n    }\n\n    // return copy of the book\n    return new Book(collection.get(bookId));\n  }\n}\n```\n\nHere's the version number pattern in action:\n\n```java\npublic class App {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n    public static void main(String[] args) throws\n            BookDuplicateException,\n            BookNotFoundException,\n            VersionMismatchException {\n        var bookId = 1;\n\n        var bookRepository = new BookRepository();\n        var book = new Book();\n        book.setId(bookId);\n        bookRepository.add(book); // adding a book with empty title and author\n        LOGGER.info(\"An empty book with version {} was added to repository\", book.getVersion());\n\n        // Alice and Bob took the book concurrently\n        final var aliceBook = bookRepository.get(bookId);\n        final var bobBook = bookRepository.get(bookId);\n\n        aliceBook.setTitle(\"Kama Sutra\"); // Alice has updated book title\n        bookRepository.update(aliceBook); // and successfully saved book in database\n        LOGGER.info(\"Alice updates the book with new version {}\", aliceBook.getVersion());\n\n        // now Bob has the stale version of the book with empty title and version = 0\n        // while actual book in database has filled title and version = 1\n        bobBook.setAuthor(\"Vatsyayana Mallanaga\"); // Bob updates the author\n        try {\n            LOGGER.info(\"Bob tries to update the book with his version {}\", bobBook.getVersion());\n            bookRepository.update(bobBook); // Bob tries to save his book to database\n        } catch (VersionMismatchException e) {\n            // Bob update fails, and book in repository remained untouchable\n            LOGGER.info(\"Exception: {}\", e.getMessage());\n            // Now Bob should reread actual book from repository, do his changes again and save again\n        }\n    }\n}\n```\n\nProgram output:\n\n```\n14:51:04.119 [main] INFO com.iluwatar.versionnumber.App -- An empty book with version 0 was added to repository\n14:51:04.122 [main] INFO com.iluwatar.versionnumber.App -- Alice updates the book with new version 1\n14:51:04.122 [main] INFO com.iluwatar.versionnumber.App -- Bob tries to update the book with his version 0\n14:51:04.123 [main] INFO com.iluwatar.versionnumber.App -- Exception: Tried to update stale version 0 while actual version is 1\n```\n\n## When to Use the Version Number Pattern in Java\n\n* Use when you need to handle concurrent data modifications in a distributed system.\n* Suitable for systems where data consistency and integrity are crucial.\n* Ideal for applications using databases that support versioning or row versioning features.\n\n## Version Number Pattern Java Tutorials\n\n* [JPA entity versioning (byteslounge.com)](https://www.byteslounge.com/tutorials/jpa-entity-versioning-version-and-optimistic-locking)\n* [Optimistic Locking in JPA (Baeldung)](https://www.baeldung.com/jpa-optimistic-locking)\n* [Versioning Entity (java2s.com)](http://www.java2s.com/Tutorial/Java/0355__JPA/VersioningEntity.htm)\n\n## Real-World Applications of Version Number Pattern in Java\n\n* Hibernate (Java Persistence API) uses version numbers to implement optimistic locking.\n* Microsoft SQL Server and Oracle databases support version-based concurrency control.\n* Apache CouchDB and other NoSQL databases implement versioning for conflict resolution.\n* [Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html#index-versioning)\n* [Apache Solr](https://lucene.apache.org/solr/guide/6_6/updating-parts-of-documents.html)\n\n## Benefits and Trade-offs of Version Number Pattern\n\nBenefits:\n\n* Improves data consistency and integrity.\n* Reduces the likelihood of lost updates in concurrent environments.\n* Provides a mechanism for conflict detection and resolution.\n\nTrade-offs:\n\n* Requires additional logic for version checking and handling conflicts.\n* Can lead to increased complexity in database schema and application logic.\n* Potential performance overhead due to version checks and conflict resolution.\n\n## Related Java Design Patterns\n\n* [Optimistic Offline Lock](https://java-design-patterns.com/patterns/optimistic-offline-lock/): Uses version numbers to detect conflicts rather than preventing them from occurring.\n* Pessimistic Offline Lock: An alternative approach to concurrency control where data is locked for updates to prevent conflicts.\n\n## References and Credits\n\n* [Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems](https://amzn.to/3y6yv1z)\n* [J2EE Design Patterns](https://amzn.to/4dpzgmx)\n* [Java Persistence with Hibernate](https://amzn.to/44tP1ox)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "version-number/etc/version-number.urm.puml",
    "content": "@startuml\npackage com.iluwatar.versionnumber {\n  class App {\n    - LOGGER : Logger {static}\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Book {\n    - author : String\n    - id : long\n    - title : String\n    - version : long\n    + Book()\n    + Book(book : Book)\n    + getAuthor() : String\n    + getId() : long\n    + getTitle() : String\n    + getVersion() : long\n    + setAuthor(author : String)\n    + setId(id : long)\n    + setTitle(title : String)\n    + setVersion(version : long)\n  }\n  class BookRepository {\n    - collection : Map<Long, Book>\n    + BookRepository()\n    + add(book : Book)\n    + get(bookId : long) : Book\n    + update(book : Book)\n  }\n}\n@enduml"
  },
  {
    "path": "version-number/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>version-number</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.versionnumber.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "version-number/src/main/java/com/iluwatar/versionnumber/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.versionnumber;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * The Version Number pattern helps to resolve concurrency conflicts in applications. Usually these\n * conflicts arise in database operations, when multiple clients are trying to update the same\n * record simultaneously. Resolving such conflicts requires determining whether an object has\n * changed. For this reason we need a version number that is incremented with each change to the\n * underlying data, e.g. database. The version number can be used by repositories to check for\n * external changes and to report concurrency issues to the users.\n *\n * <p>In this example we show how Alice and Bob will try to update the {@link Book} and save it\n * simultaneously to {@link BookRepository}, which represents a typical database.\n *\n * <p>As in real databases, each client operates with copy of the data instead of original data\n * passed by reference, that's why we are using {@link Book} copy-constructor here.\n */\npublic class App {\n  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args)\n      throws BookDuplicateException, BookNotFoundException, VersionMismatchException {\n    var bookId = 1;\n\n    var bookRepository = new BookRepository();\n    var book = new Book();\n    book.setId(bookId);\n    bookRepository.add(book); // adding a book with empty title and author\n    LOGGER.info(\"An empty book with version {} was added to repository\", book.getVersion());\n\n    // Alice and Bob took the book concurrently\n    final var aliceBook = bookRepository.get(bookId);\n    final var bobBook = bookRepository.get(bookId);\n\n    aliceBook.setTitle(\"Kama Sutra\"); // Alice has updated book title\n    bookRepository.update(aliceBook); // and successfully saved book in database\n    LOGGER.info(\"Alice updates the book with new version {}\", aliceBook.getVersion());\n\n    // now Bob has the stale version of the book with empty title and version = 0\n    // while actual book in database has filled title and version = 1\n    bobBook.setAuthor(\"Vatsyayana Mallanaga\"); // Bob updates the author\n    try {\n      LOGGER.info(\"Bob tries to update the book with his version {}\", bobBook.getVersion());\n      bookRepository.update(bobBook); // Bob tries to save his book to database\n    } catch (VersionMismatchException e) {\n      // Bob update fails, and book in repository remained untouchable\n      LOGGER.info(\"Exception: {}\", e.getMessage());\n      // Now Bob should reread actual book from repository, do his changes again and save again\n    }\n  }\n}\n"
  },
  {
    "path": "version-number/src/main/java/com/iluwatar/versionnumber/Book.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.versionnumber;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/** Model class for Book entity. */\n@Getter\n@Setter\npublic class Book {\n  private long id;\n  private String title = \"\";\n  private String author = \"\";\n  private long version = 0; // version number\n\n  public Book() {}\n\n  /** We need this copy constructor to copy book representation in {@link BookRepository}. */\n  public Book(Book book) {\n    this.id = book.id;\n    this.title = book.title;\n    this.author = book.author;\n    this.version = book.version;\n  }\n}\n"
  },
  {
    "path": "version-number/src/main/java/com/iluwatar/versionnumber/BookDuplicateException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.versionnumber;\n\n/** When someone has tried to add a book which repository already have. */\npublic class BookDuplicateException extends Exception {\n  public BookDuplicateException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "version-number/src/main/java/com/iluwatar/versionnumber/BookNotFoundException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.versionnumber;\n\n/** Client has tried to make an operation with book which repository does not have. */\npublic class BookNotFoundException extends Exception {\n  public BookNotFoundException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "version-number/src/main/java/com/iluwatar/versionnumber/BookRepository.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.versionnumber;\n\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * This repository represents simplified database. As a typical database do, repository operates\n * with copies of object. So client and repo has different copies of book, which can lead to\n * concurrency conflicts as much as in real databases.\n */\npublic class BookRepository {\n  private final ConcurrentHashMap<Long, Book> collection = new ConcurrentHashMap<>();\n  private final Object lock = new Object();\n\n  /**\n   * Adds book to collection. Actually we are putting copy of book (saving a book by value, not by\n   * reference);\n   */\n  public void add(Book book) throws BookDuplicateException {\n    if (collection.containsKey(book.getId())) {\n      throw new BookDuplicateException(\"Duplicated book with id: \" + book.getId());\n    }\n\n    // add copy of the book\n    collection.put(book.getId(), new Book(book));\n  }\n\n  /** Updates book in collection only if client has modified the latest version of the book. */\n  public void update(Book book) throws BookNotFoundException, VersionMismatchException {\n    if (!collection.containsKey(book.getId())) {\n      throw new BookNotFoundException(\"Not found book with id: \" + book.getId());\n    }\n\n    // used synchronized block to ensure only one thread compares and update the version\n    synchronized (lock) {\n      var latestBook = collection.get(book.getId());\n      if (book.getVersion() != latestBook.getVersion()) {\n        throw new VersionMismatchException(\n            \"Tried to update stale version \"\n                + book.getVersion()\n                + \" while actual version is \"\n                + latestBook.getVersion());\n      }\n\n      // update version, including client representation - modify by reference here\n      book.setVersion(book.getVersion() + 1);\n\n      // save book copy to repository\n      collection.put(book.getId(), new Book(book));\n    }\n  }\n\n  /**\n   * Returns book representation to the client. Representation means we are returning copy of the\n   * book.\n   */\n  public Book get(long bookId) throws BookNotFoundException {\n    if (!collection.containsKey(bookId)) {\n      throw new BookNotFoundException(\"Not found book with id: \" + bookId);\n    }\n\n    // return copy of the book\n    return new Book(collection.get(bookId));\n  }\n}\n"
  },
  {
    "path": "version-number/src/main/java/com/iluwatar/versionnumber/VersionMismatchException.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.versionnumber;\n\n/** Client has tried to update a stale version of the book. */\npublic class VersionMismatchException extends Exception {\n  public VersionMismatchException(String message) {\n    super(message);\n  }\n}\n"
  },
  {
    "path": "version-number/src/test/java/com/iluwatar/versionnumber/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.versionnumber;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  /**\n   * Issue: Add at least one assertion to this test case.\n   *\n   * <p>Solution: Inserted assertion to check whether the execution of the main method in {@link\n   * App#main(String[])} throws an exception.\n   */\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "version-number/src/test/java/com/iluwatar/versionnumber/BookRepositoryTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.versionnumber;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for {@link BookRepository} */\nclass BookRepositoryTest {\n  private final long bookId = 1;\n  private final BookRepository bookRepository = new BookRepository();\n\n  @BeforeEach\n  void setUp() throws BookDuplicateException {\n    var book = new Book();\n    book.setId(bookId);\n    bookRepository.add(book);\n  }\n\n  @Test\n  void testDefaultVersionRemainsZeroAfterAdd() throws BookNotFoundException {\n    var book = bookRepository.get(bookId);\n    assertEquals(0, book.getVersion());\n  }\n\n  @Test\n  void testAliceAndBobHaveDifferentVersionsAfterAliceUpdate()\n      throws BookNotFoundException, VersionMismatchException {\n    final var aliceBook = bookRepository.get(bookId);\n    final var bobBook = bookRepository.get(bookId);\n\n    aliceBook.setTitle(\"Kama Sutra\");\n    bookRepository.update(aliceBook);\n\n    assertEquals(1, aliceBook.getVersion());\n    assertEquals(0, bobBook.getVersion());\n    var actualBook = bookRepository.get(bookId);\n    assertEquals(aliceBook.getVersion(), actualBook.getVersion());\n    assertEquals(aliceBook.getTitle(), actualBook.getTitle());\n    assertNotEquals(aliceBook.getTitle(), bobBook.getTitle());\n  }\n\n  @Test\n  void testShouldThrowVersionMismatchExceptionOnStaleUpdate()\n      throws BookNotFoundException, VersionMismatchException {\n    final var aliceBook = bookRepository.get(bookId);\n    final var bobBook = bookRepository.get(bookId);\n\n    aliceBook.setTitle(\"Kama Sutra\");\n    bookRepository.update(aliceBook);\n\n    bobBook.setAuthor(\"Vatsyayana Mallanaga\");\n    try {\n      bookRepository.update(bobBook);\n    } catch (VersionMismatchException e) {\n      assertEquals(0, bobBook.getVersion());\n      var actualBook = bookRepository.get(bookId);\n      assertEquals(1, actualBook.getVersion());\n      assertEquals(aliceBook.getVersion(), actualBook.getVersion());\n      assertEquals(\"\", bobBook.getTitle());\n      assertNotEquals(aliceBook.getAuthor(), bobBook.getAuthor());\n    }\n  }\n}\n"
  },
  {
    "path": "view-helper/README.md",
    "content": "---\ntitle: \"View Helper Pattern in Java: Simplifying Presentation Logic in MVC Applications\"\nshortTitle: View Helper\ndescription: \"Discover the View Helper Design Pattern in Java, a powerful technique for separating view-related logic from business logic in MVC-based web applications. This pattern enhances maintainability, reusability, and testability by delegating complex UI operations to reusable helper components. Ideal for developers aiming to keep views clean and focused on presentation.\"\ncategory: Architectural\nlanguage: en\ntag:\n    - Architecture\n    - Presentation\n    - Decoupling\n    - Code reuse\n---\n\n## Intent of View Helper Design Pattern\nThe View Helper Design Pattern separates presentation logic from the view by delegating complex UI tasks — like formatting or conditional display — to reusable helper components. This keeps views clean, promotes reuse, and aligns with the MVC principle of separating concerns between the view and the business logic.\n\n## Detailed Explanation with Real‑World Analogy\nReal‑world example\n> Imagine you're putting together a slideshow for a business presentation. You focus on arranging the slides, choosing the layout, and telling the story. But for tasks like resizing images, formatting charts, or converting data into visual form, you use tools or templates that automate those parts.\n>\n> In this analogy, you are the view, and the tools/templates are the helpers. They handle the heavy lifting behind the scenes so you can concentrate on the presentation. Similarly, in the View Helper pattern, the view delegates logic-heavy tasks—such as formatting or conditionally displaying data—to helper classes, keeping the view layer clean and presentation-focused.\n\n### In plain words\n> The View Helper pattern is about keeping your UI code clean by moving any logic—like formatting, calculations, or decision-making—into separate helper classes. Instead of stuffing all the logic into the HTML or template files, you delegate it to helpers, so the view just focuses on showing the final result.\n\n### Sequence diagram\n![Sequence diagram for View Helper](etc/view-helper-sequence-diagram.png)\n\n## Programmatic Example of View Helper Pattern in Java\nRaw domain object\n```java\npublic record Product(String name, BigDecimal price, LocalDate releaseDate, boolean discounted) {}\n```\n\nView model object for display\n```java\npublic record ProductViewModel(String name, String price, String releasedDate) {}\n```\n\nView Helper formats data for display\n```java\nclass ProductViewHelper implements ViewHelper<Product, ProductViewModel> {\n  \n  private static final String DISCOUNT_TAG = \" (ON SALE)\";\n  \n  public ProductViewModel prepare(Product product) {\n    var displayName = product.name() + (product.discounted() ? DISCOUNT_TAG : \"\");\n    var priceWithCurrency = NumberFormat.getCurrencyInstance(US).format(product.price());\n    var formattedDate = product.releaseDate().format(ISO_DATE);\n\n    return new ProductViewModel(displayName, priceWithCurrency, formattedDate);\n  }\n}\n```\n\nView renders the formatted data\n```java\npublic class ConsoleProductView implements View<ProductViewModel> {\n  \n  @Override\n  public void render(ProductViewModel productViewModel) {\n    LOGGER.info(productViewModel.toString());\n  }\n}\n```\nThe `App.java` class simulates how the View Helper pattern works in a real application. It starts with a raw `Product` object containing unformatted data. \nThen it:\n1. Initializes a helper (`ProductViewHelper`) to format the product data for display.\n1. Creates a view (`ConsoleProductView`) to render the formatted data.\n1. Uses a controller (`ProductController`) to coordinate the flow between raw data, helper logic, and view rendering.\n\nFinally, it simulates a user request by passing the product to the controller, which prepares the view model using the helper and displays it using the view. This demonstrates a clean separation between data, presentation logic, and rendering.\n\n## When to Use the View Helper Pattern in Java\nUse the View Helper pattern when your view layer starts containing logic such as formatting data, applying conditional styles, or transforming domain objects for display. It's especially useful in MVC architectures where you want to keep views clean and focused on rendering, while delegating non-trivial presentation logic to reusable helper classes. This pattern helps improve maintainability, testability, and separation of concerns in your application's UI layer.\n\n## Real‑World Uses of View Helper Pattern in Java\nThe View Helper pattern is widely used in web frameworks that follow the MVC architecture. In Java-based web applications (e.g., JSP, Spring MVC), it's common to use helper classes or utility methods to format dates, currencies, or apply conditional logic before rendering views. Technologies like Thymeleaf or JSF often rely on custom tags or expression helpers to achieve the same effect.\n\n## Benefits and Trade‑offs\nBenefits:\n* Separation of concerns: Keeps view templates clean by moving logic into dedicated helpers.\n* Reusability: Common formatting and display logic can be reused across multiple views.\n* Improved maintainability: Easier to update presentation logic without touching the view.\n* Testability: Helpers can be unit tested independently from the UI layer.\n\nTrade‑offs:\n* Added complexity: Introduces extra classes, which may feel unnecessary for very simple views.\n* Overuse risk: Excessive use of helpers can spread logic thinly across many files, making it harder to trace behavior.\n* Tight coupling risk: If not designed carefully, helpers can become tightly coupled to specific views or data formats.\n\n## Related Java Design Patterns\n* [Model-View-Controller (MVC)](https://java-design-patterns.com/patterns/model-view-controller/): View Helper supports the View layer in MVC by offloading logic from the view to helper classes.\n* [Template Method](https://java-design-patterns.com/patterns/template-method/): Can structure the steps of rendering or data transformation, with helpers handling specific formatting tasks.\n* [Data Transfer Object (DTO)](https://java-design-patterns.com/patterns/data-transfer-object/): Often used alongside View Helper when transferring raw data that needs formatting before being displayed.\n\n## References & Credits\n* [Core J2EE Patterns: View Helper.](https://www.oracle.com/java/technologies/viewhelper.html)\n"
  },
  {
    "path": "view-helper/etc/view-helper-sequence-diagram.puml",
    "content": "@startuml\nactor Client\nparticipant Controller\nparticipant ViewHelper\nparticipant View\nparticipant Product\nparticipant ProductViewModel\n\nClient -> Controller : handle(product)\nController -> ViewHelper : prepare(product)\nViewHelper -> Product : access data\nViewHelper -> ProductViewModel : return formatted view model\nController -> View : render(viewModel)\nView -> Console : display output\n@enduml"
  },
  {
    "path": "view-helper/etc/view-helper.puml",
    "content": "@startuml\npackage com.iluwatar.viewhelper {\n    interface View<T> {\n        +render(T model)\n    }\n\n    interface ViewHelper<S, T> {\n        +prepare(S source): T\n    }\n\n    class Product {\n        -name: String\n        -price: BigDecimal\n        -releaseDate: LocalDate\n        -discounted: boolean\n    }\n\n    class ProductViewModel {\n        -name: String\n        -price: String\n        -releasedDate: String\n    }\n\n    class ProductViewHelper {\n        +prepare(Product): ProductViewModel\n    }\n\n    class ConsoleProductView {\n        +render(ProductViewModel)\n    }\n\n    class ProductController {\n        -helper: ViewHelper<Product, ProductViewModel>\n        -view: View<ProductViewModel>\n        +handle(Product)\n    }\n}\nProduct --> ProductViewHelper\nProductViewHelper ..|> ViewHelper\nConsoleProductView ..|> View\nProductViewHelper --> ProductViewModel\nProductController --> ProductViewHelper\nProductController --> ConsoleProductView\n\n@enduml"
  },
  {
    "path": "view-helper/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>view-helper</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>com.iluwatar.value.object.App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "view-helper/src/main/java/com/iluwatar/viewhelper/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.viewhelper;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\n\n/** The main application class that sets up and runs the View Helper pattern demo. */\npublic class App {\n  /**\n   * The entry point of the application.\n   *\n   * @param args the command line arguments\n   */\n  public static void main(String[] args) {\n    // Raw Product data (no formatting, no UI tags)\n    var product =\n        new Product(\n            \"Design patterns book\", new BigDecimal(\"18.90\"), LocalDate.of(2025, 4, 19), true);\n\n    // Create view, viewHelper and viewHelper\n    var helper = new ProductViewHelper();\n    var view = new ConsoleProductView();\n    var controller = new ProductController(helper, view);\n\n    // Handle “request”\n    controller.handle(product);\n  }\n}\n"
  },
  {
    "path": "view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.viewhelper;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** Renders {@link ProductViewModel} to the console. */\n@Slf4j\npublic class ConsoleProductView implements View<ProductViewModel> {\n  @Override\n  public void render(ProductViewModel productViewModel) {\n    LOGGER.info(productViewModel.toString());\n  }\n}\n"
  },
  {
    "path": "view-helper/src/main/java/com/iluwatar/viewhelper/Product.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.viewhelper;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\n\n/** Definition of product. */\npublic record Product(String name, BigDecimal price, LocalDate releaseDate, boolean discounted) {}\n"
  },
  {
    "path": "view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.viewhelper;\n\n/**\n * Controller delegates a {@link Product} to {@link ProductViewHelper} and then to {@link\n * ConsoleProductView}.\n */\npublic class ProductController {\n\n  private final ViewHelper<Product, ProductViewModel> viewHelper;\n  private final View<ProductViewModel> view;\n\n  public ProductController(\n      ViewHelper<Product, ProductViewModel> viewHelper, View<ProductViewModel> view) {\n    this.viewHelper = viewHelper;\n    this.view = view;\n  }\n\n  /**\n   * Passes the product to the helper for formatting and then forwards formatted product to the\n   * view.\n   */\n  public void handle(Product product) {\n    view.render(viewHelper.prepare(product));\n  }\n}\n"
  },
  {
    "path": "view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.viewhelper;\n\nimport static java.time.format.DateTimeFormatter.ISO_DATE;\nimport static java.util.Locale.US;\n\nimport java.text.NumberFormat;\n\n/** Formats a {@link Product} into a {@link ProductViewModel}. */\npublic class ProductViewHelper implements ViewHelper<Product, ProductViewModel> {\n\n  private static final String DISCOUNT_TAG = \" ON SALE\";\n\n  @Override\n  public ProductViewModel prepare(Product product) {\n    var displayName = product.name() + (product.discounted() ? DISCOUNT_TAG : \"\");\n    var priceWithCurrency = NumberFormat.getCurrencyInstance(US).format(product.price());\n    var formattedDate = product.releaseDate().format(ISO_DATE);\n\n    return new ProductViewModel(displayName, priceWithCurrency, formattedDate);\n  }\n}\n"
  },
  {
    "path": "view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.viewhelper;\n\n/** Class defining formatted display data of a {@link Product}. */\npublic record ProductViewModel(String name, String price, String releasedDate) {}\n"
  },
  {
    "path": "view-helper/src/main/java/com/iluwatar/viewhelper/View.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.viewhelper;\n\npublic interface View<V> {\n\n  void render(V data);\n}\n"
  },
  {
    "path": "view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.viewhelper;\n\npublic interface ViewHelper<M, V> {\n  V prepare(M source);\n}\n"
  },
  {
    "path": "view-helper/src/test/java/com/iluwatar/viewhelper/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.viewhelper;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.viewhelper;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass ProductViewHelperTest {\n\n  private ProductViewHelper helper;\n\n  @BeforeEach\n  void setUp() {\n    helper = new ProductViewHelper();\n  }\n\n  @Test\n  void shouldFormatProductWithoutDiscount() {\n    var product = new Product(\"X\", new BigDecimal(\"10.00\"), LocalDate.of(2025, 1, 1), false);\n    ProductViewModel viewModel = helper.prepare(product);\n\n    assertEquals(\"X\", viewModel.name());\n    assertEquals(\"$10.00\", viewModel.price());\n    assertEquals(\"2025-01-01\", viewModel.releasedDate());\n  }\n\n  @Test\n  void shouldFormatProductWithDiscount() {\n    var product = new Product(\"X\", new BigDecimal(\"10.00\"), LocalDate.of(2025, 1, 1), true);\n    ProductViewModel viewModel = helper.prepare(product);\n\n    assertEquals(\"X ON SALE\", viewModel.name()); // locale follows JVM default\n  }\n}\n"
  },
  {
    "path": "virtual-proxy/.gitignore",
    "content": "################## Eclipse ######################\ntarget\n.metadata\n.settings\n.classpath\n.project\n*.class\ntmp/\n*.tmp\n*.bak\n*~.nib\nlocal.properties\n.loadpath\n.recommenders\n.DS_Store\n\n#######  Java annotation processor (APT) ########\n.factorypath\n\n################ Package Files ##################\n*.jar\n*.war\n*.ear\n*.swp\ndatanucleus.log\n/bin/\n*.log\nevent-sourcing/Journal.json\n\n################## Checkstyle ###################\n.checkstyle\n\n##################### STS #######################\n.apt_generated\n.springBeans\n.sts4-cache\n\n################# IntelliJ IDEA #################\n.idea\n*.iws\n*.iml\n*.ipr\n\n################### NetBeans ####################\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\nbuild/\n!**/src/main/**/build/\n!**/src/test/**/build/\n\n#################### VS Code ####################\n.vscode/\n\n#################### Java Design Patterns #######\netc/Java Design Patterns.urm.puml\nserialized-entity/output.txt"
  },
  {
    "path": "virtual-proxy/README.md",
    "content": "---\ntitle: \"Virtual Proxy Pattern in Java: Enhancing Performance with Lazy Loading Techniques\"\nshortTitle: Virtual Proxy\ndescription: \"Explore the Virtual Proxy Design Pattern in Java to improve your applications. Learn how this pattern optimizes performance and manages resources efficiently by controlling the creation and access of resource-intensive objects. Ideal for developers looking to enhance system responsiveness.\"\ncategory: Structural\nlanguage: en\ntag:\n  - Caching\n  - Decoupling\n  - Lazy initialization\n---\n\n## Also known as\n\n* Lazy Initialization Proxy\n* Virtual Surrogate\n\n## Intent of Virtual Proxy Design Pattern\n\nThe Virtual Proxy Design Pattern is a crucial component in Java design patterns, enabling efficient resource management and performance optimization through controlled object creation. It provides a surrogate or placeholder for another object to control its creation and access, particularly when dealing with resource-intensive operations.\n\n## Detailed Explanation of Virtual Proxy Pattern with Real-World Examples\n\nReal-world example\n\n> Just as a high-end art gallery uses photographs to save resources and reduce risks, the Virtual Proxy Pattern in Java manages resource-intensive operations by displaying only necessary objects, significantly enhancing system efficiency. To protect the actual artwork and reduce the risk of damage or theft, the gallery initially displays high-quality photographs of the artworks. When a serious buyer expresses genuine interest, the gallery then brings out the original artwork from a secure storage area for viewing.\n> \n> In this analogy, the high-quality photograph serves as the virtual proxy for the actual artwork. The real artwork is only fetched and displayed when truly necessary, thus saving resources and reducing risk, similar to how the Virtual Proxy pattern defers object creation until it is needed.\n\nIn plain words\n\n> The virtual proxy pattern allows a representative class to stand in for another class to control access to it, particularly for resource-intensive operations.\n\nWikipedia says\n\n> A proxy that controls access to a resource that is expensive to create.\n\nSequence diagram\n\n![Virtual Proxy Sequence Diagram](./etc/virtual-proxy-sequence-diagram.png)\n\n## Programmatic Example of Virtual Proxy Pattern in Java\n\nThe Virtual Proxy design pattern in Java can optimize resource utilization and system performance.\n\nConsider an online video streaming platform where video objects are resource-intensive due to their large data size and required processing power. To efficiently manage resources, the system uses a virtual proxy to handle video objects. The virtual proxy defers the creation of actual video objects until they are explicitly required for playback, thus saving system resources and improving response times for users.\n\nGiven our example of a video streaming service, here is how it might be implemented:\n\nFirst, we define an `ExpensiveObject` interface, which outlines the method for processing video.\n\n```java\npublic interface ExpensiveObject {\n    void process();\n}\n```\n\nHere’s the implementation of a `RealVideoObject` that represents an expensive-to-create video object.\n\n```java\n@Slf4j\n@Getter\npublic class RealVideoObject implements ExpensiveObject {\n\n    public RealVideoObject() {\n        heavyInitialConfiguration();\n    }\n\n    private void heavyInitialConfiguration() {\n        LOGGER.info(\"Loading initial video configurations...\");\n    }\n\n    @Override\n    public void process() {\n        LOGGER.info(\"Processing and playing video content...\");\n    }\n}\n```\n\nThe `VideoObjectProxy` serves as a stand-in for `RealExpensiveObject`.\n\n```java\n@Getter\npublic class VideoObjectProxy implements ExpensiveObject {\n    \n    private RealVideoObject realVideoObject;\n\n    public void setRealVideoObject(RealVideoObject realVideoObject) {\n        this.realVideoObject = realVideoObject;\n    }\n\n    @Override\n    public void process() {\n        if (realVideoObject == null) {\n            realVideoObject = new RealVideoObject();\n        }\n        realVideoObject.process();\n    }\n}\n```\n\nAnd here’s how the proxy is used in the system.\n\n```java\npublic static void main(String[] args) {\n    ExpensiveObject videoObject = new VideoObjectProxy();\n    videoObject.process();  // The first call creates and plays the video\n    videoObject.process();  // Subsequent call uses the already created object\n}\n```\n\nProgram output:\n\n```\n14:54:30.602 [main] INFO com.iluwatar.virtual.proxy.RealVideoObject -- Loading initial video configurations...\n14:54:30.604 [main] INFO com.iluwatar.virtual.proxy.RealVideoObject -- Processing and playing video content...\n14:54:30.604 [main] INFO com.iluwatar.virtual.proxy.RealVideoObject -- Processing and playing video content...\n```\n\n## When to Use the Virtual Proxy Pattern in Java\n\nUse the Virtual Proxy pattern when:\n\n* Object creation is resource-intensive, and not all instances are utilized immediately or ever.\n* The performance of a system can be significantly improved by deferring the creation of objects until they are needed.\n* There is a need for control over resource usage in systems dealing with large quantities of high-overhead objects.\n\n## Virtual Proxy Pattern Java Tutorials\n\n* [The Proxy Pattern in Java (Baeldung)](https://www.baeldung.com/java-proxy-pattern)\n\n## Real-World Applications of Virtual Proxy Pattern in Java\n\n* Lazy Initialization: Create objects only when they are actually needed.\n* Resource Management: Efficiently manage resources by creating heavy objects only on demand.\n* Access Control: Include logic to check conditions before delegating calls to the actual object.\n* Performance Optimization: Incorporate caching of results or states that are expensive to obtain or compute.\n* Data Binding and Integration: Delay integration and binding processes until the data is actually needed.\n* In Java, the `java.awt.Image` class uses virtual proxies to load images on demand.\n* Hibernate ORM framework uses proxies to implement lazy loading of entities.\n\n## Benefits and Trade-offs of Virtual Proxy Pattern\n\nBenefits:\n\n* Reduces memory usage by deferring object creation.\n* Can improve performance by delaying heavy operations until needed.\n\nTrade-offs:\n\n* Introduces complexity in the codebase.\n* Can lead to unexpected behaviors if not handled properly, especially in multithreaded environments.\n\n## Related Java Design Patterns\n\n* [Proxy](https://java-design-patterns.com/patterns/proxy/): Virtual Proxy is a specific type of the Proxy pattern focused on lazy initialization.\n* [Lazy Loading](https://java-design-patterns.com/patterns/lazy-loading/): Directly related as the core idea of Virtual Proxy is to defer object creation.\n* [Decorator](https://java-design-patterns.com/patterns/decorator/): Similar in structure, but Decorators add behavior to the objects while proxies control access.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Effective Java](https://amzn.to/4cGk2Jz)\n* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR)\n"
  },
  {
    "path": "virtual-proxy/etc/virtual-proxy.urm.puml",
    "content": "@startuml\npackage com.iluwatar.virtual.proxy {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  interface ExpensiveObject {\n    + process() {abstract}\n  }\n  class RealVideoObject {\n    - LOGGER : Logger {static}\n    + RealVideoObject()\n    - heavyInitialConfiguration()\n    + process()\n  }\n  class VideoObjectProxy {\n    - realVideoObject : RealVideoObject\n    + VideoObjectProxy()\n    + getRealVideoObject() : RealVideoObject\n    + process()\n  }\n}\nVideoObjectProxy -->  \"-realVideoObject\" RealVideoObject\nRealVideoObject ..|> ExpensiveObject \nVideoObjectProxy ..|> ExpensiveObject \n@enduml"
  },
  {
    "path": "virtual-proxy/etc/virtual.proxy.urm.puml",
    "content": "@startuml\nclass Client {\n    + main(args : String[]) {static}\n}\n\nclass RealVideoObject {\n    - videoData : String\n    + RealVideoObject()\n    + process()\n    + getVideoData() : String\n    - heavyInitialConfiguration() : void\n}\n\ninterface ExpensiveObject {\n    + process() {abstract}\n}\n\nclass VideoObjectProxy {\n    - realVideoObject : RealVideoObject\n    + VideoObjectProxy()\n    + process()\n    + setRealVideoObject(realVideoObject : RealVideoObject) : void\n    + getRealVideoObject() : RealVideoObject\n}\n\nVideoObjectProxy -->  \"-realVideoObject\" RealVideoObject\nRealVideoObject ..|> ExpensiveObject\nVideoObjectProxy ..|> ExpensiveObject\n@enduml\n"
  },
  {
    "path": "virtual-proxy/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>com.iluwatar</groupId>\n        <artifactId>java-design-patterns</artifactId>\n        <version>1.26.0-SNAPSHOT</version>\n    </parent>\n    <artifactId>virtual-proxy</artifactId>\n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.hamcrest</groupId>\n            <artifactId>hamcrest</artifactId>\n            <version>3.0</version>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <executions>\n                    <execution>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <mainClass>App</mainClass>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>"
  },
  {
    "path": "virtual-proxy/src/main/java/com/iluwatar/virtual/proxy/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.virtual.proxy;\n\n/** The main application class that sets up and runs the Virtual Proxy pattern demo. */\npublic class App {\n  /**\n   * The entry point of the application.\n   *\n   * @param args the command line arguments\n   */\n  public static void main(String[] args) {\n    ExpensiveObject videoObject = new VideoObjectProxy();\n    videoObject.process(); // The first call creates and plays the video\n    videoObject.process(); // Subsequent call uses the already created object\n  }\n}\n"
  },
  {
    "path": "virtual-proxy/src/main/java/com/iluwatar/virtual/proxy/ExpensiveObject.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.virtual.proxy;\n\n/** Interface for expensive object and proxy object. */\npublic interface ExpensiveObject {\n  void process();\n}\n"
  },
  {
    "path": "virtual-proxy/src/main/java/com/iluwatar/virtual/proxy/RealVideoObject.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.virtual.proxy;\n\nimport lombok.Getter;\nimport lombok.extern.slf4j.Slf4j;\n\n/** Represents a real video object that is expensive to create and manage. */\n@Slf4j\n@Getter\npublic class RealVideoObject implements ExpensiveObject {\n\n  public RealVideoObject() {\n    heavyInitialConfiguration();\n  }\n\n  private void heavyInitialConfiguration() {\n    LOGGER.info(\"Loading initial video configurations...\");\n  }\n\n  @Override\n  public void process() {\n    LOGGER.info(\"Processing and playing video content...\");\n  }\n}\n"
  },
  {
    "path": "virtual-proxy/src/main/java/com/iluwatar/virtual/proxy/VideoObjectProxy.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.virtual.proxy;\n\nimport lombok.Getter;\n\n/**\n * A proxy class for the real video object, providing a layer of control over the object\n * instantiation.\n */\n@Getter\npublic class VideoObjectProxy implements ExpensiveObject {\n  private RealVideoObject realVideoObject;\n\n  @Override\n  public void process() {\n    if (realVideoObject == null) {\n      realVideoObject = new RealVideoObject();\n    }\n    realVideoObject.process();\n  }\n}\n"
  },
  {
    "path": "virtual-proxy/src/test/java/com/iluwatar/virtual/proxy/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.virtual.proxy;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test */\nclass AppTest {\n\n  @Test\n  void shouldExecuteApplicationWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "virtual-proxy/src/test/java/com/iluwatar/virtual/proxy/RealVideoObjectTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.virtual.proxy;\n\nimport static org.hamcrest.MatcherAssert.assertThat;\nimport static org.hamcrest.Matchers.instanceOf;\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Tests for RealVideoObject. */\nclass RealVideoObjectTest {\n\n  @Test\n  void testVideoObject() {\n    var videoObject = new RealVideoObject();\n    assertThat(videoObject, instanceOf(ExpensiveObject.class));\n  }\n\n  @Test\n  public void constructorDoesNotThrowException() {\n    assertDoesNotThrow(RealVideoObject::new, \"Constructor should not throw any exception\");\n  }\n\n  @Test\n  public void processDoesNotThrowException() {\n    RealVideoObject realVideoObject = new RealVideoObject();\n    assertDoesNotThrow(realVideoObject::process, \"Process method should not throw any exception\");\n  }\n}\n"
  },
  {
    "path": "virtual-proxy/src/test/java/com/iluwatar/virtual/proxy/VideoObjectProxyTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\npackage com.iluwatar.virtual.proxy;\n\nimport static org.hamcrest.core.IsInstanceOf.instanceOf;\nimport static org.junit.jupiter.api.Assertions.*;\n\nimport org.hamcrest.MatcherAssert;\nimport org.junit.jupiter.api.Test;\n\n/** Tests for VideoObjectProxy. */\npublic class VideoObjectProxyTest {\n  @Test\n  void shouldBeInstanceOfExpensiveObject() {\n    MatcherAssert.assertThat(new VideoObjectProxy(), instanceOf(ExpensiveObject.class));\n  }\n\n  @Test\n  void constructorDoesNotThrowException() {\n    assertDoesNotThrow(VideoObjectProxy::new, \"Constructor should not throw any exception\");\n  }\n\n  @Test\n  void processDoesNotThrowException() {\n    assertDoesNotThrow(\n        () -> new VideoObjectProxy().process(), \"Process method should not throw any exception\");\n  }\n}\n"
  },
  {
    "path": "visitor/README.md",
    "content": "---\ntitle: \"Visitor Pattern in Java: Implementing Robust Operations Across Diverse Object Structures\"\nshortTitle: Visitor\ndescription: \"Explore the Visitor design pattern in Java with detailed examples and class diagrams. Learn how to implement operations without altering object structures for clean and maintainable code.\"\ncategory: Behavioral\nlanguage: en\ntag:\n  - Decoupling\n  - Extensibility\n  - Gang of Four\n  - Object composition\n  - Polymorphism\n---\n\n## Intent of Visitor Design Pattern\n\nTo represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.\n\n## Detailed Explanation of Visitor Pattern with Real-World Examples\n\nReal-world example\n\n> An analogous real-world example of the Visitor design pattern can be seen in a museum tour guide system. Imagine a museum where visitors can take guided tours to learn about different types of exhibits, such as paintings, sculptures, and historical artifacts. Each exhibit type requires a different explanation, which is provided by specialized tour guides.\n> \n> In this scenario, the exhibits are like the elements in the Visitor pattern, and the tour guides are like the visitors. The museum structure remains unchanged, but new guides with new types of tours (operations) can be added without modifying the exhibits themselves. Each guide (visitor) implements a specific way to interact with the exhibits, providing detailed explanations according to their specialization, thereby separating the operations from the objects they operate on. \n\nIn plain words\n\n> The Java Visitor pattern defines operations that can be performed on nodes of various data structures, enhancing Java application extensibility. \n\nWikipedia says\n\n> In object-oriented programming and software engineering, the visitor design pattern is a way of separating an algorithm from an object structure on which it operates. A practical result of this separation is the ability to add new operations to existing object structures without modifying the structures.\n\nSequence diagram\n\n![Visitor sequence diagram](./etc/visitor-sequence-diagram.png)\n\n## Programmatic Example of Visitor Pattern in Java\n\nConsider a tree structure with army units. Commander has two sergeants under it and each sergeant has three soldiers under them. Given that the hierarchy implements the visitor pattern, we can easily create new objects that interact with the commander, sergeants, soldiers, or all of them.\n\nGiven the army unit example from above, we first have the `Unit` and `UnitVisitor` base types.\n\n```java\npublic abstract class Unit {\n\n  private final Unit[] children;\n\n  public Unit(Unit... children) {\n    this.children = children;\n  }\n\n  public void accept(UnitVisitor visitor) {\n    Arrays.stream(children).forEach(child -> child.accept(visitor));\n  }\n}\n\n```\n\n```java\npublic interface UnitVisitor {\n\n  void visit(Soldier soldier);\n\n  void visit(Sergeant sergeant);\n\n  void visit(Commander commander);\n}\n```\n\nThen we have the concrete units `Commander`, `Sergeant`, and `Soldier`.\n\n```java\npublic class Commander extends Unit {\n\n  public Commander(Unit... children) {\n    super(children);\n  }\n\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visit(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"commander\";\n  }\n}\n```\n\n```java\npublic class Sergeant extends Unit {\n\n  public Sergeant(Unit... children) {\n    super(children);\n  }\n\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visit(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"sergeant\";\n  }\n}\n```\n\n```java\npublic class Soldier extends Unit {\n\n  public Soldier(Unit... children) {\n    super(children);\n  }\n\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visit(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"soldier\";\n  }\n}\n```\n\nHere are the concrete visitors `CommanderVisitor`, `SergeantVisitor`, and `SoldierVisitor`.\n\n```java\n@Slf4j\npublic class CommanderVisitor implements UnitVisitor {\n\n  @Override\n  public void visit(Soldier soldier) {\n    // Do nothing\n  }\n\n  @Override\n  public void visit(Sergeant sergeant) {\n    // Do nothing\n  }\n\n  @Override\n  public void visit(Commander commander) {\n    LOGGER.info(\"Good to see you {}\", commander);\n  }\n}\n```\n\n```java\n@Slf4j\npublic class SergeantVisitor implements UnitVisitor {\n\n  @Override\n  public void visit(Soldier soldier) {\n    // Do nothing\n  }\n\n  @Override\n  public void visit(Sergeant sergeant) {\n    LOGGER.info(\"Hello {}\", sergeant);\n  }\n\n  @Override\n  public void visit(Commander commander) {\n    // Do nothing\n  }\n}\n```\n\n```java\n@Slf4j\npublic class SoldierVisitor implements UnitVisitor {\n\n  @Override\n  public void visit(Soldier soldier) {\n    LOGGER.info(\"Greetings {}\", soldier);\n  }\n\n  @Override\n  public void visit(Sergeant sergeant) {\n    // Do nothing\n  }\n\n  @Override\n  public void visit(Commander commander) {\n    // Do nothing\n  }\n}\n```\n\nFinally, we can show the power of visitors in action.\n\n```java\npublic static void main(String[] args) {\n\n    var commander = new Commander(\n            new Sergeant(new Soldier(), new Soldier(), new Soldier()),\n            new Sergeant(new Soldier(), new Soldier(), new Soldier())\n    );\n    commander.accept(new SoldierVisitor());\n    commander.accept(new SergeantVisitor());\n    commander.accept(new CommanderVisitor());\n}\n```\n\nProgram output:\n\n```\n14:58:06.115 [main] INFO com.iluwatar.visitor.SoldierVisitor -- Greetings soldier\n14:58:06.118 [main] INFO com.iluwatar.visitor.SoldierVisitor -- Greetings soldier\n14:58:06.118 [main] INFO com.iluwatar.visitor.SoldierVisitor -- Greetings soldier\n14:58:06.118 [main] INFO com.iluwatar.visitor.SoldierVisitor -- Greetings soldier\n14:58:06.118 [main] INFO com.iluwatar.visitor.SoldierVisitor -- Greetings soldier\n14:58:06.118 [main] INFO com.iluwatar.visitor.SoldierVisitor -- Greetings soldier\n14:58:06.118 [main] INFO com.iluwatar.visitor.SergeantVisitor -- Hello sergeant\n14:58:06.118 [main] INFO com.iluwatar.visitor.SergeantVisitor -- Hello sergeant\n14:58:06.118 [main] INFO com.iluwatar.visitor.CommanderVisitor -- Good to see you commander\n```\n\n## When to Use the Visitor Pattern in Java\n\nUse the Visitor pattern when\n\n* Implement the Visitor design pattern in Java when you need to efficiently perform operations across groups of similar objects without modifying their classes, and you want to avoid polluting their classes with this operation.\n* Use it when a class structure is stable, but you need to perform new operations on the structure without changing it.\n* It's beneficial when the set of classes are fixed and only the operations need to be extended.\n\n## Visitor Pattern Java Tutorials\n\n* [Visitor (Refactoring Guru)](https://refactoring.guru/design-patterns/visitor)\n* [Visitor Pattern Tutorial with Java Examples (DZone)](https://dzone.com/articles/design-patterns-visitor)\n* [Visitor Design Pattern (Sourcemaking)](https://sourcemaking.com/design_patterns/visitor)\n\n## Real-World Applications of Visitor Pattern in Java\n\n* Compiler design, where the Visitor pattern can be used for operations like pretty printing, semantic checks, etc.\n* Abstract Syntax Tree (AST) processing.\n* Document structure processing (e.g., HTML, XML).\n* [Apache Wicket](https://github.com/apache/wicket) component tree, see [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)\n* [javax.lang.model.element.AnnotationValue](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValue.html) and [AnnotationValueVisitor](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/AnnotationValueVisitor.html)\n* [javax.lang.model.element.Element](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/Element.html) and [Element Visitor](http://docs.oracle.com/javase/8/docs/api/javax/lang/model/element/ElementVisitor.html)\n* [java.nio.file.FileVisitor](http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileVisitor.html)\n\n## Benefits and Trade-offs of Visitor Pattern\n\nBenefits:\n\n* Simplifies adding new operations: Adding a new operation is straightforward because you can add a new visitor without changing existing code.\n* Single Responsibility Principle: The Visitor pattern allows you to move related behavior into one class.\n* Open/Closed Principle: Elements can stay closed to modification while visitors are open to extension.\n\nTrade-offs:\n\n* Adding new element classes: If you need to add new types of elements, you'll need to change both the visitor interface and all of its concrete visitors.\n* Circular dependencies: In complex systems, this pattern can introduce circular dependencies between visitor and element classes.\n* Breaking encapsulation: Visitor pattern requires that the element classes expose enough details to allow the visitor to do its job, potentially breaking encapsulation.\n\n## Related Java Design Patterns\n\n* [Composite](https://java-design-patterns.com/patterns/composite/): The Visitor pattern is often used in conjunction with the Composite pattern, where the visitor can perform operations over a composite structure.\n* [Interpreter](https://java-design-patterns.com/patterns/interpreter/): Visitors can be used to implement the non-terminal expressions in the Interpreter pattern.\n* [Strategy](https://java-design-patterns.com/patterns/strategy/): Visitor can be considered a way of making strategies work on objects that they were not designed to operate on.\n\n## References and Credits\n\n* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)\n* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq)\n* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525)\n* [Refactoring to Patterns](https://amzn.to/3VOO4F5)\n"
  },
  {
    "path": "visitor/etc/visitor.ucls",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<class-diagram version=\"1.1.8\" icons=\"true\" automaticImage=\"PNG\" always-add-relationships=\"false\" generalizations=\"true\" \n  realizations=\"true\" associations=\"true\" dependencies=\"false\" nesting-relationships=\"true\">  \n  <class id=\"1\" language=\"java\" name=\"com.iluwatar.visitor.SoldierVisitor\" project=\"visitor\" \n    file=\"/visitor/src/main/java/com/iluwatar/visitor/SoldierVisitor.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"142\" width=\"222\" x=\"181\" y=\"204\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"2\" language=\"java\" name=\"com.iluwatar.visitor.Commander\" project=\"visitor\" \n    file=\"/visitor/src/main/java/com/iluwatar/visitor/Commander.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"159\" x=\"705\" y=\"386\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"3\" language=\"java\" name=\"com.iluwatar.visitor.SergeantVisitor\" project=\"visitor\" \n    file=\"/visitor/src/main/java/com/iluwatar/visitor/SergeantVisitor.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"142\" width=\"222\" x=\"443\" y=\"204\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"4\" language=\"java\" name=\"com.iluwatar.visitor.Sergeant\" project=\"visitor\" \n    file=\"/visitor/src/main/java/com/iluwatar/visitor/Sergeant.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"159\" x=\"904\" y=\"386\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <interface id=\"5\" language=\"java\" name=\"com.iluwatar.visitor.UnitVisitor\" project=\"visitor\" \n    file=\"/visitor/src/main/java/com/iluwatar/visitor/UnitVisitor.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"222\" x=\"443\" y=\"386\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </interface>  \n  <class id=\"6\" language=\"java\" name=\"com.iluwatar.visitor.CommanderVisitor\" project=\"visitor\" \n    file=\"/visitor/src/main/java/com/iluwatar/visitor/CommanderVisitor.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"142\" width=\"222\" x=\"705\" y=\"204\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"7\" language=\"java\" name=\"com.iluwatar.visitor.Unit\" project=\"visitor\" \n    file=\"/visitor/src/main/java/com/iluwatar/visitor/Unit.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"105\" width=\"159\" x=\"967\" y=\"204\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <class id=\"8\" language=\"java\" name=\"com.iluwatar.visitor.Soldier\" project=\"visitor\" \n    file=\"/visitor/src/main/java/com/iluwatar/visitor/Soldier.java\" binary=\"false\" corner=\"BOTTOM_RIGHT\">    \n    <position height=\"124\" width=\"159\" x=\"1103\" y=\"386\"/>    \n    <display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n      sort-features=\"false\" accessors=\"true\" visibility=\"true\">      \n      <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>      \n      <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    </display>  \n  </class>  \n  <realization id=\"9\">    \n    <end type=\"SOURCE\" refId=\"1\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </realization>  \n  <association id=\"10\">    \n    <end type=\"SOURCE\" refId=\"7\" navigable=\"false\">      \n      <attribute id=\"11\" name=\"children\"/>      \n      <multiplicity id=\"12\" minimum=\"0\" maximum=\"2147483647\"/>    \n    </end>    \n    <end type=\"TARGET\" refId=\"7\" navigable=\"true\"/>    \n    <display labels=\"true\" multiplicity=\"true\"/>  \n  </association>  \n  <generalization id=\"13\">    \n    <end type=\"SOURCE\" refId=\"4\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <realization id=\"14\">    \n    <end type=\"SOURCE\" refId=\"6\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </realization>  \n  <generalization id=\"15\">    \n    <end type=\"SOURCE\" refId=\"8\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <generalization id=\"16\">    \n    <end type=\"SOURCE\" refId=\"2\"/>    \n    <end type=\"TARGET\" refId=\"7\"/>  \n  </generalization>  \n  <realization id=\"17\">    \n    <end type=\"SOURCE\" refId=\"3\"/>    \n    <end type=\"TARGET\" refId=\"5\"/>  \n  </realization>  \n  <classifier-display autosize=\"true\" stereotype=\"true\" package=\"true\" initial-value=\"false\" signature=\"true\" \n    sort-features=\"false\" accessors=\"true\" visibility=\"true\">    \n    <attributes public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>    \n    <operations public=\"true\" package=\"true\" protected=\"true\" private=\"true\" static=\"true\"/>  \n  </classifier-display>  \n  <association-display labels=\"true\" multiplicity=\"true\"/>\n</class-diagram>"
  },
  {
    "path": "visitor/etc/visitor.urm.puml",
    "content": "@startuml\npackage com.iluwatar.visitor {\n  class App {\n    + App()\n    + main(args : String[]) {static}\n  }\n  class Commander {\n    + Commander(children : Unit[])\n    + accept(visitor : UnitVisitor)\n    + toString() : String\n  }\n  class CommanderVisitor {\n    - LOGGER : Logger {static}\n    + CommanderVisitor()\n    + visitCommander(commander : Commander)\n    + visitSergeant(sergeant : Sergeant)\n    + visitSoldier(soldier : Soldier)\n  }\n  class Sergeant {\n    + Sergeant(children : Unit[])\n    + accept(visitor : UnitVisitor)\n    + toString() : String\n  }\n  class SergeantVisitor {\n    - LOGGER : Logger {static}\n    + SergeantVisitor()\n    + visitCommander(commander : Commander)\n    + visitSergeant(sergeant : Sergeant)\n    + visitSoldier(soldier : Soldier)\n  }\n  class Soldier {\n    + Soldier(children : Unit[])\n    + accept(visitor : UnitVisitor)\n    + toString() : String\n  }\n  class SoldierVisitor {\n    - LOGGER : Logger {static}\n    + SoldierVisitor()\n    + visitCommander(commander : Commander)\n    + visitSergeant(sergeant : Sergeant)\n    + visitSoldier(soldier : Soldier)\n  }\n  abstract class Unit {\n    - children : Unit[]\n    + Unit(children : Unit[])\n    + accept(visitor : UnitVisitor)\n  }\n  interface UnitVisitor {\n    + visitCommander(Commander) {abstract}\n    + visitSergeant(Sergeant) {abstract}\n    + visitSoldier(Soldier) {abstract}\n  }\n}\nCommander --|> Unit \nCommanderVisitor ..|> UnitVisitor \nSergeant --|> Unit \nSergeantVisitor ..|> UnitVisitor \nSoldier --|> Unit \nSoldierVisitor ..|> UnitVisitor \n@enduml"
  },
  {
    "path": "visitor/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n\n    This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n\n    The MIT License\n    Copyright © 2014-2022 Ilkka Seppälä\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n-->\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n  <parent>\n    <groupId>com.iluwatar</groupId>\n    <artifactId>java-design-patterns</artifactId>\n    <version>1.26.0-SNAPSHOT</version>\n  </parent>\n  <artifactId>visitor</artifactId>\n  <dependencies>\n    <dependency>\n      <groupId>org.slf4j</groupId>\n      <artifactId>slf4j-api</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>ch.qos.logback</groupId>\n      <artifactId>logback-classic</artifactId>\n    </dependency>\n    <dependency>\n      <groupId>org.junit.jupiter</groupId>\n      <artifactId>junit-jupiter-engine</artifactId>\n      <scope>test</scope>\n    </dependency>\n    <dependency>\n      <groupId>org.mockito</groupId>\n      <artifactId>mockito-core</artifactId>\n      <scope>test</scope>\n    </dependency>\n  </dependencies>\n  <build>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-assembly-plugin</artifactId>\n        <executions>\n          <execution>\n            <configuration>\n              <archive>\n                <manifest>\n                  <mainClass>com.iluwatar.visitor.App</mainClass>\n                </manifest>\n              </archive>\n            </configuration>\n          </execution>\n        </executions>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n"
  },
  {
    "path": "visitor/src/main/java/com/iluwatar/visitor/App.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\n/**\n * Visitor pattern defines a mechanism to apply operations on nodes in a hierarchy. New operations\n * can be added without altering the node interface.\n *\n * <p>In this example there is a unit hierarchy beginning from {@link Commander}. This hierarchy is\n * traversed by visitors. {@link SoldierVisitor} applies its operation on {@link Soldier}s, {@link\n * SergeantVisitor} on {@link Sergeant}s and so on.\n */\npublic class App {\n\n  /**\n   * Program entry point.\n   *\n   * @param args command line args\n   */\n  public static void main(String[] args) {\n\n    var commander =\n        new Commander(\n            new Sergeant(new Soldier(), new Soldier(), new Soldier()),\n            new Sergeant(new Soldier(), new Soldier(), new Soldier()));\n    commander.accept(new SoldierVisitor());\n    commander.accept(new SergeantVisitor());\n    commander.accept(new CommanderVisitor());\n  }\n}\n"
  },
  {
    "path": "visitor/src/main/java/com/iluwatar/visitor/Commander.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\n/** Commander. */\npublic class Commander extends Unit {\n\n  public Commander(Unit... children) {\n    super(children);\n  }\n\n  /**\n   * Accept a Visitor.\n   *\n   * @param visitor UnitVisitor to be accepted\n   */\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visit(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"commander\";\n  }\n}\n"
  },
  {
    "path": "visitor/src/main/java/com/iluwatar/visitor/CommanderVisitor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** CommanderVisitor. */\n@Slf4j\npublic class CommanderVisitor implements UnitVisitor {\n\n  /**\n   * Soldier Visitor method.\n   *\n   * @param soldier Soldier to be visited\n   */\n  @Override\n  public void visit(Soldier soldier) {\n    // Do nothing\n  }\n\n  /**\n   * Sergeant Visitor method.\n   *\n   * @param sergeant Sergeant to be visited\n   */\n  @Override\n  public void visit(Sergeant sergeant) {\n    // Do nothing\n  }\n\n  /**\n   * Commander Visitor method.\n   *\n   * @param commander Commander to be visited\n   */\n  @Override\n  public void visit(Commander commander) {\n    LOGGER.info(\"Good to see you {}\", commander);\n  }\n}\n"
  },
  {
    "path": "visitor/src/main/java/com/iluwatar/visitor/Sergeant.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\n/** Sergeant. */\npublic class Sergeant extends Unit {\n\n  public Sergeant(Unit... children) {\n    super(children);\n  }\n\n  /**\n   * Accept a Visitor.\n   *\n   * @param visitor UnitVisitor to be accepted\n   */\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visit(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"sergeant\";\n  }\n}\n"
  },
  {
    "path": "visitor/src/main/java/com/iluwatar/visitor/SergeantVisitor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** SergeantVisitor. */\n@Slf4j\npublic class SergeantVisitor implements UnitVisitor {\n\n  /**\n   * Soldier Visitor method.\n   *\n   * @param soldier Soldier to be visited\n   */\n  @Override\n  public void visit(Soldier soldier) {\n    // Do nothing\n  }\n\n  /**\n   * Sergeant Visitor method.\n   *\n   * @param sergeant Sergeant to be visited\n   */\n  @Override\n  public void visit(Sergeant sergeant) {\n    LOGGER.info(\"Hello {}\", sergeant);\n  }\n\n  /**\n   * Commander Visitor method.\n   *\n   * @param commander Commander to be visited\n   */\n  @Override\n  public void visit(Commander commander) {\n    // Do nothing\n  }\n}\n"
  },
  {
    "path": "visitor/src/main/java/com/iluwatar/visitor/Soldier.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\n/** Soldier. */\npublic class Soldier extends Unit {\n\n  public Soldier(Unit... children) {\n    super(children);\n  }\n\n  /**\n   * Accept a Visitor.\n   *\n   * @param visitor UnitVisitor to be accepted\n   */\n  @Override\n  public void accept(UnitVisitor visitor) {\n    visitor.visit(this);\n    super.accept(visitor);\n  }\n\n  @Override\n  public String toString() {\n    return \"soldier\";\n  }\n}\n"
  },
  {
    "path": "visitor/src/main/java/com/iluwatar/visitor/SoldierVisitor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\nimport lombok.extern.slf4j.Slf4j;\n\n/** SoldierVisitor. */\n@Slf4j\npublic class SoldierVisitor implements UnitVisitor {\n\n  /**\n   * Soldier Visitor method.\n   *\n   * @param soldier Soldier to be visited\n   */\n  @Override\n  public void visit(Soldier soldier) {\n    LOGGER.info(\"Greetings {}\", soldier);\n  }\n\n  /**\n   * Sergeant Visitor method.\n   *\n   * @param sergeant Sergeant to be visited\n   */\n  @Override\n  public void visit(Sergeant sergeant) {\n    // Do nothing\n  }\n\n  /**\n   * Commander Visitor method.\n   *\n   * @param commander Commander to be visited\n   */\n  @Override\n  public void visit(Commander commander) {\n    // Do nothing\n  }\n}\n"
  },
  {
    "path": "visitor/src/main/java/com/iluwatar/visitor/Unit.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\nimport java.util.Arrays;\n\n/** Interface for the nodes in hierarchy. */\npublic abstract class Unit {\n\n  private final Unit[] children;\n\n  public Unit(Unit... children) {\n    this.children = children;\n  }\n\n  /** Accept visitor. */\n  public void accept(UnitVisitor visitor) {\n    Arrays.stream(children).forEach(child -> child.accept(visitor));\n  }\n}\n"
  },
  {
    "path": "visitor/src/main/java/com/iluwatar/visitor/UnitVisitor.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\n/** Visitor interface. */\npublic interface UnitVisitor {\n\n  void visit(Soldier soldier);\n\n  void visit(Sergeant sergeant);\n\n  void visit(Commander commander);\n}\n"
  },
  {
    "path": "visitor/src/test/java/com/iluwatar/visitor/AppTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\n\nimport org.junit.jupiter.api.Test;\n\n/** Application test. */\nclass AppTest {\n\n  @Test\n  void shouldExecuteWithoutException() {\n    assertDoesNotThrow(() -> App.main(new String[] {}));\n  }\n}\n"
  },
  {
    "path": "visitor/src/test/java/com/iluwatar/visitor/CommanderTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.verify;\n\n/** CommanderTest */\nclass CommanderTest extends UnitTest<Commander> {\n\n  /** Create a new test instance for the given {@link Commander}. */\n  public CommanderTest() {\n    super(Commander::new);\n  }\n\n  @Override\n  void verifyVisit(Commander unit, UnitVisitor mockedVisitor) {\n    verify(mockedVisitor).visit(eq(unit));\n  }\n}\n"
  },
  {
    "path": "visitor/src/test/java/com/iluwatar/visitor/CommanderVisitorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\n/** CommanderVisitorTest */\nclass CommanderVisitorTest extends VisitorTest<CommanderVisitor> {\n\n  /** Create a new test instance for the given visitor. */\n  public CommanderVisitorTest() {\n    super(new CommanderVisitor(), (\"Good to see you commander\"), null, null);\n  }\n}\n"
  },
  {
    "path": "visitor/src/test/java/com/iluwatar/visitor/SergeantTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.verify;\n\n/** SergeantTest */\nclass SergeantTest extends UnitTest<Sergeant> {\n\n  /** Create a new test instance for the given {@link Sergeant}. */\n  public SergeantTest() {\n    super(Sergeant::new);\n  }\n\n  @Override\n  void verifyVisit(Sergeant unit, UnitVisitor mockedVisitor) {\n    verify(mockedVisitor).visit(eq(unit));\n  }\n}\n"
  },
  {
    "path": "visitor/src/test/java/com/iluwatar/visitor/SergeantVisitorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\n/** SergeantVisitorTest */\nclass SergeantVisitorTest extends VisitorTest<SergeantVisitor> {\n\n  /** Create a new test instance for the given visitor. */\n  public SergeantVisitorTest() {\n    super(new SergeantVisitor(), null, (\"Hello sergeant\"), null);\n  }\n}\n"
  },
  {
    "path": "visitor/src/test/java/com/iluwatar/visitor/SoldierTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.verify;\n\n/** SoldierTest */\nclass SoldierTest extends UnitTest<Soldier> {\n\n  /** Create a new test instance for the given {@link Soldier}. */\n  public SoldierTest() {\n    super(Soldier::new);\n  }\n\n  @Override\n  void verifyVisit(Soldier unit, UnitVisitor mockedVisitor) {\n    verify(mockedVisitor).visit(eq(unit));\n  }\n}\n"
  },
  {
    "path": "visitor/src/test/java/com/iluwatar/visitor/SoldierVisitorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\n/** SoldierVisitorTest */\nclass SoldierVisitorTest extends VisitorTest<SoldierVisitor> {\n\n  /** Create a new test instance for the given visitor. */\n  public SoldierVisitorTest() {\n    super(new SoldierVisitor(), null, null, (\"Greetings soldier\"));\n  }\n}\n"
  },
  {
    "path": "visitor/src/test/java/com/iluwatar/visitor/UnitTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.verifyNoMoreInteractions;\n\nimport java.util.Arrays;\nimport java.util.function.Function;\nimport org.junit.jupiter.api.Test;\n\n/**\n * Test related to Units\n *\n * @param <U> Type of Unit\n */\npublic abstract class UnitTest<U extends Unit> {\n\n  /** Factory to create new instances of the tested unit. */\n  private final Function<Unit[], U> factory;\n\n  /**\n   * Create a new test instance for the given unit type {@link U}.\n   *\n   * @param factory Factory to create new instances of the tested unit\n   */\n  public UnitTest(final Function<Unit[], U> factory) {\n    this.factory = factory;\n  }\n\n  @Test\n  void testAccept() {\n    final var children = new Unit[5];\n    Arrays.setAll(children, (i) -> mock(Unit.class));\n\n    final var unit = this.factory.apply(children);\n    final var visitor = mock(UnitVisitor.class);\n    unit.accept(visitor);\n    verifyVisit(unit, visitor);\n\n    Arrays.stream(children).forEach(child -> verify(child).accept(eq(visitor)));\n\n    verifyNoMoreInteractions(children);\n    verifyNoMoreInteractions(visitor);\n  }\n\n  /**\n   * Verify if the correct visit method is called on the mock, depending on the tested instance.\n   *\n   * @param unit The tested unit instance\n   * @param mockedVisitor The mocked {@link UnitVisitor} who should have gotten a visit by the unit\n   */\n  abstract void verifyVisit(final U unit, final UnitVisitor mockedVisitor);\n}\n"
  },
  {
    "path": "visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java",
    "content": "/*\n * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).\n *\n * The MIT License\n * Copyright © 2014-2022 Ilkka Seppälä\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\npackage com.iluwatar.visitor;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nimport ch.qos.logback.classic.Logger;\nimport ch.qos.logback.classic.spi.ILoggingEvent;\nimport ch.qos.logback.core.AppenderBase;\nimport java.util.LinkedList;\nimport java.util.List;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Test case for Visitor Pattern\n *\n * @param <V> Type of UnitVisitor\n */\npublic abstract class VisitorTest<V extends UnitVisitor> {\n\n  private InMemoryAppender appender;\n\n  @BeforeEach\n  void setUp() {\n    appender = new InMemoryAppender();\n  }\n\n  @AfterEach\n  void tearDown() {\n    appender.stop();\n  }\n\n  /** The tested visitor instance. */\n  private final V visitor;\n\n  /** The expected response when being visited by a commander. */\n  private final String commanderResponse;\n\n  /** The expected response when being visited by a sergeant. */\n  private final String sergeantResponse;\n\n  /** The expected response when being visited by a soldier. */\n  private final String soldierResponse;\n\n  /**\n   * Create a new test instance for the given visitor.\n   *\n   * @param commanderResponse The expected response when being visited by a commander\n   * @param sergeantResponse The expected response when being visited by a sergeant\n   * @param soldierResponse The expected response when being visited by a soldier\n   */\n  public VisitorTest(\n      final V visitor,\n      final String commanderResponse,\n      final String sergeantResponse,\n      final String soldierResponse) {\n    this.visitor = visitor;\n    this.commanderResponse = commanderResponse;\n    this.sergeantResponse = sergeantResponse;\n    this.soldierResponse = soldierResponse;\n  }\n\n  @Test\n  void testVisitCommander() {\n    this.visitor.visit(new Commander());\n    if (this.commanderResponse != null) {\n      assertEquals(this.commanderResponse, appender.getLastMessage());\n      assertEquals(1, appender.getLogSize());\n    }\n  }\n\n  @Test\n  void testVisitSergeant() {\n    this.visitor.visit(new Sergeant());\n    if (this.sergeantResponse != null) {\n      assertEquals(this.sergeantResponse, appender.getLastMessage());\n      assertEquals(1, appender.getLogSize());\n    }\n  }\n\n  @Test\n  void testVisitSoldier() {\n    this.visitor.visit(new Soldier());\n    if (this.soldierResponse != null) {\n      assertEquals(this.soldierResponse, appender.getLastMessage());\n      assertEquals(1, appender.getLogSize());\n    }\n  }\n\n  private static class InMemoryAppender extends AppenderBase<ILoggingEvent> {\n    private final List<ILoggingEvent> log = new LinkedList<>();\n\n    public InMemoryAppender() {\n      ((Logger) LoggerFactory.getLogger(\"root\")).addAppender(this);\n      start();\n    }\n\n    @Override\n    protected void append(ILoggingEvent eventObject) {\n      log.add(eventObject);\n    }\n\n    public int getLogSize() {\n      return log.size();\n    }\n\n    public String getLastMessage() {\n      return log.get(log.size() - 1).getFormattedMessage();\n    }\n  }\n}\n"
  }
]